From 12cd957ff9ca5cf8f8c0d174d26955dca0a44cf0 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 12:59:32 -0400 Subject: [PATCH 01/24] docs: design OTel fast usage ingestion --- ...-07-16-otel-fast-usage-ingestion-design.md | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md diff --git a/docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md b/docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md new file mode 100644 index 00000000..9d9cb950 --- /dev/null +++ b/docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md @@ -0,0 +1,236 @@ +# OTel Fast Usage Ingestion Design + +## Goal + +Enrich existing aggregate Codex usage calls with reliable Fast-versus-Standard service-tier +metadata from the local OpenTelemetry `response.completed` stream, then use confirmed Fast +status when estimating ChatGPT credit consumption. + +The feature must remain local, aggregate-only, incremental, idempotent, and conservative. It +must never create a second usage call for an OTel completion, guess when more than one logical +call could match, or persist prompts, message bodies, arbitrary OTel attributes, account data, +or tool content. + +## Non-goals + +- Reconstruct Fast usage before completion-tier telemetry was emitted. +- Treat response timing, reasoning effort, or latency as proof of Fast mode. +- Change USD text-token cost estimates based only on a service-tier label. +- Replace session JSONL as the canonical source of usage calls and token totals. +- Persist or expose raw OTel payloads through the database, dashboard, exports, support + bundles, or tests. +- Add remote telemetry export or change the user's collector configuration. + +## Source contract + +The optional local source is the file-exporter output under the tracker application directory: + +```text +~/.codex-usage-tracker/otel/codex-completions.jsonl +~/.codex-usage-tracker/otel/codex-completions-*.jsonl +``` + +Each line is one OTLP JSON object that may contain multiple resource, scope, and log-record +groups. The parser considers only log records whose allowlisted attributes identify +`event.name = codex.sse_event` and `event.kind = response.completed`. + +The parser may extract only these aggregate fields: + +- `conversation.id` +- `input_token_count` +- `cached_token_count` +- `output_token_count` +- `reasoning_token_count` +- `model` +- `model_reasoning_effort` +- `service_tier` +- `app.version` +- log-record timestamp + +All other attributes, resources, scopes, bodies, trace identifiers, and span identifiers are +ignored. Malformed lines or invalid field types increment bounded diagnostics without copying +the offending content into SQLite or report payloads. + +## Tier normalization + +The normalized call fields are: + +- `service_tier`: `fast`, `standard`, another explicit non-Fast tier, or `NULL` when unknown. +- `fast`: `1` for confirmed Fast, `0` for confirmed non-Fast, or `NULL` when unknown. +- `service_tier_source`: `otel_response_completed` for this ingestion path. +- `service_tier_confidence`: `exact` for explicit tier values and `protocol` when Standard is + established by versioned omission semantics. + +Explicit `priority` and `fast` values normalize to `service_tier = fast` and `fast = 1`. +Explicit `default` and `standard` values normalize to `service_tier = standard` and `fast = 0`. +Other explicit values are preserved as normalized lower-case tier names with `fast = 0`. + +Codex 0.143.0 and later emits `service_tier = priority` for Fast completions and omits the +field for Standard completions. Therefore, a missing service tier with a parseable +`app.version >= 0.143.0` normalizes to `service_tier = standard`, `fast = 0`, and +`service_tier_confidence = protocol`. A missing tier from an older or unparseable version +remains unknown. + +## Persistent ingestion + +Two aggregate-only sidecar tables make ingestion incremental and independent of file arrival +order. + +### OTel source cursors + +`otel_completion_sources` records the source path, device, inode, size, parsed byte offset, +parsed line number, and last refresh timestamp. Append-only files resume at the previous byte +offset. Truncation, inode replacement, or size regression resets the cursor safely. Rotated +files are discovered in deterministic path order. + +### Completion staging + +`otel_completion_events` stores one normalized aggregate completion per semantic fingerprint. +The fingerprint is a versioned SHA-256 digest over the normalized conversation ID, timestamp, +four token counters, model, effort, tier state, and app version. Re-reading a current or +rotated file is therefore idempotent. + +The staging row stores only the extracted aggregate fields, source path, source line, +fingerprint, match status, and an optional matched record ID. It never stores the OTLP line, +body, arbitrary attribute map, prompt, account metadata, or tool content. + +Supported match statuses are `pending`, `matched`, `ambiguous`, `conflict`, and `invalid`. +Pending and ambiguous rows remain available for a later refresh because session JSONL and OTel +files can advance in either order. + +## Conservative correlation + +Session JSONL remains authoritative for call identity and token totals. A normalized OTel +completion may enrich a usage call only when all of the following hold: + +1. `conversation.id` equals `usage_events.session_id`. +2. Input, cached-input, output, and reasoning-output token counts match exactly. +3. Model values match when both sources provide a model. +4. Reasoning-effort values match when both sources provide an effort. +5. The candidates resolve to exactly one canonical usage-call group. + +Timestamp proximity is not a matching key. Export batching and source-event timing can differ, +so timestamp heuristics would create false confidence. The timestamp is used only in the +completion fingerprint and diagnostics. + +If candidates span multiple canonical groups, the completion remains `ambiguous`. If exactly +one canonical group matches, every physical clone in that canonical group receives the same +tier enrichment. This preserves clone consistency without changing usage fingerprints, +canonical IDs, or deduplication decisions. + +Existing non-null tier enrichment is never silently replaced by a contradictory completion. +The completion becomes `conflict`, the existing call value is preserved, and an aggregate +conflict counter is emitted. Repeated agreement is idempotent. + +The session-log upsert must use enrichment-owned merge semantics so a later source replacement +or incremental JSONL refresh cannot erase an existing non-null service tier. + +## Refresh and rebuild behavior + +Normal refresh performs these ordered phases: + +1. Parse and upsert session JSONL usage calls as today. +2. Discover and incrementally parse OTel completion files when the optional directory exists. +3. Reconcile pending and ambiguous completion rows against current usage calls. +4. Recompute affected derived facts, thread summaries, and revision counters. +5. Record bounded OTel coverage diagnostics in refresh metadata. + +An absent OTel directory is a supported no-op. OTel parse failures do not roll back valid +session-log ingestion; they produce aggregate diagnostics and preserve the last valid cursor. + +Rebuild clears canonical usage-derived state but retains normalized OTel staging. It resets +stale match pointers, rebuilds session usage calls, then reconciles the retained completion +events. This makes tier enrichment reproducible without requiring rotated source files to +remain forever. + +## Database and public rows + +`usage_events` gains four repairable nullable columns: + +```text +service_tier TEXT +fast INTEGER +service_tier_source TEXT +service_tier_confidence TEXT +``` + +These fields are additive to existing row and export contracts. Historical calls remain +`NULL`/unknown unless a conservative OTel match exists. They are not identity fields and must +not participate in usage fingerprints, canonical IDs, or duplicate classification. + +Calls and call-detail payloads expose the four aggregate fields. Dashboard labels distinguish +Fast, Standard, and Unknown. Existing proxy analysis remains available for historical unknown +calls, but exact OTel enrichment takes precedence and proxy wording must not claim that direct +tier data is unavailable for enriched rows. + +## Credit and USD pricing semantics + +Confirmed Fast calls multiply the existing Standard ChatGPT credit estimate by the documented +model multiplier: + +- GPT-5.6: `2.5` +- GPT-5.5: `2.5` +- GPT-5.4: `2.0` + +Confirmed Standard and unknown calls use multiplier `1.0`; unknown calls must remain visibly +unknown rather than being labeled Standard. Credit annotations add the effective multiplier +and tier provenance so totals remain explainable. + +USD token-cost estimates remain unchanged. `priority` can represent ChatGPT Fast mode or API +Priority processing, and the retained aggregate fields do not prove the authentication or +billing path. Applying an API Priority price automatically would therefore be unsafe. + +## Diagnostics and privacy + +Refresh diagnostics report aggregate counts only, including files scanned, completions +imported, matched, pending, ambiguous, conflicting, malformed, and unsupported-version rows. +Support bundles may include those counts and configuration presence, never source paths, +conversation IDs, fingerprints, record IDs, timestamps, token tuples, or raw payloads. + +Default dashboards, CSV, JSON, MCP responses, screenshots, and fixtures remain aggregate-first. +All committed fixtures use synthetic conversation IDs, timestamps, models, and token counts. + +## Test strategy + +Implementation follows red-green-refactor cycles with synthetic files and databases. + +Parser tests cover: + +- OTLP batches containing multiple resource and scope groups. +- Allowlisted completion extraction and arbitrary-field rejection. +- Explicit Fast, explicit Standard, protocol-omitted Standard, and unknown older versions. +- Invalid JSON, invalid integers, missing identifiers, and non-completion log records. +- Current-file append, truncation, replacement, rotation, and semantic deduplication. + +Store tests cover: + +- OTel-before-JSONL and JSONL-before-OTel arrival. +- Unique exact match, no match, multiple canonical matches, and conflicting tiers. +- Repeated refresh idempotency. +- Canonical clone propagation. +- Session source replacement preserving tier enrichment. +- Rebuild from retained staging. +- Schema migration and repairable-column behavior. +- No raw OTel body or arbitrary attribute persisted in any table. + +Pricing and report tests cover: + +- Fast credit multipliers for GPT-5.6, GPT-5.5, and GPT-5.4. +- Standard and unknown credit multiplier behavior. +- USD cost estimates remaining unchanged. +- Exact tier taking precedence over historical proxy labels. +- Additive Calls, detail, export, and support-bundle contract behavior. + +## Acceptance criteria + +- A uniquely correlated synthetic Fast completion enriches exactly one canonical call group. +- A uniquely correlated synthetic Standard completion records confirmed Standard status. +- Ambiguous or unmatched completions never alter usage calls. +- Refresh, rotation, source replacement, and rebuild remain idempotent. +- Credit estimates use documented Fast multipliers only for confirmed Fast calls. +- USD estimates do not change from service-tier enrichment. +- Historical unknown calls remain unknown. +- No raw OTel content appears in SQLite, default reports, exports, support bundles, docs, or + committed fixtures. +- Focused parser, store, migration, pricing, report, and privacy tests pass before the full + repository verification gate. From 97f53bdad03cfe9b8b3eb0b882c4bd1ce59f64c5 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:21:16 -0400 Subject: [PATCH 02/24] docs: plan OTel fast usage ingestion --- .../2026-07-16-otel-fast-usage-ingestion.md | 1685 +++++++++++++++++ 1 file changed, 1685 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-16-otel-fast-usage-ingestion.md diff --git a/docs/superpowers/plans/2026-07-16-otel-fast-usage-ingestion.md b/docs/superpowers/plans/2026-07-16-otel-fast-usage-ingestion.md new file mode 100644 index 00000000..b2659bc4 --- /dev/null +++ b/docs/superpowers/plans/2026-07-16-otel-fast-usage-ingestion.md @@ -0,0 +1,1685 @@ +# OTel Fast Usage Ingestion Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Enrich canonical Codex usage calls with exact Fast-versus-Standard service-tier metadata from the local OTLP completion stream and apply confirmed Fast multipliers to ChatGPT credit estimates. + +**Architecture:** Session JSONL remains authoritative for usage calls and token totals. A pure parser converts allowlisted OTLP completion attributes into aggregate records, a persistent sidecar ingests them incrementally, and a conservative reconciler enriches one canonical usage group only when conversation and token identity are unique. Pricing and dashboard layers consume the additive tier fields while USD token estimates remain unchanged. + +**Tech Stack:** Python 3.10+, dataclasses, SQLite, pytest, TypeScript, React, Vitest, existing Vite dashboard build. + +## Global Constraints + +- Persist only `conversation.id`, four token counters, model, effort, service tier, app version, timestamp, source path/line, fingerprint, and match state from OTLP. +- Never persist or expose OTLP bodies, arbitrary attributes, resource attributes, prompts, account data, tool content, trace IDs, or span IDs. +- Treat timestamp as a fingerprint and diagnostic field only; never use timestamp proximity for correlation. +- Enrich only when conversation ID and all four token counters match and candidates resolve to exactly one canonical usage group. +- Normalize explicit `priority` or `fast` as confirmed Fast; explicit `default` or `standard` as confirmed Standard. +- Treat omitted tier as protocol-confirmed Standard only for parseable `app.version >= 0.143.0`; older or unparseable omissions remain unknown. +- Preserve session JSONL as the canonical source of call identity and token totals. +- Apply Fast credit multipliers only to confirmed Fast calls: GPT-5.6 `2.5`, GPT-5.5 `2.5`, GPT-5.4 `2.0`. +- Do not change USD token-cost estimates from service-tier enrichment. +- Keep committed fixtures entirely synthetic and keep aggregate-only default output behavior. + +--- + +## File structure + +- `src/codex_usage_tracker/parser/otel.py`: pure OTLP traversal, allowlisted value coercion, version-aware tier normalization, and semantic fingerprinting. +- `src/codex_usage_tracker/store/otel_schema.py`: schema version 30 sidecar tables and indexes. +- `src/codex_usage_tracker/store/otel_ingest.py`: deterministic discovery, cursor handling, complete-line reads, and normalized staging upserts. +- `src/codex_usage_tracker/store/otel_reconciliation.py`: unique canonical-group matching, clone propagation, conflict handling, and match reset. +- `src/codex_usage_tracker/pricing/fast_tier.py`: shared documented Fast multiplier policy and credit provenance. +- Existing core/store/refresh/report modules: additive usage columns, orchestration, rebuild semantics, metadata, and privacy-safe support coverage. +- Existing React source: typed tier decoding, exact/proxy distinction, Calls column, detail labels, and CSV fields. +- `tests/otel_helpers.py`: synthetic UsageEvent, session JSONL, and OTLP factories shared by focused tests. +- Focused parser/store/pricing/dashboard tests: synthetic OTLP batches and databases only. + +### Task 1: Add the aggregate tier schema and persistent sidecar tables + +**Files:** +- Modify: `src/codex_usage_tracker/core/paths.py` +- Modify: `src/codex_usage_tracker/core/models.py` +- Modify: `src/codex_usage_tracker/core/schema.py` +- Create: `src/codex_usage_tracker/store/otel_schema.py` +- Modify: `src/codex_usage_tracker/store/schema.py` +- Test: `tests/core/test_schema.py` +- Create: `tests/store/test_otel_schema.py` +- Modify: `tests/store/test_store_migrations.py` + +**Interfaces:** +- Produces: `DEFAULT_OTEL_COMPLETIONS_DIR: Path`. +- Produces: nullable `UsageEvent.service_tier`, `fast`, `service_tier_source`, and `service_tier_confidence` fields. +- Produces: `otel_completion_sources` and `otel_completion_events` tables through schema migration 30. +- Consumes: existing `UsageColumn`, migration recording, and repair-column behavior. + +- [ ] **Step 1: Write failing schema-shape and migration tests** + +```python +def test_usage_event_schema_includes_nullable_service_tier_fields() -> None: + row = usage_event_fixture().to_row() + assert row["service_tier"] is None + assert row["fast"] is None + assert row["service_tier_source"] is None + assert row["service_tier_confidence"] is None + + +def test_schema_migration_creates_otel_sidecar_tables(tmp_path: Path) -> None: + with connect(tmp_path / "usage.sqlite3") as conn: + init_db(conn) + source_columns = { + str(row["name"]) for row in conn.execute("PRAGMA table_info(otel_completion_sources)") + } + event_columns = { + str(row["name"]) for row in conn.execute("PRAGMA table_info(otel_completion_events)") + } + assert {"source_path", "device", "inode", "size", "parsed_offset", "parsed_line"} <= source_columns + assert {"fingerprint", "conversation_id", "service_tier", "fast", "match_status"} <= event_columns + + +def test_legacy_migration_exports_unknown_tier_fields_as_empty(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + csv_path = tmp_path / "usage.csv" + _write_legacy_usage_database(db_path) + export_usage_csv(csv_path, db_path=db_path) + with csv_path.open(encoding="utf-8", newline="") as handle: + row = next(csv.DictReader(handle)) + assert row["service_tier"] == "" + assert row["fast"] == "" + assert row["service_tier_source"] == "" + assert row["service_tier_confidence"] == "" +``` + +- [ ] **Step 2: Run the focused tests and verify the missing fields/tables fail** + +Run: `.venv/bin/python -m pytest tests/core/test_schema.py tests/store/test_otel_schema.py -q` + +Expected: FAIL because the four `UsageEvent` fields and OTel sidecar tables do not exist. + +- [ ] **Step 3: Add the paths, nullable columns, and migration** + +```python +# core/paths.py +DEFAULT_OTEL_COMPLETIONS_DIR = APP_DIR / "otel" + +# core/models.py, after duplicate_reason +service_tier: str | None = None +fast: int | None = None +service_tier_source: str | None = None +service_tier_confidence: str | None = None + +# core/schema.py, before derived numeric columns +UsageColumn("service_tier", "TEXT", "TEXT", repairable=True), +UsageColumn("fast", "INTEGER", "INTEGER", repairable=True), +UsageColumn("service_tier_source", "TEXT", "TEXT", repairable=True), +UsageColumn("service_tier_confidence", "TEXT", "TEXT", repairable=True), +``` + +Create `store/otel_schema.py` with one idempotent migration: + +```python +MIGRATION_NAMES = {30: "persist OTel completion tier enrichment"} + +OTEL_MATCH_STATUSES = ("pending", "matched", "ambiguous", "conflict", "invalid") + + +def migrate_otel_completion_tiers(conn: sqlite3.Connection) -> None: + existing_usage_columns = { + str(row["name"]) for row in conn.execute("PRAGMA table_info(usage_events)") + } + for column, column_type in { + "service_tier": "TEXT", + "fast": "INTEGER", + "service_tier_source": "TEXT", + "service_tier_confidence": "TEXT", + }.items(): + if column not in existing_usage_columns: + conn.execute( # nosec B608 - fixed migration column names + f"ALTER TABLE usage_events ADD COLUMN {column} {column_type}" + ) + conn.executescript( + """ + CREATE TABLE IF NOT EXISTS otel_completion_sources ( + source_path TEXT PRIMARY KEY, + device INTEGER NOT NULL, + inode INTEGER NOT NULL, + size INTEGER NOT NULL, + parsed_offset INTEGER NOT NULL, + parsed_line INTEGER NOT NULL, + updated_at TEXT NOT NULL + ); + CREATE TABLE IF NOT EXISTS otel_completion_events ( + fingerprint TEXT PRIMARY KEY, + conversation_id TEXT, + event_timestamp TEXT, + input_tokens INTEGER, + cached_input_tokens INTEGER, + output_tokens INTEGER, + reasoning_output_tokens INTEGER, + model TEXT, + effort TEXT, + service_tier TEXT, + fast INTEGER, + service_tier_source TEXT, + service_tier_confidence TEXT, + app_version TEXT, + source_path TEXT NOT NULL, + source_line INTEGER NOT NULL, + match_status TEXT NOT NULL CHECK ( + match_status IN ('pending', 'matched', 'ambiguous', 'conflict', 'invalid') + ), + matched_record_id TEXT + ); + CREATE INDEX IF NOT EXISTS idx_otel_completion_match_status + ON otel_completion_events(match_status); + CREATE INDEX IF NOT EXISTS idx_otel_completion_identity + ON otel_completion_events( + conversation_id, input_tokens, cached_input_tokens, + output_tokens, reasoning_output_tokens + ); + """ + ) +``` + +Set `SCHEMA_VERSION = 30`, merge `otel_schema.MIGRATION_NAMES`, and append `(30, otel_schema.migrate_otel_completion_tiers)` to `_schema_migrations()`. + +- [ ] **Step 4: Run the focused schema tests and verify they pass** + +Run: `.venv/bin/python -m pytest tests/core/test_schema.py tests/store/test_otel_schema.py tests/store/test_store_migrations.py -q` + +Expected: PASS. + +- [ ] **Step 5: Commit the schema slice** + +```bash +git add -- src/codex_usage_tracker/core/paths.py src/codex_usage_tracker/core/models.py src/codex_usage_tracker/core/schema.py src/codex_usage_tracker/store/otel_schema.py src/codex_usage_tracker/store/schema.py tests/core/test_schema.py tests/store/test_otel_schema.py tests/store/test_store_migrations.py +git commit -m "feat: add OTel completion tier schema" +``` + +### Task 2: Parse and normalize aggregate OTLP completions + +**Files:** +- Create: `src/codex_usage_tracker/parser/otel.py` +- Modify: `src/codex_usage_tracker/parser/__init__.py` +- Create: `tests/otel_helpers.py` +- Create: `tests/parser/test_otel_parser.py` + +**Interfaces:** +- Produces: `OtelCompletion` and `OtelParseResult` frozen dataclasses. +- Produces: `parse_otlp_json_line(raw: str) -> OtelParseResult`. +- Produces: `OTEL_DIAGNOSTIC_KEYS` for bounded refresh metadata. +- Consumes: one JSON line only; it never receives a database connection. + +- [ ] **Step 1: Write failing parser tests for traversal, normalization, omission semantics, and privacy** + +```python +def test_parse_otlp_batch_extracts_only_completion_allowlist() -> None: + raw = synthetic_otlp_line( + attributes={ + "event.name": "codex.sse_event", + "event.kind": "response.completed", + "conversation.id": "synthetic-conversation", + "input_token_count": 120, + "cached_token_count": 40, + "output_token_count": 30, + "reasoning_token_count": 10, + "model": "gpt-5.6-sol", + "model_reasoning_effort": "high", + "service_tier": "priority", + "app.version": "0.143.0", + "secret.attribute": "must-not-survive", + }, + body="synthetic private body that must not survive", + ) + result = parse_otlp_json_line(raw) + assert len(result.completions) == 1 + completion = result.completions[0] + assert completion.service_tier == "fast" + assert completion.fast == 1 + assert completion.service_tier_confidence == "exact" + assert "private body" not in repr(completion) + assert "secret.attribute" not in repr(completion) + + +@pytest.mark.parametrize( + ("version", "tier", "fast", "confidence"), + [("0.143.0", "standard", 0, "protocol"), ("0.142.9", None, None, None), ("bad", None, None, None)], +) +def test_missing_service_tier_uses_versioned_protocol_semantics( + version: str, + tier: str | None, + fast: int | None, + confidence: str | None, +) -> None: + result = parse_otlp_json_line( + synthetic_otlp_line(attributes=completion_attributes(app_version=version, service_tier=None)) + ) + completion = result.completions[0] + assert (completion.service_tier, completion.fast, completion.service_tier_confidence) == ( + tier, + fast, + confidence, + ) +``` + +Add these concrete cases in the same test file: + +```python +@pytest.mark.parametrize( + ("raw_tier", "normalized_tier", "fast"), + [ + ("fast", "fast", 1), + ("default", "standard", 0), + ("standard", "standard", 0), + ("flex", "flex", 0), + ], +) +def test_explicit_tier_aliases(raw_tier: str, normalized_tier: str, fast: int) -> None: + attributes = completion_attributes(service_tier=raw_tier) + completion = parse_otlp_json_line(synthetic_otlp_line(attributes=attributes)).completions[0] + assert (completion.service_tier, completion.fast) == (normalized_tier, fast) + + +def test_multiple_resource_and_scope_groups_are_traversed() -> None: + first = json.loads(synthetic_otlp_line(attributes=completion_attributes(conversation_id="a"))) + second = json.loads(synthetic_otlp_line(attributes=completion_attributes(conversation_id="b"))) + first["resourceLogs"].extend(second["resourceLogs"]) + result = parse_otlp_json_line(json.dumps(first)) + assert [item.conversation_id for item in result.completions] == ["a", "b"] + + +@pytest.mark.parametrize("raw", ["{", "[]", json.dumps({"resourceLogs": "bad"})]) +def test_malformed_payloads_return_bounded_diagnostics(raw: str) -> None: + result = parse_otlp_json_line(raw) + assert not result.completions + assert sum(result.diagnostics.values()) >= 1 + + +def test_non_completion_and_missing_identity_never_become_pending_matches() -> None: + unrelated = completion_attributes() + unrelated["event.kind"] = "response.created" + missing_identity = completion_attributes() + missing_identity.pop("conversation.id") + assert not parse_otlp_json_line(synthetic_otlp_line(attributes=unrelated)).completions + completion = parse_otlp_json_line( + synthetic_otlp_line(attributes=missing_identity) + ).completions[0] + assert completion.match_status == "invalid" +``` + +- [ ] **Step 2: Run the parser tests and verify the import fails** + +Run: `.venv/bin/python -m pytest tests/parser/test_otel_parser.py -q` + +Expected: FAIL because `codex_usage_tracker.parser.otel` does not exist. + +- [ ] **Step 3: Implement pure allowlisted parsing and semantic fingerprinting** + +```python +OTEL_DIAGNOSTIC_KEYS = ( + "otel_invalid_json", + "otel_invalid_record", + "otel_invalid_integer", + "otel_unsupported_version", + "otel_non_completion", +) + + +@dataclass(frozen=True) +class OtelCompletion: + fingerprint: str + conversation_id: str | None + event_timestamp: str | None + input_tokens: int | None + cached_input_tokens: int | None + output_tokens: int | None + reasoning_output_tokens: int | None + model: str | None + effort: str | None + service_tier: str | None + fast: int | None + service_tier_source: str | None + service_tier_confidence: str | None + app_version: str | None + match_status: str + + +@dataclass(frozen=True) +class OtelParseResult: + completions: Sequence[OtelCompletion] + diagnostics: dict[str, int] + + +def parse_otlp_json_line(raw: str) -> OtelParseResult: + try: + payload = json.loads(raw) + except (json.JSONDecodeError, UnicodeDecodeError): + return OtelParseResult((), {"otel_invalid_json": 1}) + completions: list[OtelCompletion] = [] + diagnostics: Counter[str] = Counter() + for record in _log_records(payload): + attributes = _allowlisted_attributes(record.get("attributes")) + if attributes.get("event.name") != "codex.sse_event" or attributes.get("event.kind") != "response.completed": + diagnostics["otel_non_completion"] += 1 + continue + completion, completion_diagnostics = _completion_from_attributes(record, attributes) + diagnostics.update(completion_diagnostics) + completions.append(completion) + return OtelParseResult(tuple(completions), dict(diagnostics)) +``` + +`_allowlisted_attributes()` must decode only the ten approved keys; `_otlp_value()` must accept only scalar `stringValue`, `intValue`, `doubleValue`, and `boolValue`. `_normalize_tier()` returns `(tier, fast, source, confidence)` and `_semantic_fingerprint()` hashes a versioned, sorted JSON object containing only the normalized allowlist fields. A syntactically valid completion without usable identity or tier semantics receives `match_status = "invalid"`. + +Create `tests/otel_helpers.py` with synthetic-only factories used by later tasks: + +```python +def completion_attributes( + *, + conversation_id: str = "synthetic-conversation", + tokens: tuple[int, int, int, int] = (120, 40, 30, 10), + model: str = "gpt-5.6-sol", + effort: str = "high", + service_tier: str | None = "priority", + app_version: str = "0.143.0", +) -> dict[str, object]: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + values: dict[str, object] = { + "event.name": "codex.sse_event", + "event.kind": "response.completed", + "conversation.id": conversation_id, + "input_token_count": input_tokens, + "cached_token_count": cached_tokens, + "output_token_count": output_tokens, + "reasoning_token_count": reasoning_tokens, + "model": model, + "model_reasoning_effort": effort, + "app.version": app_version, + } + if service_tier is not None: + values["service_tier"] = service_tier + return values + + +def synthetic_otlp_line(*, attributes: dict[str, object], body: str = "synthetic body") -> str: + encoded = [ + {"key": key, "value": {"intValue" if isinstance(value, int) else "stringValue": str(value)}} + for key, value in attributes.items() + ] + return json.dumps( + {"resourceLogs": [{"scopeLogs": [{"logRecords": [{ + "timeUnixNano": "1784160000000000000", + "body": {"stringValue": body}, + "attributes": encoded, + }]}]}]} + ) + + +def synthetic_fast_completion(conversation_id: str, input_tokens: int) -> str: + return synthetic_otlp_line( + attributes=completion_attributes( + conversation_id=conversation_id, + tokens=(input_tokens, 0, 20, 5), + service_tier="priority", + ) + ) + + +def synthetic_standard_completion(conversation_id: str, input_tokens: int) -> str: + return synthetic_otlp_line( + attributes=completion_attributes( + conversation_id=conversation_id, + tokens=(input_tokens, 0, 20, 5), + service_tier=None, + ) + ) + + +def write_lines(path: Path, lines: list[str]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("".join(f"{line}\n" for line in lines), encoding="utf-8") + + +def append_text(path: Path, value: str) -> None: + with path.open("a", encoding="utf-8") as handle: + handle.write(value) + + +@contextmanager +def initialized_connection(tmp_path: Path) -> Iterator[sqlite3.Connection]: + with connect(tmp_path / "usage.sqlite3") as conn: + init_db(conn) + yield conn +``` + +- [ ] **Step 4: Run parser tests and static checks** + +Run: `.venv/bin/python -m pytest tests/parser/test_otel_parser.py -q` + +Run: `.venv/bin/python -m ruff check src/codex_usage_tracker/parser/otel.py tests/parser/test_otel_parser.py` + +Expected: PASS. + +- [ ] **Step 5: Commit the parser slice** + +```bash +git add -- src/codex_usage_tracker/parser/otel.py src/codex_usage_tracker/parser/__init__.py tests/otel_helpers.py tests/parser/test_otel_parser.py +git commit -m "feat: parse aggregate OTel completions" +``` + +### Task 3: Incrementally ingest current and rotated completion files + +**Files:** +- Create: `src/codex_usage_tracker/store/otel_ingest.py` +- Create: `tests/store/test_otel_ingest.py` + +**Interfaces:** +- Consumes: `parse_otlp_json_line()` and an initialized SQLite connection. +- Produces: `discover_otel_sources(directory: Path) -> list[Path]`. +- Produces: `ingest_otel_completion_files(conn, directory: Path) -> OtelIngestResult`. +- Persists: normalized rows in `otel_completion_events` and complete-line cursors in `otel_completion_sources`. + +- [ ] **Step 1: Write failing ingestion tests for append, partial lines, rotation, truncation, and semantic deduplication** + +```python +def test_incremental_ingest_reads_each_complete_line_once(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + write_lines(source, [synthetic_fast_completion("conversation-a", 100)]) + with initialized_connection(tmp_path) as conn: + first = ingest_otel_completion_files(conn, directory) + append_text(source, synthetic_standard_completion("conversation-b", 200) + "\n") + second = ingest_otel_completion_files(conn, directory) + rows = conn.execute("SELECT fingerprint FROM otel_completion_events").fetchall() + assert first.imported == 1 + assert second.imported == 1 + assert len(rows) == 2 + + +def test_partial_last_line_is_retried_after_append(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + complete = synthetic_otlp_line(attributes=completion_attributes()) + source.parent.mkdir(parents=True) + source.write_text(complete[:-1], encoding="utf-8") + with initialized_connection(tmp_path) as conn: + assert ingest_otel_completion_files(conn, directory).imported == 0 + source.write_text(complete + "\n", encoding="utf-8") + assert ingest_otel_completion_files(conn, directory).imported == 1 + + +def test_rotation_and_reread_do_not_duplicate_semantic_completion(tmp_path: Path) -> None: + directory = tmp_path / "otel" + current = directory / "codex-completions.jsonl" + rotated = directory / "codex-completions-20260716.jsonl" + line = synthetic_otlp_line(attributes=completion_attributes()) + "\n" + current.parent.mkdir(parents=True) + current.write_text(line, encoding="utf-8") + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + current.replace(rotated) + current.write_text(line, encoding="utf-8") + result = ingest_otel_completion_files(conn, directory) + count = conn.execute("SELECT COUNT(*) FROM otel_completion_events").fetchone()[0] + assert count == 1 + assert result.duplicates >= 1 + + +def test_truncation_or_inode_replacement_resets_cursor_safely(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + source.parent.mkdir(parents=True) + source.write_text( + synthetic_otlp_line(attributes=completion_attributes(conversation_id="synthetic-a")) + "\n", + encoding="utf-8", + ) + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + source.unlink() + source.write_text( + synthetic_otlp_line(attributes=completion_attributes(conversation_id="synthetic-b")) + "\n", + encoding="utf-8", + ) + assert ingest_otel_completion_files(conn, directory).imported == 1 + + +def test_ingest_never_persists_body_or_arbitrary_attributes(tmp_path: Path) -> None: + directory = tmp_path / "otel" + attributes = completion_attributes() + attributes["secret.attribute"] = "synthetic-secret-value" + write_lines( + directory / "codex-completions.jsonl", + [synthetic_otlp_line(attributes=attributes, body="synthetic-private-body")], + ) + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + rows = conn.execute("SELECT * FROM otel_completion_events").fetchall() + encoded = json.dumps([dict(row) for row in rows], sort_keys=True) + assert "synthetic-private-body" not in encoded + assert "synthetic-secret-value" not in encoded + assert "secret.attribute" not in encoded +``` + +- [ ] **Step 2: Run the ingestion tests and verify the module is missing** + +Run: `.venv/bin/python -m pytest tests/store/test_otel_ingest.py -q` + +Expected: FAIL because `store.otel_ingest` does not exist. + +- [ ] **Step 3: Implement deterministic discovery, cursor reset, and staging upserts** + +```python +@dataclass(frozen=True) +class OtelIngestResult: + files_scanned: int = 0 + imported: int = 0 + duplicates: int = 0 + diagnostics: dict[str, int] = field(default_factory=dict) + + +def discover_otel_sources(directory: Path) -> list[Path]: + if not directory.is_dir(): + return [] + return sorted(path for path in directory.glob("codex-completions*.jsonl") if path.is_file()) + + +def ingest_otel_completion_files(conn: sqlite3.Connection, directory: Path) -> OtelIngestResult: + totals = _MutableIngestTotals() + for path in discover_otel_sources(directory): + state = _source_state(conn, path) + stat = path.stat() + offset, line_number = _resume_position(state, stat) + next_offset, next_line = _ingest_complete_lines(conn, path, offset, line_number, totals) + _upsert_source_cursor(conn, path, stat, next_offset, next_line) + totals.files_scanned += 1 + return totals.freeze() +``` + +Open sources in binary mode, seek to the stored offset, and advance the cursor only after a newline-terminated record is decoded and handled. Insert each completion with `ON CONFLICT(fingerprint) DO NOTHING`; count a zero rowcount as a semantic duplicate. Store the source path and line only in the sidecar table, never in public payloads. + +- [ ] **Step 4: Run ingestion and migration tests** + +Run: `.venv/bin/python -m pytest tests/store/test_otel_ingest.py tests/store/test_otel_schema.py -q` + +Expected: PASS. + +- [ ] **Step 5: Commit the incremental ingestion slice** + +```bash +git add -- src/codex_usage_tracker/store/otel_ingest.py tests/store/test_otel_ingest.py +git commit -m "feat: ingest OTel completions incrementally" +``` + +### Task 4: Reconcile exactly one canonical call group and preserve enrichment + +**Files:** +- Create: `src/codex_usage_tracker/store/otel_reconciliation.py` +- Modify: `src/codex_usage_tracker/store/api.py` +- Modify: `src/codex_usage_tracker/store/source_replacement.py` +- Create: `tests/store/test_otel_reconciliation.py` + +**Interfaces:** +- Consumes: staged rows with `match_status IN ('pending', 'ambiguous', 'matched')`. +- Produces: `reconcile_otel_completions(conn) -> OtelReconciliationResult`. +- Produces: `reset_otel_completion_matches(conn) -> None` for rebuilds. +- Preserves: non-null tier fields during record upsert and source replacement. + +- [ ] **Step 1: Write failing reconciliation tests for uniqueness, clones, ambiguity, conflicts, and preservation** + +```python +def test_unique_token_identity_enriches_every_clone_in_one_canonical_group(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group(conn, conversation_id="conversation-a", tokens=(100, 40, 30, 10)) + stage_completion(conn, conversation_id="conversation-a", tokens=(100, 40, 30, 10), fast=1) + result = reconcile_otel_completions(conn) + rows = conn.execute("SELECT service_tier, fast FROM usage_events ORDER BY record_id").fetchall() + assert result.matched == 1 + assert [(row["service_tier"], row["fast"]) for row in rows] == [("fast", 1), ("fast", 1)] + + +def test_same_tokens_in_two_canonical_groups_remain_ambiguous(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group(conn, "conversation-a", (100, 40, 30, 10), canonical="canonical-a") + insert_usage_clone_group(conn, "conversation-a", (100, 40, 30, 10), canonical="canonical-b") + fingerprint = stage_completion(conn, "conversation-a", (100, 40, 30, 10), fast=1) + reconcile_otel_completions(conn) + status = conn.execute( + "SELECT match_status FROM otel_completion_events WHERE fingerprint = ?", (fingerprint,) + ).fetchone()[0] + tiers = conn.execute("SELECT service_tier FROM usage_events").fetchall() + assert status == "ambiguous" + assert all(row[0] is None for row in tiers) + + +def test_timestamp_distance_does_not_affect_matching(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group(conn, "conversation-a", (100, 40, 30, 10)) + stage_completion( + conn, + "conversation-a", + (100, 40, 30, 10), + fast=1, + event_timestamp="2099-01-01T00:00:00Z", + ) + assert reconcile_otel_completions(conn).matched == 1 + + +def test_model_or_effort_mismatch_prevents_match_when_both_are_present(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group(conn, "conversation-a", (100, 40, 30, 10), model="gpt-5.5") + stage_completion(conn, "conversation-a", (100, 40, 30, 10), fast=1, model="gpt-5.6") + assert reconcile_otel_completions(conn).pending == 1 + + +def test_contradictory_existing_tier_is_preserved_and_marks_conflict(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group( + conn, "conversation-a", (100, 40, 30, 10), service_tier="standard", fast=0 + ) + fingerprint = stage_completion(conn, "conversation-a", (100, 40, 30, 10), fast=1) + assert reconcile_otel_completions(conn).conflicts == 1 + row = conn.execute("SELECT service_tier, fast FROM usage_events LIMIT 1").fetchone() + status = conn.execute( + "SELECT match_status FROM otel_completion_events WHERE fingerprint = ?", (fingerprint,) + ).fetchone()[0] + assert tuple(row) == ("standard", 0) + assert status == "conflict" + + +def test_usage_upsert_and_source_replacement_preserve_non_null_tier(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + original = synthetic_usage_event("record-a", "conversation-a", (100, 40, 30, 10), fast=1) + upsert_usage_events([original], db_path=db_path) + reparsed = replace(original, thread_name="reparsed", service_tier=None, fast=None) + upsert_usage_events([reparsed], db_path=db_path, replace_source_files=[Path(original.source_file)]) + row = query_usage_record(db_path=db_path, record_id="record-a") + assert row is not None + assert (row["service_tier"], row["fast"]) == ("fast", 1) +``` + +Extend `tests/otel_helpers.py` with the complete aggregate-row factory: + +```python +def synthetic_usage_event( + record_id: str, + conversation_id: str, + tokens: tuple[int, int, int, int], + *, + canonical: str = "canonical-a", + model: str = "gpt-5.6-sol", + effort: str = "high", + service_tier: str | None = None, + fast: int | None = None, + duplicate: int = 0, +) -> UsageEvent: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + total_tokens = input_tokens + output_tokens + return UsageEvent( + record_id=record_id, + session_id=conversation_id, + thread_name="Synthetic thread", + session_updated_at="2026-07-16T00:00:00Z", + event_timestamp="2026-07-16T00:00:00Z", + source_file="/synthetic/session.jsonl", + line_number=1, + turn_id="synthetic-turn", + turn_timestamp="2026-07-16T00:00:00Z", + cwd="/synthetic/project", + model=model, + effort=effort, + current_date="2026-07-16", + timezone="UTC", + call_initiator="user", + call_initiator_reason="user_message", + call_initiator_confidence="high", + is_archived=0, + thread_key="thread:Synthetic", + thread_call_index=None, + previous_record_id=None, + next_record_id=None, + thread_source="user", + subagent_type=None, + agent_role=None, + agent_nickname=None, + parent_session_id=None, + parent_thread_name=None, + parent_session_updated_at=None, + model_context_window=258_400, + input_tokens=input_tokens, + cached_input_tokens=cached_tokens, + output_tokens=output_tokens, + reasoning_output_tokens=reasoning_tokens, + total_tokens=total_tokens, + cumulative_input_tokens=input_tokens, + cumulative_cached_input_tokens=cached_tokens, + cumulative_output_tokens=output_tokens, + cumulative_reasoning_output_tokens=reasoning_tokens, + cumulative_total_tokens=total_tokens, + usage_fingerprint=f"synthetic-fingerprint-{canonical}", + canonical_record_id=canonical, + is_duplicate=duplicate, + duplicate_reason="copied_usage_fingerprint" if duplicate else None, + service_tier=service_tier or ("fast" if fast == 1 else "standard" if fast == 0 else None), + fast=fast, + service_tier_source="otel_response_completed" if fast is not None else None, + service_tier_confidence="exact" if fast is not None else None, + ) +``` + +Define `insert_usage_clone_group()` and `stage_completion()` in `test_otel_reconciliation.py`; insert rows using `UsageEvent.to_row()`/`EVENT_COLUMNS` and the exact sidecar columns from Task 1. `insert_usage_clone_group()` creates two physical rows with one canonical ID and `is_duplicate` values `0` and `1`; `stage_completion()` returns its deterministic synthetic fingerprint. These helpers contain no raw-log fields. + +```python +def insert_usage_clone_group( + conn: sqlite3.Connection, + conversation_id: str, + tokens: tuple[int, int, int, int], + *, + canonical: str = "canonical-a", + model: str = "gpt-5.6-sol", + service_tier: str | None = None, + fast: int | None = None, +) -> None: + events = [ + synthetic_usage_event( + f"{canonical}-record-{index}", + conversation_id, + tokens, + canonical=canonical, + model=model, + service_tier=service_tier, + fast=fast, + duplicate=int(index == 1), + ) + for index in range(2) + ] + placeholders = ", ".join("?" for _column in EVENT_COLUMNS) + conn.executemany( + f"INSERT INTO usage_events ({', '.join(EVENT_COLUMNS)}) VALUES ({placeholders})", + [[event.to_row()[column] for column in EVENT_COLUMNS] for event in events], + ) + + +def stage_completion( + conn: sqlite3.Connection, + conversation_id: str, + tokens: tuple[int, int, int, int], + *, + fast: int, + model: str = "gpt-5.6-sol", + event_timestamp: str = "2026-07-16T00:00:00Z", +) -> str: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + fingerprint = hashlib.sha256( + repr((conversation_id, tokens, fast, model, event_timestamp)).encode("utf-8") + ).hexdigest() + conn.execute( + """ + INSERT INTO otel_completion_events ( + fingerprint, conversation_id, event_timestamp, + input_tokens, cached_input_tokens, output_tokens, reasoning_output_tokens, + model, effort, service_tier, fast, service_tier_source, + service_tier_confidence, app_version, source_path, source_line, + match_status, matched_record_id + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'high', ?, ?, 'otel_response_completed', + 'exact', '0.143.0', '/synthetic/codex-completions.jsonl', 1, 'pending', NULL) + """, + ( + fingerprint, + conversation_id, + event_timestamp, + input_tokens, + cached_tokens, + output_tokens, + reasoning_tokens, + model, + "fast" if fast == 1 else "standard", + fast, + ), + ) + return fingerprint +``` + +- [ ] **Step 2: Run the focused tests and verify they fail** + +Run: `.venv/bin/python -m pytest tests/store/test_otel_reconciliation.py -q` + +Expected: FAIL because the reconciler and enrichment-preserving merge behavior do not exist. + +- [ ] **Step 3: Implement canonical matching, clone propagation, and conflict state** + +```python +@dataclass(frozen=True) +class OtelReconciliationResult: + matched: int = 0 + pending: int = 0 + ambiguous: int = 0 + conflicts: int = 0 + updated_usage_rows: int = 0 + + +def reconcile_otel_completions(conn: sqlite3.Connection) -> OtelReconciliationResult: + totals = _MutableReconciliationTotals() + rows = conn.execute( + "SELECT * FROM otel_completion_events " + "WHERE match_status IN ('pending', 'ambiguous', 'matched') ORDER BY source_path, source_line" + ).fetchall() + for completion in rows: + candidates = _candidate_rows(conn, completion) + group_ids = {str(row["canonical_record_id"] or row["record_id"]) for row in candidates} + if not candidates: + _set_match_state(conn, completion["fingerprint"], "pending", None) + totals.pending += 1 + elif len(group_ids) != 1: + _set_match_state(conn, completion["fingerprint"], "ambiguous", None) + totals.ambiguous += 1 + else: + _apply_to_canonical_group(conn, completion, group_ids.pop(), totals) + return totals.freeze() +``` + +`_candidate_rows()` must require exact conversation and token equality, add model/effort equality only when both sides are non-null, and omit timestamp entirely. `_apply_to_canonical_group()` must inspect all physical clones before writing: agreement is idempotent, all-null values receive the normalized tier, and any contradictory non-null value marks the staged completion `conflict` without changing usage rows. + +```python +def _candidate_rows(conn: sqlite3.Connection, completion: sqlite3.Row) -> list[sqlite3.Row]: + return conn.execute( + """ + SELECT record_id, canonical_record_id + FROM usage_events + WHERE session_id = ? + AND input_tokens = ? + AND cached_input_tokens = ? + AND output_tokens = ? + AND reasoning_output_tokens = ? + AND (? IS NULL OR model IS NULL OR lower(model) = lower(?)) + AND (? IS NULL OR effort IS NULL OR lower(effort) = lower(?)) + """, + ( + completion["conversation_id"], + completion["input_tokens"], + completion["cached_input_tokens"], + completion["output_tokens"], + completion["reasoning_output_tokens"], + completion["model"], + completion["model"], + completion["effort"], + completion["effort"], + ), + ).fetchall() + + +def _apply_to_canonical_group( + conn: sqlite3.Connection, + completion: sqlite3.Row, + canonical_id: str, + totals: _MutableReconciliationTotals, +) -> None: + clones = conn.execute( + """ + SELECT record_id, service_tier, fast, service_tier_source, service_tier_confidence + FROM usage_events + WHERE coalesce(nullif(canonical_record_id, ''), record_id) = ? + ORDER BY record_id + """, + (canonical_id,), + ).fetchall() + desired = ( + completion["service_tier"], + completion["fast"], + completion["service_tier_source"], + completion["service_tier_confidence"], + ) + tier_columns = ( + "service_tier", "fast", "service_tier_source", "service_tier_confidence" + ) + contradiction = any( + row[column] is not None and row[column] != expected + for row in clones + for column, expected in zip(tier_columns, desired, strict=True) + ) + if contradiction: + _set_match_state(conn, completion["fingerprint"], "conflict", None) + totals.conflicts += 1 + return + cursor = conn.execute( + """ + UPDATE usage_events + SET service_tier = coalesce(service_tier, ?), + fast = coalesce(fast, ?), + service_tier_source = coalesce(service_tier_source, ?), + service_tier_confidence = coalesce(service_tier_confidence, ?) + WHERE coalesce(nullif(canonical_record_id, ''), record_id) = ? + """, + (*desired, canonical_id), + ) + _set_match_state(conn, completion["fingerprint"], "matched", str(clones[0]["record_id"])) + totals.matched += 1 + totals.updated_usage_rows += max(cursor.rowcount, 0) +``` + +- [ ] **Step 4: Add enrichment-owned merge semantics to existing upserts and replacements** + +```python +OTEL_ENRICHMENT_COLUMNS = { + "service_tier", "fast", "service_tier_source", "service_tier_confidence" +} + + +def _usage_event_upsert_sql() -> str: + placeholders = ", ".join("?" for _column in EVENT_COLUMNS) + update_clause = ", ".join( + f"{column}=COALESCE(usage_events.{column}, excluded.{column})" + if column in OTEL_ENRICHMENT_COLUMNS + else f"{column}=excluded.{column}" + for column in EVENT_COLUMNS + if column != "record_id" + ) + return ( + f"INSERT INTO usage_events ({', '.join(EVENT_COLUMNS)}) " + f"VALUES ({placeholders}) " + f"ON CONFLICT(record_id) DO UPDATE SET {update_clause}" + ) +``` + +Before `_delete_usage_events_for_source_files()`, capture one consistent tier tuple per `canonical_record_id`. After `_insert_usage_event_rows()`, restore those tuples to all rows in the same canonical group. If the captured group is internally inconsistent, do not restore it; the staged completion will be re-evaluated by reconciliation. + +- [ ] **Step 5: Run reconciliation, deduplication, and source replacement tests** + +Run: `.venv/bin/python -m pytest tests/store/test_otel_reconciliation.py tests/store/test_usage_deduplication.py tests/store/test_store_large_batches.py -q` + +Expected: PASS. + +- [ ] **Step 6: Commit the correlation slice** + +```bash +git add -- src/codex_usage_tracker/store/otel_reconciliation.py src/codex_usage_tracker/store/api.py src/codex_usage_tracker/store/source_replacement.py tests/store/test_otel_reconciliation.py +git commit -m "feat: correlate OTel tiers to canonical calls" +``` + +### Task 5: Integrate OTel ingestion with refresh, rebuild, metadata, and support diagnostics + +**Files:** +- Modify: `src/codex_usage_tracker/store/refresh.py` +- Modify: `src/codex_usage_tracker/store/api.py` +- Modify: `src/codex_usage_tracker/core/api_payloads.py` +- Modify: `src/codex_usage_tracker/reports/support.py` +- Create: `tests/store/test_otel_refresh.py` +- Modify: `tests/reports/test_support.py` +- Modify: `tests/core/test_api_payloads.py` + +**Interfaces:** +- Extends: `refresh_usage_index()` with keyword `otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR`. +- Extends: `rebuild_usage_index()` with keyword `otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR`. +- Extends: `record_refresh_metadata()` with keyword `otel_diagnostics: dict[str, int] | None = None`. +- Keeps: existing refresh-result JSON fields and adds non-zero `otel_*` keys under `parser_diagnostics`. + +- [ ] **Step 1: Write failing refresh-order, no-op, rebuild, and support privacy tests** + +```python +def test_refresh_ingests_session_rows_before_reconciling_otel(tmp_path: Path) -> None: + codex_home = write_usage_session(tmp_path, conversation_id="conversation-a", tokens=(100, 40, 30, 10)) + otel_dir = tmp_path / "otel" + write_lines( + otel_dir / "codex-completions.jsonl", + [synthetic_otlp_line(attributes=completion_attributes( + conversation_id="conversation-a", tokens=(100, 40, 30, 10), service_tier="priority" + ))], + ) + result = refresh_usage_index(codex_home=codex_home, db_path=tmp_path / "usage.sqlite3", otel_dir=otel_dir) + with connect(tmp_path / "usage.sqlite3") as conn: + record_id = str(conn.execute("SELECT record_id FROM usage_events").fetchone()[0]) + row = query_usage_record(db_path=tmp_path / "usage.sqlite3", record_id=record_id) + assert row is not None + assert row["service_tier"] == "fast" + assert result.parser_diagnostics["otel_matched"] == 1 + + +def test_absent_otel_directory_is_a_supported_noop(tmp_path: Path) -> None: + result = refresh_usage_index( + codex_home=tmp_path / "codex", db_path=tmp_path / "usage.sqlite3", otel_dir=tmp_path / "missing" + ) + assert result.parser_diagnostics.get("otel_files_scanned", 0) == 0 + + +def test_refresh_records_protocol_confirmed_standard(tmp_path: Path) -> None: + codex_home = write_usage_session(tmp_path, "conversation-standard", (100, 40, 30, 10)) + otel_dir = tmp_path / "otel" + write_lines( + otel_dir / "codex-completions.jsonl", + [synthetic_otlp_line(attributes=completion_attributes( + conversation_id="conversation-standard", + tokens=(100, 40, 30, 10), + service_tier=None, + app_version="0.143.0", + ))], + ) + db_path = tmp_path / "usage.sqlite3" + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + with connect(db_path) as conn: + row = conn.execute( + "SELECT service_tier, fast, service_tier_confidence FROM usage_events" + ).fetchone() + assert tuple(row) == ("standard", 0, "protocol") + + +def test_refresh_keeps_older_omitted_tier_unknown(tmp_path: Path) -> None: + codex_home = write_usage_session(tmp_path, "conversation-legacy", (100, 40, 30, 10)) + otel_dir = tmp_path / "otel" + write_lines( + otel_dir / "codex-completions.jsonl", + [synthetic_otlp_line(attributes=completion_attributes( + conversation_id="conversation-legacy", + tokens=(100, 40, 30, 10), + service_tier=None, + app_version="0.142.9", + ))], + ) + db_path = tmp_path / "usage.sqlite3" + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + with connect(db_path) as conn: + row = conn.execute("SELECT service_tier, fast FROM usage_events").fetchone() + assert tuple(row) == (None, None) + + +def test_otel_before_jsonl_matches_on_a_later_refresh(tmp_path: Path) -> None: + otel_dir = tmp_path / "otel" + write_lines( + otel_dir / "codex-completions.jsonl", + [synthetic_otlp_line(attributes=completion_attributes( + conversation_id="conversation-a", tokens=(100, 40, 30, 10) + ))], + ) + db_path = tmp_path / "usage.sqlite3" + refresh_usage_index(codex_home=tmp_path / "empty", db_path=db_path, otel_dir=otel_dir) + codex_home = write_usage_session(tmp_path, "conversation-a", (100, 40, 30, 10)) + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + with connect(db_path) as conn: + assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "fast" + + +def test_rebuild_retains_staging_resets_match_pointer_and_reapplies_tier(tmp_path: Path) -> None: + codex_home = write_usage_session(tmp_path, "conversation-a", (100, 40, 30, 10)) + otel_dir = write_otel_directory(tmp_path, "conversation-a", (100, 40, 30, 10)) + db_path = tmp_path / "usage.sqlite3" + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + rebuild_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + with connect(db_path) as conn: + assert conn.execute("SELECT COUNT(*) FROM otel_completion_events").fetchone()[0] == 1 + assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "fast" + + +def test_support_bundle_exposes_counts_without_otel_identifiers(tmp_path: Path) -> None: + payload = support_bundle_payload(db_path=tmp_path / "usage.sqlite3", codex_home=tmp_path / "codex") + encoded = json.dumps(payload, sort_keys=True) + assert payload["otel"]["completion_directory_exists"] in {True, False} + assert "conversation-a" not in encoded + assert "fingerprint" not in encoded + assert "source_path" not in encoded +``` + +Extend `tests/otel_helpers.py` with concrete session and directory factories: + +```python +def write_usage_session( + tmp_path: Path, + conversation_id: str, + tokens: tuple[int, int, int, int], +) -> Path: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + total_tokens = input_tokens + output_tokens + codex_home = tmp_path / "codex" + log_path = codex_home / "sessions" / "2026" / "07" / "16" / "synthetic.jsonl" + rows = [ + { + "timestamp": "2026-07-16T00:00:00.000Z", + "type": "session_meta", + "payload": {"id": conversation_id}, + }, + { + "timestamp": "2026-07-16T00:00:01.000Z", + "type": "event_msg", + "payload": { + "type": "token_count", + "info": { + "total_token_usage": { + "input_tokens": input_tokens, + "cached_input_tokens": cached_tokens, + "output_tokens": output_tokens, + "reasoning_output_tokens": reasoning_tokens, + "total_tokens": total_tokens, + }, + "last_token_usage": { + "input_tokens": input_tokens, + "cached_input_tokens": cached_tokens, + "output_tokens": output_tokens, + "reasoning_output_tokens": reasoning_tokens, + "total_tokens": total_tokens, + }, + "model_context_window": 258_400, + }, + }, + }, + ] + log_path.parent.mkdir(parents=True, exist_ok=True) + log_path.write_text("".join(json.dumps(row) + "\n" for row in rows), encoding="utf-8") + return codex_home + + +def write_otel_directory( + tmp_path: Path, + conversation_id: str, + tokens: tuple[int, int, int, int], +) -> Path: + directory = tmp_path / "otel" + write_lines( + directory / "codex-completions.jsonl", + [synthetic_otlp_line(attributes=completion_attributes( + conversation_id=conversation_id, + tokens=tokens, + service_tier="priority", + ))], + ) + return directory +``` + +- [ ] **Step 2: Run focused refresh and support tests and verify failures** + +Run: `.venv/bin/python -m pytest tests/store/test_otel_refresh.py tests/reports/test_support.py tests/core/test_api_payloads.py -q` + +Expected: FAIL because refresh does not run the OTel phases or expose bounded diagnostics. + +- [ ] **Step 3: Add the refresh phase after session persistence** + +```python +def _refresh_otel_completions(*, db_path: Path, otel_dir: Path) -> dict[str, int]: + with connect(db_path) as conn: + init_db(conn) + ingest = ingest_otel_completion_files(conn, otel_dir) + reconciled = reconcile_otel_completions(conn) + if reconciled.updated_usage_rows: + touch_compression_revisions(conn, {"calls", "threads"}) + return { + "otel_files_scanned": ingest.files_scanned, + "otel_imported": ingest.imported, + "otel_duplicates": ingest.duplicates, + "otel_matched": reconciled.matched, + "otel_pending": reconciled.pending, + "otel_ambiguous": reconciled.ambiguous, + "otel_conflicts": reconciled.conflicts, + **ingest.diagnostics, + } +``` + +Define the persistence allowlist once and use it in `record_refresh_metadata()`: + +```python +OTEL_REFRESH_COUNTER_KEYS = ( + "otel_files_scanned", + "otel_imported", + "otel_duplicates", + "otel_matched", + "otel_pending", + "otel_ambiguous", + "otel_conflicts", + *OTEL_DIAGNOSTIC_KEYS, +) +``` + +Call this after `write_refresh_stream()` and before `_finalize_refresh_result()`. Merge only non-zero OTel counters into `RefreshResult.parser_diagnostics`, and store every allowlisted OTel counter under `refresh_meta` with its existing `otel_` name. Add an `otel` progress phase without changing existing phase meanings. + +- [ ] **Step 4: Preserve staging during rebuild and add support presence** + +In `rebuild_usage_index()`, call `reset_otel_completion_matches(conn)` before deleting canonical usage tables and deliberately omit both OTel sidecar tables from the deletion list. Pass `otel_dir` through to the final refresh. In support payloads, add only: + +```python +"otel": { + "completion_directory_exists": DEFAULT_OTEL_COMPLETIONS_DIR.is_dir(), + "refresh_counts": {key: value for key, value in refresh.items() if key.startswith("otel_")}, +} +``` + +Do not include the directory path, source paths, fingerprints, record IDs, conversations, timestamps, or token tuples. + +- [ ] **Step 5: Run refresh, payload, support, and callback tests** + +Run: `.venv/bin/python -m pytest tests/store/test_otel_refresh.py tests/store/test_refresh_callbacks.py tests/core/test_api_payloads.py tests/reports/test_support.py -q` + +Expected: PASS. + +- [ ] **Step 6: Commit the refresh integration slice** + +```bash +git add -- src/codex_usage_tracker/store/refresh.py src/codex_usage_tracker/store/api.py src/codex_usage_tracker/core/api_payloads.py src/codex_usage_tracker/reports/support.py tests/store/test_otel_refresh.py tests/reports/test_support.py tests/core/test_api_payloads.py +git commit -m "feat: reconcile OTel tiers during refresh" +``` + +### Task 6: Apply confirmed Fast credit multipliers without changing USD estimates + +**Files:** +- Create: `src/codex_usage_tracker/pricing/fast_tier.py` +- Modify: `src/codex_usage_tracker/pricing/allowance_usage.py` +- Modify: `src/codex_usage_tracker/pricing/allowance.py` +- Modify: `src/codex_usage_tracker/usage_drain/types.py` +- Modify: `src/codex_usage_tracker/usage_drain/spans.py` +- Modify: `tests/pricing/test_allowance.py` +- Modify: `tests/pricing/test_pricing.py` +- Modify: `tests/usage_drain/test_usage_drain_model.py` + +**Interfaces:** +- Produces: `DOCUMENTED_FAST_CREDIT_MULTIPLIERS` and `documented_fast_credit_multiplier(model)`. +- Produces: `usage_credit_multiplier`, `usage_credit_multiplier_source`, and `standard_usage_credits` annotations. +- Preserves: `estimated_cost_usd` and usage-drain Standard-baseline modeling. + +- [ ] **Step 1: Write failing multiplier, unknown, Standard, USD, and usage-drain compatibility tests** + +```python +@pytest.mark.parametrize( + ("model", "multiplier"), + [("gpt-5.6", 2.5), ("gpt-5.6-sol", 2.5), ("gpt-5.5", 2.5), ("gpt-5.4", 2.0)], +) +def test_confirmed_fast_multiplies_standard_credit_estimate(model: str, multiplier: float) -> None: + row = credit_row(model=model, fast=1, service_tier="fast") + annotated = annotate_rows_with_allowance([row], synthetic_allowance_config())[0] + assert annotated["usage_credits"] == pytest.approx(annotated["standard_usage_credits"] * multiplier) + assert annotated["usage_credit_multiplier"] == multiplier + assert annotated["usage_credit_multiplier_source"] == "otel_response_completed" + + +@pytest.mark.parametrize("fast", [0, None]) +def test_standard_and_unknown_rows_keep_multiplier_one(fast: int | None) -> None: + row = credit_row(model="gpt-5.6", fast=fast, service_tier="standard" if fast == 0 else None) + annotated = annotate_rows_with_allowance([row], synthetic_allowance_config())[0] + assert annotated["usage_credits"] == annotated["standard_usage_credits"] + assert annotated["usage_credit_multiplier"] == 1.0 + + +def test_confirmed_fast_unknown_model_does_not_invent_multiplier() -> None: + row = credit_row(model="synthetic-unknown", fast=1, service_tier="fast") + annotated = annotate_rows_with_allowance([row], synthetic_allowance_config())[0] + assert annotated["usage_credit_multiplier"] == 1.0 + assert annotated["usage_credit_multiplier_source"] == "no_documented_fast_multiplier" + + +def test_service_tier_does_not_change_estimated_cost_usd() -> None: + pricing = synthetic_pricing_config() + row = credit_row(model="gpt-5.6", fast=0, service_tier="standard") + standard = estimate_cost_usd(row, pricing) + fast = estimate_cost_usd({**row, "fast": 1, "service_tier": "fast"}, pricing) + assert fast == standard + + +def test_usage_drain_uses_standard_usage_credits_after_fast_annotation() -> None: + row = annotate_rows_with_allowance( + [credit_row(model="gpt-5.6", fast=1, service_tier="fast")], + synthetic_allowance_config(), + )[0] + span = span_from_single_row_for_test(row) + assert span.standard_usage_credits == row["standard_usage_credits"] +``` + +Use these local synthetic helpers in the focused tests: + +```python +def credit_row(*, model: str, fast: int | None, service_tier: str | None) -> dict[str, object]: + return { + "model": model, + "input_tokens": 100, + "cached_input_tokens": 20, + "uncached_input_tokens": 80, + "output_tokens": 10, + "total_tokens": 110, + "fast": fast, + "service_tier": service_tier, + "service_tier_source": "otel_response_completed" if fast is not None else None, + "service_tier_confidence": "exact" if fast is not None else None, + } + + +def synthetic_allowance_config() -> UsageAllowanceConfig: + rates = {"input_per_million": 10.0, "cached_input_per_million": 1.0, "output_per_million": 50.0} + models = ("gpt-5.6", "gpt-5.6-sol", "gpt-5.5", "gpt-5.4", "synthetic-unknown") + return UsageAllowanceConfig( + path=Path("/synthetic/allowance.json"), + rate_card_path=Path("/synthetic/rate-card.json"), + credit_rates={model: dict(rates) for model in models}, + aliases={}, + rate_metadata={model: {} for model in models}, + alias_metadata={}, + windows=[], + loaded=True, + rate_card_loaded=True, + source={"name": "Synthetic credit rates"}, + ) + + +def synthetic_pricing_config() -> PricingConfig: + return PricingConfig( + path=Path("/synthetic/pricing.json"), + models={"gpt-5.6": { + "input_per_million": 10.0, + "cached_input_per_million": 1.0, + "output_per_million": 50.0, + }}, + loaded=True, + ) + + +def span_from_single_row_for_test(row: dict[str, object]) -> UsageDeltaSpan: + return _span_from_rows([row], baseline_percent=0.0, end_used_percent=1.0, proxies={}) +``` + +- [ ] **Step 2: Run focused pricing tests and verify failures** + +Run: `.venv/bin/python -m pytest tests/pricing/test_allowance.py tests/pricing/test_pricing.py tests/usage_drain/test_usage_drain_model.py -q` + +Expected: FAIL because credit annotation has no exact-tier multiplier policy. + +- [ ] **Step 3: Implement shared documented model-family multipliers** + +```python +DOCUMENTED_FAST_CREDIT_MULTIPLIERS = { + "gpt-5.6": 2.5, + "gpt-5.5": 2.5, + "gpt-5.4": 2.0, +} + + +def documented_fast_credit_multiplier(model: object) -> float | None: + normalized = str(model or "").strip().lower() + for family, multiplier in DOCUMENTED_FAST_CREDIT_MULTIPLIERS.items(): + if normalized == family or normalized.startswith(f"{family}-") or normalized.startswith(f"{family} "): + return multiplier + return None + + +def credit_multiplier_for_row(row: Mapping[str, object]) -> tuple[float, str]: + if row.get("fast") != 1: + fallback = "confirmed_standard" if row.get("fast") == 0 else "tier_unknown" + return 1.0, str(row.get("service_tier_source") or fallback) + multiplier = documented_fast_credit_multiplier(row.get("model")) + if multiplier is None: + return 1.0, "no_documented_fast_multiplier" + return multiplier, str(row.get("service_tier_source") or "confirmed_fast") +``` + +Move the existing usage-drain constant/function to this pricing module and re-export them from `usage_drain/types.py` to preserve imports. + +- [ ] **Step 4: Split Standard and effective credit estimates** + +```python +standard_credits = estimate_standard_usage_credits(copy, rates) +multiplier, multiplier_source = credit_multiplier_for_row(copy) +copy.update( + usage_credits=standard_credits * multiplier, + standard_usage_credits=standard_credits, + usage_credit_multiplier=multiplier, + usage_credit_multiplier_source=multiplier_source, +) +``` + +Rename the existing calculation body to `estimate_standard_usage_credits()` and keep `estimate_usage_credits()` as the effective wrapper for compatibility. Add `standard_usage_credits`, `usage_credit_multiplier`, and `usage_credit_multiplier_source` in both priced and unpriced annotation branches; unpriced rows keep `usage_credits = None` and `standard_usage_credits = None`. In usage-drain span construction, read `standard_usage_credits` with a fallback to `usage_credits` for older injected rows. Do not modify `pricing/costing.py`. + +- [ ] **Step 5: Run pricing and usage-drain tests** + +Run: `.venv/bin/python -m pytest tests/pricing tests/usage_drain/test_usage_drain_model.py tests/usage_drain/test_usage_drain_reports.py -q` + +Expected: PASS. + +- [ ] **Step 6: Commit the credit-accounting slice** + +```bash +git add -- src/codex_usage_tracker/pricing/fast_tier.py src/codex_usage_tracker/pricing/allowance_usage.py src/codex_usage_tracker/pricing/allowance.py src/codex_usage_tracker/usage_drain/types.py src/codex_usage_tracker/usage_drain/spans.py tests/pricing/test_allowance.py tests/pricing/test_pricing.py tests/usage_drain/test_usage_drain_model.py +git commit -m "feat: price confirmed Fast credit usage" +``` + +### Task 7: Expose exact tiers in calls, exports, and the dashboard + +**Files:** +- Modify: `tests/store/test_content_query_exports.py` +- Modify: `tests/dashboard/test_dashboard_payload.py` +- Modify: `tests/server/test_server_call_detail.py` +- Modify: `frontend/dashboard/src/api/types.ts` +- Modify: `frontend/dashboard/src/api/client.ts` +- Modify: `frontend/dashboard/src/api/client.test.ts` +- Modify: `frontend/dashboard/src/test-fixtures/dashboardFixture.ts` +- Create: `frontend/dashboard/src/features/calls/serviceTier.ts` +- Create: `frontend/dashboard/src/features/calls/serviceTier.test.ts` +- Modify: `frontend/dashboard/src/features/shared/tables.tsx` +- Modify: `frontend/dashboard/src/features/shared/tables.test.ts` +- Modify: `frontend/dashboard/src/features/calls/CallInspector.tsx` +- Modify: `frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx` +- Regenerate: `src/codex_usage_tracker/plugin_data/dashboard/react/` + +**Interfaces:** +- Consumes: additive backend row fields already selected by `usage_events.*` and exported through schema-driven CSV. +- Produces: nullable exact `fast`, `serviceTier`, `serviceTierSource`, `serviceTierConfidence`, and separate `fastProxyCandidate` in `CallRow`. +- Produces: Calls table/CSV tier labels and exact-first detail wording. + +- [ ] **Step 1: Write failing backend export and frontend decoding tests** + +```python +def test_csv_export_includes_additive_service_tier_fields(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + upsert_usage_events( + [synthetic_usage_event("record-a", "conversation-a", (100, 40, 30, 10), fast=1)], + db_path=db_path, + ) + output_path = tmp_path / "usage.csv" + export_usage_csv(output_path, db_path=db_path) + header = next(csv.reader(output_path.read_text(encoding="utf-8").splitlines())) + assert [name for name in header if name.startswith("service_tier") or name == "fast"] == [ + "service_tier", "fast", "service_tier_source", "service_tier_confidence" + ] + + +def test_dashboard_payload_keeps_tier_fields_aggregate_only(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + upsert_usage_events( + [synthetic_usage_event("record-a", "conversation-a", (100, 40, 30, 10), fast=1)], + db_path=db_path, + ) + row = dashboard_payload(db_path=db_path)["rows"][0] + assert row["service_tier"] == "fast" + assert row["fast"] == 1 + assert "otel_source_path" not in row + + +def test_call_detail_exposes_tier_without_sidecar_identity(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + upsert_usage_events( + [synthetic_usage_event("record-a", "conversation-a", (100, 40, 30, 10), fast=1)], + db_path=db_path, + ) + payload = call_detail_payload( + "record_id=record-a", db_path=db_path, annotate_rows=lambda rows: rows + ) + record = payload["record"] + assert record["service_tier"] == "fast" + assert record["service_tier_confidence"] == "exact" + assert "source_path" not in record +``` + +```typescript +it('keeps exact tier separate from throughput proxy', () => { + const call = usageRowToCall({ service_tier: 'standard', fast: 0, service_tier_confidence: 'protocol', duration_seconds: 1, total_tokens: 9000 }, 0); + expect(call.fast).toBe(false); + expect(call.fastProxyCandidate).toBe(true); + expect(serviceTierDetail(call)).toBe('confirmed Standard · protocol'); +}); +``` + +- [ ] **Step 2: Run backend and frontend focused tests and verify failures** + +Run: `.venv/bin/python -m pytest tests/store/test_content_query_exports.py tests/dashboard/test_dashboard_payload.py tests/server/test_server_call_detail.py -q` + +Run: `npm run dashboard:test -- --run frontend/dashboard/src/api/client.test.ts frontend/dashboard/src/features/calls/serviceTier.test.ts frontend/dashboard/src/features/shared/tables.test.ts` + +Expected: FAIL because the dashboard model does not decode or label exact service tiers. + +- [ ] **Step 3: Decode exact tier fields and retain the historical proxy separately** + +```typescript +// UsageRow +service_tier?: string | null; +fast?: number | boolean | null; +service_tier_source?: string | null; +service_tier_confidence?: string | null; +standard_usage_credits?: number | null; +usage_credit_multiplier?: number | null; +usage_credit_multiplier_source?: string | null; + +// CallRow +serviceTier: string; +fast: boolean | null; +serviceTierSource: string; +serviceTierConfidence: string; +fastProxyCandidate: boolean; +usageCreditMultiplier: number; +usageCreditMultiplierSource: string; + +// usageRowToCall() +const rawFast = row.fast; +const exactFast = rawFast === true || rawFast === 1 + ? true + : rawFast === false || rawFast === 0 + ? false + : null; + +serviceTier: String(row.service_tier ?? ''), +fast: exactFast, +serviceTierSource: String(row.service_tier_source ?? ''), +serviceTierConfidence: String(row.service_tier_confidence ?? ''), +fastProxyCandidate: durationSeconds > 0 && totalTokens / Math.max(durationSeconds, 1) > 4_000, +usageCreditMultiplier: Number(row.usage_credit_multiplier ?? 1), +usageCreditMultiplierSource: String(row.usage_credit_multiplier_source ?? ''), +``` + +In `usageRowToCall()`, decode `fast` as `true`, `false`, or `null`; compute the current throughput heuristic into `fastProxyCandidate`; never let the proxy overwrite exact `fast`. Add the required defaults to `test-fixtures/dashboardFixture.ts` so hand-built `CallRow` fixtures remain type-complete. + +- [ ] **Step 4: Add exact-first labels, Calls column, details, and CSV fields** + +```typescript +export function serviceTierLabel(call: CallRow): 'Fast' | 'Standard' | 'Unknown' { + if (call.fast === true) return 'Fast'; + if (call.fast === false) return 'Standard'; + return 'Unknown'; +} + +export function serviceTierDetail(call: CallRow): string { + if (call.fast !== null) { + return `confirmed ${serviceTierLabel(call)} · ${call.serviceTierConfidence || 'exact'}`; + } + return call.fastProxyCandidate ? 'tier unknown · Fast proxy candidate' : 'tier unknown · normal throughput proxy'; +} +``` + +Add a `Service Tier` Calls column, add the four persisted tier fields plus credit multiplier fields to `callCsvColumns`, and replace both existing duration details with `serviceTierDetail(call)`. Keep duration itself unchanged. + +- [ ] **Step 5: Run focused frontend tests, typecheck, and regenerate bundled assets** + +Run: `npm run dashboard:test -- --run frontend/dashboard/src/api/client.test.ts frontend/dashboard/src/features/calls/serviceTier.test.ts frontend/dashboard/src/features/shared/tables.test.ts` + +Run: `npm run dashboard:typecheck` + +Run: `npm run dashboard:build` + +Expected: PASS and deterministic assets regenerated under `src/codex_usage_tracker/plugin_data/dashboard/react/`. + +- [ ] **Step 6: Run backend payload/export privacy tests** + +Run: `.venv/bin/python -m pytest tests/store/test_content_query_exports.py tests/dashboard/test_dashboard_payload.py tests/dashboard/test_dashboard_payload_privacy.py tests/server/test_server_call_detail.py tests/server/test_server_dashboard_shell.py -q` + +Expected: PASS. + +- [ ] **Step 7: Commit the public-surface slice** + +```bash +git add -- tests/store/test_content_query_exports.py tests/dashboard/test_dashboard_payload.py tests/server/test_server_call_detail.py frontend/dashboard/src/api/types.ts frontend/dashboard/src/api/client.ts frontend/dashboard/src/api/client.test.ts frontend/dashboard/src/test-fixtures/dashboardFixture.ts frontend/dashboard/src/features/calls/serviceTier.ts frontend/dashboard/src/features/calls/serviceTier.test.ts frontend/dashboard/src/features/shared/tables.tsx frontend/dashboard/src/features/shared/tables.test.ts frontend/dashboard/src/features/calls/CallInspector.tsx frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx src/codex_usage_tracker/plugin_data/dashboard/react +git commit -m "feat: show exact Fast tiers in Calls" +``` + +### Task 8: Document the behavior and run the complete verification gate + +**Files:** +- Modify: `docs/architecture.md` +- Modify: `docs/database-schema.md` +- Modify: `docs/pricing-and-credits.md` +- Modify: `docs/privacy.md` +- Modify: `docs/dashboard-guide.md` +- Modify: `docs/cli-json-schemas.md` +- Modify: `CHANGELOG.md` + +**Interfaces:** +- Documents: exact-versus-proxy behavior, the v30 tables/columns, cursor/rebuild semantics, credit multiplier provenance, unchanged USD estimates, and aggregate-only privacy guarantees. +- Verifies: Python, dashboard, packaging, schema, privacy, generated assets, and release readiness. + +- [ ] **Step 1: Update user and maintainer documentation with exact semantics** + +Document these concrete points in the named files: + +```text +The tracker reads only local codex-completions*.jsonl OTLP exporter files. +Fast/Standard is exact only when service_tier is explicit or Standard is established by Codex >= 0.143.0 omission semantics. +Older unmatched history remains Unknown; latency and reasoning effort are not proof of Fast. +Confirmed Fast changes ChatGPT credit estimates by the documented model multiplier but never changes USD token estimates. +Raw OTLP bodies and arbitrary attributes are neither persisted nor exported. +``` + +Add an Unreleased changelog entry covering local OTel ingestion, exact tier labels, conservative correlation, and credit-accounting changes. + +- [ ] **Step 2: Run focused Python and frontend suites** + +Run: `.venv/bin/python -m pytest tests/parser/test_otel_parser.py tests/store/test_otel_schema.py tests/store/test_otel_ingest.py tests/store/test_otel_reconciliation.py tests/store/test_otel_refresh.py tests/pricing/test_allowance.py tests/reports/test_support.py tests/dashboard/test_dashboard_payload.py -q` + +Run: `npm run dashboard:test -- --run frontend/dashboard/src/api/client.test.ts frontend/dashboard/src/features/calls/serviceTier.test.ts frontend/dashboard/src/features/shared/tables.test.ts` + +Expected: PASS. + +- [ ] **Step 3: Run the complete Python and dashboard gates** + +Run: `.venv/bin/python -m ruff check .` + +Run: `.venv/bin/python -m mypy` + +Run: `.venv/bin/python -m pytest` + +Run: `.venv/bin/python -m pytest --cov=codex_usage_tracker --cov-report=term-missing` + +Run: `.venv/bin/python -m compileall src` + +Run: `npm run dashboard:verify` + +Run: `for file in src/codex_usage_tracker/plugin_data/dashboard/dashboard*.js; do node --check "$file"; done` + +Run: `.venv/bin/python scripts/check_release.py` + +Run: `git diff --check` + +Expected: every command exits 0. + +- [ ] **Step 4: Build and inspect release artifacts** + +Run: `.venv/bin/python -m build` + +Run: `.venv/bin/python -m twine check dist/*` + +Run: `.venv/bin/python scripts/check_release.py --dist` + +Expected: wheel and sdist build successfully, Twine reports both valid, and bundled parser/dashboard/skill assets pass release inspection. + +- [ ] **Step 5: Perform the final privacy and Git review** + +Run: `git status --short --branch` + +Run: `git diff --stat main..HEAD` + +Run: `git diff main..HEAD -- . ':(exclude)src/codex_usage_tracker/plugin_data/dashboard/react/assets/*.js'` + +Run: `rg -n "conversation.id|secret.attribute|private body|/Users/|source_path" tests docs src/codex_usage_tracker/plugin_data --glob '!docs/superpowers/**'` + +Expected: only synthetic identifiers and documented schema field names appear; no real log content, local OTel paths, secrets, or private records are staged. + +- [ ] **Step 6: Commit documentation and verification evidence** + +```bash +git add -- docs/architecture.md docs/database-schema.md docs/pricing-and-credits.md docs/privacy.md docs/dashboard-guide.md docs/cli-json-schemas.md CHANGELOG.md +git commit -m "docs: explain exact Fast usage tracking" +``` From eba610f6354fd587a58df031a54c158ba312d8e0 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:30:34 -0400 Subject: [PATCH 03/24] feat: add OTel completion tier schema --- src/codex_usage_tracker/core/models.py | 4 ++ src/codex_usage_tracker/core/paths.py | 1 + src/codex_usage_tracker/core/schema.py | 4 ++ src/codex_usage_tracker/store/otel_schema.py | 76 ++++++++++++++++++++ src/codex_usage_tracker/store/schema.py | 5 +- tests/core/test_schema.py | 4 ++ tests/store/test_otel_schema.py | 38 ++++++++++ tests/store/test_store_dashboard_mcp.py | 12 ++-- tests/store/test_store_migrations.py | 30 ++++---- 9 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 src/codex_usage_tracker/store/otel_schema.py create mode 100644 tests/store/test_otel_schema.py diff --git a/src/codex_usage_tracker/core/models.py b/src/codex_usage_tracker/core/models.py index 1b2f5559..9116b952 100644 --- a/src/codex_usage_tracker/core/models.py +++ b/src/codex_usage_tracker/core/models.py @@ -71,6 +71,10 @@ class UsageEvent: canonical_record_id: str | None = None is_duplicate: int = 0 duplicate_reason: str | None = None + service_tier: str | None = None + fast: int | None = None + service_tier_source: str | None = None + service_tier_confidence: str | None = None @property def uncached_input_tokens(self) -> int: diff --git a/src/codex_usage_tracker/core/paths.py b/src/codex_usage_tracker/core/paths.py index 0ca1dcaf..0500502a 100644 --- a/src/codex_usage_tracker/core/paths.py +++ b/src/codex_usage_tracker/core/paths.py @@ -6,6 +6,7 @@ APP_DIR = Path.home() / ".codex-usage-tracker" DEFAULT_DB_PATH = APP_DIR / "usage.sqlite3" +DEFAULT_OTEL_COMPLETIONS_DIR = APP_DIR / "otel" DEFAULT_DASHBOARD_PATH = APP_DIR / "dashboard.html" DEFAULT_SUPPORT_BUNDLE_PATH = APP_DIR / "support-bundle.json" DEFAULT_PRICING_PATH = APP_DIR / "pricing.json" diff --git a/src/codex_usage_tracker/core/schema.py b/src/codex_usage_tracker/core/schema.py index 77269f91..ef0b9e27 100644 --- a/src/codex_usage_tracker/core/schema.py +++ b/src/codex_usage_tracker/core/schema.py @@ -77,6 +77,10 @@ class UsageColumn: "is_duplicate", "INTEGER NOT NULL DEFAULT 0", "INTEGER NOT NULL DEFAULT 0", repairable=True ), UsageColumn("duplicate_reason", "TEXT", "TEXT", repairable=True), + UsageColumn("service_tier", "TEXT", "TEXT", repairable=True), + UsageColumn("fast", "INTEGER", "INTEGER", repairable=True), + UsageColumn("service_tier_source", "TEXT", "TEXT", repairable=True), + UsageColumn("service_tier_confidence", "TEXT", "TEXT", repairable=True), UsageColumn("uncached_input_tokens", "INTEGER NOT NULL", "INTEGER"), UsageColumn("cache_ratio", "REAL NOT NULL", "REAL"), UsageColumn("reasoning_output_ratio", "REAL NOT NULL", "REAL"), diff --git a/src/codex_usage_tracker/store/otel_schema.py b/src/codex_usage_tracker/store/otel_schema.py new file mode 100644 index 00000000..4092cdc3 --- /dev/null +++ b/src/codex_usage_tracker/store/otel_schema.py @@ -0,0 +1,76 @@ +"""SQLite schema for aggregate OpenTelemetry completion enrichment.""" + +from __future__ import annotations + +import sqlite3 + +MIGRATION_NAMES = {30: "persist OTel completion tier enrichment"} + +OTEL_MATCH_STATUSES = ("pending", "matched", "ambiguous", "conflict", "invalid") + +_USAGE_EVENT_TIER_COLUMNS = { + "service_tier": "TEXT", + "fast": "INTEGER", + "service_tier_source": "TEXT", + "service_tier_confidence": "TEXT", +} + + +def migrate_otel_completion_tiers(conn: sqlite3.Connection) -> None: + """Add nullable tier fields plus aggregate-only OTel staging tables.""" + + existing_usage_columns = { + str(row[1]) for row in conn.execute("PRAGMA table_info(usage_events)").fetchall() + } + for column, column_type in _USAGE_EVENT_TIER_COLUMNS.items(): + if column not in existing_usage_columns: + conn.execute( # nosec B608 - fixed migration column names + f"ALTER TABLE usage_events ADD COLUMN {column} {column_type}" + ) + conn.executescript( + """ + CREATE TABLE IF NOT EXISTS otel_completion_sources ( + source_path TEXT PRIMARY KEY, + device INTEGER NOT NULL, + inode INTEGER NOT NULL, + size INTEGER NOT NULL, + parsed_offset INTEGER NOT NULL, + parsed_line INTEGER NOT NULL, + updated_at TEXT NOT NULL + ); + + CREATE TABLE IF NOT EXISTS otel_completion_events ( + fingerprint TEXT PRIMARY KEY, + conversation_id TEXT, + event_timestamp TEXT, + input_tokens INTEGER, + cached_input_tokens INTEGER, + output_tokens INTEGER, + reasoning_output_tokens INTEGER, + model TEXT, + effort TEXT, + service_tier TEXT, + fast INTEGER, + service_tier_source TEXT, + service_tier_confidence TEXT, + app_version TEXT, + source_path TEXT NOT NULL, + source_line INTEGER NOT NULL, + match_status TEXT NOT NULL CHECK ( + match_status IN ('pending', 'matched', 'ambiguous', 'conflict', 'invalid') + ), + matched_record_id TEXT + ); + + CREATE INDEX IF NOT EXISTS idx_otel_completion_match_status + ON otel_completion_events(match_status); + CREATE INDEX IF NOT EXISTS idx_otel_completion_identity + ON otel_completion_events( + conversation_id, + input_tokens, + cached_input_tokens, + output_tokens, + reasoning_output_tokens + ); + """ + ) diff --git a/src/codex_usage_tracker/store/schema.py b/src/codex_usage_tracker/store/schema.py index e0d1cddc..2c4ab7b5 100644 --- a/src/codex_usage_tracker/store/schema.py +++ b/src/codex_usage_tracker/store/schema.py @@ -9,6 +9,7 @@ import codex_usage_tracker.store.allowance_schema as allowance_schema import codex_usage_tracker.store.compression_schema as compression_schema import codex_usage_tracker.store.deduplication_schema as deduplication_schema +import codex_usage_tracker.store.otel_schema as otel_schema import codex_usage_tracker.store.recommendation_schema as recommendation_schema import codex_usage_tracker.store.schema_query_indexes as schema_query_indexes from codex_usage_tracker.core.schema import ( @@ -18,7 +19,7 @@ USAGE_EVENT_SCHEMA_CHECKSUM, ) -SCHEMA_VERSION = 29 +SCHEMA_VERSION = 30 MIGRATION_NAMES = { 1: "create usage_events aggregate fact table", 2: "track schema migration checksum metadata", @@ -39,6 +40,7 @@ **schema_query_indexes.MIGRATION_NAMES, **deduplication_schema.MIGRATION_NAMES, **allowance_schema.MIGRATION_NAMES, + **otel_schema.MIGRATION_NAMES, } CALL_ORIGIN_REPAIR_COLUMNS: dict[str, str] = dict.fromkeys( ("call_initiator", "call_initiator_reason", "call_initiator_confidence"), "TEXT" @@ -116,6 +118,7 @@ def _schema_migrations() -> tuple[tuple[int, Callable[[sqlite3.Connection], None (27, allowance_schema.migrate_allowance_intelligence_v2), (28, allowance_schema.migrate_allowance_query_indexes_v3), (29, allowance_schema.add_allowance_plan_provenance), + (30, otel_schema.migrate_otel_completion_tiers), ) diff --git a/tests/core/test_schema.py b/tests/core/test_schema.py index a8b73ef8..74a36b21 100644 --- a/tests/core/test_schema.py +++ b/tests/core/test_schema.py @@ -51,3 +51,7 @@ def test_usage_event_schema_matches_persisted_row_shape() -> None: assert tuple(EVENT_COLUMNS) == USAGE_EVENT_COLUMN_NAMES assert tuple(event.to_row().keys()) == USAGE_EVENT_COLUMN_NAMES + assert event.to_row()["service_tier"] is None + assert event.to_row()["fast"] is None + assert event.to_row()["service_tier_source"] is None + assert event.to_row()["service_tier_confidence"] is None diff --git a/tests/store/test_otel_schema.py b/tests/store/test_otel_schema.py new file mode 100644 index 00000000..864146d8 --- /dev/null +++ b/tests/store/test_otel_schema.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from pathlib import Path + +from codex_usage_tracker.store.connection import connect +from codex_usage_tracker.store.schema import SCHEMA_VERSION, init_db + + +def test_schema_migration_creates_otel_sidecar_tables(tmp_path: Path) -> None: + with connect(tmp_path / "usage.sqlite3") as conn: + init_db(conn) + source_columns = { + str(row["name"]) + for row in conn.execute("PRAGMA table_info(otel_completion_sources)") + } + event_columns = { + str(row["name"]) + for row in conn.execute("PRAGMA table_info(otel_completion_events)") + } + + assert SCHEMA_VERSION == 30 + assert { + "source_path", + "device", + "inode", + "size", + "parsed_offset", + "parsed_line", + "updated_at", + } <= source_columns + assert { + "fingerprint", + "conversation_id", + "service_tier", + "fast", + "match_status", + "matched_record_id", + } <= event_columns diff --git a/tests/store/test_store_dashboard_mcp.py b/tests/store/test_store_dashboard_mcp.py index f546c2ff..142b1eb1 100644 --- a/tests/store/test_store_dashboard_mcp.py +++ b/tests/store/test_store_dashboard_mcp.py @@ -79,12 +79,12 @@ def test_refresh_is_idempotent_and_summary_works(tmp_path: Path) -> None: assert meta["parsed_source_files"] == "0" assert meta["skipped_source_files"] == "3" assert meta["parser_adapter"] == "codex-jsonl-v2" - assert meta["schema_version"] == "29" + assert meta["schema_version"] == "30" assert meta["parser_skipped_events"] == "0" state = schema_state(db_path) - assert state["schema_version"] == 29 + assert state["schema_version"] == 30 assert state["checksum_matches"] is True - assert [row["version"] for row in state["migrations"]] == list(range(1, 30)) + assert [row["version"] for row in state["migrations"]] == list(range(1, 31)) with connect(db_path) as conn: init_db(conn) source_rows = [ @@ -711,7 +711,7 @@ def test_connect_sets_sqlite_concurrency_pragmas(tmp_path: Path) -> None: assert busy_timeout == 5000 assert str(journal_mode).lower() == "wal" - assert user_version == 29 + assert user_version == 30 def test_current_schema_reads_succeed_while_writer_is_active(tmp_path: Path) -> None: @@ -809,8 +809,8 @@ def test_init_db_repairs_version_zero_schema(tmp_path: Path) -> None: assert "used_percent" in allowance_columns assert "window_kind" in allowance_columns assert "idx_allowance_observations_window_time" in allowance_indexes - assert user_version == 29 - assert [row["version"] for row in migrations] == list(range(1, 30)) + assert user_version == 30 + assert [row["version"] for row in migrations] == list(range(1, 31)) assert "idx_usage_source_file_line" in indexes diff --git a/tests/store/test_store_migrations.py b/tests/store/test_store_migrations.py index 8867ce1f..991be64a 100644 --- a/tests/store/test_store_migrations.py +++ b/tests/store/test_store_migrations.py @@ -70,9 +70,9 @@ def test_init_db_migrates_legacy_aggregate_table_without_data_loss(tmp_path: Pat assert len(str(source_rows[0]["source_record_hash"])) == 64 assert metadata["parsed_events"] == "legacy" assert metadata["parser_invalid_integer"] == "2" - assert state["schema_version"] == 29 + assert state["schema_version"] == 30 assert state["checksum_matches"] is True - assert [row["version"] for row in state["migrations"]] == list(range(1, 30)) + assert [row["version"] for row in state["migrations"]] == list(range(1, 31)) with connect(db_path) as conn: init_db(conn) facts = conn.execute("SELECT COUNT(*) AS count FROM call_diagnostic_facts").fetchone() @@ -108,7 +108,7 @@ def test_refresh_is_idempotent_after_legacy_migration(tmp_path: Path) -> None: assert second_count == 2 assert legacy_rows[0]["record_id"] == "legacy-record" assert new_rows[0]["thread_name"] == "Synthetic migration thread" - assert metadata["schema_version"] == "29" + assert metadata["schema_version"] == "30" assert metadata["parsed_events"] == "0" assert metadata["inserted_or_updated_events"] == "0" assert metadata["parsed_source_files"] == "0" @@ -258,8 +258,8 @@ def test_init_db_records_all_schema_migrations_for_new_database(tmp_path: Path) ).fetchall() ] - assert versions == list(range(1, 30)) - assert user_version == 29 + assert versions == list(range(1, 31)) + assert user_version == 30 assert "idx_usage_source_file_line" in usage_indexes assert { "idx_recommendation_facts_rank_active", @@ -462,7 +462,7 @@ def test_init_db_upgrades_v25_database_without_changing_physical_rows(tmp_path: conn.execute("DROP TABLE allowance_source_state") conn.execute("DROP INDEX idx_allowance_observations_active_newest") conn.execute("DROP INDEX idx_allowance_observations_active_window_newest") - conn.execute("DELETE FROM schema_migrations WHERE version IN (26, 27, 28, 29)") + conn.execute("DELETE FROM schema_migrations WHERE version IN (26, 27, 28, 29, 30)") conn.execute("PRAGMA user_version = 25") versions_before = [ row[0] @@ -484,7 +484,7 @@ def test_init_db_upgrades_v25_database_without_changing_physical_rows(tmp_path: user_version = conn.execute("PRAGMA user_version").fetchone()[0] assert versions_before == list(range(1, 26)) - assert user_version == 29 + assert user_version == 30 assert { "allowance_source_state", "allowance_cycles", @@ -503,7 +503,7 @@ def test_init_db_upgrades_v27_allowance_indexes_to_v28(tmp_path: Path) -> None: """ DROP INDEX idx_allowance_intervals_evidence_cohort; DROP INDEX idx_allowance_intervals_evidence_global; - DELETE FROM schema_migrations WHERE version IN (28, 29); + DELETE FROM schema_migrations WHERE version IN (28, 29, 30); PRAGMA user_version = 27; """ ) @@ -518,8 +518,8 @@ def test_init_db_upgrades_v27_allowance_indexes_to_v28(tmp_path: Path) -> None: ] user_version = conn.execute("PRAGMA user_version").fetchone()[0] - assert user_version == 29 - assert versions == list(range(1, 30)) + assert user_version == 30 + assert versions == list(range(1, 31)) assert { "idx_allowance_intervals_evidence_cohort", "idx_allowance_intervals_evidence_global", @@ -533,7 +533,7 @@ def test_init_db_upgrades_v28_with_allowance_plan_provenance(tmp_path: Path) -> conn.executescript( """ ALTER TABLE allowance_cycles DROP COLUMN plan_type; - DELETE FROM schema_migrations WHERE version = 29; + DELETE FROM schema_migrations WHERE version IN (29, 30); PRAGMA user_version = 28; """ ) @@ -549,8 +549,8 @@ def test_init_db_upgrades_v28_with_allowance_plan_provenance(tmp_path: Path) -> ] user_version = conn.execute("PRAGMA user_version").fetchone()[0] - assert user_version == 29 - assert versions == list(range(1, 30)) + assert user_version == 30 + assert versions == list(range(1, 31)) assert "plan_type" in columns @@ -604,6 +604,10 @@ def test_csv_export_keeps_current_columns_after_legacy_migration(tmp_path: Path) assert rows[0]["next_record_id"] == "" assert rows[0]["rate_limit_plan_type"] == "" assert rows[0]["rate_limit_primary_used_percent"] == "" + assert rows[0]["service_tier"] == "" + assert rows[0]["fast"] == "" + assert rows[0]["service_tier_source"] == "" + assert rows[0]["service_tier_confidence"] == "" assert list(rows[0]) == EVENT_COLUMNS From 10f7c5fde4ce27a71ec29a5cd09bb61e80c710b0 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:34:10 -0400 Subject: [PATCH 04/24] feat: parse aggregate OTel completions --- src/codex_usage_tracker/parser/__init__.py | 14 + src/codex_usage_tracker/parser/otel.py | 341 +++++++++++++++++++++ tests/otel_helpers.py | 109 +++++++ tests/parser/test_otel_parser.py | 159 ++++++++++ 4 files changed, 623 insertions(+) create mode 100644 src/codex_usage_tracker/parser/otel.py create mode 100644 tests/otel_helpers.py create mode 100644 tests/parser/test_otel_parser.py diff --git a/src/codex_usage_tracker/parser/__init__.py b/src/codex_usage_tracker/parser/__init__.py index 901336ed..9cc560f5 100644 --- a/src/codex_usage_tracker/parser/__init__.py +++ b/src/codex_usage_tracker/parser/__init__.py @@ -5,6 +5,20 @@ from importlib import import_module from typing import Any +from codex_usage_tracker.parser.otel import ( + OTEL_DIAGNOSTIC_KEYS, + OtelCompletion, + OtelParseResult, + parse_otlp_json_line, +) + +__all__ = [ + "OTEL_DIAGNOSTIC_KEYS", + "OtelCompletion", + "OtelParseResult", + "parse_otlp_json_line", +] + _API_MODULE = "codex_usage_tracker.parser.api" diff --git a/src/codex_usage_tracker/parser/otel.py b/src/codex_usage_tracker/parser/otel.py new file mode 100644 index 00000000..89668ddc --- /dev/null +++ b/src/codex_usage_tracker/parser/otel.py @@ -0,0 +1,341 @@ +"""Pure, aggregate-only parsing for Codex OTLP completion logs.""" + +from __future__ import annotations + +import hashlib +import json +import re +from collections import Counter +from collections.abc import Iterator, Sequence +from dataclasses import dataclass +from datetime import datetime, timezone +from typing import cast + +OTEL_DIAGNOSTIC_KEYS = ( + "otel_invalid_json", + "otel_invalid_record", + "otel_invalid_integer", + "otel_unsupported_version", + "otel_non_completion", +) + +_ALLOWED_ATTRIBUTES = frozenset( + { + "event.name", + "event.kind", + "conversation.id", + "input_token_count", + "cached_token_count", + "output_token_count", + "reasoning_token_count", + "model", + "model_reasoning_effort", + "service_tier", + "app.version", + } +) +_TOKEN_FIELDS = ( + "input_token_count", + "cached_token_count", + "output_token_count", + "reasoning_token_count", +) +_STRING_FIELDS = frozenset( + { + "event.name", + "event.kind", + "conversation.id", + "model", + "model_reasoning_effort", + "service_tier", + "app.version", + } +) +_VERSION_PATTERN = re.compile(r"^v?(\d+)\.(\d+)\.(\d+)(?:[-+][0-9A-Za-z.-]+)?$") +_STANDARD_BY_OMISSION_VERSION = (0, 143, 0) +_INVALID = object() + + +@dataclass(frozen=True) +class OtelCompletion: + fingerprint: str + conversation_id: str | None + event_timestamp: str | None + input_tokens: int | None + cached_input_tokens: int | None + output_tokens: int | None + reasoning_output_tokens: int | None + model: str | None + effort: str | None + service_tier: str | None + fast: int | None + service_tier_source: str | None + service_tier_confidence: str | None + app_version: str | None + match_status: str + + +@dataclass(frozen=True) +class OtelParseResult: + completions: Sequence[OtelCompletion] + diagnostics: dict[str, int] + + +def parse_otlp_json_line(raw: str) -> OtelParseResult: + """Parse one OTLP JSON line without retaining bodies or arbitrary attributes.""" + + try: + payload = json.loads(raw) + except (json.JSONDecodeError, UnicodeDecodeError): + return OtelParseResult((), {"otel_invalid_json": 1}) + if not isinstance(payload, dict): + return OtelParseResult((), {"otel_invalid_record": 1}) + + completions: list[OtelCompletion] = [] + diagnostics: Counter[str] = Counter() + for record in _log_records(cast(dict[str, object], payload), diagnostics): + attributes, invalid_fields = _allowlisted_attributes( + record.get("attributes"), diagnostics + ) + semantic_type_errors = { + key + for key in _STRING_FIELDS + if key in attributes and not isinstance(attributes[key], str) + } + if semantic_type_errors: + diagnostics["otel_invalid_record"] += len(semantic_type_errors) + invalid_fields.update(semantic_type_errors) + if ( + _text(attributes, "event.name") != "codex.sse_event" + or _text(attributes, "event.kind") != "response.completed" + ): + diagnostics["otel_non_completion"] += 1 + continue + completion, completion_diagnostics = _completion_from_attributes( + record, attributes, invalid_fields + ) + diagnostics.update(completion_diagnostics) + completions.append(completion) + return OtelParseResult(tuple(completions), dict(diagnostics)) + + +def _log_records( + payload: dict[str, object], diagnostics: Counter[str] +) -> Iterator[dict[str, object]]: + resource_logs = payload.get("resourceLogs") + if not isinstance(resource_logs, list): + diagnostics["otel_invalid_record"] += 1 + return + for resource_log in resource_logs: + if not isinstance(resource_log, dict): + diagnostics["otel_invalid_record"] += 1 + continue + scope_logs = resource_log.get("scopeLogs") + if not isinstance(scope_logs, list): + diagnostics["otel_invalid_record"] += 1 + continue + for scope_log in scope_logs: + if not isinstance(scope_log, dict): + diagnostics["otel_invalid_record"] += 1 + continue + log_records = scope_log.get("logRecords") + if not isinstance(log_records, list): + diagnostics["otel_invalid_record"] += 1 + continue + for record in log_records: + if not isinstance(record, dict): + diagnostics["otel_invalid_record"] += 1 + continue + yield cast(dict[str, object], record) + + +def _allowlisted_attributes( + raw_attributes: object, diagnostics: Counter[str] +) -> tuple[dict[str, object], set[str]]: + values: dict[str, object] = {} + invalid_fields: set[str] = set() + if not isinstance(raw_attributes, list): + diagnostics["otel_invalid_record"] += 1 + return values, invalid_fields + for raw_attribute in raw_attributes: + if not isinstance(raw_attribute, dict): + diagnostics["otel_invalid_record"] += 1 + continue + key = raw_attribute.get("key") + if not isinstance(key, str) or key not in _ALLOWED_ATTRIBUTES: + continue + value = _otlp_value(raw_attribute.get("value")) + if value is _INVALID: + diagnostics["otel_invalid_record"] += 1 + invalid_fields.add(key) + continue + values[key] = value + return values, invalid_fields + + +def _otlp_value(raw_value: object) -> object: + if not isinstance(raw_value, dict): + return _INVALID + for key in ("stringValue", "intValue", "doubleValue", "boolValue"): + if key not in raw_value: + continue + value = raw_value[key] + if key == "stringValue" and isinstance(value, str): + return value + if key == "intValue" and isinstance(value, (str, int)) and not isinstance(value, bool): + try: + return int(value) + except ValueError: + return value + if key == "doubleValue" and isinstance(value, (int, float)) and not isinstance(value, bool): + return value + if key == "boolValue" and isinstance(value, bool): + return value + return _INVALID + return _INVALID + + +def _completion_from_attributes( + record: dict[str, object], + attributes: dict[str, object], + invalid_fields: set[str], +) -> tuple[OtelCompletion, Counter[str]]: + diagnostics: Counter[str] = Counter() + conversation_id = _text(attributes, "conversation.id") + token_values = tuple(_integer(attributes, key, diagnostics) for key in _TOKEN_FIELDS) + input_tokens, cached_input_tokens, output_tokens, reasoning_output_tokens = token_values + model = _text(attributes, "model") + effort = _text(attributes, "model_reasoning_effort") + app_version = _text(attributes, "app.version") + service_tier, fast, service_tier_source, service_tier_confidence = _normalize_tier( + attributes, invalid_fields, app_version, diagnostics + ) + event_timestamp, timestamp_invalid = _event_timestamp(record) + + has_identity = conversation_id is not None and all(value is not None for value in token_values) + has_tier = service_tier is not None and fast in (0, 1) + match_status = "pending" + if not has_identity or not has_tier or invalid_fields or timestamp_invalid: + match_status = "invalid" + diagnostics["otel_invalid_record"] += 1 + + normalized = { + "conversation_id": conversation_id, + "event_timestamp": event_timestamp, + "input_tokens": input_tokens, + "cached_input_tokens": cached_input_tokens, + "output_tokens": output_tokens, + "reasoning_output_tokens": reasoning_output_tokens, + "model": model, + "effort": effort, + "service_tier": service_tier, + "fast": fast, + "service_tier_source": service_tier_source, + "service_tier_confidence": service_tier_confidence, + "app_version": app_version, + } + return ( + OtelCompletion( + fingerprint=_semantic_fingerprint(normalized), + conversation_id=conversation_id, + event_timestamp=event_timestamp, + input_tokens=input_tokens, + cached_input_tokens=cached_input_tokens, + output_tokens=output_tokens, + reasoning_output_tokens=reasoning_output_tokens, + model=model, + effort=effort, + service_tier=service_tier, + fast=fast, + service_tier_source=service_tier_source, + service_tier_confidence=service_tier_confidence, + app_version=app_version, + match_status=match_status, + ), + diagnostics, + ) + + +def _text(attributes: dict[str, object], key: str) -> str | None: + value = attributes.get(key) + if not isinstance(value, str): + return None + normalized = value.strip() + return normalized or None + + +def _integer( + attributes: dict[str, object], key: str, diagnostics: Counter[str] +) -> int | None: + value = attributes.get(key) + if isinstance(value, bool) or value is None: + diagnostics["otel_invalid_integer"] += 1 + return None + try: + parsed = int(value) + except (TypeError, ValueError, OverflowError): + diagnostics["otel_invalid_integer"] += 1 + return None + if parsed < 0 or (isinstance(value, float) and not value.is_integer()): + diagnostics["otel_invalid_integer"] += 1 + return None + return parsed + + +def _normalize_tier( + attributes: dict[str, object], + invalid_fields: set[str], + app_version: str | None, + diagnostics: Counter[str], +) -> tuple[str | None, int | None, str | None, str | None]: + if "service_tier" in invalid_fields: + return None, None, None, None + raw_tier = _text(attributes, "service_tier") + if "service_tier" in attributes: + if raw_tier is None: + return None, None, None, None + normalized = raw_tier.lower() + if normalized in {"priority", "fast"}: + return "fast", 1, "otel_response_completed", "exact" + if normalized in {"default", "standard"}: + return "standard", 0, "otel_response_completed", "exact" + return normalized, 0, "otel_response_completed", "exact" + + parsed_version = _parse_version(app_version) + if parsed_version is None: + diagnostics["otel_unsupported_version"] += 1 + return None, None, None, None + if parsed_version >= _STANDARD_BY_OMISSION_VERSION: + return "standard", 0, "otel_response_completed", "protocol" + return None, None, None, None + + +def _parse_version(value: str | None) -> tuple[int, int, int] | None: + if value is None: + return None + match = _VERSION_PATTERN.fullmatch(value) + if match is None: + return None + return tuple(int(part) for part in match.groups()) # type: ignore[return-value] + + +def _event_timestamp(record: dict[str, object]) -> tuple[str | None, bool]: + raw = record.get("timeUnixNano") + if isinstance(raw, bool) or not isinstance(raw, (str, int)): + return None, raw is not None + try: + nanoseconds = int(raw) + seconds, remainder = divmod(nanoseconds, 1_000_000_000) + timestamp = datetime.fromtimestamp(seconds, tz=timezone.utc) + except (TypeError, ValueError, OverflowError, OSError): + return None, True + base = timestamp.strftime("%Y-%m-%dT%H:%M:%S") + if remainder: + return f"{base}.{remainder:09d}Z", False + return f"{base}Z", False + + +def _semantic_fingerprint(normalized: dict[str, object]) -> str: + payload = {"fingerprint_version": 1, **normalized} + serialized = json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=True) + return hashlib.sha256(serialized.encode("utf-8")).hexdigest() diff --git a/tests/otel_helpers.py b/tests/otel_helpers.py new file mode 100644 index 00000000..6c107cd6 --- /dev/null +++ b/tests/otel_helpers.py @@ -0,0 +1,109 @@ +from __future__ import annotations + +import json +import sqlite3 +from collections.abc import Iterator +from contextlib import contextmanager +from pathlib import Path + +from codex_usage_tracker.store.connection import connect +from codex_usage_tracker.store.schema import init_db + + +def completion_attributes( + *, + conversation_id: str = "synthetic-conversation", + tokens: tuple[int, int, int, int] = (120, 40, 30, 10), + model: str = "gpt-5.6-sol", + effort: str = "high", + service_tier: str | None = "priority", + app_version: str = "0.143.0", +) -> dict[str, object]: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + values: dict[str, object] = { + "event.name": "codex.sse_event", + "event.kind": "response.completed", + "conversation.id": conversation_id, + "input_token_count": input_tokens, + "cached_token_count": cached_tokens, + "output_token_count": output_tokens, + "reasoning_token_count": reasoning_tokens, + "model": model, + "model_reasoning_effort": effort, + "app.version": app_version, + } + if service_tier is not None: + values["service_tier"] = service_tier + return values + + +def _otlp_scalar(value: object) -> dict[str, object]: + if isinstance(value, bool): + return {"boolValue": value} + if isinstance(value, int): + return {"intValue": str(value)} + if isinstance(value, float): + return {"doubleValue": value} + return {"stringValue": str(value)} + + +def synthetic_otlp_line(*, attributes: dict[str, object], body: str = "synthetic body") -> str: + encoded = [ + {"key": key, "value": _otlp_scalar(value)} for key, value in attributes.items() + ] + return json.dumps( + { + "resourceLogs": [ + { + "scopeLogs": [ + { + "logRecords": [ + { + "timeUnixNano": "1784160000000000000", + "body": {"stringValue": body}, + "attributes": encoded, + } + ] + } + ] + } + ] + } + ) + + +def synthetic_fast_completion(conversation_id: str, input_tokens: int) -> str: + return synthetic_otlp_line( + attributes=completion_attributes( + conversation_id=conversation_id, + tokens=(input_tokens, 0, 20, 5), + service_tier="priority", + ) + ) + + +def synthetic_standard_completion(conversation_id: str, input_tokens: int) -> str: + return synthetic_otlp_line( + attributes=completion_attributes( + conversation_id=conversation_id, + tokens=(input_tokens, 0, 20, 5), + service_tier=None, + ) + ) + + +def write_lines(path: Path, lines: list[str]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("".join(f"{line}\n" for line in lines), encoding="utf-8") + + +def append_text(path: Path, value: str) -> None: + with path.open("a", encoding="utf-8") as handle: + handle.write(value) + + +@contextmanager +def initialized_connection(tmp_path: Path) -> Iterator[sqlite3.Connection]: + with connect(tmp_path / "usage.sqlite3") as conn: + init_db(conn) + yield conn diff --git a/tests/parser/test_otel_parser.py b/tests/parser/test_otel_parser.py new file mode 100644 index 00000000..46ed5e82 --- /dev/null +++ b/tests/parser/test_otel_parser.py @@ -0,0 +1,159 @@ +from __future__ import annotations + +import json + +import pytest + +from codex_usage_tracker.parser.otel import OTEL_DIAGNOSTIC_KEYS, parse_otlp_json_line +from tests.otel_helpers import completion_attributes, synthetic_otlp_line + + +def test_parse_otlp_batch_extracts_only_completion_allowlist() -> None: + raw = synthetic_otlp_line( + attributes={ + "event.name": "codex.sse_event", + "event.kind": "response.completed", + "conversation.id": "synthetic-conversation", + "input_token_count": 120, + "cached_token_count": 40, + "output_token_count": 30, + "reasoning_token_count": 10, + "model": "gpt-5.6-sol", + "model_reasoning_effort": "high", + "service_tier": "priority", + "app.version": "0.143.0", + "secret.attribute": "must-not-survive", + }, + body="synthetic private body that must not survive", + ) + + result = parse_otlp_json_line(raw) + + assert len(result.completions) == 1 + completion = result.completions[0] + assert completion.conversation_id == "synthetic-conversation" + assert completion.service_tier == "fast" + assert completion.fast == 1 + assert completion.service_tier_source == "otel_response_completed" + assert completion.service_tier_confidence == "exact" + assert completion.match_status == "pending" + assert "private body" not in repr(completion) + assert "secret.attribute" not in repr(completion) + + +@pytest.mark.parametrize( + ("version", "tier", "fast", "confidence", "status"), + [ + ("0.143.0", "standard", 0, "protocol", "pending"), + ("0.142.9", None, None, None, "invalid"), + ("bad", None, None, None, "invalid"), + ], +) +def test_missing_service_tier_uses_versioned_protocol_semantics( + version: str, + tier: str | None, + fast: int | None, + confidence: str | None, + status: str, +) -> None: + result = parse_otlp_json_line( + synthetic_otlp_line( + attributes=completion_attributes(app_version=version, service_tier=None) + ) + ) + + completion = result.completions[0] + assert (completion.service_tier, completion.fast, completion.service_tier_confidence) == ( + tier, + fast, + confidence, + ) + assert completion.match_status == status + + +@pytest.mark.parametrize( + ("raw_tier", "normalized_tier", "fast"), + [ + ("fast", "fast", 1), + ("default", "standard", 0), + ("standard", "standard", 0), + ("flex", "flex", 0), + ], +) +def test_explicit_tier_aliases(raw_tier: str, normalized_tier: str, fast: int) -> None: + attributes = completion_attributes(service_tier=raw_tier) + + completion = parse_otlp_json_line( + synthetic_otlp_line(attributes=attributes) + ).completions[0] + + assert (completion.service_tier, completion.fast) == (normalized_tier, fast) + + +def test_multiple_resource_and_scope_groups_are_traversed() -> None: + first = json.loads( + synthetic_otlp_line(attributes=completion_attributes(conversation_id="a")) + ) + second = json.loads( + synthetic_otlp_line(attributes=completion_attributes(conversation_id="b")) + ) + first["resourceLogs"].extend(second["resourceLogs"]) + + result = parse_otlp_json_line(json.dumps(first)) + + assert [item.conversation_id for item in result.completions] == ["a", "b"] + + +@pytest.mark.parametrize("raw", ["{", "[]", json.dumps({"resourceLogs": "bad"})]) +def test_malformed_payloads_return_bounded_diagnostics(raw: str) -> None: + result = parse_otlp_json_line(raw) + + assert not result.completions + assert sum(result.diagnostics.values()) >= 1 + assert set(result.diagnostics) <= set(OTEL_DIAGNOSTIC_KEYS) + + +def test_non_completion_and_missing_identity_never_become_pending_matches() -> None: + unrelated = completion_attributes() + unrelated["event.kind"] = "response.created" + missing_identity = completion_attributes() + missing_identity.pop("conversation.id") + + assert not parse_otlp_json_line( + synthetic_otlp_line(attributes=unrelated) + ).completions + completion = parse_otlp_json_line( + synthetic_otlp_line(attributes=missing_identity) + ).completions[0] + assert completion.match_status == "invalid" + + +def test_present_invalid_tier_is_not_treated_as_protocol_omission() -> None: + attributes = completion_attributes(service_tier=None) + attributes["service_tier"] = 7 + + result = parse_otlp_json_line(synthetic_otlp_line(attributes=attributes)) + + completion = result.completions[0] + assert (completion.service_tier, completion.fast) == (None, None) + assert completion.match_status == "invalid" + assert result.diagnostics["otel_invalid_record"] >= 1 + + +def test_semantic_fingerprint_is_stable_and_changes_with_aggregate_identity() -> None: + attributes = completion_attributes() + reversed_attributes = dict(reversed(list(attributes.items()))) + changed_attributes = completion_attributes(tokens=(121, 40, 30, 10)) + + first = parse_otlp_json_line( + synthetic_otlp_line(attributes=attributes) + ).completions[0] + reordered = parse_otlp_json_line( + synthetic_otlp_line(attributes=reversed_attributes) + ).completions[0] + changed = parse_otlp_json_line( + synthetic_otlp_line(attributes=changed_attributes) + ).completions[0] + + assert first.fingerprint == reordered.fingerprint + assert first.fingerprint != changed.fingerprint From 1e4c0d6e6501cbc09d89b1cc9c5bb855828114a2 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:36:10 -0400 Subject: [PATCH 05/24] feat: ingest OTel completions incrementally --- src/codex_usage_tracker/store/otel_ingest.py | 239 +++++++++++++++++++ tests/store/test_otel_ingest.py | 139 +++++++++++ 2 files changed, 378 insertions(+) create mode 100644 src/codex_usage_tracker/store/otel_ingest.py create mode 100644 tests/store/test_otel_ingest.py diff --git a/src/codex_usage_tracker/store/otel_ingest.py b/src/codex_usage_tracker/store/otel_ingest.py new file mode 100644 index 00000000..e74b6b0d --- /dev/null +++ b/src/codex_usage_tracker/store/otel_ingest.py @@ -0,0 +1,239 @@ +"""Incremental ingestion for aggregate-only Codex OTel completion files.""" + +from __future__ import annotations + +import os +import sqlite3 +from collections import Counter +from dataclasses import dataclass, field +from datetime import datetime, timezone +from pathlib import Path + +from codex_usage_tracker.parser.otel import OtelCompletion, parse_otlp_json_line + + +@dataclass(frozen=True) +class OtelIngestResult: + files_scanned: int = 0 + imported: int = 0 + duplicates: int = 0 + diagnostics: dict[str, int] = field(default_factory=dict) + + +@dataclass +class _MutableIngestTotals: + files_scanned: int = 0 + imported: int = 0 + duplicates: int = 0 + diagnostics: Counter[str] = field(default_factory=Counter) + + def freeze(self) -> OtelIngestResult: + return OtelIngestResult( + files_scanned=self.files_scanned, + imported=self.imported, + duplicates=self.duplicates, + diagnostics=dict(self.diagnostics), + ) + + +@dataclass(frozen=True) +class _SourceState: + device: int + inode: int + size: int + parsed_offset: int + parsed_line: int + + +def discover_otel_sources(directory: Path) -> list[Path]: + """Return current and rotated completion files in deterministic path order.""" + + if not directory.is_dir(): + return [] + return sorted( + path + for path in directory.glob("codex-completions*.jsonl") + if path.is_file() + ) + + +def ingest_otel_completion_files( + conn: sqlite3.Connection, directory: Path +) -> OtelIngestResult: + """Resume every completion source at its last fully handled line.""" + + totals = _MutableIngestTotals() + for path in discover_otel_sources(directory): + source_path = str(path.resolve()) + try: + initial_stat = path.stat() + state = _source_state(conn, source_path) + offset, line_number = _resume_position(state, initial_stat) + next_offset, next_line = _ingest_complete_lines( + conn, + path, + source_path, + offset, + line_number, + totals, + ) + final_stat = path.stat() + except FileNotFoundError: + continue + _upsert_source_cursor( + conn, + source_path, + final_stat, + next_offset, + next_line, + ) + totals.files_scanned += 1 + return totals.freeze() + + +def _source_state(conn: sqlite3.Connection, source_path: str) -> _SourceState | None: + row = conn.execute( + """ + SELECT device, inode, size, parsed_offset, parsed_line + FROM otel_completion_sources + WHERE source_path = ? + """, + (source_path,), + ).fetchone() + if row is None: + return None + return _SourceState( + device=int(row["device"]), + inode=int(row["inode"]), + size=int(row["size"]), + parsed_offset=int(row["parsed_offset"]), + parsed_line=int(row["parsed_line"]), + ) + + +def _resume_position( + state: _SourceState | None, stat: os.stat_result +) -> tuple[int, int]: + if state is None: + return 0, 0 + unchanged_file = state.device == stat.st_dev and state.inode == stat.st_ino + has_not_shrunk = stat.st_size >= state.size and stat.st_size >= state.parsed_offset + if unchanged_file and has_not_shrunk: + return state.parsed_offset, state.parsed_line + return 0, 0 + + +def _ingest_complete_lines( + conn: sqlite3.Connection, + path: Path, + source_path: str, + offset: int, + line_number: int, + totals: _MutableIngestTotals, +) -> tuple[int, int]: + next_offset = offset + next_line = line_number + with path.open("rb") as handle: + handle.seek(offset) + while line := handle.readline(): + if not line.endswith(b"\n"): + break + next_offset = handle.tell() + next_line += 1 + try: + raw = line.decode("utf-8") + except UnicodeDecodeError: + totals.diagnostics["otel_invalid_json"] += 1 + continue + result = parse_otlp_json_line(raw) + totals.diagnostics.update(result.diagnostics) + for completion in result.completions: + if _insert_completion(conn, completion, source_path, next_line): + totals.imported += 1 + else: + totals.duplicates += 1 + return next_offset, next_line + + +def _insert_completion( + conn: sqlite3.Connection, + completion: OtelCompletion, + source_path: str, + source_line: int, +) -> bool: + cursor = conn.execute( + """ + INSERT INTO otel_completion_events ( + fingerprint, + conversation_id, + event_timestamp, + input_tokens, + cached_input_tokens, + output_tokens, + reasoning_output_tokens, + model, + effort, + service_tier, + fast, + service_tier_source, + service_tier_confidence, + app_version, + source_path, + source_line, + match_status + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(fingerprint) DO NOTHING + """, + ( + completion.fingerprint, + completion.conversation_id, + completion.event_timestamp, + completion.input_tokens, + completion.cached_input_tokens, + completion.output_tokens, + completion.reasoning_output_tokens, + completion.model, + completion.effort, + completion.service_tier, + completion.fast, + completion.service_tier_source, + completion.service_tier_confidence, + completion.app_version, + source_path, + source_line, + completion.match_status, + ), + ) + return cursor.rowcount == 1 + + +def _upsert_source_cursor( + conn: sqlite3.Connection, + source_path: str, + stat: os.stat_result, + parsed_offset: int, + parsed_line: int, +) -> None: + conn.execute( + """ + INSERT INTO otel_completion_sources ( + source_path, device, inode, size, parsed_offset, parsed_line, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(source_path) DO UPDATE SET + device = excluded.device, + inode = excluded.inode, + size = excluded.size, + parsed_offset = excluded.parsed_offset, + parsed_line = excluded.parsed_line, + updated_at = excluded.updated_at + """, + ( + source_path, + stat.st_dev, + stat.st_ino, + stat.st_size, + parsed_offset, + parsed_line, + datetime.now(timezone.utc).isoformat(), + ), + ) diff --git a/tests/store/test_otel_ingest.py b/tests/store/test_otel_ingest.py new file mode 100644 index 00000000..f1eecccc --- /dev/null +++ b/tests/store/test_otel_ingest.py @@ -0,0 +1,139 @@ +from __future__ import annotations + +import json +from pathlib import Path + +from codex_usage_tracker.store.otel_ingest import ( + discover_otel_sources, + ingest_otel_completion_files, +) +from tests.otel_helpers import ( + append_text, + completion_attributes, + initialized_connection, + synthetic_fast_completion, + synthetic_otlp_line, + synthetic_standard_completion, + write_lines, +) + + +def test_discovery_is_bounded_and_deterministic(tmp_path: Path) -> None: + directory = tmp_path / "otel" + write_lines(directory / "codex-completions.jsonl", []) + write_lines(directory / "codex-completions-20260716.jsonl", []) + write_lines(directory / "unrelated.jsonl", []) + + assert [path.name for path in discover_otel_sources(directory)] == [ + "codex-completions-20260716.jsonl", + "codex-completions.jsonl", + ] + assert discover_otel_sources(tmp_path / "missing") == [] + + +def test_incremental_ingest_reads_each_complete_line_once(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + write_lines(source, [synthetic_fast_completion("conversation-a", 100)]) + with initialized_connection(tmp_path) as conn: + first = ingest_otel_completion_files(conn, directory) + append_text(source, synthetic_standard_completion("conversation-b", 200) + "\n") + second = ingest_otel_completion_files(conn, directory) + rows = conn.execute("SELECT fingerprint FROM otel_completion_events").fetchall() + + assert first.imported == 1 + assert second.imported == 1 + assert len(rows) == 2 + + +def test_partial_last_line_is_retried_after_append(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + complete = synthetic_otlp_line(attributes=completion_attributes()) + source.parent.mkdir(parents=True) + source.write_text(complete[:-1], encoding="utf-8") + with initialized_connection(tmp_path) as conn: + assert ingest_otel_completion_files(conn, directory).imported == 0 + source.write_text(complete + "\n", encoding="utf-8") + assert ingest_otel_completion_files(conn, directory).imported == 1 + + +def test_rotation_and_reread_do_not_duplicate_semantic_completion(tmp_path: Path) -> None: + directory = tmp_path / "otel" + current = directory / "codex-completions.jsonl" + rotated = directory / "codex-completions-20260716.jsonl" + line = synthetic_otlp_line(attributes=completion_attributes()) + "\n" + current.parent.mkdir(parents=True) + current.write_text(line, encoding="utf-8") + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + current.replace(rotated) + current.write_text(line, encoding="utf-8") + result = ingest_otel_completion_files(conn, directory) + count = conn.execute("SELECT COUNT(*) FROM otel_completion_events").fetchone()[0] + + assert count == 1 + assert result.duplicates >= 1 + + +def test_truncation_or_inode_replacement_resets_cursor_safely(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + source.parent.mkdir(parents=True) + source.write_text( + synthetic_otlp_line( + attributes=completion_attributes(conversation_id="synthetic-a") + ) + + "\n", + encoding="utf-8", + ) + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + source.unlink() + source.write_text( + synthetic_otlp_line( + attributes=completion_attributes(conversation_id="synthetic-b") + ) + + "\n", + encoding="utf-8", + ) + assert ingest_otel_completion_files(conn, directory).imported == 1 + + +def test_ingest_never_persists_body_or_arbitrary_attributes(tmp_path: Path) -> None: + directory = tmp_path / "otel" + attributes = completion_attributes() + attributes["secret.attribute"] = "synthetic-secret-value" + write_lines( + directory / "codex-completions.jsonl", + [ + synthetic_otlp_line( + attributes=attributes, body="synthetic-private-body" + ) + ], + ) + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + rows = conn.execute("SELECT * FROM otel_completion_events").fetchall() + encoded = json.dumps([dict(row) for row in rows], sort_keys=True) + + assert "synthetic-private-body" not in encoded + assert "synthetic-secret-value" not in encoded + assert "secret.attribute" not in encoded + + +def test_cursor_advances_past_complete_invalid_lines(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + write_lines(source, ["{"]) + + with initialized_connection(tmp_path) as conn: + first = ingest_otel_completion_files(conn, directory) + second = ingest_otel_completion_files(conn, directory) + cursor = conn.execute( + "SELECT parsed_line, parsed_offset FROM otel_completion_sources" + ).fetchone() + + assert first.diagnostics["otel_invalid_json"] == 1 + assert second.diagnostics == {} + assert tuple(cursor) == (1, source.stat().st_size) From 393a7b00682054e32fd082537c82e5189e7bdde9 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:40:10 -0400 Subject: [PATCH 06/24] feat: correlate OTel tiers to canonical calls --- src/codex_usage_tracker/store/api.py | 19 +- .../store/otel_reconciliation.py | 176 ++++++++++++ .../store/source_replacement.py | 78 +++++ tests/otel_helpers.py | 68 +++++ tests/store/test_otel_reconciliation.py | 268 ++++++++++++++++++ 5 files changed, 608 insertions(+), 1 deletion(-) create mode 100644 src/codex_usage_tracker/store/otel_reconciliation.py create mode 100644 tests/store/test_otel_reconciliation.py diff --git a/src/codex_usage_tracker/store/api.py b/src/codex_usage_tracker/store/api.py index 2e272d40..73b4ddda 100644 --- a/src/codex_usage_tracker/store/api.py +++ b/src/codex_usage_tracker/store/api.py @@ -104,9 +104,18 @@ from codex_usage_tracker.store.source_records import ( sync_source_records, ) +from codex_usage_tracker.store.source_replacement import ( + OTEL_ENRICHMENT_COLUMNS, +) +from codex_usage_tracker.store.source_replacement import ( + capture_otel_enrichment_for_source_files as _capture_otel_enrichment_for_source_files, +) from codex_usage_tracker.store.source_replacement import ( delete_usage_events_for_source_files as _delete_usage_events_for_source_files, ) +from codex_usage_tracker.store.source_replacement import ( + restore_otel_enrichment as _restore_otel_enrichment, +) from codex_usage_tracker.store.source_replacement import ( source_file_strings as _source_file_strings, ) @@ -571,6 +580,9 @@ def _upsert_usage_events_in_connection( source_files_to_replace = _source_file_strings(replace_source_files) affected_thread_keys = _thread_keys_for_source_files(conn, source_files_to_replace) replaced_fingerprints = fingerprints_for_source_files(conn, source_files_to_replace) + preserved_otel_enrichment = _capture_otel_enrichment_for_source_files( + conn, source_files_to_replace + ) _delete_usage_events_for_source_files( conn, source_files_to_replace, @@ -603,6 +615,7 @@ def _upsert_usage_events_in_connection( _delete_diagnostic_facts_for_record_ids(conn, inserted_record_ids) with _deferred_usage_event_indexes(conn, enabled=defer_usage_indexes): _insert_usage_event_rows(conn, rows) + _restore_otel_enrichment(conn, preserved_otel_enrichment) if maintain_allowance_observations: sync_allowance_observations_for_record_ids(conn, record_ids) if maintain_source_records: @@ -693,7 +706,11 @@ def _usage_event_record_ids(rows: list[dict[str, object]]) -> list[str]: def _usage_event_upsert_sql() -> str: placeholders = ", ".join("?" for _column in EVENT_COLUMNS) update_clause = ", ".join( - f"{column}=excluded.{column}" for column in EVENT_COLUMNS if column != "record_id" + f"{column}=COALESCE(usage_events.{column}, excluded.{column})" + if column in OTEL_ENRICHMENT_COLUMNS + else f"{column}=excluded.{column}" + for column in EVENT_COLUMNS + if column != "record_id" ) return ( f"INSERT INTO usage_events ({', '.join(EVENT_COLUMNS)}) " diff --git a/src/codex_usage_tracker/store/otel_reconciliation.py b/src/codex_usage_tracker/store/otel_reconciliation.py new file mode 100644 index 00000000..7cc4014d --- /dev/null +++ b/src/codex_usage_tracker/store/otel_reconciliation.py @@ -0,0 +1,176 @@ +"""Conservative correlation of staged OTel tiers to canonical usage calls.""" + +from __future__ import annotations + +import sqlite3 +from dataclasses import dataclass + +_TIER_COLUMNS = ( + "service_tier", + "fast", + "service_tier_source", + "service_tier_confidence", +) + + +@dataclass(frozen=True) +class OtelReconciliationResult: + matched: int = 0 + pending: int = 0 + ambiguous: int = 0 + conflicts: int = 0 + updated_usage_rows: int = 0 + + +@dataclass +class _MutableReconciliationTotals: + matched: int = 0 + pending: int = 0 + ambiguous: int = 0 + conflicts: int = 0 + updated_usage_rows: int = 0 + + def freeze(self) -> OtelReconciliationResult: + return OtelReconciliationResult( + matched=self.matched, + pending=self.pending, + ambiguous=self.ambiguous, + conflicts=self.conflicts, + updated_usage_rows=self.updated_usage_rows, + ) + + +def reconcile_otel_completions( + conn: sqlite3.Connection, +) -> OtelReconciliationResult: + """Enrich only completion identities that resolve to one canonical group.""" + + totals = _MutableReconciliationTotals() + rows = conn.execute( + """ + SELECT * + FROM otel_completion_events + WHERE match_status IN ('pending', 'ambiguous', 'matched') + ORDER BY source_path, source_line, fingerprint + """ + ).fetchall() + for completion in rows: + candidates = _candidate_rows(conn, completion) + group_ids = { + str(row["canonical_record_id"] or row["record_id"]) for row in candidates + } + if not candidates: + _set_match_state(conn, str(completion["fingerprint"]), "pending", None) + totals.pending += 1 + elif len(group_ids) != 1: + _set_match_state(conn, str(completion["fingerprint"]), "ambiguous", None) + totals.ambiguous += 1 + else: + _apply_to_canonical_group(conn, completion, group_ids.pop(), totals) + return totals.freeze() + + +def reset_otel_completion_matches(conn: sqlite3.Connection) -> None: + """Make every valid staged completion eligible for rebuild reconciliation.""" + + conn.execute( + """ + UPDATE otel_completion_events + SET match_status = 'pending', matched_record_id = NULL + WHERE match_status != 'invalid' + """ + ) + + +def _candidate_rows( + conn: sqlite3.Connection, completion: sqlite3.Row +) -> list[sqlite3.Row]: + return conn.execute( + """ + SELECT record_id, canonical_record_id + FROM usage_events + WHERE session_id = ? + AND input_tokens = ? + AND cached_input_tokens = ? + AND output_tokens = ? + AND reasoning_output_tokens = ? + AND (? IS NULL OR model IS NULL OR lower(model) = lower(?)) + AND (? IS NULL OR effort IS NULL OR lower(effort) = lower(?)) + """, + ( + completion["conversation_id"], + completion["input_tokens"], + completion["cached_input_tokens"], + completion["output_tokens"], + completion["reasoning_output_tokens"], + completion["model"], + completion["model"], + completion["effort"], + completion["effort"], + ), + ).fetchall() + + +def _apply_to_canonical_group( + conn: sqlite3.Connection, + completion: sqlite3.Row, + canonical_id: str, + totals: _MutableReconciliationTotals, +) -> None: + clones = conn.execute( + """ + SELECT record_id, service_tier, fast, + service_tier_source, service_tier_confidence + FROM usage_events + WHERE coalesce(nullif(canonical_record_id, ''), record_id) = ? + ORDER BY record_id + """, + (canonical_id,), + ).fetchall() + desired = tuple(completion[column] for column in _TIER_COLUMNS) + contradiction = any( + row[column] is not None and row[column] != expected + for row in clones + for column, expected in zip(_TIER_COLUMNS, desired, strict=True) + ) + if contradiction: + _set_match_state(conn, str(completion["fingerprint"]), "conflict", None) + totals.conflicts += 1 + return + + cursor = conn.execute( + """ + UPDATE usage_events + SET service_tier = coalesce(service_tier, ?), + fast = coalesce(fast, ?), + service_tier_source = coalesce(service_tier_source, ?), + service_tier_confidence = coalesce(service_tier_confidence, ?) + WHERE coalesce(nullif(canonical_record_id, ''), record_id) = ? + """, + (*desired, canonical_id), + ) + matched_record_id = str(clones[0]["record_id"]) + _set_match_state( + conn, + str(completion["fingerprint"]), + "matched", + matched_record_id, + ) + totals.matched += 1 + totals.updated_usage_rows += max(cursor.rowcount, 0) + + +def _set_match_state( + conn: sqlite3.Connection, + fingerprint: str, + status: str, + matched_record_id: str | None, +) -> None: + conn.execute( + """ + UPDATE otel_completion_events + SET match_status = ?, matched_record_id = ? + WHERE fingerprint = ? + """, + (status, matched_record_id, fingerprint), + ) diff --git a/src/codex_usage_tracker/store/source_replacement.py b/src/codex_usage_tracker/store/source_replacement.py index 4eefa006..91c441c1 100644 --- a/src/codex_usage_tracker/store/source_replacement.py +++ b/src/codex_usage_tracker/store/source_replacement.py @@ -16,6 +16,10 @@ ) _SOURCE_FILE_SQL_BATCH_SIZE = 400 +OTEL_ENRICHMENT_COLUMNS = frozenset( + {"service_tier", "fast", "service_tier_source", "service_tier_confidence"} +) +OtelEnrichment = tuple[object | None, object | None, object | None, object | None] def source_file_strings(replace_source_files: Iterable[Path] | None) -> list[str]: @@ -38,6 +42,75 @@ def delete_usage_events_for_source_files( _rebuild_content_fts(conn) +def capture_otel_enrichment_for_source_files( + conn: sqlite3.Connection, + source_files_to_replace: list[str], +) -> dict[str, OtelEnrichment]: + """Capture one internally consistent non-null tier tuple per affected group.""" + + group_ids: set[str] = set() + for source_batch in _source_file_batches(source_files_to_replace): + placeholders = ", ".join("?" for _source in source_batch) + rows = conn.execute( + f""" + SELECT DISTINCT coalesce(nullif(canonical_record_id, ''), record_id) AS group_id + FROM usage_events + WHERE source_file IN ({placeholders}) + """, # nosec B608 - generated placeholders + source_batch, + ).fetchall() + group_ids.update(str(row["group_id"]) for row in rows) + + tuples_by_group: dict[str, set[OtelEnrichment]] = {} + for group_batch in _value_batches(sorted(group_ids)): + placeholders = ", ".join("?" for _group in group_batch) + rows = conn.execute( + f""" + SELECT coalesce(nullif(canonical_record_id, ''), record_id) AS group_id, + service_tier, fast, service_tier_source, service_tier_confidence + FROM usage_events + WHERE coalesce(nullif(canonical_record_id, ''), record_id) IN ({placeholders}) + """, # nosec B608 - generated placeholders + group_batch, + ).fetchall() + for row in rows: + enrichment: OtelEnrichment = ( + row["service_tier"], + row["fast"], + row["service_tier_source"], + row["service_tier_confidence"], + ) + tuples_by_group.setdefault(str(row["group_id"]), set()).add(enrichment) + + captured: dict[str, OtelEnrichment] = {} + for group_id, enrichments in tuples_by_group.items(): + if len(enrichments) != 1: + continue + enrichment = next(iter(enrichments)) + if any(value is not None for value in enrichment): + captured[group_id] = enrichment + return captured + + +def restore_otel_enrichment( + conn: sqlite3.Connection, + captured: Mapping[str, OtelEnrichment], +) -> None: + """Restore captured tiers to reparsed clones without overwriting fresh values.""" + + conn.executemany( + """ + UPDATE usage_events + SET service_tier = coalesce(service_tier, ?), + fast = coalesce(fast, ?), + service_tier_source = coalesce(service_tier_source, ?), + service_tier_confidence = coalesce(service_tier_confidence, ?) + WHERE coalesce(nullif(canonical_record_id, ''), record_id) = ? + """, + [(*enrichment, group_id) for group_id, enrichment in captured.items()], + ) + + def thread_keys_for_source_files( conn: sqlite3.Connection, source_files_to_replace: list[str], @@ -108,6 +181,11 @@ def _source_file_batches(source_files: list[str]) -> Iterator[list[str]]: yield source_files[start : start + _SOURCE_FILE_SQL_BATCH_SIZE] +def _value_batches(values: list[str]) -> Iterator[list[str]]: + for start in range(0, len(values), _SOURCE_FILE_SQL_BATCH_SIZE): + yield values[start : start + _SOURCE_FILE_SQL_BATCH_SIZE] + + def _usage_row_value( row: Mapping[str, object] | sqlite3.Row, key: str, diff --git a/tests/otel_helpers.py b/tests/otel_helpers.py index 6c107cd6..0632aeee 100644 --- a/tests/otel_helpers.py +++ b/tests/otel_helpers.py @@ -6,6 +6,7 @@ from contextlib import contextmanager from pathlib import Path +from codex_usage_tracker.core.models import UsageEvent from codex_usage_tracker.store.connection import connect from codex_usage_tracker.store.schema import init_db @@ -92,6 +93,73 @@ def synthetic_standard_completion(conversation_id: str, input_tokens: int) -> st ) +def synthetic_usage_event( + record_id: str, + conversation_id: str, + tokens: tuple[int, int, int, int], + *, + canonical: str = "canonical-a", + model: str = "gpt-5.6-sol", + effort: str = "high", + service_tier: str | None = None, + fast: int | None = None, + duplicate: int = 0, +) -> UsageEvent: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + total_tokens = input_tokens + output_tokens + return UsageEvent( + record_id=record_id, + session_id=conversation_id, + thread_name="Synthetic thread", + session_updated_at="2026-07-16T00:00:00Z", + event_timestamp="2026-07-16T00:00:00Z", + source_file="/synthetic/session.jsonl", + line_number=1, + turn_id="synthetic-turn", + turn_timestamp="2026-07-16T00:00:00Z", + cwd="/synthetic/project", + model=model, + effort=effort, + current_date="2026-07-16", + timezone="UTC", + call_initiator="user", + call_initiator_reason="user_message", + call_initiator_confidence="high", + is_archived=0, + thread_key="thread:Synthetic", + thread_call_index=None, + previous_record_id=None, + next_record_id=None, + thread_source="user", + subagent_type=None, + agent_role=None, + agent_nickname=None, + parent_session_id=None, + parent_thread_name=None, + parent_session_updated_at=None, + model_context_window=258_400, + input_tokens=input_tokens, + cached_input_tokens=cached_tokens, + output_tokens=output_tokens, + reasoning_output_tokens=reasoning_tokens, + total_tokens=total_tokens, + cumulative_input_tokens=input_tokens, + cumulative_cached_input_tokens=cached_tokens, + cumulative_output_tokens=output_tokens, + cumulative_reasoning_output_tokens=reasoning_tokens, + cumulative_total_tokens=total_tokens, + usage_fingerprint=f"synthetic-fingerprint-{canonical}", + canonical_record_id=canonical, + is_duplicate=duplicate, + duplicate_reason="copied_usage_fingerprint" if duplicate else None, + service_tier=service_tier + or ("fast" if fast == 1 else "standard" if fast == 0 else None), + fast=fast, + service_tier_source="otel_response_completed" if fast is not None else None, + service_tier_confidence="exact" if fast is not None else None, + ) + + def write_lines(path: Path, lines: list[str]) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text("".join(f"{line}\n" for line in lines), encoding="utf-8") diff --git a/tests/store/test_otel_reconciliation.py b/tests/store/test_otel_reconciliation.py new file mode 100644 index 00000000..18fef871 --- /dev/null +++ b/tests/store/test_otel_reconciliation.py @@ -0,0 +1,268 @@ +from __future__ import annotations + +import hashlib +import sqlite3 +from dataclasses import replace +from pathlib import Path + +from codex_usage_tracker.store.api import EVENT_COLUMNS, query_usage_record, upsert_usage_events +from codex_usage_tracker.store.otel_reconciliation import ( + reconcile_otel_completions, + reset_otel_completion_matches, +) +from tests.otel_helpers import initialized_connection, synthetic_usage_event + + +def insert_usage_clone_group( + conn: sqlite3.Connection, + conversation_id: str, + tokens: tuple[int, int, int, int], + *, + canonical: str = "canonical-a", + model: str | None = "gpt-5.6-sol", + effort: str | None = "high", + service_tier: str | None = None, + fast: int | None = None, +) -> None: + events = [ + synthetic_usage_event( + f"{canonical}-record-{index}", + conversation_id, + tokens, + canonical=canonical, + model=model or "", + effort=effort or "", + service_tier=service_tier, + fast=fast, + duplicate=int(index == 1), + ) + for index in range(2) + ] + rows = [event.to_row() for event in events] + if model is None: + for row in rows: + row["model"] = None + if effort is None: + for row in rows: + row["effort"] = None + placeholders = ", ".join("?" for _column in EVENT_COLUMNS) + conn.executemany( + f"INSERT INTO usage_events ({', '.join(EVENT_COLUMNS)}) VALUES ({placeholders})", # nosec B608 + [[row[column] for column in EVENT_COLUMNS] for row in rows], + ) + + +def stage_completion( + conn: sqlite3.Connection, + conversation_id: str, + tokens: tuple[int, int, int, int], + *, + fast: int, + model: str | None = "gpt-5.6-sol", + effort: str | None = "high", + event_timestamp: str = "2026-07-16T00:00:00Z", +) -> str: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + fingerprint = hashlib.sha256( + repr((conversation_id, tokens, fast, model, effort, event_timestamp)).encode() + ).hexdigest() + conn.execute( + """ + INSERT INTO otel_completion_events ( + fingerprint, conversation_id, event_timestamp, + input_tokens, cached_input_tokens, output_tokens, reasoning_output_tokens, + model, effort, service_tier, fast, service_tier_source, + service_tier_confidence, app_version, source_path, source_line, + match_status, matched_record_id + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'otel_response_completed', + 'exact', '0.143.0', '/synthetic/codex-completions.jsonl', 1, 'pending', NULL) + """, + ( + fingerprint, + conversation_id, + event_timestamp, + input_tokens, + cached_tokens, + output_tokens, + reasoning_tokens, + model, + effort, + "fast" if fast == 1 else "standard", + fast, + ), + ) + return fingerprint + + +def test_unique_token_identity_enriches_every_clone_in_one_canonical_group( + tmp_path: Path, +) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group( + conn, conversation_id="conversation-a", tokens=(100, 40, 30, 10) + ) + stage_completion( + conn, conversation_id="conversation-a", tokens=(100, 40, 30, 10), fast=1 + ) + result = reconcile_otel_completions(conn) + rows = conn.execute( + "SELECT service_tier, fast FROM usage_events ORDER BY record_id" + ).fetchall() + + assert result.matched == 1 + assert [(row["service_tier"], row["fast"]) for row in rows] == [ + ("fast", 1), + ("fast", 1), + ] + assert result.updated_usage_rows == 2 + + +def test_same_tokens_in_two_canonical_groups_remain_ambiguous(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group( + conn, "conversation-a", (100, 40, 30, 10), canonical="canonical-a" + ) + insert_usage_clone_group( + conn, "conversation-a", (100, 40, 30, 10), canonical="canonical-b" + ) + fingerprint = stage_completion( + conn, "conversation-a", (100, 40, 30, 10), fast=1 + ) + reconcile_otel_completions(conn) + status = conn.execute( + "SELECT match_status FROM otel_completion_events WHERE fingerprint = ?", + (fingerprint,), + ).fetchone()[0] + tiers = conn.execute("SELECT service_tier FROM usage_events").fetchall() + + assert status == "ambiguous" + assert all(row[0] is None for row in tiers) + + +def test_timestamp_distance_does_not_affect_matching(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group(conn, "conversation-a", (100, 40, 30, 10)) + stage_completion( + conn, + "conversation-a", + (100, 40, 30, 10), + fast=1, + event_timestamp="2099-01-01T00:00:00Z", + ) + + assert reconcile_otel_completions(conn).matched == 1 + + +def test_model_or_effort_mismatch_prevents_match_when_both_are_present( + tmp_path: Path, +) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group( + conn, + "conversation-a", + (100, 40, 30, 10), + model="gpt-5.5", + effort="medium", + ) + stage_completion( + conn, + "conversation-a", + (100, 40, 30, 10), + fast=1, + model="gpt-5.6", + effort="high", + ) + + assert reconcile_otel_completions(conn).pending == 1 + + +def test_missing_model_or_effort_does_not_block_exact_token_match(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group( + conn, + "conversation-a", + (100, 40, 30, 10), + model=None, + effort=None, + ) + stage_completion( + conn, "conversation-a", (100, 40, 30, 10), fast=1 + ) + + assert reconcile_otel_completions(conn).matched == 1 + + +def test_contradictory_existing_tier_is_preserved_and_marks_conflict( + tmp_path: Path, +) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group( + conn, + "conversation-a", + (100, 40, 30, 10), + service_tier="standard", + fast=0, + ) + fingerprint = stage_completion( + conn, "conversation-a", (100, 40, 30, 10), fast=1 + ) + assert reconcile_otel_completions(conn).conflicts == 1 + row = conn.execute( + "SELECT service_tier, fast FROM usage_events LIMIT 1" + ).fetchone() + status = conn.execute( + "SELECT match_status FROM otel_completion_events WHERE fingerprint = ?", + (fingerprint,), + ).fetchone()[0] + + assert tuple(row) == ("standard", 0) + assert status == "conflict" + + +def test_usage_upsert_and_source_replacement_preserve_non_null_tier( + tmp_path: Path, +) -> None: + db_path = tmp_path / "usage.sqlite3" + original = synthetic_usage_event( + "record-a", "conversation-a", (100, 40, 30, 10), fast=1 + ) + upsert_usage_events([original], db_path=db_path) + reparsed = replace( + original, + thread_name="reparsed", + service_tier=None, + fast=None, + service_tier_source=None, + service_tier_confidence=None, + ) + + upsert_usage_events( + [reparsed], + db_path=db_path, + replace_source_files=[Path(original.source_file)], + ) + + row = query_usage_record(db_path=db_path, record_id="record-a") + assert row is not None + assert (row["service_tier"], row["fast"]) == ("fast", 1) + assert row["service_tier_source"] == "otel_response_completed" + assert row["service_tier_confidence"] == "exact" + + +def test_matched_rows_are_idempotent_and_can_be_reset_for_rebuild(tmp_path: Path) -> None: + with initialized_connection(tmp_path) as conn: + insert_usage_clone_group(conn, "conversation-a", (100, 40, 30, 10)) + fingerprint = stage_completion( + conn, "conversation-a", (100, 40, 30, 10), fast=1 + ) + first = reconcile_otel_completions(conn) + second = reconcile_otel_completions(conn) + reset_otel_completion_matches(conn) + state = conn.execute( + "SELECT match_status, matched_record_id FROM otel_completion_events WHERE fingerprint = ?", + (fingerprint,), + ).fetchone() + + assert first.matched == 1 + assert second.matched == 1 + assert tuple(state) == ("pending", None) From ce62d5381c615132ac220d7ff51d3a6a4817927d Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:45:37 -0400 Subject: [PATCH 07/24] feat: reconcile OTel tiers during refresh --- src/codex_usage_tracker/reports/support.py | 12 +- src/codex_usage_tracker/store/api.py | 25 ++- .../store/otel_reconciliation.py | 6 + src/codex_usage_tracker/store/refresh.py | 63 ++++++- tests/core/test_api_payloads.py | 18 ++ tests/otel_helpers.py | 68 +++++++ tests/reports/test_support.py | 13 ++ tests/store/test_otel_reconciliation.py | 1 + tests/store/test_otel_refresh.py | 171 ++++++++++++++++++ 9 files changed, 373 insertions(+), 4 deletions(-) create mode 100644 tests/core/test_api_payloads.py create mode 100644 tests/store/test_otel_refresh.py diff --git a/src/codex_usage_tracker/reports/support.py b/src/codex_usage_tracker/reports/support.py index b7f214a7..eb66339f 100644 --- a/src/codex_usage_tracker/reports/support.py +++ b/src/codex_usage_tracker/reports/support.py @@ -17,6 +17,7 @@ DEFAULT_DASHBOARD_PATH, DEFAULT_DB_PATH, DEFAULT_MARKETPLACE_PATH, + DEFAULT_OTEL_COMPLETIONS_DIR, DEFAULT_PLUGIN_LINK, DEFAULT_PRICING_PATH, DEFAULT_PROJECTS_PATH, @@ -41,6 +42,7 @@ "paths", "database", "refresh", + "otel", "pricing", "allowance", "thresholds", @@ -58,6 +60,7 @@ "paths.sessions_dir_exists", "database", "refresh", + "otel", "pricing.loaded", "pricing.error", "pricing.model_count", @@ -162,6 +165,7 @@ def support_bundle_payload( allowance = load_allowance_config(allowance_path, rate_card_path=rate_card_path) thresholds = load_threshold_config(thresholds_path) projects = load_project_config(projects_path) + refresh = refresh_metadata(db_path) payload = { "bundle_version": 1, "generated_at": datetime.now(timezone.utc) @@ -197,7 +201,13 @@ def support_bundle_payload( }, "issue_report": support_bundle_issue_guidance(privacy_mode), "database": schema_state(db_path), - "refresh": refresh_metadata(db_path), + "refresh": refresh, + "otel": { + "completion_directory_exists": DEFAULT_OTEL_COMPLETIONS_DIR.is_dir(), + "refresh_counts": { + key: value for key, value in refresh.items() if key.startswith("otel_") + }, + }, "pricing": { "loaded": pricing.loaded, "error": pricing.error, diff --git a/src/codex_usage_tracker/store/api.py b/src/codex_usage_tracker/store/api.py index 73b4ddda..f995612e 100644 --- a/src/codex_usage_tracker/store/api.py +++ b/src/codex_usage_tracker/store/api.py @@ -12,12 +12,17 @@ from typing import Any from codex_usage_tracker.core.models import DiagnosticFact, RefreshResult, UsageEvent -from codex_usage_tracker.core.paths import DEFAULT_CODEX_HOME, DEFAULT_DB_PATH +from codex_usage_tracker.core.paths import ( + DEFAULT_CODEX_HOME, + DEFAULT_DB_PATH, + DEFAULT_OTEL_COMPLETIONS_DIR, +) from codex_usage_tracker.core.schema import ( DIAGNOSTIC_FACT_COLUMN_NAMES, USAGE_EVENT_COLUMN_NAMES, USAGE_EVENT_SCHEMA_CHECKSUM, ) +from codex_usage_tracker.parser.otel import OTEL_DIAGNOSTIC_KEYS from codex_usage_tracker.parser.state import ( PARSER_ADAPTER_VERSION, PARSER_DIAGNOSTIC_KEYS, @@ -152,6 +157,16 @@ EVENT_COLUMNS = list(USAGE_EVENT_COLUMN_NAMES) DIAGNOSTIC_FACT_COLUMNS = list(DIAGNOSTIC_FACT_COLUMN_NAMES) +OTEL_REFRESH_COUNTER_KEYS = ( + "otel_files_scanned", + "otel_imported", + "otel_duplicates", + "otel_matched", + "otel_pending", + "otel_ambiguous", + "otel_conflicts", + *OTEL_DIAGNOSTIC_KEYS, +) __all__ = ["EVENT_COLUMNS", "SCHEMA_VERSION", "SchemaMigrationError", "init_db"] SQLITE_VARIABLE_BATCH_SIZE = 500 RefreshProgressCallback = Callable[[dict[str, object]], None] @@ -162,6 +177,7 @@ def refresh_usage_index( db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, + otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, progress_callback: RefreshProgressCallback | None = None, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: @@ -176,6 +192,7 @@ def refresh_usage_index( db_path=db_path, include_archived=include_archived, aggregate_only=aggregate_only, + otel_dir=otel_dir, progress_callback=progress_callback, derived_fact_sync=derived_fact_sync, ) @@ -186,6 +203,7 @@ def rebuild_usage_index( db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, + otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: """Drop and rebuild the usage index from all selected Codex logs.""" @@ -199,6 +217,7 @@ def rebuild_usage_index( db_path=db_path, include_archived=include_archived, aggregate_only=aggregate_only, + otel_dir=otel_dir, derived_fact_sync=derived_fact_sync, ) @@ -348,6 +367,7 @@ def record_refresh_metadata( skipped_events: int, inserted_or_updated_events: int, parser_diagnostics: dict[str, int] | None = None, + otel_diagnostics: dict[str, int] | None = None, parsed_source_files: int | None = None, skipped_source_files: int | None = None, ) -> None: @@ -370,6 +390,9 @@ def record_refresh_metadata( diagnostics = parser_diagnostics or {} for key in PARSER_DIAGNOSTIC_KEYS: values[f"parser_{key}"] = str(int(diagnostics.get(key, 0))) + otel_counters = otel_diagnostics or {} + for key in OTEL_REFRESH_COUNTER_KEYS: + values[key] = str(int(otel_counters.get(key, 0))) with connect(db_path) as conn: init_db(conn) conn.executemany( diff --git a/src/codex_usage_tracker/store/otel_reconciliation.py b/src/codex_usage_tracker/store/otel_reconciliation.py index 7cc4014d..9f820a39 100644 --- a/src/codex_usage_tracker/store/otel_reconciliation.py +++ b/src/codex_usage_tracker/store/otel_reconciliation.py @@ -146,6 +146,12 @@ def _apply_to_canonical_group( service_tier_source = coalesce(service_tier_source, ?), service_tier_confidence = coalesce(service_tier_confidence, ?) WHERE coalesce(nullif(canonical_record_id, ''), record_id) = ? + AND ( + service_tier IS NULL + OR fast IS NULL + OR service_tier_source IS NULL + OR service_tier_confidence IS NULL + ) """, (*desired, canonical_id), ) diff --git a/src/codex_usage_tracker/store/refresh.py b/src/codex_usage_tracker/store/refresh.py index 1077874b..306bc020 100644 --- a/src/codex_usage_tracker/store/refresh.py +++ b/src/codex_usage_tracker/store/refresh.py @@ -6,15 +6,26 @@ from pathlib import Path from codex_usage_tracker.core.models import RefreshResult -from codex_usage_tracker.core.paths import DEFAULT_CODEX_HOME, DEFAULT_DB_PATH +from codex_usage_tracker.core.paths import ( + DEFAULT_CODEX_HOME, + DEFAULT_DB_PATH, + DEFAULT_OTEL_COMPLETIONS_DIR, +) from codex_usage_tracker.parser.api import find_session_logs, load_session_index from codex_usage_tracker.parser.state import compact_parser_diagnostics from codex_usage_tracker.store.api import ( + OTEL_REFRESH_COUNTER_KEYS, clear_content_index_rows, init_db, record_refresh_metadata, ) +from codex_usage_tracker.store.compression_revisions import touch_compression_revisions from codex_usage_tracker.store.connection import connect +from codex_usage_tracker.store.otel_ingest import ingest_otel_completion_files +from codex_usage_tracker.store.otel_reconciliation import ( + reconcile_otel_completions, + reset_otel_completion_matches, +) from codex_usage_tracker.store.refresh_callbacks import DerivedFactSyncCallback from codex_usage_tracker.store.refresh_parse import ( RefreshProgressCallback, @@ -29,6 +40,7 @@ def refresh_usage_index( db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, + otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, progress_callback: RefreshProgressCallback | None = None, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: @@ -87,6 +99,24 @@ def refresh_usage_index( force_serial=True, derived_fact_sync=derived_fact_sync, ) + emit_refresh_progress( + progress_callback, + phase="otel", + status="running", + completed=0, + total=1, + message="Reconciling aggregate OTel completion tiers", + ) + otel_diagnostics = _refresh_otel_completions(db_path=db_path, otel_dir=otel_dir) + emit_refresh_progress( + progress_callback, + phase="otel", + status="completed", + completed=1, + total=1, + message="Reconciled aggregate OTel completion tiers", + **otel_diagnostics, + ) emit_refresh_progress( progress_callback, phase="finalizing", @@ -102,6 +132,7 @@ def refresh_usage_index( stats=stream_result.stats, parsed_events=stream_result.parsed_events, inserted=stream_result.inserted_or_updated_events, + otel_diagnostics=otel_diagnostics, ) emit_refresh_progress( progress_callback, @@ -131,9 +162,13 @@ def _finalize_refresh_result( stats: dict[str, int], parsed_events: int, inserted: int, + otel_diagnostics: dict[str, int], ) -> RefreshResult: skipped_events = stats.get("skipped_events", 0) - diagnostics = compact_parser_diagnostics(stats) + diagnostics = { + **compact_parser_diagnostics(stats), + **{key: value for key, value in otel_diagnostics.items() if value}, + } record_refresh_metadata( db_path=db_path, scanned_files=scanned_files, @@ -141,6 +176,7 @@ def _finalize_refresh_result( skipped_events=skipped_events, inserted_or_updated_events=inserted, parser_diagnostics=diagnostics, + otel_diagnostics=otel_diagnostics, parsed_source_files=parsed_source_files, skipped_source_files=scanned_files - parsed_source_files, ) @@ -154,17 +190,39 @@ def _finalize_refresh_result( ) +def _refresh_otel_completions(*, db_path: Path, otel_dir: Path) -> dict[str, int]: + with connect(db_path) as conn: + init_db(conn) + ingest = ingest_otel_completion_files(conn, otel_dir) + reconciled = reconcile_otel_completions(conn) + if reconciled.updated_usage_rows: + touch_compression_revisions(conn, {"calls", "threads"}) + counters = { + "otel_files_scanned": ingest.files_scanned, + "otel_imported": ingest.imported, + "otel_duplicates": ingest.duplicates, + "otel_matched": reconciled.matched, + "otel_pending": reconciled.pending, + "otel_ambiguous": reconciled.ambiguous, + "otel_conflicts": reconciled.conflicts, + **ingest.diagnostics, + } + return {key: int(counters.get(key, 0)) for key in OTEL_REFRESH_COUNTER_KEYS} + + def rebuild_usage_index( codex_home: Path = DEFAULT_CODEX_HOME, db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, + otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: """Clear aggregate rows and rescan local Codex logs.""" with connect(db_path) as conn: init_db(conn) + reset_otel_completion_matches(conn) clear_content_index_rows(conn) for table in ( "allowance_observations", @@ -183,5 +241,6 @@ def rebuild_usage_index( db_path=db_path, include_archived=include_archived, aggregate_only=aggregate_only, + otel_dir=otel_dir, derived_fact_sync=derived_fact_sync, ) diff --git a/tests/core/test_api_payloads.py b/tests/core/test_api_payloads.py new file mode 100644 index 00000000..35b444ca --- /dev/null +++ b/tests/core/test_api_payloads.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from codex_usage_tracker.core.api_payloads import refresh_result_payload +from codex_usage_tracker.core.models import RefreshResult + + +def test_refresh_payload_preserves_nonzero_otel_diagnostics() -> None: + result = RefreshResult( + scanned_files=1, + parsed_events=1, + inserted_or_updated_events=1, + db_path="/synthetic/usage.sqlite3", + parser_diagnostics={"otel_matched": 1}, + ) + + payload = refresh_result_payload(result, schema="synthetic-refresh-v1") + + assert payload["parser_diagnostics"] == {"otel_matched": 1} diff --git a/tests/otel_helpers.py b/tests/otel_helpers.py index 0632aeee..01dcd854 100644 --- a/tests/otel_helpers.py +++ b/tests/otel_helpers.py @@ -160,6 +160,74 @@ def synthetic_usage_event( ) +def write_usage_session( + tmp_path: Path, + conversation_id: str, + tokens: tuple[int, int, int, int], +) -> Path: + input_tokens, cached_tokens, output_tokens, reasoning_tokens = tokens + total_tokens = input_tokens + output_tokens + codex_home = tmp_path / "codex" + log_path = codex_home / "sessions" / "2026" / "07" / "16" / "synthetic.jsonl" + rows = [ + { + "timestamp": "2026-07-16T00:00:00.000Z", + "type": "session_meta", + "payload": {"id": conversation_id}, + }, + { + "timestamp": "2026-07-16T00:00:01.000Z", + "type": "event_msg", + "payload": { + "type": "token_count", + "info": { + "total_token_usage": { + "input_tokens": input_tokens, + "cached_input_tokens": cached_tokens, + "output_tokens": output_tokens, + "reasoning_output_tokens": reasoning_tokens, + "total_tokens": total_tokens, + }, + "last_token_usage": { + "input_tokens": input_tokens, + "cached_input_tokens": cached_tokens, + "output_tokens": output_tokens, + "reasoning_output_tokens": reasoning_tokens, + "total_tokens": total_tokens, + }, + "model_context_window": 258_400, + }, + }, + }, + ] + log_path.parent.mkdir(parents=True, exist_ok=True) + log_path.write_text( + "".join(json.dumps(row) + "\n" for row in rows), encoding="utf-8" + ) + return codex_home + + +def write_otel_directory( + tmp_path: Path, + conversation_id: str, + tokens: tuple[int, int, int, int], +) -> Path: + directory = tmp_path / "otel" + write_lines( + directory / "codex-completions.jsonl", + [ + synthetic_otlp_line( + attributes=completion_attributes( + conversation_id=conversation_id, + tokens=tokens, + service_tier="priority", + ) + ) + ], + ) + return directory + + def write_lines(path: Path, lines: list[str]) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text("".join(f"{line}\n" for line in lines), encoding="utf-8") diff --git a/tests/reports/test_support.py b/tests/reports/test_support.py index 7eb5aa46..023d919f 100644 --- a/tests/reports/test_support.py +++ b/tests/reports/test_support.py @@ -119,6 +119,19 @@ def test_support_bundle_strict_mode_redacts_local_paths_and_doctor_text( assert raw_path not in bundle_text +def test_support_bundle_exposes_counts_without_otel_identifiers(tmp_path: Path) -> None: + payload = support_bundle_payload( + db_path=tmp_path / "usage.sqlite3", codex_home=tmp_path / "codex" + ) + encoded = json.dumps(payload, sort_keys=True) + otel_encoded = json.dumps(payload["otel"], sort_keys=True) + + assert payload["otel"]["completion_directory_exists"] in {True, False} + assert "conversation-a" not in encoded + assert "fingerprint" not in otel_encoded + assert "source_path" not in otel_encoded + + def _make_support_fixture(tmp_path: Path) -> dict[str, Path]: codex_home = tmp_path / ".codex" db_path = tmp_path / "usage.sqlite3" diff --git a/tests/store/test_otel_reconciliation.py b/tests/store/test_otel_reconciliation.py index 18fef871..b9ac904e 100644 --- a/tests/store/test_otel_reconciliation.py +++ b/tests/store/test_otel_reconciliation.py @@ -265,4 +265,5 @@ def test_matched_rows_are_idempotent_and_can_be_reset_for_rebuild(tmp_path: Path assert first.matched == 1 assert second.matched == 1 + assert second.updated_usage_rows == 0 assert tuple(state) == ("pending", None) diff --git a/tests/store/test_otel_refresh.py b/tests/store/test_otel_refresh.py new file mode 100644 index 00000000..a1db5ef4 --- /dev/null +++ b/tests/store/test_otel_refresh.py @@ -0,0 +1,171 @@ +from __future__ import annotations + +from pathlib import Path + +from codex_usage_tracker.store.api import ( + query_usage_record, + rebuild_usage_index, + refresh_metadata, + refresh_usage_index, +) +from codex_usage_tracker.store.connection import connect +from tests.otel_helpers import ( + completion_attributes, + synthetic_otlp_line, + write_lines, + write_otel_directory, + write_usage_session, +) + + +def test_refresh_ingests_session_rows_before_reconciling_otel(tmp_path: Path) -> None: + codex_home = write_usage_session( + tmp_path, conversation_id="conversation-a", tokens=(100, 40, 30, 10) + ) + otel_dir = tmp_path / "otel" + write_lines( + otel_dir / "codex-completions.jsonl", + [ + synthetic_otlp_line( + attributes=completion_attributes( + conversation_id="conversation-a", + tokens=(100, 40, 30, 10), + service_tier="priority", + ) + ) + ], + ) + db_path = tmp_path / "usage.sqlite3" + + result = refresh_usage_index( + codex_home=codex_home, db_path=db_path, otel_dir=otel_dir + ) + + with connect(db_path) as conn: + record_id = str(conn.execute("SELECT record_id FROM usage_events").fetchone()[0]) + row = query_usage_record(db_path=db_path, record_id=record_id) + assert row is not None + assert row["service_tier"] == "fast" + assert result.parser_diagnostics["otel_matched"] == 1 + + +def test_absent_otel_directory_is_a_supported_noop(tmp_path: Path) -> None: + result = refresh_usage_index( + codex_home=tmp_path / "codex", + db_path=tmp_path / "usage.sqlite3", + otel_dir=tmp_path / "missing", + ) + + assert result.parser_diagnostics.get("otel_files_scanned", 0) == 0 + + +def test_refresh_records_protocol_confirmed_standard(tmp_path: Path) -> None: + codex_home = write_usage_session( + tmp_path, "conversation-standard", (100, 40, 30, 10) + ) + otel_dir = tmp_path / "otel" + write_lines( + otel_dir / "codex-completions.jsonl", + [ + synthetic_otlp_line( + attributes=completion_attributes( + conversation_id="conversation-standard", + tokens=(100, 40, 30, 10), + service_tier=None, + app_version="0.143.0", + ) + ) + ], + ) + db_path = tmp_path / "usage.sqlite3" + + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + + with connect(db_path) as conn: + row = conn.execute( + "SELECT service_tier, fast, service_tier_confidence FROM usage_events" + ).fetchone() + assert tuple(row) == ("standard", 0, "protocol") + + +def test_refresh_keeps_older_omitted_tier_unknown(tmp_path: Path) -> None: + codex_home = write_usage_session( + tmp_path, "conversation-legacy", (100, 40, 30, 10) + ) + otel_dir = tmp_path / "otel" + write_lines( + otel_dir / "codex-completions.jsonl", + [ + synthetic_otlp_line( + attributes=completion_attributes( + conversation_id="conversation-legacy", + tokens=(100, 40, 30, 10), + service_tier=None, + app_version="0.142.9", + ) + ) + ], + ) + db_path = tmp_path / "usage.sqlite3" + + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + + with connect(db_path) as conn: + row = conn.execute("SELECT service_tier, fast FROM usage_events").fetchone() + assert tuple(row) == (None, None) + + +def test_otel_before_jsonl_matches_on_a_later_refresh(tmp_path: Path) -> None: + otel_dir = write_otel_directory( + tmp_path, "conversation-a", (100, 40, 30, 10) + ) + db_path = tmp_path / "usage.sqlite3" + refresh_usage_index( + codex_home=tmp_path / "empty", db_path=db_path, otel_dir=otel_dir + ) + codex_home = write_usage_session( + tmp_path, "conversation-a", (100, 40, 30, 10) + ) + + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + + with connect(db_path) as conn: + assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "fast" + + +def test_rebuild_retains_staging_resets_match_pointer_and_reapplies_tier( + tmp_path: Path, +) -> None: + codex_home = write_usage_session( + tmp_path, "conversation-a", (100, 40, 30, 10) + ) + otel_dir = write_otel_directory( + tmp_path, "conversation-a", (100, 40, 30, 10) + ) + db_path = tmp_path / "usage.sqlite3" + refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + + rebuild_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) + + with connect(db_path) as conn: + assert conn.execute("SELECT COUNT(*) FROM otel_completion_events").fetchone()[0] == 1 + assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "fast" + state = conn.execute( + "SELECT match_status, matched_record_id FROM otel_completion_events" + ).fetchone() + assert state["match_status"] == "matched" + assert state["matched_record_id"] is not None + + +def test_refresh_persists_all_bounded_otel_metadata_counters(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + + refresh_usage_index( + codex_home=tmp_path / "codex", + db_path=db_path, + otel_dir=tmp_path / "missing", + ) + + metadata = refresh_metadata(db_path) + assert metadata["otel_files_scanned"] == "0" + assert metadata["otel_invalid_json"] == "0" From 55a914abed48bbfddb64f5f226d4d656f218782f Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:50:04 -0400 Subject: [PATCH 08/24] feat: price confirmed Fast credit usage --- src/codex_usage_tracker/pricing/allowance.py | 2 + .../pricing/allowance_usage.py | 26 +++- src/codex_usage_tracker/pricing/fast_tier.py | 37 ++++++ src/codex_usage_tracker/usage_drain/spans.py | 7 +- src/codex_usage_tracker/usage_drain/types.py | 17 +-- tests/pricing/test_allowance.py | 118 ++++++++++++++++++ tests/pricing/test_pricing.py | 38 ++++++ tests/usage_drain/test_usage_drain_model.py | 12 ++ 8 files changed, 242 insertions(+), 15 deletions(-) create mode 100644 src/codex_usage_tracker/pricing/fast_tier.py diff --git a/src/codex_usage_tracker/pricing/allowance.py b/src/codex_usage_tracker/pricing/allowance.py index c4d18cf3..dd893f87 100644 --- a/src/codex_usage_tracker/pricing/allowance.py +++ b/src/codex_usage_tracker/pricing/allowance.py @@ -29,6 +29,7 @@ ) from codex_usage_tracker.pricing.allowance_usage import ( annotate_rows_with_allowance, + estimate_standard_usage_credits, estimate_usage_credits, resolve_credit_rate, summarize_allowance_usage, @@ -45,6 +46,7 @@ "UsageAllowanceConfig", "RateCardUpdateResult", "annotate_rows_with_allowance", + "estimate_standard_usage_credits", "estimate_usage_credits", "load_allowance_config", "load_bundled_rate_card", diff --git a/src/codex_usage_tracker/pricing/allowance_usage.py b/src/codex_usage_tracker/pricing/allowance_usage.py index 2209f604..4ed41ec4 100644 --- a/src/codex_usage_tracker/pricing/allowance_usage.py +++ b/src/codex_usage_tracker/pricing/allowance_usage.py @@ -17,9 +17,11 @@ number_value, optional_str, ) +from codex_usage_tracker.pricing.fast_tier import credit_multiplier_for_row __all__ = ( "annotate_rows_with_allowance", + "estimate_standard_usage_credits", "estimate_usage_credits", "resolve_credit_rate", "summarize_allowance_usage", @@ -41,10 +43,14 @@ def annotate_rows_with_allowance( copy = dict(row) model = copy.get(model_field) match = resolve_credit_rate(model, resolved) + multiplier, multiplier_source = credit_multiplier_for_row(copy) if match is None: copy.update( { "usage_credits": None, + "standard_usage_credits": None, + "usage_credit_multiplier": multiplier, + "usage_credit_multiplier_source": multiplier_source, "usage_credit_model": None, "usage_credit_confidence": "unpriced", "usage_credit_source": "No Codex credit rate", @@ -56,9 +62,13 @@ def annotate_rows_with_allowance( ) else: rated_model, rates, confidence, note, metadata = match + standard_credits = estimate_standard_usage_credits(copy, rates) copy.update( { - "usage_credits": estimate_usage_credits(copy, rates), + "usage_credits": standard_credits * multiplier, + "standard_usage_credits": standard_credits, + "usage_credit_multiplier": multiplier, + "usage_credit_multiplier_source": multiplier_source, "usage_credit_model": rated_model, "usage_credit_confidence": confidence, "usage_credit_source": metadata.get("source_name") @@ -185,8 +195,10 @@ def _resolve_alias_credit_rate( return target, rates, confidence, note, metadata -def estimate_usage_credits(row: dict[str, Any], rates: dict[str, float]) -> float: - """Estimate Codex credits from aggregate token counters.""" +def estimate_standard_usage_credits( + row: dict[str, Any], rates: dict[str, float] +) -> float: + """Estimate Standard-tier Codex credits from aggregate token counters.""" input_rate = rates["input_per_million"] cached_rate = rates["cached_input_per_million"] @@ -199,3 +211,11 @@ def estimate_usage_credits(row: dict[str, Any], rates: dict[str, float]) -> floa return ( (uncached_input * input_rate) + (cached_input * cached_rate) + (output_tokens * output_rate) ) / 1_000_000 + + +def estimate_usage_credits(row: dict[str, Any], rates: dict[str, float]) -> float: + """Estimate effective Codex credits, including confirmed Fast multipliers.""" + + standard = estimate_standard_usage_credits(row, rates) + multiplier, _source = credit_multiplier_for_row(row) + return standard * multiplier diff --git a/src/codex_usage_tracker/pricing/fast_tier.py b/src/codex_usage_tracker/pricing/fast_tier.py new file mode 100644 index 00000000..de8f4d67 --- /dev/null +++ b/src/codex_usage_tracker/pricing/fast_tier.py @@ -0,0 +1,37 @@ +"""Documented Codex Fast credit multipliers for exact-tier accounting.""" + +from __future__ import annotations + +from collections.abc import Mapping + +DOCUMENTED_FAST_CREDIT_MULTIPLIERS = { + "gpt-5.6": 2.5, + "gpt-5.5": 2.5, + "gpt-5.4": 2.0, +} + + +def documented_fast_credit_multiplier(model: object) -> float | None: + """Return the documented Fast multiplier for a model family label.""" + + normalized = str(model or "").strip().lower() + for family, multiplier in DOCUMENTED_FAST_CREDIT_MULTIPLIERS.items(): + if ( + normalized == family + or normalized.startswith(f"{family}-") + or normalized.startswith(f"{family} ") + ): + return multiplier + return None + + +def credit_multiplier_for_row(row: Mapping[str, object]) -> tuple[float, str]: + """Return an effective credit multiplier and bounded provenance label.""" + + if row.get("fast") != 1: + fallback = "confirmed_standard" if row.get("fast") == 0 else "tier_unknown" + return 1.0, str(row.get("service_tier_source") or fallback) + multiplier = documented_fast_credit_multiplier(row.get("model")) + if multiplier is None: + return 1.0, "no_documented_fast_multiplier" + return multiplier, str(row.get("service_tier_source") or "confirmed_fast") diff --git a/src/codex_usage_tracker/usage_drain/spans.py b/src/codex_usage_tracker/usage_drain/spans.py index 6bd3d7d9..3b3f1023 100644 --- a/src/codex_usage_tracker/usage_drain/spans.py +++ b/src/codex_usage_tracker/usage_drain/spans.py @@ -337,7 +337,12 @@ def _span_from_rows( token_totals: dict[str, float] = dict.fromkeys(TOKEN_TOTAL_FIELDS, 0.0) timing_totals: dict[str, float] = dict.fromkeys(TIMING_TOTAL_FIELDS, 0.0) for row in rows: - credits = max(_span_number(row.get("usage_credits")), 0.0) + credit_field = ( + "standard_usage_credits" + if "standard_usage_credits" in row + else "usage_credits" + ) + credits = max(_span_number(row.get(credit_field)), 0.0) standard += credits _add_span_row_dimensions( row, diff --git a/src/codex_usage_tracker/usage_drain/types.py b/src/codex_usage_tracker/usage_drain/types.py index 87088c09..7f7a2e21 100644 --- a/src/codex_usage_tracker/usage_drain/types.py +++ b/src/codex_usage_tracker/usage_drain/types.py @@ -5,10 +5,12 @@ from dataclasses import asdict, dataclass, field from typing import Any -DOCUMENTED_FAST_CREDIT_MULTIPLIERS = { - "gpt-5.5": 2.5, - "gpt-5.4": 2.0, -} +from codex_usage_tracker.pricing.fast_tier import ( + DOCUMENTED_FAST_CREDIT_MULTIPLIERS as DOCUMENTED_FAST_CREDIT_MULTIPLIERS, +) +from codex_usage_tracker.pricing.fast_tier import ( + documented_fast_credit_multiplier as documented_fast_credit_multiplier, +) DEFAULT_PROXY_NAMES = ( "all_candidates", @@ -177,10 +179,3 @@ class PredictiveModelSpec: numeric_features: tuple[str, ...] categorical_features: tuple[str, ...] = () ridge_alpha: float = 1.0 - - -def documented_fast_credit_multiplier(model: object) -> float | None: - """Return the documented fast-mode credit multiplier for a model label.""" - - normalized = str(model or "").strip().lower() - return DOCUMENTED_FAST_CREDIT_MULTIPLIERS.get(normalized) diff --git a/tests/pricing/test_allowance.py b/tests/pricing/test_allowance.py index 3be25758..064bad2e 100644 --- a/tests/pricing/test_allowance.py +++ b/tests/pricing/test_allowance.py @@ -3,7 +3,10 @@ import json from pathlib import Path +import pytest + from codex_usage_tracker.pricing.allowance import ( + UsageAllowanceConfig, annotate_rows_with_allowance, load_allowance_config, parse_allowance_text, @@ -13,6 +16,121 @@ ) +def _credit_row( + *, model: str, fast: int | None, service_tier: str | None +) -> dict[str, object]: + return { + "model": model, + "input_tokens": 100, + "cached_input_tokens": 20, + "uncached_input_tokens": 80, + "output_tokens": 10, + "total_tokens": 110, + "fast": fast, + "service_tier": service_tier, + "service_tier_source": "otel_response_completed" if fast is not None else None, + "service_tier_confidence": "exact" if fast is not None else None, + } + + +def _synthetic_allowance_config() -> UsageAllowanceConfig: + rates = { + "input_per_million": 10.0, + "cached_input_per_million": 1.0, + "output_per_million": 50.0, + } + models = ( + "gpt-5.6", + "gpt-5.6-sol", + "gpt-5.5", + "gpt-5.4", + "synthetic-unknown", + ) + return UsageAllowanceConfig( + path=Path("/synthetic/allowance.json"), + rate_card_path=Path("/synthetic/rate-card.json"), + credit_rates={model: dict(rates) for model in models}, + aliases={}, + rate_metadata={model: {} for model in models}, + alias_metadata={}, + windows=[], + loaded=True, + rate_card_loaded=True, + source={"name": "Synthetic credit rates"}, + ) + + +@pytest.mark.parametrize( + ("model", "multiplier"), + [ + ("gpt-5.6", 2.5), + ("gpt-5.6-sol", 2.5), + ("gpt-5.5", 2.5), + ("gpt-5.4", 2.0), + ], +) +def test_confirmed_fast_multiplies_standard_credit_estimate( + model: str, multiplier: float +) -> None: + row = _credit_row(model=model, fast=1, service_tier="fast") + + annotated = annotate_rows_with_allowance( + [row], _synthetic_allowance_config() + )[0] + + assert annotated["usage_credits"] == pytest.approx( + annotated["standard_usage_credits"] * multiplier + ) + assert annotated["usage_credit_multiplier"] == multiplier + assert annotated["usage_credit_multiplier_source"] == "otel_response_completed" + + +@pytest.mark.parametrize("fast", [0, None]) +def test_standard_and_unknown_rows_keep_multiplier_one(fast: int | None) -> None: + row = _credit_row( + model="gpt-5.6", + fast=fast, + service_tier="standard" if fast == 0 else None, + ) + + annotated = annotate_rows_with_allowance( + [row], _synthetic_allowance_config() + )[0] + + assert annotated["usage_credits"] == annotated["standard_usage_credits"] + assert annotated["usage_credit_multiplier"] == 1.0 + + +def test_confirmed_fast_unknown_model_does_not_invent_multiplier() -> None: + row = _credit_row(model="synthetic-unknown", fast=1, service_tier="fast") + + annotated = annotate_rows_with_allowance( + [row], _synthetic_allowance_config() + )[0] + + assert annotated["usage_credit_multiplier"] == 1.0 + assert ( + annotated["usage_credit_multiplier_source"] + == "no_documented_fast_multiplier" + ) + + +def test_unpriced_rows_include_bounded_multiplier_annotations() -> None: + row = _credit_row(model="not-in-rate-card", fast=1, service_tier="fast") + + annotated = annotate_rows_with_allowance( + [row], _synthetic_allowance_config() + )[0] + + assert annotated["usage_credits"] is None + assert annotated["standard_usage_credits"] is None + assert annotated["usage_credit_multiplier"] == 1.0 + assert ( + annotated["usage_credit_multiplier_source"] + == "no_documented_fast_multiplier" + ) + + def test_allowance_estimates_exact_codex_credit_usage() -> None: rows = annotate_rows_with_allowance( [ diff --git a/tests/pricing/test_pricing.py b/tests/pricing/test_pricing.py index 6f9e4f9c..74f9a01e 100644 --- a/tests/pricing/test_pricing.py +++ b/tests/pricing/test_pricing.py @@ -11,6 +11,7 @@ OPENAI_LATEST_MODEL_MD_URL, OPENAI_PRICING_MD_URL, PRICING_SCHEMA, + PricingConfig, PricingParseError, annotate_rows_with_efficiency, efficiency_flags, @@ -45,6 +46,43 @@ """ +def test_service_tier_does_not_change_estimated_cost_usd() -> None: + pricing = PricingConfig( + path=Path("/synthetic/pricing.json"), + models={ + "gpt-5.6": { + "input_per_million": 10.0, + "cached_input_per_million": 1.0, + "output_per_million": 50.0, + } + }, + loaded=True, + ) + row = _credit_row_for_cost(fast=0, service_tier="standard") + + standard = estimate_cost_usd(row, pricing) + fast = estimate_cost_usd( + {**row, "fast": 1, "service_tier": "fast"}, pricing + ) + + assert fast == standard + + +def _credit_row_for_cost( + *, fast: int | None, service_tier: str | None +) -> dict[str, object]: + return { + "record_id": "synthetic-call", + "model": "gpt-5.6", + "input_tokens": 100, + "cached_input_tokens": 20, + "uncached_input_tokens": 80, + "output_tokens": 10, + "fast": fast, + "service_tier": service_tier, + } + + def test_pricing_fetch_rejects_non_https_sources() -> None: with pytest.raises(ValueError, match="must use HTTPS"): pricing_openai._fetch_text("file:///tmp/pricing.md") diff --git a/tests/usage_drain/test_usage_drain_model.py b/tests/usage_drain/test_usage_drain_model.py index 789a1bfb..f5b59e9f 100644 --- a/tests/usage_drain/test_usage_drain_model.py +++ b/tests/usage_drain/test_usage_drain_model.py @@ -13,6 +13,7 @@ load_fast_proxy_annotations, summarize_usage_drain_model, ) +from codex_usage_tracker.usage_drain.spans import _span_from_rows from tests.usage_drain.model_test_helpers import ( coefficients_by_feature as _coefficients_by_feature, ) @@ -147,6 +148,17 @@ def test_alternate_codex_limit_rows_count_as_work_but_not_boundaries() -> None: assert spans[0].rate_limit_limit_id == "codex" +def test_usage_drain_prefers_standard_credits_after_fast_annotation() -> None: + row = _row("fast", "2026-06-01T00:00:00Z", 1.0, 2.5) + row["standard_usage_credits"] = 1.0 + + span = _span_from_rows( + [row], baseline_percent=0.0, end_used_percent=1.0, proxies={} + ) + + assert span.standard_usage_credits == 1.0 + + def test_build_usage_delta_spans_prefers_five_hour_window_when_secondary() -> None: rows = [ _row( From 5779126315a6192c0792bc27be10e6d378204ff7 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:57:01 -0400 Subject: [PATCH 09/24] feat: show exact Fast tiers in Calls --- frontend/dashboard/src/api/client.test.ts | 16 +++++- frontend/dashboard/src/api/client.ts | 15 +++++- frontend/dashboard/src/api/modelInsights.ts | 2 +- frontend/dashboard/src/api/types.ts | 16 +++++- .../CallInvestigatorPage.tsx | 3 +- .../src/features/calls/CallInspector.tsx | 3 +- .../src/features/calls/serviceTier.test.ts | 30 +++++++++++ .../src/features/calls/serviceTier.ts | 16 ++++++ .../src/features/reports/reportModel.ts | 2 +- .../src/features/shared/tables.test.ts | 16 ++++++ .../dashboard/src/features/shared/tables.tsx | 19 +++++++ .../src/test-fixtures/dashboardFixture.ts | 9 +++- .../plugin_data/dashboard/react/assets/App.js | 50 +++++++++---------- .../react/assets/CallInvestigatorPage.js | 4 +- .../dashboard/react/assets/CallsPage.js | 8 +-- .../dashboard/react/assets/ReportsPage.js | 2 +- .../dashboard/react/assets/SettingsPage.js | 2 +- .../dashboard/react/assets/dashboardRouter.js | 2 +- .../dashboard/react/assets/useBaseQuery.js | 2 +- .../react/assets/useInfiniteQuery.js | 2 +- tests/dashboard/test_dashboard_payload.py | 20 ++++++++ tests/server/test_server_call_detail.py | 23 +++++++++ tests/store/test_content_query_exports.py | 32 ++++++++++++ 23 files changed, 250 insertions(+), 44 deletions(-) create mode 100644 frontend/dashboard/src/features/calls/serviceTier.test.ts create mode 100644 frontend/dashboard/src/features/calls/serviceTier.ts diff --git a/frontend/dashboard/src/api/client.test.ts b/frontend/dashboard/src/api/client.test.ts index 66653ee1..3636817c 100644 --- a/frontend/dashboard/src/api/client.test.ts +++ b/frontend/dashboard/src/api/client.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; -import { loadUsagePayload, modelFromBootPayload } from './client'; +import { loadUsagePayload, modelFromBootPayload, usageRowToCall } from './client'; import type { DashboardBootPayload } from './types'; afterEach(() => { @@ -8,6 +8,20 @@ afterEach(() => { }); describe('dashboard API model builder', () => { + it('keeps exact tier separate from throughput proxy', () => { + const call = usageRowToCall({ + service_tier: 'standard', + fast: 0, + service_tier_confidence: 'protocol', + duration_seconds: 1, + total_tokens: 9000, + }, 0); + + expect(call.fast).toBe(false); + expect(call.fastProxyCandidate).toBe(true); + expect(call.serviceTier).toBe('standard'); + }); + it('derives model cost bars from live aggregate rows', () => { const payload: DashboardBootPayload = { loaded_row_count: 3, diff --git a/frontend/dashboard/src/api/client.ts b/frontend/dashboard/src/api/client.ts index 3109e355..33006929 100644 --- a/frontend/dashboard/src/api/client.ts +++ b/frontend/dashboard/src/api/client.ts @@ -537,6 +537,12 @@ export function usageRowToCall(row: UsageRow, index = 0): CallRow { const contextWindowPct = percentNumber(row.context_window_percent); const modelContextWindow = Number(row.model_context_window); const cumulativeTotalTokens = Number(row.cumulative_total_tokens); + const rawFast = row.fast; + const exactFast = rawFast === true || rawFast === 1 + ? true + : rawFast === false || rawFast === 0 + ? false + : null; return { id, @@ -565,7 +571,14 @@ export function usageRowToCall(row: UsageRow, index = 0): CallRow { initiator: String(row.call_initiator ?? 'unknown'), initiatorReason: String(row.call_initiator_reason ?? ''), initiatorConfidence: String(row.call_initiator_confidence ?? ''), - fast: durationSeconds > 0 && totalTokens / Math.max(durationSeconds, 1) > 4_000, + serviceTier: String(row.service_tier ?? ''), + fast: exactFast, + serviceTierSource: String(row.service_tier_source ?? ''), + serviceTierConfidence: String(row.service_tier_confidence ?? ''), + fastProxyCandidate: durationSeconds > 0 && totalTokens / Math.max(durationSeconds, 1) > 4_000, + standardUsageCredits: Number(row.standard_usage_credits ?? row.usage_credits ?? 0), + usageCreditMultiplier: Number(row.usage_credit_multiplier ?? 1), + usageCreditMultiplierSource: String(row.usage_credit_multiplier_source ?? ''), usageCreditConfidence: String(row.usage_credit_confidence ?? 'unknown'), usageCreditModel: String(row.usage_credit_model ?? ''), usageCreditSource: String(row.usage_credit_source ?? ''), diff --git a/frontend/dashboard/src/api/modelInsights.ts b/frontend/dashboard/src/api/modelInsights.ts index 14678abb..b86a68f0 100644 --- a/frontend/dashboard/src/api/modelInsights.ts +++ b/frontend/dashboard/src/api/modelInsights.ts @@ -52,7 +52,7 @@ export function buildReports(calls: CallRow[]): ReportSummary[] { description: 'Highest estimated credit-impact calls from loaded aggregate rows.', }, ]; - if (calls.some(call => call.fast || call.effort.toLowerCase() === 'low')) { + if (calls.some(call => call.fastProxyCandidate || call.effort.toLowerCase() === 'low')) { reports.push({ title: 'Fast Mode Proxy', status: 'Ready', diff --git a/frontend/dashboard/src/api/types.ts b/frontend/dashboard/src/api/types.ts index d86def01..8dc8460b 100644 --- a/frontend/dashboard/src/api/types.ts +++ b/frontend/dashboard/src/api/types.ts @@ -44,6 +44,13 @@ export type UsageRow = { uncached_input_tokens?: number; estimated_cost_usd?: number; usage_credits?: number; + standard_usage_credits?: number | null; + usage_credit_multiplier?: number | null; + usage_credit_multiplier_source?: string | null; + service_tier?: string | null; + fast?: number | boolean | null; + service_tier_source?: string | null; + service_tier_confidence?: string | null; rate_limit_plan_type?: string | null; rate_limit_limit_id?: string | null; rate_limit_primary_used_percent?: number | null; @@ -317,7 +324,14 @@ export type CallRow = { initiator: string; initiatorReason: string; initiatorConfidence: string; - fast: boolean; + serviceTier: string; + fast: boolean | null; + serviceTierSource: string; + serviceTierConfidence: string; + fastProxyCandidate: boolean; + standardUsageCredits: number; + usageCreditMultiplier: number; + usageCreditMultiplierSource: string; usageCreditConfidence: string; usageCreditModel: string; usageCreditSource: string; diff --git a/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx b/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx index 8fda4ace..7c248e7b 100644 --- a/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx +++ b/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx @@ -7,6 +7,7 @@ import { enableContextApi, loadCallContext, type ContextRequestOptions } from '. import type { CallContextEntry, CallContextPayload, CallRow, ContextRuntime, DashboardModel } from '../../api/types'; import { Panel } from '../../components/Panel'; import { StatusBadge } from '../../components/StatusBadge'; +import { serviceTierDetail } from '../calls/serviceTier'; import { CallCacheDelta } from '../shared/CallCacheDelta'; import { CallDecisionCard } from '../shared/CallDecisionCard'; import { ContextAttributionModule } from '../shared/ContextAttributionModule'; @@ -210,7 +211,7 @@ throw new Error('Clipboard unavailable'); - + diff --git a/frontend/dashboard/src/features/calls/CallInspector.tsx b/frontend/dashboard/src/features/calls/CallInspector.tsx index d1cb279b..bc045a4a 100644 --- a/frontend/dashboard/src/features/calls/CallInspector.tsx +++ b/frontend/dashboard/src/features/calls/CallInspector.tsx @@ -27,6 +27,7 @@ import { CallSignalPucks } from '../shared/tables'; import { compareCallTimeDescending } from './callsFilterSort'; import { CallContextEvidence } from './CallContextEvidence'; import { DetailRow, DrillMetric } from './CallDetailPrimitives'; +import { serviceTierDetail } from './serviceTier'; type DrillDownTab = 'summary' | 'tokens' | 'cache' | 'thread' | 'evidence'; @@ -166,7 +167,7 @@ function SummaryTab({ call }: { call: CallRow }) { - + diff --git a/frontend/dashboard/src/features/calls/serviceTier.test.ts b/frontend/dashboard/src/features/calls/serviceTier.test.ts new file mode 100644 index 00000000..03f2113c --- /dev/null +++ b/frontend/dashboard/src/features/calls/serviceTier.test.ts @@ -0,0 +1,30 @@ +import { describe, expect, it } from 'vitest'; + +import { usageRowToCall } from '../../api/client'; +import { serviceTierDetail, serviceTierLabel } from './serviceTier'; + +describe('service tier labels', () => { + it('shows protocol-confirmed Standard separately from the throughput proxy', () => { + const call = usageRowToCall({ + service_tier: 'standard', + fast: 0, + service_tier_source: 'otel_response_completed', + service_tier_confidence: 'protocol', + duration_seconds: 1, + total_tokens: 9000, + }); + + expect(serviceTierLabel(call)).toBe('Standard'); + expect(serviceTierDetail(call)).toBe('confirmed Standard · protocol'); + expect(call.fastProxyCandidate).toBe(true); + }); + + it('describes unknown tiers with the historical throughput proxy', () => { + const candidate = usageRowToCall({ duration_seconds: 1, total_tokens: 9000 }); + const normal = usageRowToCall({ duration_seconds: 10, total_tokens: 100 }); + + expect(serviceTierLabel(candidate)).toBe('Unknown'); + expect(serviceTierDetail(candidate)).toBe('tier unknown · Fast proxy candidate'); + expect(serviceTierDetail(normal)).toBe('tier unknown · normal throughput proxy'); + }); +}); diff --git a/frontend/dashboard/src/features/calls/serviceTier.ts b/frontend/dashboard/src/features/calls/serviceTier.ts new file mode 100644 index 00000000..eea43f7d --- /dev/null +++ b/frontend/dashboard/src/features/calls/serviceTier.ts @@ -0,0 +1,16 @@ +import type { CallRow } from '../../api/types'; + +export function serviceTierLabel(call: CallRow): 'Fast' | 'Standard' | 'Unknown' { + if (call.fast === true) return 'Fast'; + if (call.fast === false) return 'Standard'; + return 'Unknown'; +} + +export function serviceTierDetail(call: CallRow): string { + if (call.fast !== null) { + return `confirmed ${serviceTierLabel(call)} · ${call.serviceTierConfidence || 'exact'}`; + } + return call.fastProxyCandidate + ? 'tier unknown · Fast proxy candidate' + : 'tier unknown · normal throughput proxy'; +} diff --git a/frontend/dashboard/src/features/reports/reportModel.ts b/frontend/dashboard/src/features/reports/reportModel.ts index 6bea68d4..3e5173fd 100644 --- a/frontend/dashboard/src/features/reports/reportModel.ts +++ b/frontend/dashboard/src/features/reports/reportModel.ts @@ -45,7 +45,7 @@ export function reportEvidenceCalls(report: ReportView | undefined, calls: CallR const rows = [...calls]; if (text.includes('fast')) { return rows - .filter(call => call.fast || call.effort.toLowerCase() === 'low') + .filter(call => call.fastProxyCandidate || call.effort.toLowerCase() === 'low') .sort((left, right) => left.durationSeconds - right.durationSeconds || callCredits(right) - callCredits(left)) .slice(0, 8); } diff --git a/frontend/dashboard/src/features/shared/tables.test.ts b/frontend/dashboard/src/features/shared/tables.test.ts index 9c4d626f..6700c1a6 100644 --- a/frontend/dashboard/src/features/shared/tables.test.ts +++ b/frontend/dashboard/src/features/shared/tables.test.ts @@ -33,6 +33,13 @@ describe('call CSV columns', () => { initiatorReason: 'tool-driven continuation', initiatorConfidence: 'high', fast: false, + serviceTier: 'standard', + serviceTierSource: 'otel_response_completed', + serviceTierConfidence: 'protocol', + fastProxyCandidate: true, + standardUsageCredits: 4.5, + usageCreditMultiplier: 1, + usageCreditMultiplierSource: 'otel_response_completed', usageCreditConfidence: 'credit-estimated', usageCreditModel: 'codex-1', usageCreditSource: 'rate-card', @@ -88,6 +95,10 @@ describe('call CSV columns', () => { expect(header).toContain('previous_call_event_timestamp'); expect(header).toContain('pricing_model'); expect(header).toContain('usage_credit_confidence'); + expect(header).toContain('service_tier'); + expect(header).toContain('service_tier_confidence'); + expect(header).toContain('fast_proxy_candidate'); + expect(header).toContain('usage_credit_multiplier'); expect(header).toContain('thread_attachment'); expect(header).toContain('model_context_window'); expect(values).toContain('record-csv-1'); @@ -101,9 +112,14 @@ expect(header).toContain('model_context_window'); expect(values).toContain('2026-07-01T11:54:30Z'); expect(values).toContain('codex-1-pricing'); expect(values).toContain('credit-estimated'); + expect(values).toContain('otel_response_completed'); expect(values).toContain('spawned child'); expect(values).toContain('cache-drop|context-heavy'); }); + + it('includes an exact Service Tier column', () => { + expect(callColumns.some(column => column.id === 'serviceTier')).toBe(true); + }); }); describe('call table columns', () => { diff --git a/frontend/dashboard/src/features/shared/tables.tsx b/frontend/dashboard/src/features/shared/tables.tsx index ca9c3851..15a0e310 100644 --- a/frontend/dashboard/src/features/shared/tables.tsx +++ b/frontend/dashboard/src/features/shared/tables.tsx @@ -2,6 +2,7 @@ import type { ColumnDef } from '@tanstack/react-table'; import { useShellI18n } from '../../app/i18nContext'; import type { CallRow, ThreadRow } from '../../api/types'; import type { ColumnChoice } from '../../components/ColumnChooser'; +import { serviceTierLabel } from '../calls/serviceTier'; import type { CsvColumn } from './exportCsv'; import { formatCompact, formatNumber, money, pct } from './format'; @@ -71,6 +72,16 @@ export const callColumns: Array> = [ }, }, { accessorKey: 'duration', header: 'Duration' }, + { + id: 'serviceTier', + accessorFn: call => serviceTierLabel(call), + header: 'Service Tier', + cell: info => { + const label = String(info.getValue()); + const tone = label === 'Fast' ? 'green' : label === 'Standard' ? 'blue' : ''; + return {label}; + }, + }, { accessorKey: 'previousCallGap', header: 'Prev Gap', @@ -108,6 +119,14 @@ export const callCsvColumns: Array> = [ { header: 'reasoning_output_tokens', value: row => row.reasoningOutput }, { header: 'estimated_cost_usd', value: row => row.cost.toFixed(6) }, { header: 'usage_credits', value: row => row.credits.toFixed(6) }, + { header: 'standard_usage_credits', value: row => row.standardUsageCredits.toFixed(6) }, + { header: 'service_tier', value: row => row.serviceTier }, + { header: 'fast', value: row => row.fast === null ? '' : row.fast ? 1 : 0 }, + { header: 'service_tier_source', value: row => row.serviceTierSource }, + { header: 'service_tier_confidence', value: row => row.serviceTierConfidence }, + { header: 'fast_proxy_candidate', value: row => String(row.fastProxyCandidate) }, + { header: 'usage_credit_multiplier', value: row => row.usageCreditMultiplier }, + { header: 'usage_credit_multiplier_source', value: row => row.usageCreditMultiplierSource }, { header: 'cache_ratio', value: row => row.cachedPct.toFixed(2) }, { header: 'context_window_percent', value: row => row.contextWindowPct?.toFixed(2) ?? '' }, { header: 'pricing_model', value: row => row.pricingModel }, diff --git a/frontend/dashboard/src/test-fixtures/dashboardFixture.ts b/frontend/dashboard/src/test-fixtures/dashboardFixture.ts index a27c8057..77cf2ce1 100644 --- a/frontend/dashboard/src/test-fixtures/dashboardFixture.ts +++ b/frontend/dashboard/src/test-fixtures/dashboardFixture.ts @@ -150,7 +150,14 @@ export const fixtureModel: DashboardModel = { initiator: index % 3 === 0 ? 'user' : index % 3 === 1 ? 'assistant' : 'tool', initiatorReason: index % 3 === 0 ? 'direct user request' : index % 3 === 1 ? 'assistant follow-up' : 'tool-driven continuation', initiatorConfidence: index % 2 === 0 ? 'exact' : 'estimated', - fast: Boolean(fast), + serviceTier: '', + fast: null, + serviceTierSource: '', + serviceTierConfidence: '', + fastProxyCandidate: Boolean(fast), + standardUsageCredits: (index === 4 ? 0 : Number(cost)) * 25, + usageCreditMultiplier: 1, + usageCreditMultiplierSource: 'tier_unknown', usageCreditConfidence: index === 7 ? 'user_override' : index % 4 === 0 ? 'exact' : index % 4 === 1 ? 'estimated' : index % 4 === 2 ? 'missing' : 'fixture', usageCreditModel: index === 4 ? '' : `${model}-credits`, usageCreditSource: index === 4 ? '' : 'fixture-rate-card', diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js index f2ade763..aea09e6d 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js @@ -1,45 +1,45 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ThreadsPage.js","assets/dashboard-react.js","assets/index.css","assets/useInfiniteQuery.js","assets/useBaseQuery.js","assets/exploreQueries.js","assets/queryOptions.js","assets/infiniteQueryOptions.js","assets/ExploreWorkspaceSwitcher.js","assets/Primitives.js","assets/Primitives.css","assets/EvidenceGridControls.js","assets/router.js","assets/EvidenceGridControls.css","assets/filtering.js","assets/threadSummaryAdapter.js","assets/UsageConstellation.js","assets/triangle-alert.js","assets/UsageConstellation.css","assets/StatusBadge.js","assets/PageLoadProgress.js","assets/PageLoadProgress.css","assets/index2.js","assets/rowActionEvents.js","assets/search.js","assets/locale-zh-Hans.js","assets/dashboardRouter.js","assets/ThreadsPage.css","assets/CacheContextPage.js","assets/LineChart.js","assets/DataTable.js","assets/overviewQueries.js","assets/gauge.js","assets/Panel.js","assets/useQuery.js","assets/tableActions.js","assets/UsageDrainPage.js","assets/chevron-right.js","assets/shield-check.js","assets/UsageDrainPage.css","assets/DiagnosticsPage.js","assets/diagnosticsQueries.js","assets/ReportsPage.js","assets/ReportsPage.css","assets/CallsPage.js","assets/EvidenceGrid.js","assets/contextEvidenceState.js","assets/lock-keyhole.js","assets/CallsPage.css","assets/OverviewPage.js","assets/OverviewPage.css","assets/InvestigatorPage.js","assets/InvestigatorPage.css","assets/CompressionLabPage.js","assets/CompressionLabPage.css","assets/ExploreRoutePage.js","assets/ExploreRoutePage.css","assets/CallInvestigatorPage.js","assets/SettingsPage.js","assets/SettingsPage.css"])))=>i.map(i=>d[i]); -var qn=e=>{throw TypeError(e)};var Kt=(e,t,n)=>t.has(e)||qn("Cannot "+n);var l=(e,t,n)=>(Kt(e,t,"read from private field"),n?n.call(e):t.get(e)),P=(e,t,n)=>t.has(e)?qn("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),x=(e,t,n,a)=>(Kt(e,t,"write to private field"),a?a.call(e,n):t.set(e,n),n),V=(e,t,n)=>(Kt(e,t,"access private method"),n);var St=(e,t,n,a)=>({set _(r){x(e,t,r,n)},get _(){return l(e,t,a)}});import{r as C,j as c,_ as O}from"./dashboard-react.js";import{t as bs}from"./locale-zh-Hans.js";import{i as vs}from"./dashboardRouter.js";import{a9 as se}from"./router.js";/** +var Ka=e=>{throw TypeError(e)};var Kt=(e,t,a)=>t.has(e)||Ka("Cannot "+a);var l=(e,t,a)=>(Kt(e,t,"read from private field"),a?a.call(e):t.get(e)),j=(e,t,a)=>t.has(e)?Ka("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,a),k=(e,t,a,n)=>(Kt(e,t,"write to private field"),n?n.call(e,a):t.set(e,a),a),V=(e,t,a)=>(Kt(e,t,"access private method"),a);var St=(e,t,a,n)=>({set _(r){k(e,t,r,a)},get _(){return l(e,t,n)}});import{r as C,j as c,_ as O}from"./dashboard-react.js";import{t as bs}from"./locale-zh-Hans.js";import{i as ws}from"./dashboardRouter.js";import{a9 as se}from"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const ws=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),Na=(...e)=>e.filter((t,n,a)=>!!t&&t.trim()!==""&&a.indexOf(t)===n).join(" ").trim();/** + */const ys=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),Nn=(...e)=>e.filter((t,a,n)=>!!t&&t.trim()!==""&&n.indexOf(t)===a).join(" ").trim();/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */var ys={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** + */var _s={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const _s=C.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:n=2,absoluteStrokeWidth:a,className:r="",children:s,iconNode:i,...o},h)=>C.createElement("svg",{ref:h,...ys,width:t,height:t,stroke:e,strokeWidth:a?Number(n)*24/Number(t):n,className:Na("lucide",r),...o},[...i.map(([f,d])=>C.createElement(f,d)),...Array.isArray(s)?s:[s]]));/** + */const Ss=C.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:a=2,absoluteStrokeWidth:n,className:r="",children:s,iconNode:i,...o},h)=>C.createElement("svg",{ref:h,..._s,width:t,height:t,stroke:e,strokeWidth:n?Number(a)*24/Number(t):a,className:Nn("lucide",r),...o},[...i.map(([f,d])=>C.createElement(f,d)),...Array.isArray(s)?s:[s]]));/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const I=(e,t)=>{const n=C.forwardRef(({className:a,...r},s)=>C.createElement(_s,{ref:s,iconNode:t,className:Na(`lucide-${ws(e)}`,a),...r}));return n.displayName=`${e}`,n};/** + */const I=(e,t)=>{const a=C.forwardRef(({className:n,...r},s)=>C.createElement(Ss,{ref:s,iconNode:t,className:Nn(`lucide-${ys(e)}`,n),...r}));return a.displayName=`${e}`,a};/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ss=I("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);/** + */const Cs=I("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Cs=I("ArrowUp",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/** + */const xs=I("ArrowUp",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const xs=I("BookOpen",[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]]);/** + */const ks=I("BookOpen",[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const ks=I("Boxes",[["path",{d:"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z",key:"lc1i9w"}],["path",{d:"m7 16.5-4.74-2.85",key:"1o9zyk"}],["path",{d:"m7 16.5 5-3",key:"va8pkn"}],["path",{d:"M7 16.5v5.17",key:"jnp8gn"}],["path",{d:"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z",key:"8zsnat"}],["path",{d:"m17 16.5-5-3",key:"8arw3v"}],["path",{d:"m17 16.5 4.74-2.85",key:"8rfmw"}],["path",{d:"M17 16.5v5.17",key:"k6z78m"}],["path",{d:"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z",key:"1xygjf"}],["path",{d:"M12 8 7.26 5.15",key:"1vbdud"}],["path",{d:"m12 8 4.74-2.85",key:"3rx089"}],["path",{d:"M12 13.5V8",key:"1io7kd"}]]);/** + */const Ts=I("Boxes",[["path",{d:"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z",key:"lc1i9w"}],["path",{d:"m7 16.5-4.74-2.85",key:"1o9zyk"}],["path",{d:"m7 16.5 5-3",key:"va8pkn"}],["path",{d:"M7 16.5v5.17",key:"jnp8gn"}],["path",{d:"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z",key:"8zsnat"}],["path",{d:"m17 16.5-5-3",key:"8arw3v"}],["path",{d:"m17 16.5 4.74-2.85",key:"8rfmw"}],["path",{d:"M17 16.5v5.17",key:"k6z78m"}],["path",{d:"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z",key:"1xygjf"}],["path",{d:"M12 8 7.26 5.15",key:"1vbdud"}],["path",{d:"m12 8 4.74-2.85",key:"3rx089"}],["path",{d:"M12 13.5V8",key:"1io7kd"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. @@ -54,75 +54,75 @@ var qn=e=>{throw TypeError(e)};var Kt=(e,t,n)=>t.has(e)||qn("Cannot "+n);var l=( * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ts=I("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/** + */const Ms=I("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ms=I("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/** + */const Ps=I("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ps=I("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/** + */const js=I("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const js=I("FileText",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]]);/** + */const As=I("FileText",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const As=I("Filter",[["polygon",{points:"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3",key:"1yg77f"}]]);/** + */const Ns=I("Filter",[["polygon",{points:"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3",key:"1yg77f"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ns=I("FlaskConical",[["path",{d:"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2",key:"18mbvz"}],["path",{d:"M6.453 15h11.094",key:"3shlmq"}],["path",{d:"M8.5 2h7",key:"csnxdl"}]]);/** + */const Es=I("FlaskConical",[["path",{d:"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2",key:"18mbvz"}],["path",{d:"M6.453 15h11.094",key:"3shlmq"}],["path",{d:"M8.5 2h7",key:"csnxdl"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Es=I("House",[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"1d0kgt"}]]);/** + */const Ds=I("House",[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"1d0kgt"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ds=I("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** + */const Fs=I("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Fs=I("Settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/** + */const Is=I("Settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Is=I("ShieldAlert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);/** + */const $s=I("ShieldAlert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const $s=I("Table2",[["path",{d:"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18",key:"gugj83"}]]);/** + */const Os=I("Table2",[["path",{d:"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18",key:"gugj83"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Os=I("Terminal",[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]]);/** + */const Us=I("Terminal",[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Us=I("TimerReset",[["path",{d:"M10 2h4",key:"n1abiw"}],["path",{d:"M12 14v-4",key:"1evpnu"}],["path",{d:"M4 13a8 8 0 0 1 8-7 8 8 0 1 1-5.3 14L4 17.6",key:"1ts96g"}],["path",{d:"M9 17H4v5",key:"8t5av"}]]);/** + */const Vs=I("TimerReset",[["path",{d:"M10 2h4",key:"n1abiw"}],["path",{d:"M12 14v-4",key:"1evpnu"}],["path",{d:"M4 13a8 8 0 0 1 8-7 8 8 0 1 1-5.3 14L4 17.6",key:"1ts96g"}],["path",{d:"M9 17H4v5",key:"8t5av"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Vs=I("Workflow",[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2",key:"by2w9f"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4",key:"xkn7yn"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2",key:"1cgmvn"}]]);/** + */const Ks=I("Workflow",[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2",key:"by2w9f"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4",key:"xkn7yn"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2",key:"1cgmvn"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const un=I("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),Ea="codex-usage-dashboard-language",Ks={"button.back_to_dashboard":"Back to dashboard","button.clear":"Clear","button.copy_link":"Copy link","button.enable_context_loading":"Enable context loading","button.export_csv":"Export CSV","button.full_serialized_analysis":"Run full serialized analysis","button.hide_details":"Hide details","button.include_tool_output":"Include tool output","button.load_more":"Load more","button.load_older_context":"Load older entries","button.next_call":"Next call","button.no_char_limit":"No char limit","button.open_investigator":"Open investigator","button.previous_call":"Previous call","button.refresh":"Refresh","button.show_compaction_history":"Show compacted replacement","button.show_tool_output":"Show tool output","button.top":"Top","button.show_turn_evidence":"Show turn log evidence","badge.live":"Live","dashboard.eyebrow":"Local Codex analytics","dashboard.call_details":"Call Details","dashboard.title":"Usage Dashboard","dashboard.view.call":"Call Investigator","dashboard.view.calls":"Calls","dashboard.view.insights":"Overview","dashboard.view.overview":"Overview","dashboard.view.threads":"Threads","detail.next_action":"Next action","filter.search":"Search dashboard","filter.search_placeholder":"Search calls, threads, models, diagnostics...","language.label":"Language","nav.history":"History","nav.load":"Load","nav.live":"Live","option.active_sessions_only":"Active","option.all_history":"All history","status.paused":"Paused","status.static":"Static"},qs={overview:"dashboard.view.overview",calls:"dashboard.view.calls",call:"dashboard.view.call",threads:"dashboard.view.threads"};function jl(e,t){return typeof t=="string"?e.translateText(t):e.formatText(t.template,t.values)}function Da(e,t){const n=Fa(e),a=Ia(t,n),r=(e==null?void 0:e.translation_catalog)??{},s=r[a]??((e==null?void 0:e.language)===a?e==null?void 0:e.translations:void 0)??{},i=r.en??((e==null?void 0:e.language)==="en"?e.translations:void 0)??{},o={...Ks,...i,...s},h=Qs(i,s),f=Hs(i,s),d=n.find(p=>p.code===a),v=(d==null?void 0:d.dir)==="rtl"||!d&&(e==null?void 0:e.language_direction)==="rtl"?"rtl":"ltr",u=p=>a==="zh-Hans"?bs(p,h,f):h.get(p)??p;return{language:a,direction:v,languages:n,t:(p,g)=>o[p]??g??p,translateText:u,formatText:(p,g)=>u(p).replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu,(b,w)=>String(g[String(w)]??b)),navLabel:(p,g)=>{const b=qs[p];return b?o[b]??g:g}}}function Hs(e,t){const n=[];for(const[a,r]of Object.entries(e)){const s=t[a];if(!s||s===r||!r.includes("{"))continue;const i=[],o=[];let h=0;for(const f of r.matchAll(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu)){const d=f.index??h;o.push(Hn(r.slice(h,d))),o.push("(.+?)"),i.push(f[1]),h=d+f[0].length}o.push(Hn(r.slice(h))),n.push({pattern:new RegExp(`^${o.join("")}$`,"u"),placeholders:i,translatedTemplate:s})}return n.sort((a,r)=>r.translatedTemplate.length-a.translatedTemplate.length)}function Hn(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function Qs(e,t){const n=new Map;for(const[a,r]of Object.entries(e)){const s=t[a];s&&s!==r&&n.set(r,s)}return n}function Fa(e){var n;const t=((n=e==null?void 0:e.available_languages)==null?void 0:n.filter(a=>a.code))??[];return t.length?t:[{code:"en",english_name:"English",native_name:"English",dir:"ltr"}]}function Ws(e){return Ia(Bs()||(e==null?void 0:e.language)||"en",Fa(e))}function zs(e){var t;try{(t=window.localStorage)==null||t.setItem(Ea,e)}catch{}}function Bs(){var e;try{return((e=window.localStorage)==null?void 0:e.getItem(Ea))??""}catch{return""}}function Ia(e,t){if(new Set(t.map(s=>s.code)).has(e))return e;const a=e.toLowerCase(),r=t.find(s=>s.code.toLowerCase()===a);return(r==null?void 0:r.code)??"en"}const Gs=Da(null,"en"),$a=C.createContext(Gs);function Js({value:e,children:t}){return c.jsx($a.Provider,{value:e,children:t})}function Oa(){return C.useContext($a)}var Et=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Ne,ve,Be,xa,Zs=(xa=class extends Et{constructor(){super();P(this,Ne);P(this,ve);P(this,Be);x(this,Be,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t();return window.addEventListener("visibilitychange",n,!1),()=>{window.removeEventListener("visibilitychange",n)}}})}onSubscribe(){l(this,ve)||this.setEventListener(l(this,Be))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,ve))==null||t.call(this),x(this,ve,void 0))}setEventListener(t){var n;x(this,Be,t),(n=l(this,ve))==null||n.call(this),x(this,ve,t(a=>{typeof a=="boolean"?this.setFocused(a):this.onFocus()}))}setFocused(t){l(this,Ne)!==t&&(x(this,Ne,t),this.onFocus())}onFocus(){const t=this.isFocused();this.listeners.forEach(n=>{n(t)})}isFocused(){var t;return typeof l(this,Ne)=="boolean"?l(this,Ne):((t=globalThis.document)==null?void 0:t.visibilityState)!=="hidden"}},Ne=new WeakMap,ve=new WeakMap,Be=new WeakMap,xa),Ua=new Zs,Xs={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},we,ln,ka,Ys=(ka=class{constructor(){P(this,we,Xs);P(this,ln,!1)}setTimeoutProvider(e){x(this,we,e)}setTimeout(e,t){return l(this,we).setTimeout(e,t)}clearTimeout(e){l(this,we).clearTimeout(e)}setInterval(e,t){return l(this,we).setInterval(e,t)}clearInterval(e){l(this,we).clearInterval(e)}},we=new WeakMap,ln=new WeakMap,ka),Bt=new Ys;function ei(e){setTimeout(e,0)}var ti=typeof window>"u"||"Deno"in globalThis;function ne(){}function ni(e,t){return typeof e=="function"?e(t):e}function ai(e){return typeof e=="number"&&e>=0&&e!==1/0}function ri(e,t){return Math.max(e+(t||0)-Date.now(),0)}function Gt(e,t){return typeof e=="function"?e(t):e}function si(e,t){return typeof e=="function"?e(t):e}function Qn(e,t){const{type:n="all",exact:a,fetchStatus:r,predicate:s,queryKey:i,stale:o}=e;if(i){if(a){if(t.queryHash!==dn(i,t.options))return!1}else if(!ut(t.queryKey,i))return!1}if(n!=="all"){const h=t.isActive();if(n==="active"&&!h||n==="inactive"&&h)return!1}return!(typeof o=="boolean"&&t.isStale()!==o||r&&r!==t.state.fetchStatus||s&&!s(t))}function Wn(e,t){const{exact:n,status:a,predicate:r,mutationKey:s}=e;if(s){if(!t.options.mutationKey)return!1;if(n){if(lt(t.options.mutationKey)!==lt(s))return!1}else if(!ut(t.options.mutationKey,s))return!1}return!(a&&t.state.status!==a||r&&!r(t))}function dn(e,t){return((t==null?void 0:t.queryKeyHashFn)||lt)(e)}function lt(e){return JSON.stringify(e,(t,n)=>Jt(n)?Object.keys(n).sort().reduce((a,r)=>(a[r]=n[r],a),{}):n)}function ut(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="object"&&typeof t=="object"?Object.keys(t).every(n=>ut(e[n],t[n])):!1}var ii=Object.prototype.hasOwnProperty;function Va(e,t,n=0){if(e===t)return e;if(n>500)return t;const a=zn(e)&&zn(t);if(!a&&!(Jt(e)&&Jt(t)))return t;const s=(a?e:Object.keys(e)).length,i=a?t:Object.keys(t),o=i.length,h=a?new Array(o):{};let f=0;for(let d=0;d{Bt.setTimeout(t,e)})}function ci(e,t,n){return typeof n.structuralSharing=="function"?n.structuralSharing(e,t):n.structuralSharing!==!1?Va(e,t):t}function li(e,t,n=0){const a=[...e,t];return n&&a.length>n?a.slice(1):a}function ui(e,t,n=0){const a=[t,...e];return n&&a.length>n?a.slice(0,-1):a}var hn=Symbol();function Ka(e,t){return!e.queryFn&&(t!=null&&t.initialPromise)?()=>t.initialPromise:!e.queryFn||e.queryFn===hn?()=>Promise.reject(new Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function Nl(e,t){return typeof e=="function"?e(...t):!!e}function di(e,t,n){let a=!1,r;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(r??(r=t()),a||(a=!0,r.aborted?n():r.addEventListener("abort",n,{once:!0})),r)}),e}var qa=(()=>{let e=()=>ti;return{isServer(){return e()},setIsServer(t){e=t}}})();function hi(){let e,t;const n=new Promise((r,s)=>{e=r,t=s});n.status="pending",n.catch(()=>{});function a(r){Object.assign(n,r),delete n.resolve,delete n.reject}return n.resolve=r=>{a({status:"fulfilled",value:r}),e(r)},n.reject=r=>{a({status:"rejected",reason:r}),t(r)},n}var fi=ei;function mi(){let e=[],t=0,n=o=>{o()},a=o=>{o()},r=fi;const s=o=>{t?e.push(o):r(()=>{n(o)})},i=()=>{const o=e;e=[],o.length&&r(()=>{a(()=>{o.forEach(h=>{n(h)})})})};return{batch:o=>{let h;t++;try{h=o()}finally{t--,t||i()}return h},batchCalls:o=>(...h)=>{s(()=>{o(...h)})},schedule:s,setNotifyFunction:o=>{n=o},setBatchNotifyFunction:o=>{a=o},setScheduler:o=>{r=o}}}var z=mi(),Ge,ye,Je,La,gi=(La=class extends Et{constructor(){super();P(this,Ge,!0);P(this,ye);P(this,Je);x(this,Je,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t(!0),a=()=>t(!1);return window.addEventListener("online",n,!1),window.addEventListener("offline",a,!1),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",a)}}})}onSubscribe(){l(this,ye)||this.setEventListener(l(this,Je))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,ye))==null||t.call(this),x(this,ye,void 0))}setEventListener(t){var n;x(this,Je,t),(n=l(this,ye))==null||n.call(this),x(this,ye,t(this.setOnline.bind(this)))}setOnline(t){l(this,Ge)!==t&&(x(this,Ge,t),this.listeners.forEach(a=>{a(t)}))}isOnline(){return l(this,Ge)}},Ge=new WeakMap,ye=new WeakMap,Je=new WeakMap,La),kt=new gi;function pi(e){return Math.min(1e3*2**e,3e4)}function Ha(e){return(e??"online")==="online"?kt.isOnline():!0}var Lt=class extends Error{constructor(e){super("CancelledError"),this.revert=e==null?void 0:e.revert,this.silent=e==null?void 0:e.silent}};function bi(e){return e instanceof Lt}function Qa(e){let t=!1,n=0,a;const r=hi(),s=()=>r.status!=="pending",i=b=>{var w;if(!s()){const L=new Lt(b);u(L),(w=e.onCancel)==null||w.call(e,L)}},o=()=>{t=!0},h=()=>{t=!1},f=()=>Ua.isFocused()&&(e.networkMode==="always"||kt.isOnline())&&e.canRun(),d=()=>Ha(e.networkMode)&&e.canRun(),v=b=>{s()||(a==null||a(),r.resolve(b))},u=b=>{s()||(a==null||a(),r.reject(b))},p=()=>new Promise(b=>{var w;a=L=>{(s()||f())&&b(L)},(w=e.onPause)==null||w.call(e)}).then(()=>{var b;a=void 0,s()||(b=e.onContinue)==null||b.call(e)}),g=()=>{if(s())return;let b;const w=n===0?e.initialPromise:void 0;try{b=w??e.fn()}catch(L){b=Promise.reject(L)}Promise.resolve(b).then(v).catch(L=>{var y;if(s())return;const N=e.retry??(qa.isServer()?0:3),T=e.retryDelay??pi,_=typeof T=="function"?T(n,L):T,R=N===!0||typeof N=="number"&&nf()?void 0:p()).then(()=>{t?u(L):g()})})};return{promise:r,status:()=>r.status,cancel:i,continue:()=>(a==null||a(),r),cancelRetry:o,continueRetry:h,canStart:d,start:()=>(d()?g():p().then(g),r)}}var Ee,Ra,Wa=(Ra=class{constructor(){P(this,Ee)}destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),ai(this.gcTime)&&x(this,Ee,Bt.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(qa.isServer()?1/0:300*1e3))}clearGcTimeout(){l(this,Ee)!==void 0&&(Bt.clearTimeout(l(this,Ee)),x(this,Ee,void 0))}},Ee=new WeakMap,Ra);function vi(e){return{onFetch:(t,n)=>{var d,v,u,p,g;const a=t.options,r=(u=(v=(d=t.fetchOptions)==null?void 0:d.meta)==null?void 0:v.fetchMore)==null?void 0:u.direction,s=((p=t.state.data)==null?void 0:p.pages)||[],i=((g=t.state.data)==null?void 0:g.pageParams)||[];let o={pages:[],pageParams:[]},h=0;const f=async()=>{let b=!1;const w=T=>{di(T,()=>t.signal,()=>b=!0)},L=Ka(t.options,t.fetchOptions),N=async(T,_,R)=>{if(b)return Promise.reject(t.signal.reason);if(_==null&&T.pages.length)return Promise.resolve(T);const k=(()=>{const me={client:t.client,queryKey:t.queryKey,pageParam:_,direction:R?"backward":"forward",meta:t.options.meta};return w(me),me})(),j=await L(k),{maxPages:E}=t.options,D=R?ui:li;return{pages:D(T.pages,j,E),pageParams:D(T.pageParams,_,E)}};if(r&&s.length){const T=r==="backward",_=T?za:Zt,R={pages:s,pageParams:i},y=_(a,R);o=await N(R,y,T)}else{const T=e??s.length;do{const _=h===0?i[0]??a.initialPageParam:Zt(a,o);if(h>0&&_==null)break;o=await N(o,_),h++}while(h{var b,w;return(w=(b=t.options).persister)==null?void 0:w.call(b,f,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},n)}:t.fetchFn=f}}}function Zt(e,{pages:t,pageParams:n}){const a=t.length-1;return t.length>0?e.getNextPageParam(t[a],t,n[a],n):void 0}function za(e,{pages:t,pageParams:n}){var a;return t.length>0?(a=e.getPreviousPageParam)==null?void 0:a.call(e,t[0],t,n[0],n):void 0}function El(e,t){return t?Zt(e,t)!=null:!1}function Dl(e,t){return!t||!e.getPreviousPageParam?!1:za(e,t)!=null}var Ze,De,Xe,X,Fe,U,ht,Ie,Z,Ba,he,Ta,wi=(Ta=class extends Wa{constructor(t){super();P(this,Z);P(this,Ze);P(this,De);P(this,Xe);P(this,X);P(this,Fe);P(this,U);P(this,ht);P(this,Ie);x(this,Ie,!1),x(this,ht,t.defaultOptions),this.setOptions(t.options),this.observers=[],x(this,Fe,t.client),x(this,X,l(this,Fe).getQueryCache()),this.queryKey=t.queryKey,this.queryHash=t.queryHash,x(this,De,Jn(this.options)),this.state=t.state??l(this,De),this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return l(this,Ze)}get promise(){var t;return(t=l(this,U))==null?void 0:t.promise}setOptions(t){if(this.options={...l(this,ht),...t},t!=null&&t._type&&x(this,Ze,t._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){const n=Jn(this.options);n.data!==void 0&&(this.setState(Gn(n.data,n.dataUpdatedAt)),x(this,De,n))}}optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"&&l(this,X).remove(this)}setData(t,n){const a=ci(this.state.data,t,this.options);return V(this,Z,he).call(this,{data:a,type:"success",dataUpdatedAt:n==null?void 0:n.updatedAt,manual:n==null?void 0:n.manual}),a}setState(t){V(this,Z,he).call(this,{type:"setState",state:t})}cancel(t){var a,r;const n=(a=l(this,U))==null?void 0:a.promise;return(r=l(this,U))==null||r.cancel(t),n?n.then(ne).catch(ne):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return l(this,De)}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(t=>si(t.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===hn||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0?this.observers.some(t=>Gt(t.options.staleTime,this)==="static"):!1}isStale(){return this.getObserversCount()>0?this.observers.some(t=>t.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(t=0){return this.state.data===void 0?!0:t==="static"?!1:this.state.isInvalidated?!0:!ri(this.state.dataUpdatedAt,t)}onFocus(){var n;const t=this.observers.find(a=>a.shouldFetchOnWindowFocus());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}onOnline(){var n;const t=this.observers.find(a=>a.shouldFetchOnReconnect());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}addObserver(t){this.observers.includes(t)||(this.observers.push(t),this.clearGcTimeout(),l(this,X).notify({type:"observerAdded",query:this,observer:t}))}removeObserver(t){this.observers.includes(t)&&(this.observers=this.observers.filter(n=>n!==t),this.observers.length||(l(this,U)&&(l(this,Ie)||V(this,Z,Ba).call(this)?l(this,U).cancel({revert:!0}):l(this,U).cancelRetry()),this.scheduleGc()),l(this,X).notify({type:"observerRemoved",query:this,observer:t}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||V(this,Z,he).call(this,{type:"invalidate"})}async fetch(t,n){var f,d,v,u,p,g,b,w,L,N,T;if(this.state.fetchStatus!=="idle"&&((f=l(this,U))==null?void 0:f.status())!=="rejected"){if(this.state.data!==void 0&&(n!=null&&n.cancelRefetch))this.cancel({silent:!0});else if(l(this,U))return l(this,U).continueRetry(),l(this,U).promise}if(t&&this.setOptions(t),!this.options.queryFn){const _=this.observers.find(R=>R.options.queryFn);_&&this.setOptions(_.options)}const a=new AbortController,r=_=>{Object.defineProperty(_,"signal",{enumerable:!0,get:()=>(x(this,Ie,!0),a.signal)})},s=()=>{const _=Ka(this.options,n),y=(()=>{const k={client:l(this,Fe),queryKey:this.queryKey,meta:this.meta};return r(k),k})();return x(this,Ie,!1),this.options.persister?this.options.persister(_,y,this):_(y)},o=(()=>{const _={fetchOptions:n,options:this.options,queryKey:this.queryKey,client:l(this,Fe),state:this.state,fetchFn:s};return r(_),_})(),h=l(this,Ze)==="infinite"?vi(this.options.pages):this.options.behavior;h==null||h.onFetch(o,this),x(this,Xe,this.state),(this.state.fetchStatus==="idle"||this.state.fetchMeta!==((d=o.fetchOptions)==null?void 0:d.meta))&&V(this,Z,he).call(this,{type:"fetch",meta:(v=o.fetchOptions)==null?void 0:v.meta}),x(this,U,Qa({initialPromise:n==null?void 0:n.initialPromise,fn:o.fetchFn,onCancel:_=>{_ instanceof Lt&&_.revert&&this.setState({...l(this,Xe),fetchStatus:"idle"}),a.abort()},onFail:(_,R)=>{V(this,Z,he).call(this,{type:"failed",failureCount:_,error:R})},onPause:()=>{V(this,Z,he).call(this,{type:"pause"})},onContinue:()=>{V(this,Z,he).call(this,{type:"continue"})},retry:o.options.retry,retryDelay:o.options.retryDelay,networkMode:o.options.networkMode,canRun:()=>!0}));try{const _=await l(this,U).start();if(_===void 0)throw new Error(`${this.queryHash} data is undefined`);return this.setData(_),(p=(u=l(this,X).config).onSuccess)==null||p.call(u,_,this),(b=(g=l(this,X).config).onSettled)==null||b.call(g,_,this.state.error,this),_}catch(_){if(_ instanceof Lt){if(_.silent)return l(this,U).promise;if(_.revert){if(this.state.data===void 0)throw _;return this.state.data}}throw V(this,Z,he).call(this,{type:"error",error:_}),(L=(w=l(this,X).config).onError)==null||L.call(w,_,this),(T=(N=l(this,X).config).onSettled)==null||T.call(N,this.state.data,_,this),_}finally{this.scheduleGc()}}},Ze=new WeakMap,De=new WeakMap,Xe=new WeakMap,X=new WeakMap,Fe=new WeakMap,U=new WeakMap,ht=new WeakMap,Ie=new WeakMap,Z=new WeakSet,Ba=function(){return this.state.fetchStatus==="paused"&&this.state.status==="pending"},he=function(t){const n=a=>{switch(t.type){case"failed":return{...a,fetchFailureCount:t.failureCount,fetchFailureReason:t.error};case"pause":return{...a,fetchStatus:"paused"};case"continue":return{...a,fetchStatus:"fetching"};case"fetch":return{...a,...yi(a.data,this.options),fetchMeta:t.meta??null};case"success":const r={...a,...Gn(t.data,t.dataUpdatedAt),dataUpdateCount:a.dataUpdateCount+1,...!t.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return x(this,Xe,t.manual?r:void 0),r;case"error":const s=t.error;return{...a,error:s,errorUpdateCount:a.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:a.fetchFailureCount+1,fetchFailureReason:s,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...a,isInvalidated:!0};case"setState":return{...a,...t.state}}};this.state=n(this.state),z.batch(()=>{this.observers.forEach(a=>{a.onQueryUpdate()}),l(this,X).notify({query:this,type:"updated",action:t})})},Ta);function yi(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Ha(t.networkMode)?"fetching":"paused",...e===void 0&&{error:null,status:"pending"}}}function Gn(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:"success"}}function Jn(e){const t=typeof e.initialData=="function"?e.initialData():e.initialData,n=t!==void 0,a=n?typeof e.initialDataUpdatedAt=="function"?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:n?a??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:n?"success":"pending",fetchStatus:"idle"}}var ft,le,K,$e,ue,be,Ma,_i=(Ma=class extends Wa{constructor(t){super();P(this,ue);P(this,ft);P(this,le);P(this,K);P(this,$e);x(this,ft,t.client),this.mutationId=t.mutationId,x(this,K,t.mutationCache),x(this,le,[]),this.state=t.state||Si(),this.setOptions(t.options),this.scheduleGc()}setOptions(t){this.options=t,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(t){l(this,le).includes(t)||(l(this,le).push(t),this.clearGcTimeout(),l(this,K).notify({type:"observerAdded",mutation:this,observer:t}))}removeObserver(t){x(this,le,l(this,le).filter(n=>n!==t)),this.scheduleGc(),l(this,K).notify({type:"observerRemoved",mutation:this,observer:t})}optionalRemove(){l(this,le).length||(this.state.status==="pending"?this.scheduleGc():l(this,K).remove(this))}continue(){var t;return((t=l(this,$e))==null?void 0:t.continue())??this.execute(this.state.variables)}async execute(t){var i,o,h,f,d,v,u,p,g,b,w,L,N,T,_,R,y,k;const n=()=>{V(this,ue,be).call(this,{type:"continue"})},a={client:l(this,ft),meta:this.options.meta,mutationKey:this.options.mutationKey};x(this,$e,Qa({fn:()=>this.options.mutationFn?this.options.mutationFn(t,a):Promise.reject(new Error("No mutationFn found")),onFail:(j,E)=>{V(this,ue,be).call(this,{type:"failed",failureCount:j,error:E})},onPause:()=>{V(this,ue,be).call(this,{type:"pause"})},onContinue:n,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>l(this,K).canRun(this)}));const r=this.state.status==="pending",s=!l(this,$e).canStart();try{if(r)n();else{V(this,ue,be).call(this,{type:"pending",variables:t,isPaused:s}),l(this,K).config.onMutate&&await l(this,K).config.onMutate(t,this,a);const E=await((o=(i=this.options).onMutate)==null?void 0:o.call(i,t,a));E!==this.state.context&&V(this,ue,be).call(this,{type:"pending",context:E,variables:t,isPaused:s})}const j=await l(this,$e).start();return await((f=(h=l(this,K).config).onSuccess)==null?void 0:f.call(h,j,t,this.state.context,this,a)),await((v=(d=this.options).onSuccess)==null?void 0:v.call(d,j,t,this.state.context,a)),await((p=(u=l(this,K).config).onSettled)==null?void 0:p.call(u,j,null,this.state.variables,this.state.context,this,a)),await((b=(g=this.options).onSettled)==null?void 0:b.call(g,j,null,t,this.state.context,a)),V(this,ue,be).call(this,{type:"success",data:j}),j}catch(j){try{await((L=(w=l(this,K).config).onError)==null?void 0:L.call(w,j,t,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((T=(N=this.options).onError)==null?void 0:T.call(N,j,t,this.state.context,a))}catch(E){Promise.reject(E)}try{await((R=(_=l(this,K).config).onSettled)==null?void 0:R.call(_,void 0,j,this.state.variables,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((k=(y=this.options).onSettled)==null?void 0:k.call(y,void 0,j,t,this.state.context,a))}catch(E){Promise.reject(E)}throw V(this,ue,be).call(this,{type:"error",error:j}),j}finally{l(this,K).runNext(this)}}},ft=new WeakMap,le=new WeakMap,K=new WeakMap,$e=new WeakMap,ue=new WeakSet,be=function(t){const n=a=>{switch(t.type){case"failed":return{...a,failureCount:t.failureCount,failureReason:t.error};case"pause":return{...a,isPaused:!0};case"continue":return{...a,isPaused:!1};case"pending":return{...a,context:t.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:t.isPaused,status:"pending",variables:t.variables,submittedAt:Date.now()};case"success":return{...a,data:t.data,failureCount:0,failureReason:null,error:null,status:"success",isPaused:!1};case"error":return{...a,data:void 0,error:t.error,failureCount:a.failureCount+1,failureReason:t.error,isPaused:!1,status:"error"}}};this.state=n(this.state),z.batch(()=>{l(this,le).forEach(a=>{a.onMutationUpdate(t)}),l(this,K).notify({mutation:this,type:"updated",action:t})})},Ma);function Si(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:"idle",variables:void 0,submittedAt:0}}var fe,ae,mt,Pa,Ci=(Pa=class extends Et{constructor(t={}){super();P(this,fe);P(this,ae);P(this,mt);this.config=t,x(this,fe,new Set),x(this,ae,new Map),x(this,mt,0)}build(t,n,a){const r=new _i({client:t,mutationCache:this,mutationId:++St(this,mt)._,options:t.defaultMutationOptions(n),state:a});return this.add(r),r}add(t){l(this,fe).add(t);const n=Ct(t);if(typeof n=="string"){const a=l(this,ae).get(n);a?a.push(t):l(this,ae).set(n,[t])}this.notify({type:"added",mutation:t})}remove(t){if(l(this,fe).delete(t)){const n=Ct(t);if(typeof n=="string"){const a=l(this,ae).get(n);if(a)if(a.length>1){const r=a.indexOf(t);r!==-1&&a.splice(r,1)}else a[0]===t&&l(this,ae).delete(n)}}this.notify({type:"removed",mutation:t})}canRun(t){const n=Ct(t);if(typeof n=="string"){const a=l(this,ae).get(n),r=a==null?void 0:a.find(s=>s.state.status==="pending");return!r||r===t}else return!0}runNext(t){var a;const n=Ct(t);if(typeof n=="string"){const r=(a=l(this,ae).get(n))==null?void 0:a.find(s=>s!==t&&s.state.isPaused);return(r==null?void 0:r.continue())??Promise.resolve()}else return Promise.resolve()}clear(){z.batch(()=>{l(this,fe).forEach(t=>{this.notify({type:"removed",mutation:t})}),l(this,fe).clear(),l(this,ae).clear()})}getAll(){return Array.from(l(this,fe))}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Wn(n,a))}findAll(t={}){return this.getAll().filter(n=>Wn(t,n))}notify(t){z.batch(()=>{this.listeners.forEach(n=>{n(t)})})}resumePausedMutations(){const t=this.getAll().filter(n=>n.state.isPaused);return z.batch(()=>Promise.all(t.map(n=>n.continue().catch(ne))))}},fe=new WeakMap,ae=new WeakMap,mt=new WeakMap,Pa);function Ct(e){var t;return(t=e.options.scope)==null?void 0:t.id}var de,ja,xi=(ja=class extends Et{constructor(t={}){super();P(this,de);this.config=t,x(this,de,new Map)}build(t,n,a){const r=n.queryKey,s=n.queryHash??dn(r,n);let i=this.get(s);return i||(i=new wi({client:t,queryKey:r,queryHash:s,options:t.defaultQueryOptions(n),state:a,defaultOptions:t.getQueryDefaults(r)}),this.add(i)),i}add(t){l(this,de).has(t.queryHash)||(l(this,de).set(t.queryHash,t),this.notify({type:"added",query:t}))}remove(t){const n=l(this,de).get(t.queryHash);n&&(t.destroy(),n===t&&l(this,de).delete(t.queryHash),this.notify({type:"removed",query:t}))}clear(){z.batch(()=>{this.getAll().forEach(t=>{this.remove(t)})})}get(t){return l(this,de).get(t)}getAll(){return[...l(this,de).values()]}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Qn(n,a))}findAll(t={}){const n=this.getAll();return Object.keys(t).length>0?n.filter(a=>Qn(t,a)):n}notify(t){z.batch(()=>{this.listeners.forEach(n=>{n(t)})})}onFocus(){z.batch(()=>{this.getAll().forEach(t=>{t.onFocus()})})}onOnline(){z.batch(()=>{this.getAll().forEach(t=>{t.onOnline()})})}},de=new WeakMap,ja),F,_e,Se,Ye,et,Ce,tt,nt,Aa,ki=(Aa=class{constructor(e={}){P(this,F);P(this,_e);P(this,Se);P(this,Ye);P(this,et);P(this,Ce);P(this,tt);P(this,nt);x(this,F,e.queryCache||new xi),x(this,_e,e.mutationCache||new Ci),x(this,Se,e.defaultOptions||{}),x(this,Ye,new Map),x(this,et,new Map),x(this,Ce,0)}mount(){St(this,Ce)._++,l(this,Ce)===1&&(x(this,tt,Ua.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onFocus())})),x(this,nt,kt.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onOnline())})))}unmount(){var e,t;St(this,Ce)._--,l(this,Ce)===0&&((e=l(this,tt))==null||e.call(this),x(this,tt,void 0),(t=l(this,nt))==null||t.call(this),x(this,nt,void 0))}isFetching(e){return l(this,F).findAll({...e,fetchStatus:"fetching"}).length}isMutating(e){return l(this,_e).findAll({...e,status:"pending"}).length}getQueryData(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,F).get(t.queryHash))==null?void 0:n.state.data}ensureQueryData(e){const t=this.defaultQueryOptions(e),n=l(this,F).build(this,t),a=n.state.data;return a===void 0?this.fetchQuery(e):(e.revalidateIfStale&&n.isStaleByTime(Gt(t.staleTime,n))&&this.prefetchQuery(t),Promise.resolve(a))}getQueriesData(e){return l(this,F).findAll(e).map(({queryKey:t,state:n})=>{const a=n.data;return[t,a]})}setQueryData(e,t,n){const a=this.defaultQueryOptions({queryKey:e}),r=l(this,F).get(a.queryHash),s=r==null?void 0:r.state.data,i=ni(t,s);if(i!==void 0)return l(this,F).build(this,a).setData(i,{...n,manual:!0})}setQueriesData(e,t,n){return z.batch(()=>l(this,F).findAll(e).map(({queryKey:a})=>[a,this.setQueryData(a,t,n)]))}getQueryState(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,F).get(t.queryHash))==null?void 0:n.state}removeQueries(e){const t=l(this,F);z.batch(()=>{t.findAll(e).forEach(n=>{t.remove(n)})})}resetQueries(e,t){const n=l(this,F);return z.batch(()=>(n.findAll(e).forEach(a=>{a.reset()}),this.refetchQueries({type:"active",...e},t)))}cancelQueries(e,t={}){const n={revert:!0,...t},a=z.batch(()=>l(this,F).findAll(e).map(r=>r.cancel(n)));return Promise.all(a).then(ne).catch(ne)}invalidateQueries(e,t={}){return z.batch(()=>(l(this,F).findAll(e).forEach(n=>{n.invalidate()}),(e==null?void 0:e.refetchType)==="none"?Promise.resolve():this.refetchQueries({...e,type:(e==null?void 0:e.refetchType)??(e==null?void 0:e.type)??"active"},t)))}refetchQueries(e,t={}){const n={...t,cancelRefetch:t.cancelRefetch??!0},a=z.batch(()=>l(this,F).findAll(e).filter(r=>!r.isDisabled()&&!r.isStatic()).map(r=>{let s=r.fetch(void 0,n);return n.throwOnError||(s=s.catch(ne)),r.state.fetchStatus==="paused"?Promise.resolve():s}));return Promise.all(a).then(ne)}fetchQuery(e){const t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);const n=l(this,F).build(this,t);return n.isStaleByTime(Gt(t.staleTime,n))?n.fetch(t):Promise.resolve(n.state.data)}prefetchQuery(e){return this.fetchQuery(e).then(ne).catch(ne)}fetchInfiniteQuery(e){return e._type="infinite",this.fetchQuery(e)}prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(ne).catch(ne)}ensureInfiniteQueryData(e){return e._type="infinite",this.ensureQueryData(e)}resumePausedMutations(){return kt.isOnline()?l(this,_e).resumePausedMutations():Promise.resolve()}getQueryCache(){return l(this,F)}getMutationCache(){return l(this,_e)}getDefaultOptions(){return l(this,Se)}setDefaultOptions(e){x(this,Se,e)}setQueryDefaults(e,t){l(this,Ye).set(lt(e),{queryKey:e,defaultOptions:t})}getQueryDefaults(e){const t=[...l(this,Ye).values()],n={};return t.forEach(a=>{ut(e,a.queryKey)&&Object.assign(n,a.defaultOptions)}),n}setMutationDefaults(e,t){l(this,et).set(lt(e),{mutationKey:e,defaultOptions:t})}getMutationDefaults(e){const t=[...l(this,et).values()],n={};return t.forEach(a=>{ut(e,a.mutationKey)&&Object.assign(n,a.defaultOptions)}),n}defaultQueryOptions(e){if(e._defaulted)return e;const t={...l(this,Se).queries,...this.getQueryDefaults(e.queryKey),...e,_defaulted:!0};return t.queryHash||(t.queryHash=dn(t.queryKey,t)),t.refetchOnReconnect===void 0&&(t.refetchOnReconnect=t.networkMode!=="always"),t.throwOnError===void 0&&(t.throwOnError=!!t.suspense),!t.networkMode&&t.persister&&(t.networkMode="offlineFirst"),t.queryFn===hn&&(t.enabled=!1),t}defaultMutationOptions(e){return e!=null&&e._defaulted?e:{...l(this,Se).mutations,...(e==null?void 0:e.mutationKey)&&this.getMutationDefaults(e.mutationKey),...e,_defaulted:!0}}clear(){l(this,F).clear(),l(this,_e).clear()}},F=new WeakMap,_e=new WeakMap,Se=new WeakMap,Ye=new WeakMap,et=new WeakMap,Ce=new WeakMap,tt=new WeakMap,nt=new WeakMap,Aa),Ga=C.createContext(void 0),Fl=e=>{const t=C.useContext(Ga);if(!t)throw new Error("No QueryClient set, use QueryClientProvider to set one");return t},Li=({client:e,children:t})=>(C.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),c.jsx(Ga.Provider,{value:e,children:t}));function Ri(e,t=window.location.href){var a;const n=(a=new URL(t).searchParams.get("record"))==null?void 0:a.trim();if(n){const r=e.calls.find(s=>s.id===n);return r?[r]:[]}return e.calls[0]?[e.calls[0]]:[]}function Il({calls:e,recordId:t,detail:n}){const a=e.findIndex(v=>v.id===t),r=a>=0?a:!t&&e.length?0:-1,s=(n==null?void 0:n.record.id)===t?n:null,i=(s==null?void 0:s.record)??(r>=0?e[r]:null),o=(s==null?void 0:s.previousRecord)??(r>0?e[r-1]:null),h=(s==null?void 0:s.nextRecord)??(r>=0&&r=0?`${r+1} of ${e.length} loaded calls`:"Record outside loaded snapshot";return{modelIndex:a,activeIndex:r,hydratedDetail:s,call:i,previous:o,next:h,threadCalls:f,positionLabel:d}}function Ti(e,t,n){const a=e.filter(i=>i.thread===t.thread),r=[n==null?void 0:n.previousRecord,n==null?void 0:n.record,n==null?void 0:n.nextRecord].filter(Mi),s=new Map;for(const i of[...a,...r,t])s.set(i.id,i);return[...s.values()].sort(Pi)}function Mi(e){return!!(e!=null&&e.id)}function Pi(e,t){return Date.parse(t.rawTime||t.time)-Date.parse(e.rawTime||e.time)}function ji(e,t){const n=t.map(r=>Zn(r.header)).join(","),a=e.map(r=>t.map(s=>Zn(s.value(r))).join(","));return[n,...a].join(` -`)}function Ai(e,t){const n=new Blob([t],{type:"text/csv;charset=utf-8"}),a=typeof URL.createObjectURL=="function"?URL.createObjectURL(n):`data:text/csv;charset=utf-8,${encodeURIComponent(t)}`,r=document.createElement("a");r.href=a,r.download=e,r.rel="noopener",document.body.append(r),r.click(),r.remove(),a.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(a)}function Ni(e=new Date){return e.toISOString().slice(0,10)}function Zn(e){const t=String(e??"");return/[",\n\r]/.test(t)?`"${t.replaceAll('"','""')}"`:t}function Le(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Re(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Xt(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function Rt(e){return`${e.toFixed(1)}%`}const $l=[{id:"time",accessorFn:e=>Number(Date.parse(e.eventTimestamp||e.callStartedAt||e.rawTime||e.time))||0,header:"Time",cell:e=>e.row.original.time},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:e=>c.jsx("span",{className:`pill effort-${String(e.getValue())}`,children:String(e.getValue())})},{accessorKey:"input",header:"Input Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"output",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:e=>c.jsx("span",{className:"cache-pill",children:Rt(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:Re(Number(e.getValue()))})},{accessorKey:"contextWindowPct",header:"Context %",cell:e=>{const t=e.getValue(),n=typeof t=="number"?t:Number.NaN;return c.jsx("span",{className:"num",children:Number.isFinite(n)?Rt(n):"-"})}},{accessorKey:"duration",header:"Duration"},{accessorKey:"previousCallGap",header:"Prev Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiator",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"signal",header:"Signals",cell:e=>c.jsx(Di,{call:e.row.original})}],ce=[{header:"timestamp",value:e=>e.eventTimestamp||e.rawTime||e.time},{header:"thread",value:e=>e.thread},{header:"call_started_at",value:e=>e.callStartedAt||e.rawTime||e.time},{header:"call_duration_seconds",value:e=>e.durationSeconds},{header:"previous_call_event_timestamp",value:e=>e.previousCallEventTimestamp},{header:"previous_call_delta_seconds",value:e=>e.previousCallGapSeconds},{header:"initiated",value:e=>e.initiator},{header:"initiated_reason",value:e=>e.initiatorReason},{header:"project",value:e=>e.project},{header:"model",value:e=>e.model},{header:"effort",value:e=>e.effort},{header:"total_tokens",value:e=>e.totalTokens},{header:"input_tokens",value:e=>e.input},{header:"cached_input_tokens",value:e=>e.cachedInput},{header:"uncached_input_tokens",value:e=>e.uncachedInput},{header:"output_tokens",value:e=>e.output},{header:"reasoning_output_tokens",value:e=>e.reasoningOutput},{header:"estimated_cost_usd",value:e=>e.cost.toFixed(6)},{header:"usage_credits",value:e=>e.credits.toFixed(6)},{header:"cache_ratio",value:e=>e.cachedPct.toFixed(2)},{header:"context_window_percent",value:e=>{var t;return((t=e.contextWindowPct)==null?void 0:t.toFixed(2))??""}},{header:"pricing_model",value:e=>e.pricingModel},{header:"usage_credit_confidence",value:e=>e.usageCreditConfidence},{header:"recommendation",value:e=>e.recommendation},{header:"record_id",value:e=>e.id},{header:"thread_attachment",value:e=>e.threadAttachmentLabel},{header:"thread_source",value:e=>e.threadSource},{header:"parent_thread",value:e=>e.parentThread},{header:"session_id",value:e=>e.sessionId},{header:"turn_id",value:e=>e.turnId},{header:"parent_session_id",value:e=>e.parentSessionId},{header:"parent_session_updated_at",value:e=>e.parentSessionUpdatedAt},{header:"project_relative_cwd",value:e=>e.projectRelativeCwd},{header:"cwd",value:e=>e.cwd},{header:"source_file",value:e=>e.sourceFile},{header:"source_line",value:e=>e.lineNumber??""},{header:"git_branch",value:e=>e.gitBranch},{header:"git_remote_label",value:e=>e.gitRemoteLabel},{header:"git_remote_hash",value:e=>e.gitRemoteHash},{header:"pricing_estimated",value:e=>String(e.pricingEstimated)},{header:"usage_credit_model",value:e=>e.usageCreditModel},{header:"usage_credit_source",value:e=>e.usageCreditSource},{header:"usage_credit_tier",value:e=>e.usageCreditTier},{header:"usage_credit_fetched_at",value:e=>e.usageCreditFetchedAt},{header:"usage_credit_note",value:e=>e.usageCreditNote},{header:"model_context_window",value:e=>e.modelContextWindow??""},{header:"cumulative_total_tokens",value:e=>e.cumulativeTotalTokens??""},{header:"estimated_cache_savings_usd",value:e=>e.estimatedCacheSavings.toFixed(6)},{header:"initiated_confidence",value:e=>e.initiatorConfidence},{header:"signal",value:e=>e.signal},{header:"tags",value:e=>e.tags.join("|")},{header:"efficiency_flags",value:e=>e.efficiencyFlags.join("|")}];function Ei(e,t=3){const a=Fi([e.signal,...e.efficiencyFlags]).map((r,s)=>({key:`${r}-${s}`,label:Ja(r),shortLabel:Ii(r)}));return{visible:a.slice(0,t),hidden:a.slice(t)}}function Di({call:e}){const t=Oa(),{visible:n,hidden:a}=Ei(e);if(!n.length)return c.jsx("span",{className:"muted",children:"None"});const r=n.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),s=a.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),i=s.map(o=>o.label).join("、");return c.jsxs("span",{className:"flags compact-flags","aria-label":t.language==="zh-Hans"?`信号:${[...r,...s].map(o=>o.label).join("、")}`:`Signals: ${[...n,...a].map(o=>o.label).join(", ")}`,children:[r.map(o=>c.jsx("span",{className:"flag signal-puck",title:o.label,children:o.shortLabel},o.key)),s.length?c.jsxs("span",{className:"flag signal-puck more",title:i,children:["+",s.length]}):null]})}function Fi(e){const t=new Set;return e.map(n=>n.trim()).filter(n=>n&&n!=="aggregate").filter(n=>{const a=n.toLowerCase();return t.has(a)?!1:(t.add(a),!0)})}function Ja(e){return e.replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function Ii(e){const t=e.toLowerCase().replace(/[_\s]+/g,"-"),n={"cache-drop":"CACHE","cache-risk":"CACHE","context-bloat":"CTX","context-heavy":"CTX","elevated-context":"CTX","elevated-context-use":"CTX","estimated-pricing":"EST","expensive-low-output-call":"LO","high-context-use":"CTX","high-cost":"$","high-estimated-cost":"$","high-reasoning-share":"RSN","large-thread":"BIG","low-cache":"CACHE","low-cache-reuse":"CACHE","low-output":"LO","pricing-gap":"PRICE","reasoning-spike":"RSN","subagent-attribution":"SUB"};if(n[t])return n[t];const a=Ja(e).split(/\s+/).filter(Boolean);return a.length?a.length===1?a[0].slice(0,4).toUpperCase():a.slice(0,3).map(r=>r[0]).join("").toUpperCase():"?"}const Ol=[{accessorKey:"name",header:"Thread"},{accessorKey:"latestActivity",header:"Latest"},{accessorKey:"turns",header:"Turns",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalDuration",header:"Duration"},{accessorKey:"averageGap",header:"Avg Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiatorSummary",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"modelSummary",header:"Models",cell:e=>c.jsx("span",{className:"pill model-pill",children:String(e.getValue())})},{accessorKey:"effortSummary",header:"Effort Mix"},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Re(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Re(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Re(Number(e.getValue()))})},{accessorKey:"outputTokens",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Re(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Re(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:Re(Number(e.getValue()))})},{accessorKey:"cachePct",header:"Cache %",cell:e=>c.jsx("span",{className:"cache-pill",children:Rt(Number(e.getValue()))})},{accessorKey:"contextPct",header:"Context %",cell:e=>{const t=e.getValue();return c.jsx("span",{className:"num",children:typeof t=="number"?Rt(t):"-"})}},{accessorKey:"costPerCall",header:"Cost / Call",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"coldResumeRisk",header:"Cold Resume Risk",cell:e=>c.jsx("span",{className:`status-badge ${$i(String(e.getValue()))}`,children:String(e.getValue())})},{accessorKey:"productivity",header:"Productivity",cell:e=>c.jsx("span",{className:"score",children:Number(e.getValue())})}],Ul=[{id:"name",label:"Thread",locked:!0},{id:"latestActivity",label:"Latest"},{id:"turns",label:"Turns"},{id:"totalDuration",label:"Duration"},{id:"averageGap",label:"Avg Gap"},{id:"initiatorSummary",label:"Initiated"},{id:"modelSummary",label:"Models"},{id:"effortSummary",label:"Effort Mix"},{id:"totalTokens",label:"Total Tokens"},{id:"cachedInput",label:"Cached Input"},{id:"uncachedInput",label:"Uncached Input"},{id:"outputTokens",label:"Output Tokens"},{id:"reasoningOutput",label:"Reasoning Output"},{id:"cost",label:"Est. Cost"},{id:"credits",label:"Codex Credits"},{id:"cachePct",label:"Cache %"},{id:"contextPct",label:"Context %"},{id:"costPerCall",label:"Cost / Call"},{id:"coldResumeRisk",label:"Cold Resume Risk"},{id:"productivity",label:"Productivity"},{id:"investigate",label:"Investigate",locked:!0}];function $i(e){return e==="High"?"red":e==="Medium"?"orange":e==="Low"?"green":"neutral"}const dt=1,re=0,qt=100,Za=1e3,Xa=500,Ya="codexUsageDashboardLoadSettings",Oi={day:1440*60*1e3,week:10080*60*1e3};function ct(e,t=Xa){if((e==null?void 0:e.limit_label)==="All"||t===re&&(e==null?void 0:e.limit)==null)return re;const n=Number((e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??t);return Number.isFinite(n)&&n>=0?n:t}function gt(e){return Number.isFinite(e)?e<=re?re:Math.max(dt,Math.round(e)):dt}function je(...e){const t=e.find(n=>typeof n=="number"&&Number.isFinite(n)&&n>0);return t?Math.max(dt,Math.round(t)):dt}function Ui(e,t,n=null,a="rows"){const r=gt(e);return{historyScope:t,loadWindow:a,limit:r===re?null:r,since:n}}function Vi(e){return e.limit??re}function fn(e){return mn(e==null?void 0:e.load_window)?e.load_window:e!=null&&e.since?"week":(e==null?void 0:e.limit_label)==="All"||(e==null?void 0:e.limit)==null?"all":"rows"}function Ki(e){return mn(e==null?void 0:e.default_load_window)?e.default_load_window:fn(e)}function Ht(e,t=new Date){const n=Oi[e];if(!n)return null;const a=Math.floor(t.getTime()/6e4)*6e4;return new Date(a-n).toISOString()}function Te(e,t=Xa){return e==="day"?"Last 24 hours":e==="week"?"Last 7 days":e==="all"?"All time":`Most recent ${gt(t).toLocaleString()}`}function qi(e=er()){if(!e)return null;try{const t=e.getItem(Ya);if(!t)return null;const n=JSON.parse(t),a=typeof n.loadLimit=="number"&&Number.isFinite(n.loadLimit)?gt(n.loadLimit):void 0,r=n.historyScope==="active"||n.historyScope==="all"?n.historyScope:void 0,s=mn(n.loadWindow)?n.loadWindow:void 0;return a===void 0&&r===void 0&&s===void 0?null:{loadLimit:a,historyScope:r,loadWindow:s}}catch{return null}}function Hi(e,t,n="rows",a=er()){if(a)try{a.setItem(Ya,JSON.stringify({loadLimit:gt(e),historyScope:t,loadWindow:n}))}catch{}}function mn(e){return e==="day"||e==="week"||e==="rows"||e==="all"}function Qi({currentLimit:e,loadedRows:t,pendingLimit:n}){const a=n===re?0:n+qt,s=Math.max(dt,e===re?0:e,a,t);return Math.ceil((s+Za)/qt)*qt}function Wi({currentLimit:e,loadedRows:t,pendingLimit:n}){return Math.max(je(e),je(n),je(t))+Za}function zi({loadedRows:e,limit:t,totalRows:n}){return t===re&&e>0?`Loaded all ${e.toLocaleString()}`:n>e?`Loaded ${e.toLocaleString()} of ${n.toLocaleString()}`:`Loaded ${e.toLocaleString()} rows`}function er(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}async function Bi(e,t,n,a="",r=""){const s=Ni();switch(e){case"threads":{const{threadCallsForCurrentUrl:i}=await O(async()=>{const{threadCallsForCurrentUrl:o}=await import("./ThreadsPage.js");return{threadCallsForCurrentUrl:o}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]));return te(`codex-thread-filtered-calls-${s}.csv`,i(t,a),ce,"call rows")}case"cache-context":{const{cacheContextCallsForCurrentUrl:i}=await O(async()=>{const{cacheContextCallsForCurrentUrl:o}=await import("./CacheContextPage.js");return{cacheContextCallsForCurrentUrl:o}},__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12]));return te(`codex-${e}-calls-${s}.csv`,i(t),ce,"call rows")}case"usage-drain":{const{usageDrainCallsForCurrentUrl:i}=await O(async()=>{const{usageDrainCallsForCurrentUrl:o}=await import("./UsageDrainPage.js");return{usageDrainCallsForCurrentUrl:o}},__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39]));return te(`codex-usage-drain-calls-${s}.csv`,i(t),ce,"call rows")}case"diagnostics":{const{diagnosticsCallsForCurrentUrl:i}=await O(async()=>{const{diagnosticsCallsForCurrentUrl:o}=await import("./DiagnosticsPage.js");return{diagnosticsCallsForCurrentUrl:o}},__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12]));return te(`codex-diagnostics-calls-${s}.csv`,i(t),ce,"call rows")}case"reports":{const{reportCallsForCurrentUrl:i}=await O(async()=>{const{reportCallsForCurrentUrl:o}=await import("./ReportsPage.js");return{reportCallsForCurrentUrl:o}},__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43]));return te(`codex-reports-evidence-${s}.csv`,i(t),ce,"call rows")}case"settings":return te(`codex-dashboard-settings-${s}.csv`,Ji(t,n),Gi,"settings rows");case"calls":{const{callsForCurrentUrl:i}=await O(async()=>{const{callsForCurrentUrl:o}=await import("./CallsPage.js");return{callsForCurrentUrl:o}},__vite__mapDeps([44,1,2,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48]));return te(`codex-calls-${s}.csv`,i(t.calls,a,r),ce,"call rows")}case"overview":{const{overviewCallsForQuery:i}=await O(async()=>{const{overviewCallsForQuery:o}=await import("./OverviewPage.js");return{overviewCallsForQuery:o}},__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50]));return te(`codex-overview-calls-${s}.csv`,i(t.calls,a),ce,"call rows")}case"investigator":{const{investigatorCallsForCurrentUrl:i}=await O(async()=>{const{investigatorCallsForCurrentUrl:o}=await import("./InvestigatorPage.js");return{investigatorCallsForCurrentUrl:o}},__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52]));return te(`codex-investigator-calls-${s}.csv`,i(t),ce,"call rows")}case"compression-lab":return te(`codex-compression-lab-scope-${s}.csv`,t.calls,ce,"call rows");case"call":return te(`codex-call-calls-${s}.csv`,Ri(t),ce,"call rows")}}function te(e,t,n,a){return{filename:e,csv:ji(t,n),rowCount:t.length,label:a}}const Gi=[{header:"Field",value:e=>e.field},{header:"Value",value:e=>e.value}];function Ji(e,t){return[{field:"live_api",value:t.canUseLiveApi?"available":"static snapshot"},{field:"context_api",value:t.contextRuntime.contextApiEnabled?"enabled":"gated"},{field:"history_scope",value:t.historyScope},{field:"data_window",value:Te(t.loadWindow,t.loadLimit)},{field:"scope_since",value:t.scopeSince??"none"},{field:"row_request",value:t.loadLimit===re?"no cap":String(t.loadLimit)},{field:"loaded_rows",value:String(t.loadedRowCount)},{field:"total_available_rows",value:String(t.totalAvailableRows)},{field:"auto_refresh",value:t.autoRefreshEnabled?"enabled":"paused"},{field:"refresh_state",value:t.refreshState},{field:"visible_calls",value:String(e.calls.length)},{field:"visible_threads",value:String(e.threads.length)}]}function Zi(e){return e instanceof Error?e.message:String(e)}function Xn(e,t){const n=t==="all"?"all history":"active history",a=e.message||"Refreshing usage index",r=typeof e.percent=="number"?` ${Math.round(e.percent)}%`:"";return`${a}${r} (${n})`}function Qt(e,t="active"){return e?typeof e.include_archived=="boolean"?e.include_archived?"all":"active":e.history_scope==="all-history"||e.history_scope==="all"?"all":e.history_scope==="active"?"active":t:t}function Xi({historyScope:e,activeRows:t,allRows:n,archivedRows:a}){const r=Yi({activeRows:t,allRows:n,archivedRows:a});return e==="all"?r===null?"All history selected":r>0?`All history includes ${r.toLocaleString()} archived calls`:"All history selected; no archived calls are indexed yet":r===null||r<=0?"Active sessions only":`Active sessions only; ${r.toLocaleString()} archived calls hidden`}function Yi({activeRows:e,allRows:t,archivedRows:n}){const a=Wt(n);if(a!==null)return a;const r=Wt(e),s=Wt(t);return r!==null&&s!==null?Math.max(s-r,0):null}function Wt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.round(e):null}const tr=["aria-description","aria-label","aria-valuetext","title","placeholder","alt"],eo="data-localization-attributes",to=new Set(["CODE","KBD","PRE","SAMP","SCRIPT","STYLE","TEXTAREA"]),Yt=new WeakMap,en=new WeakMap;function no({value:e,children:t}){return c.jsxs(Js,{value:e,children:[c.jsx(ao,{}),t]})}function ao(){const e=Oa();return C.useLayoutEffect(()=>{const t=document.querySelector("[data-dashboard-localization-root]");if(!t)return;if(e.language!=="zh-Hans"){so(t),document.title="Codex Usage Tracker React Dashboard";return}document.title="Codex Usage Tracker · 用量仪表盘",Yn(t,e.translateText);const n=new MutationObserver(a=>{for(const r of a){if(r.type==="characterData"&&r.target instanceof Text){tn(r.target,e.translateText);continue}if(r.type==="attributes"&&r.target instanceof Element){nn(r.target,e.translateText);continue}for(const s of r.addedNodes)s instanceof Text?tn(s,e.translateText):s instanceof Element&&Yn(s,e.translateText)}});return n.observe(t,{attributes:!0,attributeFilter:[...tr],characterData:!0,childList:!0,subtree:!0}),()=>n.disconnect()},[e]),null}function Yn(e,t){if(Tt(e))return;nn(e,t);const n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);let a=n.nextNode();for(;a;){if(a instanceof Element){if(Tt(a)){a=ro(n,a,e);continue}nn(a,t)}else a instanceof Text&&tn(a,t);a=n.nextNode()}}function ro(e,t,n){let a=t;for(;a&&a!==n;){const r=e.nextSibling();if(r)return r;a=a.parentNode,a&&(e.currentNode=a)}return null}function tn(e,t){const n=e.parentElement;if(!n||Tt(n))return;const a=e.nodeValue??"",r=Yt.get(e),s=r&&(a===r.source||a===r.translated)?r.source:a,i=s.match(/^(\s*)([\s\S]*?)(\s*)$/u);if(!i||!i[2])return;const o=t(i[2]),h=`${i[1]}${o}${i[3]}`;Yt.set(e,{source:s,translated:h}),h!==a&&(e.nodeValue=h)}function nn(e,t){if(Tt(e))return;const n=new Set((e.getAttribute(eo)??"").split(/[\s,]+/u).filter(Boolean));if(!n.size)return;const a=en.get(e)??new Map;for(const r of tr){if(!n.has(r))continue;const s=e.getAttribute(r);if(!s)continue;const i=a.get(r),o=i&&(s===i.source||s===i.translated)?i.source:s,h=t(o);a.set(r,{source:o,translated:h}),h!==s&&e.setAttribute(r,h)}a.size&&en.set(e,a)}function so(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);ea(e);let n=t.nextNode();for(;n;){if(n instanceof Text){const a=Yt.get(n);a&&n.nodeValue===a.translated&&(n.nodeValue=a.source)}else n instanceof Element&&ea(n);n=t.nextNode()}}function ea(e){const t=en.get(e);if(t)for(const[n,a]of t)e.getAttribute(n)===a.translated&&e.setAttribute(n,a.source)}function Tt(e){return to.has(e.tagName)||!!e.closest('[data-localization-skip="true"]')}const Mt=["May 12","May 19","May 26","Jun 02","Jun 09","Jun 16","Jun 23","Jun 30"],it=Mt.slice(2),nr={contextRuntime:{apiToken:"",contextApiEnabled:!1,fileMode:!1},cards:[{label:"Total Tokens",value:"24.83M",detail:"7-day total: 12.56M",trend:"up 18.7% vs prior 7 days",tone:"blue"},{label:"Estimated Cost",value:"$42.67",detail:"7-day total: $24.81",trend:"up 14.2% vs prior 7 days",tone:"green"},{label:"Cache Hit Rate",value:"38.7%",detail:"7-day average: 42.3%",trend:"down 3.6pp vs prior 7 days",tone:"purple"},{label:"Total Calls",value:"1,342",detail:"678 calls in last 7 days",trend:"up 11.3% vs prior 7 days",tone:"blue"},{label:"Usage Remaining",value:"32.4%",detail:"~15.9K credits estimated",trend:"resets in 4d 12h",tone:"green"}],tokenSeries:[Q("input","Input","#2563eb",[5.2,6.4,7.5,9.2,6.7,7.5,6.6,9],1e6),Q("output","Output","#059669",[2.5,3,3.6,5.1,3.7,5,4,5.4],1e6),Q("cached","Cached","#7c3aed",[1.1,1.4,1.7,2.4,1.8,2.3,1.8,2.6],1e6,!0)],costSeries:[Q("cost","Estimated Cost","#2563eb",[8.4,10.1,14.3,9.9,11.4,7.8,12.7,16.5])],cacheSeries:[Q("cache","Cache Hit Rate","#059669",[58,61,39,45,50,44,48,41])],weeklyCreditSeries:[{id:"pro",label:"Pro observed",color:"#2563eb",points:Mt.map((e,t)=>({label:e,value:[59800,44900,45e3,40500,42800,38900,31400,35900][t]??0,low:[52100,38800,38900,34700,36200,32200,26100,29900][t]??0,high:[67400,51200,51100,46800,49200,45100,37300,41900][t]??0}))},Q("pro-trend","Pro trend","#1d4ed8",[54.2,51,47.8,44.6,41.4,38.2,35,31.8],1e3,!0),Q("prolite","Prolite observed","#0f766e",[15.9,15.8,15.9,16.1,15.7,15.6,15.9,15.8],1e3)],usageRemainingSeries:[Q("remaining","Usage remaining","#059669",[87,71,63,56,56,48,50,54]),Q("allowance","Allowance guide","#0f766e",[86,85,84,83,82,81,80,79],1,!0)],actualVsPredictedSeries:[Q("observed","Observed drain","#2563eb",[18.7,22.1,45.3,31,34.8],1e3),Q("predicted","Predicted baseline","#1d4ed8",[17.9,21.4,41.2,29.6,33.9],1e3,!0)],findings:[{rank:1,title:"Long Thread: data-engine-refactor",severity:"High",credits:12847,share:25.6,summary:"Very long duration with high model effort."},{rank:2,title:"Cache Misses (Large Inputs)",severity:"High",credits:9612,share:19.1,summary:"Large uncached inputs across 214 calls."},{rank:3,title:"High Model Effort",severity:"Medium",credits:7404,share:14.7,summary:"Reasoning and output token volume are concentrated."},{rank:4,title:"Tool Output Volume",severity:"Medium",credits:5231,share:10.4,summary:"Large tool outputs returned to the model."}],calls:[["2026-06-01T10:24:00Z","Jun 1, 10:24 AM","thread-9f3a1c","codex-1","high",128542,45231,62,.42,"18.4s",!1,["review"]],["2026-06-01T10:18:00Z","Jun 1, 10:18 AM","thread-7b2e91","o4-mini","medium",98731,32104,41,.31,"12.7s",!0,["analysis"]],["2026-06-01T10:12:00Z","Jun 1, 10:12 AM","thread-3c8d4e","o3","high",64221,18903,28,.12,"9.3s",!0,["uncached"]],["2026-06-01T10:06:00Z","Jun 1, 10:06 AM","thread-1a2b3c","codex-1","high",245123,98112,71,.87,"27.6s",!1,["large"]],["2026-06-01T10:01:00Z","Jun 1, 10:01 AM","thread-8d7c6b","gpt-4.1","low",12543,4231,12,.03,"3.6s",!0,["quick"]],["2026-06-01T09:55:00Z","Jun 1, 09:55 AM","thread-2f9e7d","o4-mini","medium",76881,28442,39,.24,"11.2s",!1,["subagent"]],["2026-06-01T09:50:00Z","Jun 1, 09:50 AM","thread-6a5b4c","codex-1","high",312654,112991,67,1.12,"31.8s",!1,["file-heavy"]],["2026-06-01T09:47:00Z","Jun 1, 09:47 AM","thread-0f1e2d","o3","low",8221,2903,15,.02,"2.8s",!0,["fast"]]].map(([e,t,n,a,r,s,i,o,h,f,d,v],u)=>{const p=Number(s),g=Number(i),b=Number(o),w=Math.round(p*Math.max(100-b,0)/100);return{id:`fixture-call-${u}`,rawTime:String(e),eventTimestamp:String(e),callStartedAt:String(e),time:String(t),thread:String(n),model:String(a),effort:String(r),input:p,output:g,reasoningOutput:Math.round(g*.2),totalTokens:p+g,cachedInput:Math.round(p*b/100),uncachedInput:w,cachedPct:b,cost:u===4?0:Number(h),credits:(u===4?0:Number(h))*25,duration:String(f),durationSeconds:Number.parseFloat(String(f))||0,previousCallGap:u===0?"-":`${u*7}m 0s`,previousCallEventTimestamp:u===0?"":`2026-06-01T09:${String(40+u).padStart(2,"0")}:00Z`,previousCallGapSeconds:u*420,initiator:u%3===0?"user":u%3===1?"assistant":"tool",initiatorReason:u%3===0?"direct user request":u%3===1?"assistant follow-up":"tool-driven continuation",initiatorConfidence:u%2===0?"exact":"estimated",fast:!!d,usageCreditConfidence:u===7?"user_override":u%4===0?"exact":u%4===1?"estimated":u%4===2?"missing":"fixture",usageCreditModel:u===4?"":`${a}-credits`,usageCreditSource:u===4?"":"fixture-rate-card",usageCreditFetchedAt:u===4?"":"2026-06-01T10:00:00Z",usageCreditTier:u%2===0?"standard":"estimated",usageCreditNote:u===2?"fixture inherited rate card":"",pricingModel:u===4?"":`${a}-pricing`,pricingEstimated:u===1||u===5,signal:w>5e4?"cache-risk":"aggregate",recommendation:w>5e4?"Review uncached aggregate input before continuing this thread.":"",tags:v,sessionId:`fixture-session-${u}`,turnId:`fixture-turn-${u}`,parentSessionId:u%3===0?"fixture-parent-session":"",parentSessionUpdatedAt:u%3===0?"2026-06-01T09:30:00Z":"",parentThread:u%3===0?"parent-thread-analysis":"",threadAttachmentLabel:u%3===0?"spawned child thread":"direct active thread",threadSource:u%3===0?"subagent":"user",subagentType:u%3===0?"analysis":"",agentRole:u%3===0?"reviewer":"",agentNickname:u%3===0?"usage-reviewer":"",project:u%2===0?"codex-usage-tracker":"local-ops",projectRelativeCwd:u%2===0?"frontend/dashboard":".",projectTags:u%2===0?["dashboard","rewrite"]:["local"],cwd:`/fixtures/${u%2===0?"codex-usage-tracker":"local-ops"}`,sourceFile:`fixture-thread-${u}.jsonl`,lineNumber:120+u,gitBranch:"experiment/frontend-rewrite",gitRemoteLabel:"origin",gitRemoteHash:`fixture-${u}`,contextWindowPct:Math.min(18+b,96),modelContextWindow:128e3,cumulativeTotalTokens:p+g+u*1e4,estimatedCacheSavings:Math.round((p-w)*1e-5*100)/100,efficiencyFlags:w>5e4?["cache-risk"]:[]}}),threads:[["thread-9f3a",142,58400,8.76,12,1.38,"High",42],["thread-7c2b",87,31200,4.21,22,1.12,"Medium",55],["thread-1a8c",64,22700,3.02,18,.98,"High",48],["thread-d3e1",53,18100,2.11,41,.81,"Low",72],["thread-b7f0",41,13600,1.65,47,.73,"Low",75],["thread-3c5d",36,9900,1.18,35,.66,"Medium",63],["thread-0e16",28,6400,.72,56,.58,"Low",82]].map(([e,t,n,a,r,s,i,o],h)=>{const f=Number(t),d=Number(n),v=Number(r),u=f*48,p=(h+1)*420;return{name:String(e),latestCallId:`fixture-call-${h}`,latestActivity:`Jun ${h+1}, 10:${String(24-h).padStart(2,"0")} AM`,latestActivityRaw:`2026-06-${String(h+1).padStart(2,"0")}T10:${String(24-h).padStart(2,"0")}:00Z`,turns:f,totalDurationSeconds:u,totalDuration:`${Math.floor(u/60)}m ${u%60}s`,averageGapSeconds:p,averageGap:`${Math.floor(p/60)}m ${p%60}s`,initiatorSummary:h%2===0?"user x4, assistant x2":"assistant x3, tool x1",modelSummary:h%2===0?"codex-1 x5, o4-mini x2":"o4-mini x3, o3 x1",effortSummary:h%2===0?"high x5, medium x2":"medium x3, low x1",totalTokens:d,cachedInput:Math.round(d*v/100),uncachedInput:Math.round(d*Math.max(100-v,0)/100),outputTokens:Math.round(d*.28),reasoningOutput:Math.round(d*.08),cost:Number(a),credits:Number(a)*25,cachePct:v,contextPct:Math.min(96,28+h*7),costPerCall:Number(s),coldResumeRisk:i,productivity:Number(o)}}),weeklyWindows:Mt.map((e,t)=>({week:e,plan:t===0?"Prolite":"Pro",observedPct:[61.4,49.2,47.7,48.3,44.5,37.4,40.1,35.8][t]??0,credits:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,projected:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,ciLow:[42156,34892,33424,34021,31241,26164,28234,29450][t]??0,ciHigh:[57467,47657,46349,47105,43326,36676,39450,41900][t]??0,confidence:t===0?"Medium":"High",note:["Prolite baseline","Drop in credits","Stable","Slight uptick","Down again","Lowest window","Recovery","Latest"][t]??""})),modelCosts:[{label:"codex-1",value:16.21,color:"#2563eb"},{label:"o3",value:12.43,color:"#1d4ed8"},{label:"o4-mini",value:7.62,color:"#059669"},{label:"gpt-4.1",value:4.91,color:"#f59e0b"},{label:"other",value:1.5,color:"#94a3b8"}],commandActions:[{title:"Show highest uncached calls",status:"Ready",owner:"Calls",description:"214 calls above the uncached threshold."},{title:"Compare Pro weeks",status:"Ready",owner:"Usage Drain",description:"Allowance windows with confidence intervals."},{title:"Find cold resumes",status:"Ready",owner:"Cache",description:"14 threads with long idle gaps."},{title:"Export support bundle",status:"Planned",owner:"Reports",description:"Local aggregate artifacts only."}],cacheSegments:[{label:"Cache read",value:38.7,color:"#2563eb"},{label:"Cache write",value:29.6,color:"#059669"},{label:"Uncached",value:31.7,color:"#7c3aed"}],cacheHeatmap:[{thread:"thread-8c1e",labels:it,values:[62,71,89,82,74,31]},{thread:"thread-2b9d",labels:it,values:[42,58,77,61,51,24]},{thread:"thread-713a",labels:it,values:[78,81,83,66,59,37]},{thread:"thread-4af2",labels:it,values:[24,36,63,54,71,44]},{thread:"thread-f9c3",labels:it,values:[18,25,41,38,52,22]}],diagnostics:[{title:"Usage Drain",status:"Ready",finding:"Projected weekly credits declined from the baseline and partially recovered in the latest window.",confidence:"High",metric:"33,842 credits / week",series:[Q("usage-drain","Projected credits","#2563eb",[41.8,46.7,45.9,32.1,33.8],1e3)]},{title:"Cache Behavior",status:"Ready",finding:"Cache hit rate is healthy overall, with spikes aligned to large cache misses and cold resumes.",confidence:"Medium",metric:"41.1% hit rate",series:[Q("cache","Cache hit %","#059669",[44,48,38,33,40])]},{title:"Thread Efficiency",status:"Ready",finding:"Long threads account for most estimated cost and are the clearest optimization target.",confidence:"High",metric:"65% cost share",series:[Q("threads","Cost share","#1d4ed8",[65,23,8,4])]},{title:"Tool And Command Activity",status:"Stale",finding:"Command volume is stable with a slight upward trend; read and shell commands dominate.",confidence:"Medium",metric:"912 commands",series:[Q("commands","Commands","#7c3aed",[542,488,611,883,912])]}],reports:[{title:"Weekly Credits",status:"Ready",owner:"Usage Drain",description:"Plan-specific weekly credits, trend lines, and confidence intervals."},{title:"Usage Remaining",status:"Ready",owner:"Usage Drain",description:"Observed remaining usage over time with reset handling."},{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Cumulative estimated cost by thread and concentration metrics."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Actual-vs-predicted drain and feature group comparisons."},{title:"Fast Mode Proxy",status:"Planned",owner:"Calls",description:"Candidate detection, speedup histogram, and confidence breakdowns."},{title:"Allowance Change",status:"Planned",owner:"Reports",description:"Week-to-week allowance estimate changes with careful language."}]};function Q(e,t,n,a,r=1,s=!1){return{id:e,label:t,color:n,dashed:s,points:a.map((i,o)=>({label:Mt[o]??`Point ${o+1}`,value:i*r}))}}function ar(e){if(window.location.protocol==="file:")throw new Error("Live refresh requires the localhost dashboard server.");if(!(e!=null&&e.api_token))throw new Error("Live refresh requires localhost dashboard API token.")}function gn(e){return{Accept:"application/json","X-Codex-Usage-Token":e.api_token||""}}function io(e,t){return new Promise((n,a)=>{if(t!=null&&t.aborted){a(ta(t));return}const r=window.setTimeout(()=>{t==null||t.removeEventListener("abort",s),n()},e);function s(){window.clearTimeout(r),a(ta(t))}t==null||t.addEventListener("abort",s,{once:!0})})}function rr(e){return(e instanceof DOMException||e instanceof Error)&&e.name==="AbortError"}function ta(e){return(e==null?void 0:e.reason)instanceof Error?e.reason:new DOMException("The request was cancelled.","AbortError")}const oo=["#2563eb","#1d4ed8","#059669","#f59e0b","#94a3b8"];function sr(e){const t=new Map;e.forEach(r=>{const s=r.model||"unknown";t.set(s,(t.get(s)??0)+r.cost)});const n=[...t.entries()].sort((r,s)=>s[1]-r[1]||r[0].localeCompare(s[0]));return(n.length>5?[...n.slice(0,4),["other",n.slice(4).reduce((r,s)=>r+s[1],0)]]:n).map(([r,s],i)=>({label:r,value:s,color:oo[i]??"#94a3b8"}))}function ir(e){if(!e.length)return[];const t=Math.max(e.reduce((n,a)=>n+pt(a),0),1);return[co(e,t),lo(e,t),uo(e,t),ho(e,t)].filter(n=>!!n).sort((n,a)=>a.credits-n.credits).map((n,a)=>({...n,rank:a+1}))}function or(e){if(!e.length)return[];const t=[{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Estimated cost concentration by loaded aggregate thread."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Highest estimated credit-impact calls from loaded aggregate rows."}];return e.some(n=>n.fast||n.effort.toLowerCase()==="low")&&t.push({title:"Fast Mode Proxy",status:"Ready",owner:"Calls",description:"Low-effort and fast-call candidates inferred from aggregate rows."}),t}function co(e,t){const n=new Map;e.forEach(i=>n.set(i.thread,[...n.get(i.thread)??[],i]));const[a,r]=[...n.entries()].sort((i,o)=>Ae(o[1],f=>f.totalTokens)-Ae(i[1],f=>f.totalTokens)||o[1].length-i[1].length)[0]??[];if(!a||!(r!=null&&r.length)||r.length<2)return null;const s=Ae(r,pt);return{rank:0,title:`Long Thread: ${a}`,severity:s/t>=.25||r.length>=8?"High":"Medium",credits:Math.round(s),share:s/t*100,summary:`${r.length.toLocaleString()} loaded calls and ${Ae(r,i=>i.totalTokens).toLocaleString()} tokens in this thread.`}}function lo(e,t){const n=e.filter(r=>r.signal==="cache-risk"||r.cachedPct<35||r.uncachedInput>5e4);if(!n.length)return null;const a=Ae(n,pt);return{rank:0,title:"Cache Misses (Large Inputs)",severity:n.some(r=>r.cachedPct<20||r.uncachedInput>5e4)?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls show low cache reuse or large uncached input.`}}function uo(e,t){const n=e.filter(r=>r.effort.toLowerCase()==="high"||r.reasoningOutput>0);if(!n.length)return null;const a=Ae(n,pt);return{rank:0,title:"High Model Effort",severity:a/t>=.25?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls use high effort or report reasoning output.`}}function ho(e,t){const n=Math.max(25e3,fo(e.map(s=>s.output),.75)),a=e.filter(s=>s.output>=n||s.tags.some(i=>["file-heavy","subagent","large"].includes(i)));if(!a.length)return null;const r=Ae(a,pt);return{rank:0,title:"Tool Output Volume",severity:a.some(s=>s.output>5e4)?"High":"Medium",credits:Math.round(r),share:r/t*100,summary:`${a.length.toLocaleString()} loaded calls have high output volume or file-heavy/subagent tags.`}}function pt(e){return e.credits>0?e.credits:e.cost*25}function Ae(e,t){return e.reduce((n,a)=>n+t(a),0)}function fo(e,t){const n=e.filter(a=>Number.isFinite(a)).sort((a,r)=>a-r);return n.length?n[Math.min(n.length-1,Math.max(0,Math.floor((n.length-1)*t)))]??0:0}function cr(e){const t=new Map;for(const a of e){if(!Number.isFinite(a.timestamp))continue;const r=lr(a.timestamp),s=t.get(r)??{label:ur(a.timestamp),timestamp:go(a.timestamp),cached:0,cost:0,input:0,output:0};s.cached+=a.cached,s.cost+=a.cost,s.input+=a.input,s.output+=a.output,t.set(r,s)}const n=mo(t);return n.length?{tokenSeries:[{id:"input",label:"Input",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input}))},{id:"output",label:"Output",color:"#059669",points:n.map(a=>({label:a.label,value:a.output}))},{id:"cached",label:"Cached",color:"#7c3aed",dashed:!0,points:n.map(a=>({label:a.label,value:a.cached}))}],costSeries:[{id:"cost",label:"Estimated Cost",color:"#f59e0b",points:n.map(a=>({label:a.label,value:a.cost}))}],cacheSeries:[{id:"cache",label:"Cache hit %",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input>0?a.cached/a.input*100:0}))}]}:{tokenSeries:[],costSeries:[],cacheSeries:[]}}function mo(e){const t=[...e.values()].sort((s,i)=>s.timestamp-i.timestamp),n=t.at(0),a=t.at(-1);if(!n||!a)return[];const r=[];for(const s=new Date(n.timestamp);s.getTime()<=a.timestamp;s.setDate(s.getDate()+1)){const i=s.getTime(),o=lr(i);r.push(e.get(o)??{label:ur(i),timestamp:i,cached:0,cost:0,input:0,output:0})}return r}function lr(e){const t=new Date(e),n=String(t.getMonth()+1).padStart(2,"0"),a=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${n}-${a}`}function go(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}function ur(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function W(e,t){var a;const n=Number(((a=e.summary)==null?void 0:a[t])??0);return Number.isFinite(n)?n:0}function po(e){if(!(!e.summary||e.load_window==="rows"))return{visibleCalls:W(e,"visible_calls"),inputTokens:W(e,"input_tokens"),cachedInputTokens:W(e,"cached_input_tokens"),uncachedInputTokens:W(e,"uncached_input_tokens"),outputTokens:W(e,"output_tokens"),reasoningOutputTokens:W(e,"reasoning_output_tokens"),totalTokens:W(e,"total_tokens"),estimatedCostUsd:W(e,"estimated_cost_usd"),usageCredits:W(e,"usage_credits")}}const bo=1e4,vo=500;async function na(e,t,n){var s,i;const a=t.limit&&t.limit>0?t.limit:vo,r=await n(e,{...t,limit:a});return(i=t.onProgress)==null||i.call(t,{status:"completed",phase:"loading_rows",message:`Loaded ${t.loadWindow==="all"?"all-history":t.loadWindow} evidence window`,completed:Number(r.loaded_row_count??((s=r.rows)==null?void 0:s.length)??0),total:Number(r.total_available_rows??r.loaded_row_count??0),percent:100}),r}async function aa(e,t,n){var o,h;const a=[];let r=0,s=null,i=Number((e==null?void 0:e.total_available_rows)??0);for(let f=0;f<1e3;f+=1){(o=t.signal)==null||o.throwIfAborted();const d=await n(e,{...t,refresh:f===0?t.refresh:!1,limit:bo,offset:r}),v=d.rows??[];s=d,a.push(...v),i=Number(d.total_available_rows??i??a.length);const u=a.length>=i||!d.has_more;if((h=t.onProgress)==null||h.call(t,{status:u?"completed":"running",phase:"loading_rows",message:"Loading all rows",completed:a.length,total:i,percent:u?100:i>0?Math.min(99,Math.floor(a.length/i*100)):0}),r+=v.length,!d.has_more||v.length===0||a.length>=i)break}return{...s??e??{},rows:a,loaded_row_count:a.length,limit:null,limit_label:"All",has_more:!1,total_available_rows:i||a.length}}function wo(){if(window.__CODEX_USAGE_BOOT__)return window.__CODEX_USAGE_BOOT__;const e=document.getElementById("usage-data");if(!(e!=null&&e.textContent))return null;try{return JSON.parse(e.textContent)}catch{return null}}async function yo(e,t={}){if(t.refresh&&(e!=null&&e.refresh_jobs_available)){const n=await _o(e,t),a={...t,refresh:!n};return a.loadWindow&&a.loadWindow!=="rows"?na(e,a,He):a.limit===0?aa(e,a,He):He(e,a)}return t.loadWindow&&t.loadWindow!=="rows"?na(e,t,He):t.limit===0?aa(e,t,He):He(e,t)}async function _o(e,t){try{return await So(e,t),!0}catch(n){if(rr(n)||n instanceof dr)throw n;return!1}}async function He(e,t={}){ar(e);const n=new URLSearchParams({refresh:t.refresh?"1":"0",limit:String(t.limit??(e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??500),_:String(Date.now())});t.loadWindow&&n.set("load_window",t.loadWindow),t.since&&n.set("since",t.since),t.offset&&t.offset>0&&n.set("offset",String(t.offset)),(t.includeArchived??vr(e))&&n.set("include_archived","1");const r=await fetch(`/api/usage?${n.toString()}`,{headers:gn(e),cache:"no-store",signal:t.signal});return await pn(r,"Usage refresh")}async function So(e,t){var o;ar(e);const n=new URLSearchParams({_:String(Date.now())});(t.includeArchived??vr(e))&&n.set("include_archived","1");const r=await fetch(`/api/refresh/start?${n.toString()}`,{headers:gn(e),cache:"no-store",signal:t.signal}),s=await pn(r,"Usage refresh start");(o=t.onProgress)==null||o.call(t,s);const i=typeof s.job_id=="string"?s.job_id:"";if(!i)throw new Error("Usage refresh start did not return a job id.");return Co(e,i,t.onProgress,t.signal)}async function Co(e,t,n,a){for(let r=0;r<600;r+=1){a==null||a.throwIfAborted();const s=new URLSearchParams({job_id:t,_:String(Date.now())}),i=await fetch(`/api/refresh/status?${s.toString()}`,{headers:gn(e),cache:"no-store",signal:a}),o=await pn(i,"Usage refresh status");if(n==null||n(o),o.status==="completed")return o;if(o.status==="failed")throw new dr(o.error||o.message||"Usage refresh failed.");await io(Math.min(1e3,150+r*50),a)}throw new Error("Usage refresh did not complete before the polling timeout.")}class dr extends Error{}function ra(e){if(!e)return{...nr,contextRuntime:rn(e)};const t=e.rows??[],n=t.map(fr),a=t.length?ke(t,b=>Number(b.total_tokens??0)):W(e,"total_tokens"),r=t.length?ke(t,b=>Number(b.estimated_cost_usd??0)):W(e,"estimated_cost_usd"),s=t.length?ke(t,b=>Number(b.cached_input_tokens??0)):W(e,"cached_input_tokens"),i=t.length?ke(t,b=>Number(b.input_tokens??0)):W(e,"input_tokens"),o=t.length?ke(t,b=>{const w=Number(b.input_tokens??0),L=Number(b.cached_input_tokens??0);return Number(b.uncached_input_tokens??Math.max(w-L,0))}):Math.max(i-s,0),h=t.length?ke(t,b=>Number(b.output_tokens??0)):W(e,"output_tokens"),f=t.length?ke(t,b=>Number(b.reasoning_output_tokens??0)):W(e,"reasoning_output_tokens"),d=i>0?s/i*100:0,v=n.length||Math.max(0,Number(e.loaded_row_count??0)),u=ko(t),p=Lo(t),g=Po({cachePct:d,cachedTokens:s,estimatedCost:r,historyScope:e.history_scope??"active",totalCalls:v,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:o,output:h,reasoningOutput:f},usageRemainingCard:jo(e)});return{...xo(e),contextRuntime:rn(e),scopeSummary:po(e),cards:g,...u,...p,calls:n,threads:wr(n),findings:ir(n),modelCosts:sr(n),reports:or(n),cacheSegments:[{label:"Cache read",value:d,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-d,0),color:"#7c3aed"}]}}function xo(e){return{...nr,contextRuntime:rn(e),tokenSeries:[],costSeries:[],cacheSeries:[],weeklyCreditSeries:[],usageRemainingSeries:[],actualVsPredictedSeries:[],calls:[],threads:[],findings:[],weeklyWindows:[],modelCosts:[],commandActions:[],cacheSegments:[],cacheHeatmap:[],diagnostics:[],reports:[]}}function ko(e){return cr(e.map(t=>({timestamp:vn(t),cached:Number(t.cached_input_tokens??0),cost:Number(t.estimated_cost_usd??0),input:Number(t.input_tokens??0),output:Number(t.output_tokens??0)})))}function Lo(e){const t=[...e].map(f=>({row:f,timestamp:vn(f)})).filter(f=>Number.isFinite(f.timestamp)).sort((f,d)=>f.timestamp-d.timestamp),n=new Map;for(const{row:f,timestamp:d}of t){const v=an(d),u=n.get(v)??{timestamp:d,credits:0,weeklyUsedPercent:null};u.credits+=Math.max(0,Number(f.usage_credits??0));const p=Oe(f.rate_limit_secondary_used_percent);p!==null&&(u.weeklyUsedPercent=p),n.set(v,u)}const a=[...n.entries()].map(([f,d])=>({label:f,...d}));let r=0;const s=a.map(f=>(r+=f.credits,{label:f.label,value:r})),i=s.map((f,d)=>{var v;return{label:f.label,value:s.length>1?(((v=s.at(-1))==null?void 0:v.value)??0)*((d+1)/s.length):f.value}}),o=a.filter(f=>f.weeklyUsedPercent!==null).map(f=>({label:f.label,value:Pt(100-(f.weeklyUsedPercent??0))})),h=Ro(e);return{weeklyCreditSeries:To(h),usageRemainingSeries:o.length?[{id:"weekly-remaining",label:"Weekly remaining",color:"#059669",points:o}]:[],actualVsPredictedSeries:s.length?[{id:"observed-drain",label:"Observed drain",color:"#2563eb",points:s},{id:"loaded-baseline",label:"Loaded-row baseline",color:"#1d4ed8",dashed:!0,points:i}]:[],weeklyWindows:h}}function Ro(e){const t=new Map;for(const n of e){const a=vn(n);if(!Number.isFinite(a))continue;const r=Mo(n,a),s=t.get(r)??{rows:[],latestTimestamp:0,latestUsedPercent:null};s.rows.push(n),a>=s.latestTimestamp&&(s.latestTimestamp=a,s.latestUsedPercent=Oe(n.rate_limit_secondary_used_percent)),t.set(r,s)}return[...t.entries()].map(([n,a])=>{var i;const r=a.rows.reduce((o,h)=>o+Math.max(0,Number(h.usage_credits??0)),0),s=a.latestUsedPercent??0;return{week:n,plan:String(((i=a.rows[0])==null?void 0:i.rate_limit_plan_type)??"unknown"),observedPct:s,credits:r,projected:s>0?r/(s/100):r,ciLow:s>0?r/(s/100)*.85:r,ciHigh:s>0?r/(s/100)*1.15:r,confidence:a.rows.length>=20?"Medium":"Low",note:`Loaded ${bn(a.rows.length)} rows`}}).sort((n,a)=>n.week.localeCompare(a.week))}function To(e){return e.length?[{id:"weekly-projected",label:"Projected weekly credits",color:"#2563eb",points:e.map(t=>({label:t.week,value:t.projected,low:t.ciLow,high:t.ciHigh}))},{id:"loaded-credits",label:"Loaded-row credits",color:"#0f766e",dashed:!0,points:e.map(t=>({label:t.week,value:t.credits}))}]:[]}function Mo(e,t){const n=We(e.rate_limit_secondary_resets_at);return n!==null&&n>0?an(n*1e3):an(t)}function an(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function rn(e){return{apiToken:String((e==null?void 0:e.api_token)??""),contextApiEnabled:!!(e!=null&&e.context_api_enabled),fileMode:window.location.protocol==="file:"}}function Po(e){return[{label:"Total Tokens",value:Me(e.totalTokens),detail:`${e.historyScope} history scope`,trend:"loaded aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Me(e.tokenBreakdown.cachedInput)},{label:"Uncached",value:Me(e.tokenBreakdown.uncachedInput)},{label:"Output",value:Me(e.tokenBreakdown.output)},{label:"Reasoning",value:Me(e.tokenBreakdown.reasoningOutput)}]},{label:"Estimated Cost",value:$o(e.estimatedCost),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.cachePct.toFixed(1)}%`,detail:`${Me(e.cachedTokens)} cached input`,trend:e.cachePct>=40?"healthy cache reuse":"cache risk",tone:e.cachePct>=40?"purple":"orange"},{label:"Total Calls",value:bn(e.totalCalls),detail:"loaded calls in this dashboard",trend:"privacy-safe",tone:"blue"},e.usageRemainingCard]}function jo(e){const t=Ao(e.observed_usage);if(t)return t;const n=No(e.allowance_windows);return n||{label:"Usage Remaining",value:"Unknown",detail:e.allowance_configured?"allowance configured; no current window":"no observed usage or allowance window",trend:e.allowance_error?`config issue: ${e.allowance_error}`:"not available in payload",tone:e.allowance_error?"red":"orange"}}function Ao(e){const t=Array.isArray(e==null?void 0:e.windows)?e.windows:[];if(!(e!=null&&e.available)||!t.length)return null;const n=hr(t,s=>Oe(s.used_percent)!==null);if(!n)return null;const a=Oe(n.used_percent)??0,r=Pt(100-a);return{label:"Usage Remaining",value:mr(r),detail:`${pr(n.label||n.key,"Observed usage")} observed usage`,trend:gr(n.resets_at)||e.source||"observed locally",tone:br(r)}}function No(e){if(!Array.isArray(e)||!e.length)return null;const t=hr(e,o=>{const h=Oe(o.remaining_percent),f=We(o.remaining_credits),d=We(o.total_credits);return h!==null||f!==null||d!==null&&d>0});if(!t)return null;const n=We(t.remaining_credits),a=We(t.total_credits),r=n!==null&&a!==null&&a>0?n/a*100:null,s=Oe(t.remaining_percent)??r;return{label:"Usage Remaining",value:s!==null?mr(Pt(s)):`${sa(n??0)} left`,detail:`${pr(t.label||t.key,"Allowance")} allowance window`,trend:[n===null?"":`${sa(n)} left`,gr(t.reset_at)].filter(Boolean).join(" · ")||"configured allowance",tone:s===null?"green":br(Pt(s))}}function hr(e,t){const n=e.filter(t);return n.find(Eo)??n[0]??null}function Eo(e){const t=We(e.window_minutes),n=`${e.key??""} ${e.label??""}`.toLowerCase();return t===10080||/\b(weekly|week|7d|7-day|7 day)\b/.test(n)}function fr(e,t=0){const n=String(e.event_timestamp??e.time??e.turn_timestamp??e.started_at??e.call_started_at??""),a=n,r=String(e.call_started_at??e.started_at??n),s=Number(e.input_tokens??0),i=Number(e.output_tokens??0),o=Number(e.reasoning_output_tokens??0),h=Number(e.cached_input_tokens??0),f=Number(e.cache_hit_ratio??e.cache_ratio??0),d=s>0?h/s*100:f*100,v=Number(e.total_tokens??s+i),u=Number(e.duration_seconds??e.call_duration_seconds??0),p=String(e.previous_call_event_timestamp??""),g=Number(e.previous_call_delta_seconds??0),b=Number(e.uncached_input_tokens??Math.max(s-h,0)),w=String(e.record_id??e.id??`${a||"row"}-${t}`),L=String(e.primary_signal??"").trim(),N=Number(e.line_number),T=Oe(e.context_window_percent),_=Number(e.model_context_window),R=Number(e.cumulative_total_tokens);return{id:w,threadKey:String(e.thread_key??""),rawTime:a,eventTimestamp:n,callStartedAt:r,time:yr(a),thread:Fo(e),model:String(e.model??"unknown"),effort:String(e.effort??"blank"),input:s,output:i,reasoningOutput:o,totalTokens:v,cachedInput:h,uncachedInput:b,cachedPct:d,cost:Number(e.estimated_cost_usd??0),credits:Number(e.usage_credits??0),duration:jt(u),durationSeconds:u,previousCallGap:jt(g),previousCallEventTimestamp:p,previousCallGapSeconds:Number.isFinite(g)?g:0,initiator:String(e.call_initiator??"unknown"),initiatorReason:String(e.call_initiator_reason??""),initiatorConfidence:String(e.call_initiator_confidence??""),fast:u>0&&v/Math.max(u,1)>4e3,usageCreditConfidence:String(e.usage_credit_confidence??"unknown"),usageCreditModel:String(e.usage_credit_model??""),usageCreditSource:String(e.usage_credit_source??""),usageCreditFetchedAt:String(e.usage_credit_fetched_at??""),usageCreditTier:String(e.usage_credit_tier??""),usageCreditNote:String(e.usage_credit_note??""),pricingModel:String(e.pricing_model??""),pricingEstimated:!!e.pricing_estimated,signal:L||(d<25?"cache-risk":"aggregate"),recommendation:String(e.recommended_action??""),tags:d<25?["uncached"]:d>60?["healthy-cache"]:[],sessionId:String(e.session_id??""),turnId:String(e.turn_id??""),parentSessionId:String(e.parent_session_id??""),parentSessionUpdatedAt:String(e.resolved_parent_session_updated_at??e.parent_session_updated_at??""),parentThread:String(e.resolved_parent_thread_name??e.parent_thread_name??""),threadAttachmentLabel:String(e.thread_attachment_label??""),threadSource:String(e.thread_source??""),subagentType:String(e.subagent_type??""),agentRole:String(e.agent_role??""),agentNickname:String(e.agent_nickname??""),project:String(e.project_name??""),projectRelativeCwd:String(e.project_relative_cwd??""),projectTags:Array.isArray(e.project_tags)?e.project_tags.map(y=>String(y)):[],cwd:String(e.cwd??""),sourceFile:String(e.source_file??""),lineNumber:Number.isFinite(N)&&N>0?N:null,gitBranch:String(e.git_branch??""),gitRemoteLabel:String(e.git_remote_label??""),gitRemoteHash:String(e.git_remote_hash??""),contextWindowPct:T,modelContextWindow:Number.isFinite(_)&&_>0?_:null,cumulativeTotalTokens:Number.isFinite(R)&&R>0?R:null,estimatedCacheSavings:Number(e.estimated_cache_savings_usd??0),efficiencyFlags:Array.isArray(e.efficiency_flags)?e.efficiency_flags.map(y=>String(y)):[]}}function Oe(e){const t=Number(e);return Number.isFinite(t)?t<=1?t*100:t:null}function We(e){const t=Number(e);return Number.isFinite(t)?t:null}function Pt(e){return Math.max(0,Math.min(100,e))}function mr(e){const t=Math.abs(e)>=10?0:1;return`${e.toFixed(t)}%`}function sa(e){return`${Me(e)} cr`}function gr(e){if(e==null||e==="")return"";const t=typeof e=="number"?e*1e3:Date.parse(e);return Number.isFinite(t)?`resets ${Do(t)}`:""}function Do(e){const t=new Date(e);return Number.isNaN(t.getTime())?String(e):`${t.toISOString().slice(0,16).replace("T"," ")} UTC`}function pr(e,t){return(e==null?void 0:e.trim())||t}function br(e){return e<20?"red":e<40?"orange":"green"}function vr(e){return typeof e.include_archived=="boolean"?e.include_archived:e.history_scope==="all-history"||e.history_scope==="all"}function Fo(e){const t=e.thread_name??e.thread??e.resolved_parent_thread_name??e.parent_thread_name;if(t&&String(t).trim())return String(t);const n=e.project_name??e.project_relative_cwd,a=e.session_id?e.session_id.slice(-6):"";return n&&a?`${n} ${a}`:e.thread_attachment_label?String(e.thread_attachment_label):"Untitled thread"}function wr(e){const t=new Map;for(const n of e)t.set(n.thread,[...t.get(n.thread)??[],n]);return[...t.entries()].map(([n,a])=>{const r=a.length,i=[...a].sort((y,k)=>ia(k)-ia(y))[0]??null,o=(i==null?void 0:i.rawTime)||(i==null?void 0:i.time)||"",h=a.reduce((y,k)=>y+k.totalTokens,0),f=a.reduce((y,k)=>y+k.cachedInput,0),d=a.reduce((y,k)=>y+k.uncachedInput,0),v=a.reduce((y,k)=>y+k.output,0),u=a.reduce((y,k)=>y+k.reasoningOutput,0),p=a.reduce((y,k)=>y+k.cost,0),g=a.reduce((y,k)=>y+k.credits,0),b=a.reduce((y,k)=>y+k.durationSeconds,0),w=a.filter(y=>y.previousCallGapSeconds>0),L=w.reduce((y,k)=>y+k.previousCallGapSeconds,0)/Math.max(w.length,1),N=f+d,T=N>0?f/N*100:a.reduce((y,k)=>y+k.cachedPct,0)/Math.max(r,1),_=a.map(y=>y.contextWindowPct).filter(y=>typeof y=="number"&&Number.isFinite(y)),R=T<25?"High":T<45?"Medium":"Low";return{name:n,latestCallId:(i==null?void 0:i.id)??"",latestActivity:yr(o),latestActivityRaw:o,turns:r,totalDurationSeconds:b,totalDuration:jt(b),averageGapSeconds:L,averageGap:jt(L),initiatorSummary:zt(a.map(y=>y.initiator)),modelSummary:zt(a.map(y=>y.model)),effortSummary:zt(a.map(y=>y.effort)),totalTokens:h,cachedInput:f,uncachedInput:d,outputTokens:v,reasoningOutput:u,cost:p,credits:g,cachePct:T,contextPct:_.length?Math.max(..._):null,costPerCall:p/Math.max(r,1),coldResumeRisk:R,productivity:Math.max(20,Math.round(T-p/Math.max(r,1)*4))}}).sort((n,a)=>a.cost-n.cost).slice(0,20)}function ia(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function zt(e,t=3){const n=new Map;for(const a of e){const r=a.trim()||"unknown";n.set(r,(n.get(r)??0)+1)}return[...n.entries()].sort((a,r)=>r[1]-a[1]||a[0].localeCompare(r[0])).slice(0,t).map(([a,r])=>`${a} x${bn(r)}`).join(", ")||"unknown"}function ke(e,t){return e.reduce((n,a)=>n+t(a),0)}async function pn(e,t){let n;try{n=await e.json()}catch(a){if(e.ok)throw new Error(`${t} response could not be read as JSON: ${Io(a)}`);n={}}if(!e.ok){const a=typeof n.error=="string"?n.error:`${t} request failed (${e.status})`;throw new Error(a)}return n}function Io(e){return e instanceof Error?e.message:String(e)}function bn(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Me(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function $o(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function jt(e){if(!Number.isFinite(e)||e<=0)return"-";if(e<60)return`${e.toFixed(0)}s`;const t=Math.floor(e/60),n=Math.round(e%60);return`${t}m ${n}s`}function yr(e){const t=new Date(e);return Number.isNaN(t.getTime())?e||"-":new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).format(t)}function vn(e){return Date.parse(String(e.started_at??e.call_started_at??e.time??e.event_timestamp??e.turn_timestamp??""))}const Pe=1440*60*1e3;function Oo(e,t,n=window.location.search){const a=_r(n);if(!a.active)return e;const r=e.calls.filter(s=>Uo(s,a));return r.length===e.calls.length?e:Wo(e,r,`${t} filtered`)}function _r(e){var h,f,d,v,u,p;const t=new URLSearchParams(e),n=((h=t.get("model"))==null?void 0:h.trim())??"",a=((f=t.get("effort"))==null?void 0:f.trim())??"",r=((d=t.get("confidence")||t.get("pricing"))==null?void 0:d.trim())??"",s=((v=t.get("date")||t.get("time"))==null?void 0:v.trim())??"",i=((u=t.get("from"))==null?void 0:u.trim())??"",o=((p=t.get("to"))==null?void 0:p.trim())??"";return{model:n,effort:a,confidence:r,datePreset:s,dateStart:i,dateEnd:o,active:!!(n||a||r||s||i||o)}}function Uo(e,t){return!(t.model&&e.model!==t.model||t.effort&&e.effort!==t.effort||t.confidence&&!Vo(e,t.confidence)||!Ko(e,t))}function Vo(e,t){return t==="official"||t==="cost-exact"?!!(e.pricingModel&&!e.pricingEstimated):t==="estimated"||t==="cost-estimated"?e.pricingEstimated:t==="unpriced"||t==="cost-unpriced"?!e.pricingModel:t==="credit-exact"?e.usageCreditConfidence==="exact":t==="credit-estimated"?e.usageCreditConfidence==="estimated":t==="credit-override"?e.usageCreditConfidence==="user_override":t==="credit-missing"?e.usageCreditConfidence==="missing"||e.usageCreditConfidence==="unknown":!0}function Ko(e,t){const n=qo(t);if(!n.active)return!0;if(n.invalid)return!1;const a=Date.parse(e.rawTime||e.time);return!(!Number.isFinite(a)||n.start!==null&&a=n.endExclusive)}function qo(e){if(e.datePreset&&e.datePreset!=="all"&&e.datePreset!=="custom"){const a=Ho(e.datePreset);return a?{active:!0,invalid:!1,...a}:{active:!1,invalid:!1,start:null,endExclusive:null}}const t=oa(e.dateStart),n=oa(e.dateEnd);return t!==null&&n!==null&&t>n?{active:!0,invalid:!0,start:t,endExclusive:n+Pe}:{active:t!==null||n!==null,invalid:!1,start:t,endExclusive:n===null?null:n+Pe}}function Ho(e){const t=Qo(new Date);if(e==="today")return{start:t,endExclusive:t+Pe};if(e==="last-7-days")return{start:t-6*Pe,endExclusive:t+Pe};if(e==="this-week"){const a=new Date(t).getDay(),r=a===0?-6:1-a,s=t+r*Pe;return{start:s,endExclusive:s+7*Pe}}if(e==="this-month"){const n=new Date(t),a=new Date(n.getFullYear(),n.getMonth(),1).getTime(),r=new Date(n.getFullYear(),n.getMonth()+1,1).getTime();return{start:a,endExclusive:r}}return null}function oa(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function Qo(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function Wo(e,t,n="filtered"){const a=t.reduce((u,p)=>u+p.totalTokens,0),r=t.reduce((u,p)=>u+p.cost,0),s=t.reduce((u,p)=>u+p.cachedInput,0),i=t.reduce((u,p)=>u+p.uncachedInput,0),o=t.reduce((u,p)=>u+p.output,0),h=t.reduce((u,p)=>u+p.reasoningOutput,0),f=t.reduce((u,p)=>u+p.input,0),d=f>0?s/f*100:0,v=e.cards.find(u=>u.label==="Usage Remaining")??{label:"Usage Remaining",value:"Unknown",detail:"not available in filtered view",trend:"not available in payload",tone:"orange"};return{...e,cards:zo({cachePct:d,cachedTokens:s,estimatedCost:r,historyScope:n,totalCalls:t.length,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:i,output:o,reasoningOutput:h},usageRemainingCard:v}),...Bo(t),calls:t,threads:wr(t),findings:ir(t),modelCosts:sr(t),reports:or(t),cacheSegments:[{label:"Cache read",value:d,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-d,0),color:"#7c3aed"}]}}function zo({cachePct:e,cachedTokens:t,estimatedCost:n,historyScope:a,totalCalls:r,totalTokens:s,tokenBreakdown:i,usageRemainingCard:o}){return[{label:"Total Tokens",value:Qe(s),detail:`${a} history scope`,trend:"filtered aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Qe(i.cachedInput)},{label:"Uncached",value:Qe(i.uncachedInput)},{label:"Output",value:Qe(i.output)},{label:"Reasoning",value:Qe(i.reasoningOutput)}]},{label:"Estimated Cost",value:Jo(n),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.toFixed(1)}%`,detail:`${Qe(t)} cached input`,trend:e>=40?"healthy cache reuse":"cache risk",tone:e>=40?"purple":"orange"},{label:"Total Calls",value:Go(r),detail:"loaded calls matching filters",trend:"legacy shell filters",tone:"blue"},o]}function Bo(e){return cr(e.map(t=>({timestamp:Date.parse(t.rawTime||t.time),cached:t.cachedInput,cost:t.cost,input:t.input,output:t.output})))}function Qe(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Go(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Jo(e){return new Intl.NumberFormat("en-US",{currency:"USD",maximumFractionDigits:2,minimumFractionDigits:2,style:"currency"}).format(e)}const Sr=[{id:"overview",label:"Overview",description:"High-level telemetry",icon:Es},{id:"investigator",label:"Investigate",description:"Root-cause evidence",icon:Ns},{id:"compression-lab",label:"Compression Lab",description:"Context savings",icon:Ls},{id:"calls",label:"Calls",description:"Model-call table",icon:$s},{id:"threads",label:"Threads",description:"Thread efficiency",icon:Vs},{id:"usage-drain",label:"Limits",description:"Allowance intelligence",icon:Us},{id:"cache-context",label:"Cache And Context",description:"Cache and cold resumes",icon:Ms},{id:"diagnostics",label:"Diagnostics Notebook",description:"Technical report",icon:xs},{id:"reports",label:"Reports",description:"Generated analyses",icon:Rs},{id:"settings",label:"Settings",description:"Local configuration",icon:Fs}],Cr=[{label:"Files",icon:js,target:"settings"},{label:"Commands",icon:Ss,target:"investigator"},{label:"Models",icon:ks,target:"calls"}];function xr(e){return vs(e)}const Zo=[{value:"day",label:"24 hours",ariaLabel:"Last 24h"},{value:"week",label:"7 days",ariaLabel:"Last 7 days"},{value:"rows",label:"Recent",ariaLabel:"Recent rows"},{value:"all",label:"All time",ariaLabel:"All time"}];function Xo(e){const t=e.refreshing||!e.canUseLiveApi,n=e.loadWindow==="rows",a=`${e.loadedRowCount.toLocaleString()} detail row${e.loadedRowCount===1?"":"s"} cached`,r=n?`${e.loadedRowCount.toLocaleString()} loaded / ${e.totalAvailableRows.toLocaleString()} total`:`${e.totalAvailableRows.toLocaleString()} calls analyzed · ${a}`,s=n?`${e.loadedRowCount.toLocaleString()} of ${e.totalAvailableRows.toLocaleString()} evidence rows loaded`:`Focused pages analyze all ${e.totalAvailableRows.toLocaleString()} calls in scope; ${e.loadedRowCount.toLocaleString()} call rows are cached for immediate detail views.`,i=n?e.rowLoadStatus:`${e.rowLoadModeLabel} analysis uses ${e.totalAvailableRows.toLocaleString()} calls; ${a}`;return c.jsxs("section",{className:"data-window-control","aria-label":"Analysis scope",children:[c.jsxs("div",{className:"data-window-summary",children:[c.jsx("span",{children:"Analysis scope"}),c.jsx("strong",{children:e.rowLoadModeLabel}),c.jsx("small",{title:s,children:r})]}),c.jsx("div",{className:"data-window-options",role:"group","aria-label":"Choose loaded call window",children:Zo.map(o=>c.jsx("button",{type:"button","aria-label":o.ariaLabel,"aria-pressed":e.loadWindow===o.value,disabled:t,onClick:()=>e.onWindowChange(o.value),children:o.label},o.value))}),e.loadWindow==="rows"?c.jsxs("div",{className:"row-window-editor",children:[c.jsx("input",{"aria-label":"Rows to load slider","aria-valuetext":`${e.finitePendingLoadLimit.toLocaleString()} recent rows`,type:"range",min:1,max:e.rowLimitSliderMax,step:100,value:e.rowLimitSliderValue,onChange:o=>e.onSliderChange(o.target.value),disabled:t}),c.jsx("input",{"aria-label":"Rows to load",type:"number",min:1,step:100,value:e.pendingLoadLimit,onChange:o=>e.onDraftChange(o.target.value),disabled:t}),c.jsx("button",{type:"button","data-primary":"true",onClick:e.onApply,disabled:t||!e.rowLimitChanged,children:e.loadLabel}),c.jsx("button",{type:"button",onClick:e.onLoadMore,disabled:t||!e.hasMoreRows,children:e.loadMoreLabel})]}):null,e.refreshing?c.jsxs("div",{className:"row-load-progress","aria-label":"Row loading progress",children:[c.jsx("div",{className:"row-load-progress-track",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":e.refreshProgressPercent??void 0,children:c.jsx("span",{style:{width:`${e.refreshProgressPercent??8}%`}})}),c.jsxs("span",{children:[e.refreshProgressPercent===null?e.refreshProgressText:`${Math.round(e.refreshProgressPercent)}% loaded`,c.jsx("button",{className:"icon-button",type:"button",onClick:()=>void e.onCancel(),"aria-label":"Cancel refresh",title:"Cancel refresh",children:c.jsx(un,{size:13})})]})]}):null,c.jsx("span",{className:"sr-only",role:"status","aria-live":"polite",children:i})]})}const wn=[{value:"all",label:"All time"},{value:"today",label:"Today"},{value:"this-week",label:"This week"},{value:"last-7-days",label:"Last 7 days"},{value:"this-month",label:"This month"},{value:"custom",label:"Custom"}],kr=[{value:"all",label:"All confidence"},{value:"cost-exact",label:"Exact cost"},{value:"cost-estimated",label:"Estimated cost"},{value:"cost-unpriced",label:"Unpriced cost"},{value:"credit-exact",label:"Exact credit"},{value:"credit-estimated",label:"Estimated credit"},{value:"credit-override",label:"Credit override"},{value:"credit-missing",label:"Missing credit"}];function Yo({activeView:e,locationSearch:t,model:n,onUrlChange:a}){const r=_r(t),s=C.useMemo(()=>ca(n.calls.map(g=>g.model)),[n.calls]),i=C.useMemo(()=>ca(n.calls.map(g=>g.effort)),[n.calls]),o=r.dateStart||r.dateEnd?"custom":ec(r.datePreset),h=nc(r,o);if(e==="calls"||e==="call"||!n.calls.length)return null;function f(g){const b=new URL(window.location.href);g(b),a(b)}function d(g,b){f(w=>{g==="confidence"&&w.searchParams.delete("pricing"),!b||b==="all"?w.searchParams.delete(g):w.searchParams.set(g,b)})}function v(g){f(b=>{if(!g||g==="all"){b.searchParams.delete("date"),b.searchParams.delete("time"),b.searchParams.delete("from"),b.searchParams.delete("to");return}b.searchParams.set("date",g),b.searchParams.set("time",g),g!=="custom"&&(b.searchParams.delete("from"),b.searchParams.delete("to"))})}function u(g,b){f(w=>{b?(w.searchParams.set(g,b),w.searchParams.set("date","custom"),w.searchParams.set("time","custom")):(w.searchParams.delete(g),!w.searchParams.get("from")&&!w.searchParams.get("to")&&(w.searchParams.delete("date"),w.searchParams.delete("time")))})}function p(){f(g=>{for(const b of["model","effort","confidence","pricing","date","time","from","to"])g.searchParams.delete(b)})}return c.jsxs("section",{className:"global-filter-strip span-all","aria-label":"Dashboard filters",children:[c.jsxs("strong",{children:[c.jsx(As,{size:15}),"Filters"]}),c.jsxs("label",{children:[c.jsx("span",{children:"Model"}),c.jsxs("select",{"aria-label":"Global model filter",value:r.model||"all",onChange:g=>d("model",g.target.value),children:[c.jsx("option",{value:"all",children:"All models"}),s.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Effort"}),c.jsxs("select",{"aria-label":"Global effort filter",value:r.effort||"all",onChange:g=>d("effort",g.target.value),children:[c.jsx("option",{value:"all",children:"All effort"}),i.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Confidence"}),c.jsx("select",{"aria-label":"Global confidence filter",value:tc(r.confidence),onChange:g=>d("confidence",g.target.value),children:kr.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Time"}),c.jsx("select",{"aria-label":"Global time filter",value:o,onChange:g=>v(g.target.value),children:wn.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))}),h?c.jsx("span",{className:"filter-status","data-state":h.state,"aria-live":"polite",children:h.label}):null]}),c.jsxs("label",{children:[c.jsx("span",{children:"Start"}),c.jsx("input",{"aria-label":"Global start date",type:"date",value:r.dateStart,onChange:g=>u("from",g.target.value)})]}),c.jsxs("label",{children:[c.jsx("span",{children:"End"}),c.jsx("input",{"aria-label":"Global end date",type:"date",value:r.dateEnd,onChange:g=>u("to",g.target.value)})]}),c.jsxs("button",{className:"toolbar-button",type:"button",disabled:!r.active,onClick:p,children:[c.jsx(un,{size:15}),"Clear filters"]})]})}function ca(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean))).sort((t,n)=>t.localeCompare(n))}function ec(e){return wn.some(t=>t.value===e)?e:"all"}function tc(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":kr.some(t=>t.value===e)?e:"all"}function nc(e,t){var r;const n=ua(e.dateStart),a=ua(e.dateEnd);if(n!==null&&a!==null&&n>a)return{label:"Invalid date range",state:"error"};if(t==="custom"&&(e.dateStart||e.dateEnd))return{label:ac(e.dateStart,e.dateEnd),state:"active"};if(t!=="all"){const s=((r=wn.find(o=>o.value===t))==null?void 0:r.label)??t,i=rc(t);return{label:i?`${s}: ${la(i.start)} to ${la(ze(i.endExclusive,-1))}`:s,state:"active"}}return null}function ac(e,t){return e&&t?`Custom: ${e} to ${t}`:e?`Custom: from ${e}`:t?`Custom: through ${t}`:"Custom range"}function rc(e){const t=sc();if(e==="today")return{start:t,endExclusive:ze(t,1)};if(e==="this-week"){const n=ic(t);return{start:n,endExclusive:ze(n,7)}}return e==="last-7-days"?{start:ze(t,-6),endExclusive:ze(t,1)}:e==="this-month"?{start:new Date(t.getFullYear(),t.getMonth(),1),endExclusive:new Date(t.getFullYear(),t.getMonth()+1,1)}:null}function sc(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function ic(e){const t=e.getDay();return ze(e,t===0?-6:1-t)}function ze(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function la(e){const t=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${e.getFullYear()}-${t}-${n}`}function ua(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function oc(e){return xr(e)&&e!=="call"}function sn(e,t="overview"){return e==="insights"?"overview":xr(e)?e:t}function da(e=window.location.search,t="calls"){const n=new URLSearchParams(e).get("return"),a=sn(n,t);return oc(a)?a:t}function ha(e=window.location.search){return new URLSearchParams(e).has("return")}function cc(e){var t,n;return((t=Sr.find(a=>a.id===e))==null?void 0:t.label)??((n=Cr.find(a=>a.target===e))==null?void 0:n.label)??"Calls"}function fa(e,t=window.location.search){return new URLSearchParams(t).get("history")==="all"?"all":e}function ma(e,t=window.location.href){const n=new URL(t);return e==="all"?n.searchParams.set("history","all"):n.searchParams.delete("history"),n}const lc={investigator:["finding"],threads:["thread","expand","threads","thread_q","risk","thread_call_sort","thread_call_page"],"cache-context":["cache_thread"],reports:["report"],"usage-drain":["usage_plan","usage_effort","usage_subagents","usage_sample","usage_confidence","limit_window","limit_hypothesis"],diagnostics:["diagnostic_source","diagnostic_fact"],calls:["explore","detail","call_q","source","sort","direction","density","page"],call:["record","return","mode","max_entries","max_chars","include_tool_output","include_compaction_history"]};function xt(e,t,n=[]){const a=new Set([t,...Array.isArray(n)?n:[n]]);for(const[r,s]of Object.entries(lc))if(!a.has(r))for(const i of s)e.searchParams.delete(i)}function ga(e){let t=!1;return e.searchParams.get("view")==="insights"&&(e.searchParams.set("view","overview"),t=!0),e.searchParams.get("return")==="insights"&&(e.searchParams.set("return","overview"),t=!0),t}const Lr=[{key:"overview",title:"Overview",path:"/api/diagnostics/overview",refreshPath:"/api/diagnostics/overview/refresh"},{key:"toolOutput",title:"Tool Output",path:"/api/diagnostics/tool-output",refreshPath:"/api/diagnostics/tool-output/refresh"},{key:"commands",title:"Commands",path:"/api/diagnostics/commands",refreshPath:"/api/diagnostics/commands/refresh"},{key:"gitInteractions",title:"Git Interactions",path:"/api/diagnostics/git-interactions",refreshPath:"/api/diagnostics/git-interactions/refresh"},{key:"fileReads",title:"File Reads",path:"/api/diagnostics/file-reads",refreshPath:"/api/diagnostics/file-reads/refresh"},{key:"fileModifications",title:"File Modifications",path:"/api/diagnostics/file-modifications",refreshPath:"/api/diagnostics/file-modifications/refresh"},{key:"readProductivity",title:"Read Productivity",path:"/api/diagnostics/read-productivity",refreshPath:"/api/diagnostics/read-productivity/refresh"},{key:"concentration",title:"Concentration",path:"/api/diagnostics/concentration",refreshPath:"/api/diagnostics/concentration/refresh"},{key:"guidedSummary",title:"What Is Driving Usage?",path:"/api/diagnostics/guided-summary",refreshPath:"/api/diagnostics/guided-summary/refresh"},{key:"usageDrain",title:"Usage Drain",path:"/api/diagnostics/usage-drain",refreshPath:"/api/diagnostics/usage-drain/refresh"}],At=new Map,Dt=new Map;function uc(){At.clear(),Dt.clear()}async function Vl(e,t,n={}){Sn(t);const a=gc(e);return n.signal?Nt(a,t,n.signal):mc(Dt,_n(e,t,n.cacheKey),()=>Nt(a,t))}async function Kl(e,t={}){Sn(e);const n=await fetch(`/api/diagnostics/refresh?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:t.signal}),a=await Ft(n,"Diagnostic snapshot refresh"),r=a.sections??(Tr(a)?await dc(e,await Rr(a,e,t),t.signal):{});At.set(yn(e),r);for(const[s,i]of Object.entries(r))Dt.set(_n(s,e),i);return r}async function ql(e,t,n={}){Sn(t);const a=await fetch(`${e.refreshPath}?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),r=await Ft(a,e.title),s=Tr(r)?await hc(t,e,await Rr(r,t,n),n.signal):r,i=yn(t),o=At.get(i),h=o?await Promise.resolve(o):{};return At.set(i,{...h,[e.key]:s}),Dt.set(_n(e.key,t),s),s}async function Rr(e,t,n){var r,s,i,o;let a=e;for((r=n.onProgress)==null||r.call(n,a);a.status==="pending"||a.status==="running";){const h=n.pollIntervalMs??((s=a.next)==null?void 0:s.poll_after_ms)??250;await fc(h,n.signal);const f=new URLSearchParams({job_id:a.job_id,_:String(Date.now())}),d=await fetch(`/api/diagnostics/refresh/status?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});a=await Ft(d,"Diagnostic refresh status"),(i=n.onProgress)==null||i.call(n,a)}if(a.status!=="completed")throw new Error(`Diagnostic refresh failed: ${((o=a.error)==null?void 0:o.code)??a.status}`);return a}async function dc(e,t,n){const a=await Promise.all(Lr.map(async r=>[r.key,await Nt(r,e,n)]));return Object.fromEntries(a)}async function hc(e,t,n,a){return Nt(t,e,a)}function Tr(e){if(!e||typeof e!="object")return!1;const t=e;return t.schema==="codex-usage-tracker-analysis-job-v1"&&t.job_kind==="diagnostic-refresh"&&typeof t.job_id=="string"}function fc(e,t){return t!=null&&t.aborted?Promise.reject(t.reason??new DOMException("Aborted","AbortError")):e<=0?Promise.resolve():new Promise((n,a)=>{const r=()=>{window.clearTimeout(s),t==null||t.removeEventListener("abort",r),a((t==null?void 0:t.reason)??new DOMException("Aborted","AbortError"))},s=window.setTimeout(()=>{t==null||t.removeEventListener("abort",r),n()},e);t==null||t.addEventListener("abort",r,{once:!0})})}function mc(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function yn(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function _n(e,t,n=""){return`snapshot:${yn(t)}:${n}:${e}`}function gc(e){const t=Lr.find(n=>n.key===e);if(!t)throw new Error(`Unknown diagnostic snapshot: ${e}`);return t}async function Nt(e,t,n){const a=await fetch(`${e.path}?_=${Date.now()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n});return await Ft(a,e.title)}function Sn(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Ft(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(typeof n.error=="string"&&n.error)throw new Error(n.error);return n}const pa=[{key:"facts",label:"Top Facts",title:"Top Diagnostic Facts",path:"/api/diagnostics/facts",limit:50},{key:"tools",label:"Tools",title:"Tool and Function Activity",path:"/api/diagnostics/tools",limit:25},{key:"compactions",label:"Compactions",title:"Compaction Activity",path:"/api/diagnostics/compactions",limit:25}],Mr=new Map,Pr=new Map;function pc(){uc(),Mr.clear(),Pr.clear()}async function Hl(e,t,n={}){Er(t);const a=pa.find(f=>f.key===e)??pa[0],r=vc(n.sort??"uncached"),s=n.direction??"desc",i=Math.max(1,Math.round(n.limit??a.limit)),o=Math.max(0,Math.round(n.offset??0)),h=async()=>{const f=new URLSearchParams({limit:String(i),offset:String(o),sort:r,direction:s});Nr(f,"include_archived",n.includeArchived);const d=await fetch(`${a.path}?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});return await Dr(d,a.title)};return n.signal?h():jr(Mr,bc(a.key,t,i,o,r,s,n.cacheKey,n.includeArchived),h)}async function Ql(e,t,n={}){Er(t);const a=Math.max(1,Math.round(n.limit??8)),r=Math.max(0,Math.round(n.offset??0)),s=n.sort??"tokens",i=n.direction??"desc",o=async()=>{const h=String(e.fact_type??""),f=String(e.fact_name??"");if(!h||!f)throw new Error("Diagnostic fact type and name are required.");const d=new URLSearchParams({fact_type:h,fact_name:f,limit:String(a),offset:String(r),sort:s,direction:i});Nr(d,"include_archived",n.includeArchived);const v=await fetch(`/api/diagnostics/fact-calls?${d.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),u=await Dr(v,"Diagnostic fact calls");return{calls:(u.rows??[]).map((p,g)=>fr(p,g)),rawPayload:u}};return n.signal?o():jr(Pr,wc(e,t,a,r,s,i,n.cacheKey,n.includeArchived),o)}function jr(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function Ar(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function bc(e,t,n,a,r,s,i="",o){return["facts",e,Ar(t),i,o??"default",n,a,r,s].join(":")}function vc(e){return e==="total"?"tokens":e==="latest"?"time":e}function wc(e,t,n,a,r,s,i="",o){return["fact-calls",Ar(t),i,o??"default",String(e.fact_type??""),String(e.fact_name??""),n,a,r,s].join(":")}function Nr(e,t,n){n!==void 0&&e.set(t,String(n))}function Er(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Dr(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(n.error)throw new Error(n.error);return n}const yc=[{id:"usage-snapshot",endpoint:"/api/usage",dataClass:"snapshot",schema:"codex-usage-tracker-dashboard-v1"},{id:"overview-summary",endpoint:"/api/summary",dataClass:"aggregate",schema:"codex-usage-tracker-summary-v1"},{id:"overview-recommendations",endpoint:"/api/recommendations",dataClass:"aggregate",schema:"codex-usage-tracker-recommendations-v1"},{id:"calls",endpoint:"/api/calls",dataClass:"aggregate",schema:"codex-usage-tracker-calls-v1"},{id:"threads",endpoint:"/api/threads",dataClass:"aggregate",schema:"codex-usage-tracker-threads-v1"},{id:"thread-calls",endpoint:"/api/thread-calls",dataClass:"detail",schema:"codex-usage-tracker-thread-calls-v1"},{id:"investigator-agentic",endpoint:"/api/investigations/agentic",dataClass:"aggregate",schema:"codex-usage-tracker-agentic-investigation-v1"},{id:"investigator-walk",endpoint:"/api/investigations/walk",dataClass:"userAction",schema:"codex-usage-tracker-investigation-walk-v1"},{id:"diagnostics-facts",endpoint:"/api/diagnostics/facts",dataClass:"aggregate",schema:null},{id:"diagnostics-fact-calls",endpoint:"/api/diagnostics/fact-calls",dataClass:"detail",schema:null},{id:"diagnostics-dedupe",endpoint:"/api/diagnostics/dedupe",dataClass:"aggregate",schema:"codex-usage-tracker-dedupe-diagnostics-v1"},{id:"diagnostics-snapshot",endpoint:"/api/diagnostics/{snapshot}",dataClass:"aggregate",schema:null},{id:"compression-profile",endpoint:"/api/compression/profile",dataClass:"aggregate",schema:"codex-usage-tracker-compression-api-v1"},{id:"reports",endpoint:"/api/reports/pack",dataClass:"aggregate",schema:"codex-usage-tracker-reports-pack-v1"}],_c=yc,Sc=new Map(_c.map(e=>[e.id,e])),Cc=15*6e4,xc=3e4,Fr={snapshot:ot({persistedCache:"aggregate-only"}),aggregate:ot({persistedCache:"aggregate-only"}),detail:ot(),heavyJob:ot({cancellation:"shared-job",staleTime:1e3}),userAction:ot({retry:0,staleTime:0})};function kc({sourceKey:e,sourceRevision:t}){return{sourceKey:ba(e,"local-api"),sourceRevision:ba(t,"unversioned")}}function Lc(e,t,n={},...a){return["dashboard",e.id,t.sourceKey,t.sourceRevision,Mc(n),...a]}function Rc(e){return["dashboard",e.id]}function Tc(e){const t=Sc.get(e);if(!t)throw new Error(`Unknown dashboard query definition: ${e}`);return t}function Ir(e){const t=Fr[e];return{gcTime:t.gcTime,refetchOnReconnect:t.refetchOnReconnect,refetchOnWindowFocus:t.refetchOnWindowFocus,retry:t.retry,staleTime:t.staleTime}}function Wl({enabled:e,hasData:t,isError:n,isFetching:a,isPending:r}){return e?t?a?"updating":"ready":n?"error":a||r?"loading":"waiting":"waiting"}function zl(e){const t=e.filter(a=>a==="ready"||a==="updating").length,n=e.length;return{ready:t,total:n,percent:n===0?100:Math.round(t/n*100),loading:e.filter(a=>a==="loading").length,errors:e.filter(a=>a==="error").length}}function Mc(e){return{historyScope:e.historyScope??"active",loadWindow:e.loadWindow??"all",limit:e.limit??null,since:e.since??""}}function ba(e,t){return(e==null?void 0:e.trim())||t}function ot(e={}){return{staleTime:xc,gcTime:Cc,retry:1,refetchOnReconnect:!1,refetchOnWindowFocus:!1,cancellation:"observer",persistedCache:"none",...e}}const Pc=new Set(["command_text","content_fragment","content_fragments","excerpt","indexed_content","indexed_fragment","indexed_fragments","prompt","raw_context","raw_output","snippet","tool_output"]),jc=new Set(["includes_indexed_content","includes_raw_fragment","includes_raw_fragments","indexed_content_included","raw_content_included","raw_context_included"]),Ac=new Set(["codex-usage-tracker-context-v1"]);function va(e){return on(e,new WeakSet)}function on(e,t){if(!e||typeof e!="object")return!0;if(t.has(e))return!1;t.add(e);const n=Array.isArray(e)?e.every(a=>on(a,t)):Object.entries(e).every(([a,r])=>{const s=a.toLowerCase();return Pc.has(s)||jc.has(s)&&r===!0||s==="schema"&&typeof r=="string"&&Ac.has(r)?!1:on(r,t)});return t.delete(e),n}const Nc="codexUsageDashboard",Ec=1,Y="usageSnapshots",Dc=6,Fc=10080*60*1e3,Ic={async read(e){if(!e.sourceRevision)return null;try{const t=await ya();if(!t)return null;const n=await $r(t.transaction(Y,"readonly").objectStore(Y).get(wa(e)));return!n||n.sourceRevision!==e.sourceRevision||Date.now()-n.storedAt>Fc?null:va(n.payload)?n.payload:(await $c(t,n.cacheKey),null)}catch{return null}},async write(e,t){if(!(!e.sourceRevision||!va(t)))try{const n=await ya();if(!n)return;const a=n.transaction(Y,"readwrite");a.objectStore(Y).put({...e,cacheKey:wa(e),payload:t,storedAt:Date.now()}),await Cn(a),await Oc(n)}catch{}}};async function $c(e,t){const n=e.transaction(Y,"readwrite");n.objectStore(Y).delete(t),await Cn(n)}function wa(e){const{historyScope:t,loadWindow:n,limit:a,since:r}=e.scope;return JSON.stringify([e.sourceKey,t,n,a,r])}function ya(){return typeof indexedDB>"u"?Promise.resolve(null):new Promise(e=>{const t=indexedDB.open(Nc,Ec);t.onupgradeneeded=()=>{t.result.objectStoreNames.contains(Y)||t.result.createObjectStore(Y,{keyPath:"cacheKey"})},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)})}function $r(e){return new Promise((t,n)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>n(e.error??new Error("IndexedDB request failed"))})}function Cn(e){return new Promise((t,n)=>{e.oncomplete=()=>t(),e.onerror=()=>n(e.error??new Error("IndexedDB transaction failed")),e.onabort=()=>n(e.error??new Error("IndexedDB transaction aborted"))})}async function Oc(e){const t=e.transaction(Y,"readonly"),a=(await $r(t.objectStore(Y).getAll())).sort((i,o)=>o.storedAt-i.storedAt).slice(Dc);if(!a.length)return;const r=e.transaction(Y,"readwrite"),s=r.objectStore(Y);a.forEach(i=>s.delete(i.cacheKey)),await Cn(r)}const Uc={kind:"production",load:yo},Vc="codexUsageDashboardRuntimeMetadata",Kc=2048,cn=Tc("usage-snapshot"),Or={all:Rc(cn),snapshot:(e,t,n)=>Lc(cn,kc({sourceKey:e,sourceRevision:t}),n)};function qc(){return new ki({defaultOptions:{queries:{...Ir("aggregate")}}})}const xn=qc();async function Hc({currentPayload:e,historyScope:t,loadWindow:n,loadLimit:a,since:r=null,onProgress:s,queryClient:i=xn,refresh:o=!1,snapshotStore:h=Ic,transport:f=Uc}){const d=Ui(a,t,r,n),v=kn(e),u=Or.snapshot(v.sourceKey,v.sourceRevision,d);!i.getQueryData(u)&&Gc(e,d)&&i.setQueryData(u,e),o&&await i.invalidateQueries({queryKey:u,exact:!0});const p=_a(e,d),g=await i.fetchQuery({queryKey:u,...Ir(cn.dataClass),queryFn:async({signal:b})=>{var T;const w=!o&&p?await h.read(p):null;if(w)return s==null||s({status:"completed",phase:"loading_rows",message:"Loaded cached dashboard snapshot",completed:Number(w.loaded_row_count??((T=w.rows)==null?void 0:T.length)??0),total:Number(w.total_available_rows??w.loaded_row_count??0),percent:100}),w;const L=await f.load(e,{refresh:o,limit:Vi(d),includeArchived:d.historyScope==="all",loadWindow:n,since:d.since,onProgress:s,signal:b}),N=p?{...p,sourceRevision:String(L.latest_refresh_at??p.sourceRevision)}:_a(L,d);return N&&await h.write(N,L),L},staleTime:o?0:Fr.snapshot.staleTime});return Bc(zc(g,d)),g}function _a(e,t){if(!(e!=null&&e.api_token))return null;const n=String(e.latest_refresh_at??"");return n?{sourceKey:Ur(e),sourceRevision:n,scope:t}:null}async function Qc(e=xn){await e.cancelQueries({queryKey:Or.all})}function Wc(e){return bi(e)||rr(e)}function zc(e,t){return{schema:"codex-usage-dashboard-runtime-v1",...kn(e),scope:t,updatedAt:Date.now()}}function kn(e){return{sourceKey:Ur(e),sourceRevision:Jc(e)}}function Bc(e,t=Zc()){if(t)try{const n=JSON.stringify(e);n.length<=Kc&&t.setItem(Vc,n)}catch{}}function Gc(e,t){var o;if(!e||!(((o=e.rows)==null?void 0:o.length)??0))return!1;const n=ct(e),a=t.limit===null?n===0:n===t.limit,r=(e.since??null)===t.since,s=fn(e)===t.loadWindow,i=e.include_archived||e.history_scope==="all-history"?"all":"active";return a&&r&&s&&i===t.historyScope}function Ur(e){const t=e,n=Number((t==null?void 0:t.payload_cache_version)??0),a=String((t==null?void 0:t.payload_cache_key)??(e!=null&&e.api_token?"live":"static"));return`${n}:${a}`}function Jc(e){return String((e==null?void 0:e.latest_refresh_at)??"unversioned")}function Zc(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}const Xc=new Set(["duplicate_cumulative_total"]);function Yc({canUseLiveApi:e,payload:t,shellI18n:n}){const a=el(t,e,n);return c.jsxs("section",{className:"environment-status","aria-label":n.t("aria.dashboard_status","Dashboard status"),children:[c.jsx("span",{className:"environment-status-title",children:n.t("aria.dashboard_status","Dashboard status")}),c.jsx("div",{className:"environment-status-grid",children:a.map(r=>c.jsx("span",{className:"environment-chip","data-state":r.state,title:r.title,children:r.label},r.label))})]})}function el(e,t,n){const a=sl(e==null?void 0:e.parser_diagnostics,n);return[{label:n.t("badge.unofficial_project","Unofficial project"),state:"neutral",title:n.t("badge.unofficial_project_title","Codex Usage Tracker is independent and is not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI. OpenAI and Codex are trademarks of OpenAI.")},{label:t?`${n.t("badge.live","Live")} API`:n.t("badge.static","Static"),state:t?"ready":"warn",title:t?"Local API token present for refresh actions.":"Static embedded snapshot; live refresh is unavailable."},nl(e,n),al(e,n),rl(e,n),tl(e),...a?[a]:[]]}function tl(e){const t=e==null?void 0:e.dedupe,n=Number((t==null?void 0:t.excluded_copied_rows)||0),a=Number((t==null?void 0:t.canonical_rows)||0),r=Number((t==null?void 0:t.physical_rows)||0);return{label:`Deduped · ${n.toLocaleString()} copied excluded`,state:"ready",title:`Billable totals use ${a.toLocaleString()} canonical rows while preserving ${r.toLocaleString()} physical source rows.`}}function nl(e,t){var s;const n=!!(e!=null&&e.pricing_configured),a=((s=e==null?void 0:e.pricing_snapshot_warning)==null?void 0:s.trim())??"",r=Vr(e==null?void 0:e.pricing_source);return{label:n?t.t("badge.costs","Costs"):t.t("badge.no_costs","No costs"),state:n?a?"warn":"ready":"missing",title:n?[r||"Pricing configured",a].filter(Boolean).join(" - "):t.t("pricing.configure_hint","Run codex-usage-tracker update-pricing to configure estimated costs.")}}function al(e,t){var s,i;const n=((s=e==null?void 0:e.allowance_error)==null?void 0:s.trim())??"",a=((i=e==null?void 0:e.rate_card_error)==null?void 0:i.trim())??"",r=Vr(e==null?void 0:e.allowance_source)||"Codex credit rates";return n?{label:t.t("state.allowance_config_error","Allowance config error"),state:"missing",title:`Config error: ${n}`}:a?{label:"Rate-card error",state:"missing",title:`Rate-card error: ${a}`}:e!=null&&e.allowance_configured?{label:t.t("state.allowance_configured","Allowance configured"),state:"ready",title:r}:e!=null&&e.rate_card_configured?{label:"Credit rates loaded",state:"ready",title:r}:{label:t.t("action.set_limits","Set limits"),state:"warn",title:"No local allowance windows are configured."}}function rl(e,t){const n=e==null?void 0:e.project_metadata_privacy,a=(n==null?void 0:n.mode)||(e==null?void 0:e.privacy_mode)||"normal",r=a==="normal",s=[n!=null&&n.cwd_redacted?"cwd redacted":"",n!=null&&n.project_names_redacted?"project names redacted":"",n!=null&&n.git_remote_label_hidden?"git remote hidden":"",n!=null&&n.relative_cwd_hidden?"relative cwd hidden":"",n!=null&&n.git_branch_hidden?"git branch hidden":"",n!=null&&n.tags_hidden?"tags hidden":""].filter(Boolean);return{label:r?t.t("badge.metadata_normal","Metadata normal"):Kr(t.t("badge.metadata_mode","Metadata {mode}"),{mode:a}),state:r?"ready":"warn",title:r?"Project metadata is shown normally.":[`Metadata mode: ${a}`,...s].join(" - ")}}function sl(e,t){const n=Object.entries(e??{}).filter(([s,i])=>Number(i||0)>0&&!Xc.has(s));if(!n.length)return null;const a=n.reduce((s,[,i])=>s+Number(i||0),0),r=n.map(([s,i])=>`${s}=${Number(i||0)}`).join(", ");return{label:t.t("badge.parser_warnings","Parser warnings"),state:"missing",title:Kr(t.t("parser.warnings_title","Latest refresh reported {count} parser diagnostics: {entries}. Run codex-usage-tracker inspect-log to investigate schema drift."),{count:a.toLocaleString(),entries:r})}}function Vr(e){if(!e)return"";if(typeof e=="string")return e;const t=e.label??e.name??e.type??e.path??"";return typeof t=="string"?t:""}function Kr(e,t){return e.replace(/\{([a-zA-Z0-9_]+)\}/g,(n,a)=>t[a]??n)}async function Sa(e){var n;if((n=navigator.clipboard)!=null&&n.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly","readonly"),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}const il={"highest-cost":"Highest Cost Threads","context-bloat":"Context Bloat","cache-misses":"Cache Misses","pricing-gaps":"Pricing Gaps","codex-credits":"Codex Credits","reasoning-spike":"Reasoning Spike"};function Bl(e,t){return t==="context-bloat"?Number(e.contextWindowPct??0)>=60||e.totalTokens>=2e5:t==="cache-misses"?e.signal==="cache-risk"||e.cachedPct<30||e.uncachedInput>=5e4:t==="pricing-gaps"?e.pricingEstimated||!Number.isFinite(e.cost):t==="codex-credits"?e.credits>0:t==="reasoning-spike"?e.reasoningOutput>0:!0}function ol(e){return il[e]??e}const cl=se(()=>O(()=>import("./OverviewPage.js"),__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50])),"OverviewPage"),ll=se(()=>O(()=>import("./InvestigatorPage.js"),__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52])),"InvestigatorPage"),ul=se(()=>O(()=>import("./CompressionLabPage.js"),__vite__mapDeps([53,1,2,34,4,6,9,10,17,25,26,12,54])),"CompressionLabPage"),dl=se(()=>O(()=>import("./ExploreRoutePage.js"),__vite__mapDeps([55,1,2,44,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48,8,9,10,56])),"ExploreRoutePage"),hl=se(()=>O(()=>import("./CallInvestigatorPage.js"),__vite__mapDeps([57,1,2,46,33,19,37,38,47,25,26,12])),"CallInvestigatorPage"),fl=se(()=>O(()=>import("./ThreadsPage.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27])),"ThreadsPage"),ml=se(()=>O(()=>import("./UsageDrainPage.js"),__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39])),"UsageDrainPage"),gl=se(()=>O(()=>import("./CacheContextPage.js"),__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12])),"CacheContextPage"),pl=se(()=>O(()=>import("./DiagnosticsPage.js"),__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12])),"DiagnosticsPage"),bl=se(()=>O(()=>import("./ReportsPage.js"),__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43])),"ReportsPage"),vl=se(()=>O(()=>import("./SettingsPage.js"),__vite__mapDeps([58,1,2,33,19,32,38,47,17,25,26,12,59])),"SettingsPage");function wl(e){return c.jsx(C.Suspense,{fallback:c.jsx(_l,{activeView:e.activeView}),children:yl(e)})}function yl(e){const{activePreset:t,activeRecordId:n,activeView:a,autoRefreshEnabled:r,applicationI18n:s,backFromCallInvestigator:i,callBackLabel:o,canLoadAllRows:h,canUseLiveApi:f,contextRuntime:d,copyCallInvestigatorLink:v,dashboardPayload:u,globalFilters:p,globalQuery:g,hasMoreRows:b,historyScope:w,loadWindow:L,loadAllRows:N,loadedRowCount:T,loadLimit:_,loadMoreRows:R,scopeSince:y,model:k,navigateView:j,onRefresh:E,openCallInvestigator:D,refreshing:me,refreshState:bt,setContextApiEnabled:vt,sourceIdentity:$,totalAvailableRows:at}=e;switch(a){case"overview":return c.jsx(cl,{model:k,contextRuntime:d,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onRefresh:E,globalQuery:g,runtime:{historyScope:w,loadLimit:_,loadWindow:L,loadedRowCount:T,scopeSince:y,totalAvailableRows:at},refreshing:me,canLoadMoreRows:f&&b,onLoadMoreRows:R,onOpenInvestigator:D,onCopyCallLink:v,onNavigateView:j,globalFilters:p});case"investigator":return c.jsx(ll,{model:k,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:v,onNavigateView:j});case"compression-lab":return c.jsx(ul,{contextRuntime:d,includeArchived:w==="all",since:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision});case"calls":return c.jsx(dl,{model:k,globalQuery:g,activePreset:t,onRefresh:E,contextRuntime:d,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onContextApiEnabledChange:vt,onOpenInvestigator:D,onCopyCallLink:v,onNavigateView:j});case"call":return c.jsx(hl,{model:k,recordId:n,contextRuntime:d,onContextApiEnabledChange:vt,onNavigateRecord:D,onCopyCallLink:v,onBackToCalls:i,backLabel:o});case"threads":return c.jsx(fl,{model:k,globalQuery:g,onOpenInvestigator:D,onCopyCallLink:v,globalFilters:p,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onNavigateView:j});case"usage-drain":return c.jsx(ml,{model:k,contextRuntime:d,includeArchived:w==="all",sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:v});case"cache-context":return c.jsx(gl,{model:k,contextRuntime:d,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:v});case"diagnostics":return c.jsx(pl,{model:k,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,rowLoadControls:{loadedRowCount:T,totalAvailableRows:at,canLoadMoreRows:f&&b,canLoadAllRows:h,refreshing:me,onLoadMoreRows:R,onLoadAllRows:N},onOpenInvestigator:D,onCopyCallLink:v,globalFilters:p});case"reports":return c.jsx(bl,{model:k,refreshState:bt,includeArchived:w==="all",loadWindow:L,loadLimit:_,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:v});case"settings":return c.jsx(vl,{model:k,payload:u,historyScope:w,loadWindow:L,loadLimit:_,scopeSince:y,loadedRowCount:T,totalAvailableRows:at,canUseLiveApi:f,autoRefreshEnabled:r,refreshState:bt,applicationI18n:s})}}function _l({activeView:e}){return c.jsxs("section",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:["Loading ",e.replace("-"," "),"..."]})}const Ca=1e4,Sl={1:"overview",2:"calls",3:"threads",4:"diagnostics"},Cl=new Set(["call","compression-lab","diagnostics","investigator"]);function qr(e){return!Cl.has(e)}function xl(e){return e instanceof Element?!!e.closest('input, select, textarea, button, [contenteditable="true"]'):!1}function Hr(){var Un;const e=C.useRef(null),t=C.useMemo(()=>wo(),[]),[n,a]=C.useState(t),[r,s]=C.useState(()=>ra(t)),[i,o]=C.useState(()=>{const m=new URLSearchParams(window.location.search);return sn(m.get("view"))}),[h,f]=C.useState(()=>new URLSearchParams(window.location.search).get("record")??""),[d,v]=C.useState(()=>da()),[u,p]=C.useState(()=>ha()),[g,b]=C.useState(()=>new URLSearchParams(window.location.search).get("q")??""),[w,L]=C.useState(()=>new URLSearchParams(window.location.search).get("preset")??""),[N,T]=C.useState(()=>window.location.search),[_,R]=C.useState("Stored snapshot loaded just now"),[y,k]=C.useState(null),[j,E]=C.useState(!1),[D,me]=C.useState(!1),[bt,vt]=C.useState(!1),[$,at]=C.useState(()=>Ws(t)),It=C.useRef(!1),[G,Ln]=C.useState(()=>je(ct(t),500)),[Ue,wt]=C.useState(()=>je(ct(t),500)),[q,Rn]=C.useState(()=>Ki(t)),[J,yt]=C.useState(()=>fa(Qt(t))),[Tn,Mn]=C.useState(r.contextRuntime.contextApiEnabled),H=!!(n!=null&&n.api_token),Qr=C.useMemo(()=>kn(n),[n]),A=C.useMemo(()=>Da(n,$),[n,$]),Pn=C.useMemo(()=>({...r.contextRuntime,contextApiEnabled:Tn}),[Tn,r.contextRuntime]),Wr=C.useMemo(()=>Oo(r,J,N),[J,N,r]),jn=i==="calls"||i==="call"?r:Wr,rt=qr(i),$t=je(Ue,G,500),ge=Math.max(0,Number((n==null?void 0:n.loaded_row_count)??((Un=n==null?void 0:n.rows)==null?void 0:Un.length)??r.calls.length??0)),Ve=Math.max(0,Number((n==null?void 0:n.total_available_rows)??ge)),zr=Ue!==G,An=Qi({currentLimit:G,loadedRows:ge,pendingLimit:Ue}),Br=Math.min($t,An),Nn=!!(n!=null&&n.has_more)||Ve>0&&ge{const m=new URL(window.location.href);ga(m)&&Ke(m)},[]),C.useEffect(()=>{function m(){const S=window.location.search,M=new URLSearchParams(S);o(sn(M.get("view"))),f(M.get("record")??""),v(da(S)),p(ha(S)),b(M.get("q")??""),L(M.get("preset")??""),yt(fa(Qt(n),S)),T(S)}return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[n]),C.useEffect(()=>{function m(S){var oe;if(xl(S.target))return;if(S.key==="/"){S.preventDefault(),(oe=e.current)==null||oe.focus();return}const M=Sl[S.key];M&&(S.preventDefault(),st(M))}return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[]),C.useEffect(()=>{function m(){vt(window.scrollY>320)}return m(),window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]);function ts(m){const S=i==="call"?d:i;v(S),p(i==="call"?u:!0),o("call"),f(m);const M=new URL(window.location.href);xt(M,i,i==="call"?d:[]),M.searchParams.set("view","call"),M.searchParams.set("record",m),M.searchParams.set("return",S),Fn(M)}function ns(){st(d)}function as(m){b(m),L("");const S=new URL(window.location.href);S.searchParams.delete("preset"),m?S.searchParams.set("q",m):S.searchParams.delete("q"),Ke(S)}async function ie(m={}){var _t;if(j)return;It.current=!0;const S=m.loadLimit??G,M=m.loadWindow??q,oe=Ht(M),pe=m.historyScope??J,ee=m.refresh??!0,Ot=!!(n!=null&&n.refresh_jobs_available);E(!0),k(Ot?{status:"running",phase:ee?"refreshing_index":"loading_rows",message:`${ee?"Refreshing":"Loading"} ${Te(M,S)}`}:null),R(`${ee?"Refreshing index for":"Loading"} ${Te(M,S)}...`);let qe=!1;try{const B=await Hc({currentPayload:n,refresh:ee,loadLimit:S,loadWindow:M,since:oe,historyScope:pe,onProgress:Vt=>{qe||(qe=Vt.message==="Loaded cached dashboard snapshot"),k(Vt),R(Xn(Vt,pe))}});pc(),a(B),s(ra(B)),Mn(!!B.context_api_enabled);const xe=M==="rows"?je(ct(B,S),S):S;Ln(xe),wt(xe),Rn(M);const Vn=Qt(B,pe);yt(Vn),Hi(xe,Vn,M);const Ut=B.loaded_row_count??((_t=B.rows)==null?void 0:_t.length)??0,Kn=B.total_available_rows??Ut;R(M==="rows"?`${qe?"Cache hit; l":ee?"Refreshed index; l":"L"}oaded ${Ut.toLocaleString()} of ${Kn.toLocaleString()} calls from ${Te(M,xe)}`:`${qe?"Cache hit; ":ee?"Refreshed index; ":""}${Te(M,xe)} analysis ready across ${Kn.toLocaleString()} calls; ${Ut.toLocaleString()} detail rows cached`)}catch(B){if(k(null),Wc(B)){R("Refresh cancelled; stored snapshot remains visible");return}const xe=new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});R(`${Zi(B)} Stored snapshot kept at ${xe}`)}finally{k(null),E(!1)}}async function rs(){await Qc(),k(null),E(!1),R("Refresh cancelled; stored snapshot remains visible")}C.useEffect(()=>{document.documentElement.lang=A.language,document.documentElement.dir=A.direction},[A.direction,A.language]),C.useEffect(()=>{var B;const m=Number((n==null?void 0:n.total_available_rows)??0),S=Number((n==null?void 0:n.loaded_row_count)??((B=n==null?void 0:n.rows)==null?void 0:B.length)??0),M=qi(),oe=(M==null?void 0:M.historyScope)??J,pe=(M==null?void 0:M.loadLimit)??G,ee=(M==null?void 0:M.loadWindow)??q,Ot=fn(n),qe=oe!==J||ee!==Ot||ee==="rows"&&pe!==ct(n),_t=S>0;!H||!qe&&_t||m<=0||j||It.current||(It.current=!0,qe&&(yt(oe),Ln(pe),wt(pe),Rn(ee),Ke(ma(oe))),ie({refresh:!1,historyScope:oe,loadLimit:pe,loadWindow:ee}))},[H,n,J,G,q,j]),C.useEffect(()=>{!H&&D&&me(!1)},[D,H]),C.useEffect(()=>{if(!D||!H||!rt)return;const m=window.setInterval(()=>{ie()},Ca);return()=>window.clearInterval(m)},[D,rt,H,n,J,G,q,j]),C.useEffect(()=>{if(!D||!H||!rt)return;function m(){document.visibilityState==="visible"&&ie()}return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[D,rt,H,n,J,G,q,j]);function In(m){const S=m.trim();wt(Math.max(1,gt(S===""?Number.NaN:Number(S))))}function ss(m){In(m)}function is(){ie({refresh:!1,loadLimit:Ue,loadWindow:"rows"})}function os(){ie({refresh:!1,loadWindow:"all"})}function $n(){wt(En),ie({refresh:!1,loadLimit:En,loadWindow:q})}function cs(m){m!==q&&ie({refresh:!1,loadWindow:m})}function ls(m){const S=m==="all"?"all":"active";yt(S),Ke(ma(S)),ie({refresh:!1,historyScope:S})}function us(m){if(me(m),m){if(!rt){R("Auto refresh pauses on this evidence-heavy view");return}R(`Auto refresh every ${Ca/1e3}s`),ie()}else R("Auto refresh paused")}function ds(m){at(m),zs(m)}async function hs(){try{const m=new URL(window.location.href);if(ga(m),xt(m,i,i==="call"?d:[]),!await Sa(m.toString()))throw new Error("Clipboard unavailable");R("Copied current view link")}catch{R("Copy unavailable in browser")}}async function fs(m){try{const S=new URL(window.location.href);xt(S,i,i==="call"?d:[]);const M=i==="call"?d:i;if(S.searchParams.set("view","call"),S.searchParams.set("record",m),S.searchParams.set("return",M),!await Sa(S.toString()))throw new Error("Clipboard unavailable");R("Copied call investigator link")}catch{R("Copy unavailable in browser")}}async function ms(){const m=await Bi(i,jn,{contextRuntime:Pn,historyScope:J,loadWindow:q,loadLimit:G,scopeSince:(n==null?void 0:n.since)??Ht(q),loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,refreshState:_},g,w);if(!m.rowCount){R(`No ${m.label} to export`);return}Ai(m.filename,m.csv),R(`Exported ${m.rowCount} ${m.label}`)}function gs(){L("");const m=new URL(window.location.href);m.searchParams.delete("preset"),Ke(m),R("Investigation preset cleared")}function ps(){window.scrollTo({top:0,behavior:"smooth"})}return c.jsx(no,{value:A,children:c.jsxs("div",{className:"app-shell","data-dashboard-localization-root":!0,children:[c.jsxs("aside",{className:"sidebar",children:[c.jsxs("div",{className:"brand",children:[c.jsx("div",{className:"brand-mark",children:c.jsx(Os,{size:22})}),c.jsxs("div",{children:[c.jsx("strong",{children:"Codex Usage Tracker"}),c.jsx("span",{children:A.t("dashboard.eyebrow","Local telemetry console")})]})]}),c.jsxs("div",{className:"local-pill",children:[c.jsx("span",{"aria-hidden":"true"}),"Local data only"]}),c.jsx(Yc,{payload:n,canUseLiveApi:H,shellI18n:A}),c.jsx("nav",{className:"primary-nav","aria-label":"Primary",children:Sr.map(m=>{const S=m.icon,M=i===m.id||i==="call"&&m.id==="calls";return c.jsxs("button",{type:"button","aria-pressed":M,className:M?"active":"",onClick:()=>st(m.id),children:[c.jsx(S,{size:18}),c.jsx("span",{children:A.navLabel(m.id,m.label)})]},m.id)})}),c.jsxs("div",{className:"secondary-block",role:"group","aria-label":"Quick Links",children:[c.jsx("span",{children:"Quick Links"}),Cr.map(m=>{const S=m.icon;return c.jsxs("button",{type:"button",onClick:()=>st(m.target),children:[c.jsx(S,{size:16}),m.label]},m.label)})]})]}),c.jsxs("main",{className:"workspace",children:[c.jsxs("div",{className:"unofficial-banner",role:"note","aria-label":"Unofficial project notice",children:[c.jsx(Is,{size:16}),c.jsxs("span",{children:[c.jsx("strong",{children:"Unofficial project."})," Not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI."]})]}),c.jsxs("header",{className:"topbar","aria-label":"Dashboard toolbar",children:[c.jsxs("label",{className:"global-search",children:[c.jsx("span",{className:"sr-only",children:A.t("filter.search","Search dashboard")}),c.jsx("input",{ref:e,"aria-label":A.t("filter.search","Search dashboard"),value:g,onChange:m=>as(m.target.value),placeholder:A.t("filter.search_placeholder","Search calls, threads, models, diagnostics...")})]}),c.jsxs("div",{className:"topbar-actions",children:[c.jsxs("div",{className:"topbar-scope-controls",children:[A.languages.length>1?c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("language.label","Language")}),c.jsx("select",{"data-localization-skip":"true","aria-label":A.t("language.label","Language"),value:A.language,onChange:m=>ds(m.target.value),children:A.languages.map(m=>c.jsx("option",{value:m.code,children:m.native_name||m.english_name||m.code},m.code))})]}):null,c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("nav.history","History")}),c.jsxs("select",{"aria-label":"History scope",title:Dn,value:J,onChange:m=>ls(m.target.value),disabled:j||!H,children:[c.jsx("option",{value:"active",children:A.t("option.active_sessions_only","Active")}),c.jsx("option",{value:"all",children:A.t("option.all_history","All history")})]}),c.jsx("small",{className:"sr-only",children:Dn})]})]}),c.jsx(Xo,{canUseLiveApi:H,finitePendingLoadLimit:$t,hasMoreRows:Nn,loadLabel:A.t("nav.load","Load"),loadMoreLabel:A.t("button.load_more","Load more"),loadWindow:q,loadedRowCount:ge,pendingLoadLimit:Ue,refreshProgressPercent:Xr,refreshProgressText:Yr,refreshing:j,rowLimitChanged:zr,rowLimitSliderMax:An,rowLimitSliderValue:Br,rowLoadModeLabel:Jr,rowLoadStatus:Gr,totalAvailableRows:Ve,onApply:is,onCancel:rs,onDraftChange:In,onLoadMore:$n,onSliderChange:ss,onWindowChange:cs}),c.jsxs("div",{className:"topbar-meta",children:[c.jsxs("div",{className:"topbar-statuses",children:[w?c.jsxs("button",{className:"toolbar-button",type:"button",onClick:gs,children:[c.jsx(un,{size:15}),A.t("button.clear","Clear")," ",ol(w)]}):null,c.jsxs("label",{className:"topbar-toggle",children:[c.jsx("input",{"aria-label":"Auto refresh",type:"checkbox",checked:D,onChange:m=>us(m.target.checked),disabled:j||!H}),c.jsx("span",{children:"Auto"})]})]}),c.jsxs("div",{className:"topbar-icon-actions",children:[c.jsx("button",{className:"icon-button",type:"button",onClick:hs,"aria-label":A.t("button.copy_link","Copy link"),title:A.t("button.copy_link","Copy link"),children:c.jsx(Ts,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:ms,"aria-label":A.t("button.export_csv","Export CSV"),title:A.t("button.export_csv","Export CSV"),children:c.jsx(Ps,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:On,"aria-label":A.t("button.refresh","Refresh"),title:A.t("button.refresh","Refresh"),disabled:j,children:c.jsx(Ds,{size:17})})]})]})]})]}),c.jsx("p",{className:"sr-only",role:"status","aria-live":"polite",children:_}),c.jsx(wl,{activeView:i,model:jn,navigateView:st,onRefresh:On,refreshState:_,globalQuery:g,activePreset:w,activeRecordId:h,contextRuntime:Pn,setContextApiEnabled:Mn,openCallInvestigator:ts,copyCallInvestigatorLink:fs,callBackLabel:u?`Back to ${cc(d)}`:A.t("button.back_to_dashboard","Back to dashboard"),backFromCallInvestigator:ns,dashboardPayload:n,sourceIdentity:Qr,historyScope:J,loadWindow:q,scopeSince:(n==null?void 0:n.since)??Ht(q),loadLimit:G,loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,applicationI18n:A,refreshing:j,hasMoreRows:Nn,canLoadAllRows:es,loadMoreRows:$n,loadAllRows:os,globalFilters:c.jsx(Yo,{activeView:i,locationSearch:N,model:r,onUrlChange:Ke})})]}),bt?c.jsxs("button",{className:"to-top-button",type:"button",onClick:ps,"aria-label":"Back to top",children:[c.jsx(Cs,{size:18}),A.t("button.top","Top")]}):null]})});function On(){ie()}}function kl(){return c.jsx(Li,{client:xn,children:c.jsx(Hr,{})})}const Gl=Object.freeze(Object.defineProperty({__proto__:null,App:Hr,RoutedApp:kl,shouldAutoRefreshUsageView:qr},Symbol.toStringTag,{value:"Module"}));export{Dl as $,Cs as A,jl as B,Di as C,Ps as D,$l as E,Ns as F,Ss as G,Ms as H,va as I,Et as J,z as K,Al as L,Va as M,ne as N,Hl as O,vc as P,Vl as Q,Ds as R,Fs as S,Ql as T,Rs as U,$s as V,Bl as W,Sa as X,As as Y,un as Z,ol as _,Ts as a,El as a0,hi as a1,si as a2,Gt as a3,qa as a4,ai as a5,ri as a6,Bt as a7,Ua as a8,yi as a9,ci as aa,Nl as ab,Il as ac,xt as ad,da as ae,Te as af,Gl as ag,Ol as b,I as c,Ai as d,ce as e,Re as f,Ni as g,zl as h,Wl as i,Le as j,cr as k,Fl as l,Xt as m,Lr as n,ql as o,Rt as p,Kl as q,ji as r,pa as s,Ul as t,Oa as u,fr as v,Ir as w,Lc as x,kc as y,Tc as z}; + */const la=I("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),En="codex-usage-dashboard-language",qs={"button.back_to_dashboard":"Back to dashboard","button.clear":"Clear","button.copy_link":"Copy link","button.enable_context_loading":"Enable context loading","button.export_csv":"Export CSV","button.full_serialized_analysis":"Run full serialized analysis","button.hide_details":"Hide details","button.include_tool_output":"Include tool output","button.load_more":"Load more","button.load_older_context":"Load older entries","button.next_call":"Next call","button.no_char_limit":"No char limit","button.open_investigator":"Open investigator","button.previous_call":"Previous call","button.refresh":"Refresh","button.show_compaction_history":"Show compacted replacement","button.show_tool_output":"Show tool output","button.top":"Top","button.show_turn_evidence":"Show turn log evidence","badge.live":"Live","dashboard.eyebrow":"Local Codex analytics","dashboard.call_details":"Call Details","dashboard.title":"Usage Dashboard","dashboard.view.call":"Call Investigator","dashboard.view.calls":"Calls","dashboard.view.insights":"Overview","dashboard.view.overview":"Overview","dashboard.view.threads":"Threads","detail.next_action":"Next action","filter.search":"Search dashboard","filter.search_placeholder":"Search calls, threads, models, diagnostics...","language.label":"Language","nav.history":"History","nav.load":"Load","nav.live":"Live","option.active_sessions_only":"Active","option.all_history":"All history","status.paused":"Paused","status.static":"Static"},Hs={overview:"dashboard.view.overview",calls:"dashboard.view.calls",call:"dashboard.view.call",threads:"dashboard.view.threads"};function Al(e,t){return typeof t=="string"?e.translateText(t):e.formatText(t.template,t.values)}function Dn(e,t){const a=Fn(e),n=In(t,a),r=(e==null?void 0:e.translation_catalog)??{},s=r[n]??((e==null?void 0:e.language)===n?e==null?void 0:e.translations:void 0)??{},i=r.en??((e==null?void 0:e.language)==="en"?e.translations:void 0)??{},o={...qs,...i,...s},h=Ws(i,s),f=Qs(i,s),d=a.find(p=>p.code===n),b=(d==null?void 0:d.dir)==="rtl"||!d&&(e==null?void 0:e.language_direction)==="rtl"?"rtl":"ltr",u=p=>n==="zh-Hans"?bs(p,h,f):h.get(p)??p;return{language:n,direction:b,languages:a,t:(p,g)=>o[p]??g??p,translateText:u,formatText:(p,g)=>u(p).replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu,(v,w)=>String(g[String(w)]??v)),navLabel:(p,g)=>{const v=Hs[p];return v?o[v]??g:g}}}function Qs(e,t){const a=[];for(const[n,r]of Object.entries(e)){const s=t[n];if(!s||s===r||!r.includes("{"))continue;const i=[],o=[];let h=0;for(const f of r.matchAll(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu)){const d=f.index??h;o.push(qa(r.slice(h,d))),o.push("(.+?)"),i.push(f[1]),h=d+f[0].length}o.push(qa(r.slice(h))),a.push({pattern:new RegExp(`^${o.join("")}$`,"u"),placeholders:i,translatedTemplate:s})}return a.sort((n,r)=>r.translatedTemplate.length-n.translatedTemplate.length)}function qa(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function Ws(e,t){const a=new Map;for(const[n,r]of Object.entries(e)){const s=t[n];s&&s!==r&&a.set(r,s)}return a}function Fn(e){var a;const t=((a=e==null?void 0:e.available_languages)==null?void 0:a.filter(n=>n.code))??[];return t.length?t:[{code:"en",english_name:"English",native_name:"English",dir:"ltr"}]}function zs(e){return In(Gs()||(e==null?void 0:e.language)||"en",Fn(e))}function Bs(e){var t;try{(t=window.localStorage)==null||t.setItem(En,e)}catch{}}function Gs(){var e;try{return((e=window.localStorage)==null?void 0:e.getItem(En))??""}catch{return""}}function In(e,t){if(new Set(t.map(s=>s.code)).has(e))return e;const n=e.toLowerCase(),r=t.find(s=>s.code.toLowerCase()===n);return(r==null?void 0:r.code)??"en"}const Js=Dn(null,"en"),$n=C.createContext(Js);function Zs({value:e,children:t}){return c.jsx($n.Provider,{value:e,children:t})}function On(){return C.useContext($n)}var Et=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Ne,be,Be,xn,Xs=(xn=class extends Et{constructor(){super();j(this,Ne);j(this,be);j(this,Be);k(this,Be,t=>{if(typeof window<"u"&&window.addEventListener){const a=()=>t();return window.addEventListener("visibilitychange",a,!1),()=>{window.removeEventListener("visibilitychange",a)}}})}onSubscribe(){l(this,be)||this.setEventListener(l(this,Be))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,be))==null||t.call(this),k(this,be,void 0))}setEventListener(t){var a;k(this,Be,t),(a=l(this,be))==null||a.call(this),k(this,be,t(n=>{typeof n=="boolean"?this.setFocused(n):this.onFocus()}))}setFocused(t){l(this,Ne)!==t&&(k(this,Ne,t),this.onFocus())}onFocus(){const t=this.isFocused();this.listeners.forEach(a=>{a(t)})}isFocused(){var t;return typeof l(this,Ne)=="boolean"?l(this,Ne):((t=globalThis.document)==null?void 0:t.visibilityState)!=="hidden"}},Ne=new WeakMap,be=new WeakMap,Be=new WeakMap,xn),Un=new Xs,Ys={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},we,ca,kn,ei=(kn=class{constructor(){j(this,we,Ys);j(this,ca,!1)}setTimeoutProvider(e){k(this,we,e)}setTimeout(e,t){return l(this,we).setTimeout(e,t)}clearTimeout(e){l(this,we).clearTimeout(e)}setInterval(e,t){return l(this,we).setInterval(e,t)}clearInterval(e){l(this,we).clearInterval(e)}},we=new WeakMap,ca=new WeakMap,kn),Bt=new ei;function ti(e){setTimeout(e,0)}var ai=typeof window>"u"||"Deno"in globalThis;function ae(){}function ni(e,t){return typeof e=="function"?e(t):e}function ri(e){return typeof e=="number"&&e>=0&&e!==1/0}function si(e,t){return Math.max(e+(t||0)-Date.now(),0)}function Gt(e,t){return typeof e=="function"?e(t):e}function ii(e,t){return typeof e=="function"?e(t):e}function Ha(e,t){const{type:a="all",exact:n,fetchStatus:r,predicate:s,queryKey:i,stale:o}=e;if(i){if(n){if(t.queryHash!==ua(i,t.options))return!1}else if(!ut(t.queryKey,i))return!1}if(a!=="all"){const h=t.isActive();if(a==="active"&&!h||a==="inactive"&&h)return!1}return!(typeof o=="boolean"&&t.isStale()!==o||r&&r!==t.state.fetchStatus||s&&!s(t))}function Qa(e,t){const{exact:a,status:n,predicate:r,mutationKey:s}=e;if(s){if(!t.options.mutationKey)return!1;if(a){if(lt(t.options.mutationKey)!==lt(s))return!1}else if(!ut(t.options.mutationKey,s))return!1}return!(n&&t.state.status!==n||r&&!r(t))}function ua(e,t){return((t==null?void 0:t.queryKeyHashFn)||lt)(e)}function lt(e){return JSON.stringify(e,(t,a)=>Jt(a)?Object.keys(a).sort().reduce((n,r)=>(n[r]=a[r],n),{}):a)}function ut(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="object"&&typeof t=="object"?Object.keys(t).every(a=>ut(e[a],t[a])):!1}var oi=Object.prototype.hasOwnProperty;function Vn(e,t,a=0){if(e===t)return e;if(a>500)return t;const n=Wa(e)&&Wa(t);if(!n&&!(Jt(e)&&Jt(t)))return t;const s=(n?e:Object.keys(e)).length,i=n?t:Object.keys(t),o=i.length,h=n?new Array(o):{};let f=0;for(let d=0;d{Bt.setTimeout(t,e)})}function li(e,t,a){return typeof a.structuralSharing=="function"?a.structuralSharing(e,t):a.structuralSharing!==!1?Vn(e,t):t}function ui(e,t,a=0){const n=[...e,t];return a&&n.length>a?n.slice(1):n}function di(e,t,a=0){const n=[t,...e];return a&&n.length>a?n.slice(0,-1):n}var da=Symbol();function Kn(e,t){return!e.queryFn&&(t!=null&&t.initialPromise)?()=>t.initialPromise:!e.queryFn||e.queryFn===da?()=>Promise.reject(new Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function El(e,t){return typeof e=="function"?e(...t):!!e}function hi(e,t,a){let n=!1,r;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(r??(r=t()),n||(n=!0,r.aborted?a():r.addEventListener("abort",a,{once:!0})),r)}),e}var qn=(()=>{let e=()=>ai;return{isServer(){return e()},setIsServer(t){e=t}}})();function fi(){let e,t;const a=new Promise((r,s)=>{e=r,t=s});a.status="pending",a.catch(()=>{});function n(r){Object.assign(a,r),delete a.resolve,delete a.reject}return a.resolve=r=>{n({status:"fulfilled",value:r}),e(r)},a.reject=r=>{n({status:"rejected",reason:r}),t(r)},a}var mi=ti;function gi(){let e=[],t=0,a=o=>{o()},n=o=>{o()},r=mi;const s=o=>{t?e.push(o):r(()=>{a(o)})},i=()=>{const o=e;e=[],o.length&&r(()=>{n(()=>{o.forEach(h=>{a(h)})})})};return{batch:o=>{let h;t++;try{h=o()}finally{t--,t||i()}return h},batchCalls:o=>(...h)=>{s(()=>{o(...h)})},schedule:s,setNotifyFunction:o=>{a=o},setBatchNotifyFunction:o=>{n=o},setScheduler:o=>{r=o}}}var z=gi(),Ge,ye,Je,Tn,pi=(Tn=class extends Et{constructor(){super();j(this,Ge,!0);j(this,ye);j(this,Je);k(this,Je,t=>{if(typeof window<"u"&&window.addEventListener){const a=()=>t(!0),n=()=>t(!1);return window.addEventListener("online",a,!1),window.addEventListener("offline",n,!1),()=>{window.removeEventListener("online",a),window.removeEventListener("offline",n)}}})}onSubscribe(){l(this,ye)||this.setEventListener(l(this,Je))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,ye))==null||t.call(this),k(this,ye,void 0))}setEventListener(t){var a;k(this,Je,t),(a=l(this,ye))==null||a.call(this),k(this,ye,t(this.setOnline.bind(this)))}setOnline(t){l(this,Ge)!==t&&(k(this,Ge,t),this.listeners.forEach(n=>{n(t)}))}isOnline(){return l(this,Ge)}},Ge=new WeakMap,ye=new WeakMap,Je=new WeakMap,Tn),kt=new pi;function vi(e){return Math.min(1e3*2**e,3e4)}function Hn(e){return(e??"online")==="online"?kt.isOnline():!0}var Tt=class extends Error{constructor(e){super("CancelledError"),this.revert=e==null?void 0:e.revert,this.silent=e==null?void 0:e.silent}};function bi(e){return e instanceof Tt}function Qn(e){let t=!1,a=0,n;const r=fi(),s=()=>r.status!=="pending",i=v=>{var w;if(!s()){const T=new Tt(v);u(T),(w=e.onCancel)==null||w.call(e,T)}},o=()=>{t=!0},h=()=>{t=!1},f=()=>Un.isFocused()&&(e.networkMode==="always"||kt.isOnline())&&e.canRun(),d=()=>Hn(e.networkMode)&&e.canRun(),b=v=>{s()||(n==null||n(),r.resolve(v))},u=v=>{s()||(n==null||n(),r.reject(v))},p=()=>new Promise(v=>{var w;n=T=>{(s()||f())&&v(T)},(w=e.onPause)==null||w.call(e)}).then(()=>{var v;n=void 0,s()||(v=e.onContinue)==null||v.call(e)}),g=()=>{if(s())return;let v;const w=a===0?e.initialPromise:void 0;try{v=w??e.fn()}catch(T){v=Promise.reject(T)}Promise.resolve(v).then(b).catch(T=>{var y;if(s())return;const N=e.retry??(qn.isServer()?0:3),R=e.retryDelay??vi,_=typeof R=="function"?R(a,T):R,L=N===!0||typeof N=="number"&&af()?void 0:p()).then(()=>{t?u(T):g()})})};return{promise:r,status:()=>r.status,cancel:i,continue:()=>(n==null||n(),r),cancelRetry:o,continueRetry:h,canStart:d,start:()=>(d()?g():p().then(g),r)}}var Ee,Ln,Wn=(Ln=class{constructor(){j(this,Ee)}destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),ri(this.gcTime)&&k(this,Ee,Bt.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(qn.isServer()?1/0:300*1e3))}clearGcTimeout(){l(this,Ee)!==void 0&&(Bt.clearTimeout(l(this,Ee)),k(this,Ee,void 0))}},Ee=new WeakMap,Ln);function wi(e){return{onFetch:(t,a)=>{var d,b,u,p,g;const n=t.options,r=(u=(b=(d=t.fetchOptions)==null?void 0:d.meta)==null?void 0:b.fetchMore)==null?void 0:u.direction,s=((p=t.state.data)==null?void 0:p.pages)||[],i=((g=t.state.data)==null?void 0:g.pageParams)||[];let o={pages:[],pageParams:[]},h=0;const f=async()=>{let v=!1;const w=R=>{hi(R,()=>t.signal,()=>v=!0)},T=Kn(t.options,t.fetchOptions),N=async(R,_,L)=>{if(v)return Promise.reject(t.signal.reason);if(_==null&&R.pages.length)return Promise.resolve(R);const x=(()=>{const me={client:t.client,queryKey:t.queryKey,pageParam:_,direction:L?"backward":"forward",meta:t.options.meta};return w(me),me})(),M=await T(x),{maxPages:E}=t.options,D=L?di:ui;return{pages:D(R.pages,M,E),pageParams:D(R.pageParams,_,E)}};if(r&&s.length){const R=r==="backward",_=R?zn:Zt,L={pages:s,pageParams:i},y=_(n,L);o=await N(L,y,R)}else{const R=e??s.length;do{const _=h===0?i[0]??n.initialPageParam:Zt(n,o);if(h>0&&_==null)break;o=await N(o,_),h++}while(h{var v,w;return(w=(v=t.options).persister)==null?void 0:w.call(v,f,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},a)}:t.fetchFn=f}}}function Zt(e,{pages:t,pageParams:a}){const n=t.length-1;return t.length>0?e.getNextPageParam(t[n],t,a[n],a):void 0}function zn(e,{pages:t,pageParams:a}){var n;return t.length>0?(n=e.getPreviousPageParam)==null?void 0:n.call(e,t[0],t,a[0],a):void 0}function Dl(e,t){return t?Zt(e,t)!=null:!1}function Fl(e,t){return!t||!e.getPreviousPageParam?!1:zn(e,t)!=null}var Ze,De,Xe,X,Fe,U,ht,Ie,Z,Bn,he,Rn,yi=(Rn=class extends Wn{constructor(t){super();j(this,Z);j(this,Ze);j(this,De);j(this,Xe);j(this,X);j(this,Fe);j(this,U);j(this,ht);j(this,Ie);k(this,Ie,!1),k(this,ht,t.defaultOptions),this.setOptions(t.options),this.observers=[],k(this,Fe,t.client),k(this,X,l(this,Fe).getQueryCache()),this.queryKey=t.queryKey,this.queryHash=t.queryHash,k(this,De,Ga(this.options)),this.state=t.state??l(this,De),this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return l(this,Ze)}get promise(){var t;return(t=l(this,U))==null?void 0:t.promise}setOptions(t){if(this.options={...l(this,ht),...t},t!=null&&t._type&&k(this,Ze,t._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){const a=Ga(this.options);a.data!==void 0&&(this.setState(Ba(a.data,a.dataUpdatedAt)),k(this,De,a))}}optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"&&l(this,X).remove(this)}setData(t,a){const n=li(this.state.data,t,this.options);return V(this,Z,he).call(this,{data:n,type:"success",dataUpdatedAt:a==null?void 0:a.updatedAt,manual:a==null?void 0:a.manual}),n}setState(t){V(this,Z,he).call(this,{type:"setState",state:t})}cancel(t){var n,r;const a=(n=l(this,U))==null?void 0:n.promise;return(r=l(this,U))==null||r.cancel(t),a?a.then(ae).catch(ae):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return l(this,De)}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(t=>ii(t.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===da||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0?this.observers.some(t=>Gt(t.options.staleTime,this)==="static"):!1}isStale(){return this.getObserversCount()>0?this.observers.some(t=>t.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(t=0){return this.state.data===void 0?!0:t==="static"?!1:this.state.isInvalidated?!0:!si(this.state.dataUpdatedAt,t)}onFocus(){var a;const t=this.observers.find(n=>n.shouldFetchOnWindowFocus());t==null||t.refetch({cancelRefetch:!1}),(a=l(this,U))==null||a.continue()}onOnline(){var a;const t=this.observers.find(n=>n.shouldFetchOnReconnect());t==null||t.refetch({cancelRefetch:!1}),(a=l(this,U))==null||a.continue()}addObserver(t){this.observers.includes(t)||(this.observers.push(t),this.clearGcTimeout(),l(this,X).notify({type:"observerAdded",query:this,observer:t}))}removeObserver(t){this.observers.includes(t)&&(this.observers=this.observers.filter(a=>a!==t),this.observers.length||(l(this,U)&&(l(this,Ie)||V(this,Z,Bn).call(this)?l(this,U).cancel({revert:!0}):l(this,U).cancelRetry()),this.scheduleGc()),l(this,X).notify({type:"observerRemoved",query:this,observer:t}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||V(this,Z,he).call(this,{type:"invalidate"})}async fetch(t,a){var f,d,b,u,p,g,v,w,T,N,R;if(this.state.fetchStatus!=="idle"&&((f=l(this,U))==null?void 0:f.status())!=="rejected"){if(this.state.data!==void 0&&(a!=null&&a.cancelRefetch))this.cancel({silent:!0});else if(l(this,U))return l(this,U).continueRetry(),l(this,U).promise}if(t&&this.setOptions(t),!this.options.queryFn){const _=this.observers.find(L=>L.options.queryFn);_&&this.setOptions(_.options)}const n=new AbortController,r=_=>{Object.defineProperty(_,"signal",{enumerable:!0,get:()=>(k(this,Ie,!0),n.signal)})},s=()=>{const _=Kn(this.options,a),y=(()=>{const x={client:l(this,Fe),queryKey:this.queryKey,meta:this.meta};return r(x),x})();return k(this,Ie,!1),this.options.persister?this.options.persister(_,y,this):_(y)},o=(()=>{const _={fetchOptions:a,options:this.options,queryKey:this.queryKey,client:l(this,Fe),state:this.state,fetchFn:s};return r(_),_})(),h=l(this,Ze)==="infinite"?wi(this.options.pages):this.options.behavior;h==null||h.onFetch(o,this),k(this,Xe,this.state),(this.state.fetchStatus==="idle"||this.state.fetchMeta!==((d=o.fetchOptions)==null?void 0:d.meta))&&V(this,Z,he).call(this,{type:"fetch",meta:(b=o.fetchOptions)==null?void 0:b.meta}),k(this,U,Qn({initialPromise:a==null?void 0:a.initialPromise,fn:o.fetchFn,onCancel:_=>{_ instanceof Tt&&_.revert&&this.setState({...l(this,Xe),fetchStatus:"idle"}),n.abort()},onFail:(_,L)=>{V(this,Z,he).call(this,{type:"failed",failureCount:_,error:L})},onPause:()=>{V(this,Z,he).call(this,{type:"pause"})},onContinue:()=>{V(this,Z,he).call(this,{type:"continue"})},retry:o.options.retry,retryDelay:o.options.retryDelay,networkMode:o.options.networkMode,canRun:()=>!0}));try{const _=await l(this,U).start();if(_===void 0)throw new Error(`${this.queryHash} data is undefined`);return this.setData(_),(p=(u=l(this,X).config).onSuccess)==null||p.call(u,_,this),(v=(g=l(this,X).config).onSettled)==null||v.call(g,_,this.state.error,this),_}catch(_){if(_ instanceof Tt){if(_.silent)return l(this,U).promise;if(_.revert){if(this.state.data===void 0)throw _;return this.state.data}}throw V(this,Z,he).call(this,{type:"error",error:_}),(T=(w=l(this,X).config).onError)==null||T.call(w,_,this),(R=(N=l(this,X).config).onSettled)==null||R.call(N,this.state.data,_,this),_}finally{this.scheduleGc()}}},Ze=new WeakMap,De=new WeakMap,Xe=new WeakMap,X=new WeakMap,Fe=new WeakMap,U=new WeakMap,ht=new WeakMap,Ie=new WeakMap,Z=new WeakSet,Bn=function(){return this.state.fetchStatus==="paused"&&this.state.status==="pending"},he=function(t){const a=n=>{switch(t.type){case"failed":return{...n,fetchFailureCount:t.failureCount,fetchFailureReason:t.error};case"pause":return{...n,fetchStatus:"paused"};case"continue":return{...n,fetchStatus:"fetching"};case"fetch":return{...n,..._i(n.data,this.options),fetchMeta:t.meta??null};case"success":const r={...n,...Ba(t.data,t.dataUpdatedAt),dataUpdateCount:n.dataUpdateCount+1,...!t.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return k(this,Xe,t.manual?r:void 0),r;case"error":const s=t.error;return{...n,error:s,errorUpdateCount:n.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:n.fetchFailureCount+1,fetchFailureReason:s,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...n,isInvalidated:!0};case"setState":return{...n,...t.state}}};this.state=a(this.state),z.batch(()=>{this.observers.forEach(n=>{n.onQueryUpdate()}),l(this,X).notify({query:this,type:"updated",action:t})})},Rn);function _i(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Hn(t.networkMode)?"fetching":"paused",...e===void 0&&{error:null,status:"pending"}}}function Ba(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:"success"}}function Ga(e){const t=typeof e.initialData=="function"?e.initialData():e.initialData,a=t!==void 0,n=a?typeof e.initialDataUpdatedAt=="function"?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:a?n??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:a?"success":"pending",fetchStatus:"idle"}}var ft,le,K,$e,ue,ve,Mn,Si=(Mn=class extends Wn{constructor(t){super();j(this,ue);j(this,ft);j(this,le);j(this,K);j(this,$e);k(this,ft,t.client),this.mutationId=t.mutationId,k(this,K,t.mutationCache),k(this,le,[]),this.state=t.state||Ci(),this.setOptions(t.options),this.scheduleGc()}setOptions(t){this.options=t,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(t){l(this,le).includes(t)||(l(this,le).push(t),this.clearGcTimeout(),l(this,K).notify({type:"observerAdded",mutation:this,observer:t}))}removeObserver(t){k(this,le,l(this,le).filter(a=>a!==t)),this.scheduleGc(),l(this,K).notify({type:"observerRemoved",mutation:this,observer:t})}optionalRemove(){l(this,le).length||(this.state.status==="pending"?this.scheduleGc():l(this,K).remove(this))}continue(){var t;return((t=l(this,$e))==null?void 0:t.continue())??this.execute(this.state.variables)}async execute(t){var i,o,h,f,d,b,u,p,g,v,w,T,N,R,_,L,y,x;const a=()=>{V(this,ue,ve).call(this,{type:"continue"})},n={client:l(this,ft),meta:this.options.meta,mutationKey:this.options.mutationKey};k(this,$e,Qn({fn:()=>this.options.mutationFn?this.options.mutationFn(t,n):Promise.reject(new Error("No mutationFn found")),onFail:(M,E)=>{V(this,ue,ve).call(this,{type:"failed",failureCount:M,error:E})},onPause:()=>{V(this,ue,ve).call(this,{type:"pause"})},onContinue:a,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>l(this,K).canRun(this)}));const r=this.state.status==="pending",s=!l(this,$e).canStart();try{if(r)a();else{V(this,ue,ve).call(this,{type:"pending",variables:t,isPaused:s}),l(this,K).config.onMutate&&await l(this,K).config.onMutate(t,this,n);const E=await((o=(i=this.options).onMutate)==null?void 0:o.call(i,t,n));E!==this.state.context&&V(this,ue,ve).call(this,{type:"pending",context:E,variables:t,isPaused:s})}const M=await l(this,$e).start();return await((f=(h=l(this,K).config).onSuccess)==null?void 0:f.call(h,M,t,this.state.context,this,n)),await((b=(d=this.options).onSuccess)==null?void 0:b.call(d,M,t,this.state.context,n)),await((p=(u=l(this,K).config).onSettled)==null?void 0:p.call(u,M,null,this.state.variables,this.state.context,this,n)),await((v=(g=this.options).onSettled)==null?void 0:v.call(g,M,null,t,this.state.context,n)),V(this,ue,ve).call(this,{type:"success",data:M}),M}catch(M){try{await((T=(w=l(this,K).config).onError)==null?void 0:T.call(w,M,t,this.state.context,this,n))}catch(E){Promise.reject(E)}try{await((R=(N=this.options).onError)==null?void 0:R.call(N,M,t,this.state.context,n))}catch(E){Promise.reject(E)}try{await((L=(_=l(this,K).config).onSettled)==null?void 0:L.call(_,void 0,M,this.state.variables,this.state.context,this,n))}catch(E){Promise.reject(E)}try{await((x=(y=this.options).onSettled)==null?void 0:x.call(y,void 0,M,t,this.state.context,n))}catch(E){Promise.reject(E)}throw V(this,ue,ve).call(this,{type:"error",error:M}),M}finally{l(this,K).runNext(this)}}},ft=new WeakMap,le=new WeakMap,K=new WeakMap,$e=new WeakMap,ue=new WeakSet,ve=function(t){const a=n=>{switch(t.type){case"failed":return{...n,failureCount:t.failureCount,failureReason:t.error};case"pause":return{...n,isPaused:!0};case"continue":return{...n,isPaused:!1};case"pending":return{...n,context:t.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:t.isPaused,status:"pending",variables:t.variables,submittedAt:Date.now()};case"success":return{...n,data:t.data,failureCount:0,failureReason:null,error:null,status:"success",isPaused:!1};case"error":return{...n,data:void 0,error:t.error,failureCount:n.failureCount+1,failureReason:t.error,isPaused:!1,status:"error"}}};this.state=a(this.state),z.batch(()=>{l(this,le).forEach(n=>{n.onMutationUpdate(t)}),l(this,K).notify({mutation:this,type:"updated",action:t})})},Mn);function Ci(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:"idle",variables:void 0,submittedAt:0}}var fe,ne,mt,Pn,xi=(Pn=class extends Et{constructor(t={}){super();j(this,fe);j(this,ne);j(this,mt);this.config=t,k(this,fe,new Set),k(this,ne,new Map),k(this,mt,0)}build(t,a,n){const r=new Si({client:t,mutationCache:this,mutationId:++St(this,mt)._,options:t.defaultMutationOptions(a),state:n});return this.add(r),r}add(t){l(this,fe).add(t);const a=Ct(t);if(typeof a=="string"){const n=l(this,ne).get(a);n?n.push(t):l(this,ne).set(a,[t])}this.notify({type:"added",mutation:t})}remove(t){if(l(this,fe).delete(t)){const a=Ct(t);if(typeof a=="string"){const n=l(this,ne).get(a);if(n)if(n.length>1){const r=n.indexOf(t);r!==-1&&n.splice(r,1)}else n[0]===t&&l(this,ne).delete(a)}}this.notify({type:"removed",mutation:t})}canRun(t){const a=Ct(t);if(typeof a=="string"){const n=l(this,ne).get(a),r=n==null?void 0:n.find(s=>s.state.status==="pending");return!r||r===t}else return!0}runNext(t){var n;const a=Ct(t);if(typeof a=="string"){const r=(n=l(this,ne).get(a))==null?void 0:n.find(s=>s!==t&&s.state.isPaused);return(r==null?void 0:r.continue())??Promise.resolve()}else return Promise.resolve()}clear(){z.batch(()=>{l(this,fe).forEach(t=>{this.notify({type:"removed",mutation:t})}),l(this,fe).clear(),l(this,ne).clear()})}getAll(){return Array.from(l(this,fe))}find(t){const a={exact:!0,...t};return this.getAll().find(n=>Qa(a,n))}findAll(t={}){return this.getAll().filter(a=>Qa(t,a))}notify(t){z.batch(()=>{this.listeners.forEach(a=>{a(t)})})}resumePausedMutations(){const t=this.getAll().filter(a=>a.state.isPaused);return z.batch(()=>Promise.all(t.map(a=>a.continue().catch(ae))))}},fe=new WeakMap,ne=new WeakMap,mt=new WeakMap,Pn);function Ct(e){var t;return(t=e.options.scope)==null?void 0:t.id}var de,jn,ki=(jn=class extends Et{constructor(t={}){super();j(this,de);this.config=t,k(this,de,new Map)}build(t,a,n){const r=a.queryKey,s=a.queryHash??ua(r,a);let i=this.get(s);return i||(i=new yi({client:t,queryKey:r,queryHash:s,options:t.defaultQueryOptions(a),state:n,defaultOptions:t.getQueryDefaults(r)}),this.add(i)),i}add(t){l(this,de).has(t.queryHash)||(l(this,de).set(t.queryHash,t),this.notify({type:"added",query:t}))}remove(t){const a=l(this,de).get(t.queryHash);a&&(t.destroy(),a===t&&l(this,de).delete(t.queryHash),this.notify({type:"removed",query:t}))}clear(){z.batch(()=>{this.getAll().forEach(t=>{this.remove(t)})})}get(t){return l(this,de).get(t)}getAll(){return[...l(this,de).values()]}find(t){const a={exact:!0,...t};return this.getAll().find(n=>Ha(a,n))}findAll(t={}){const a=this.getAll();return Object.keys(t).length>0?a.filter(n=>Ha(t,n)):a}notify(t){z.batch(()=>{this.listeners.forEach(a=>{a(t)})})}onFocus(){z.batch(()=>{this.getAll().forEach(t=>{t.onFocus()})})}onOnline(){z.batch(()=>{this.getAll().forEach(t=>{t.onOnline()})})}},de=new WeakMap,jn),F,_e,Se,Ye,et,Ce,tt,at,An,Ti=(An=class{constructor(e={}){j(this,F);j(this,_e);j(this,Se);j(this,Ye);j(this,et);j(this,Ce);j(this,tt);j(this,at);k(this,F,e.queryCache||new ki),k(this,_e,e.mutationCache||new xi),k(this,Se,e.defaultOptions||{}),k(this,Ye,new Map),k(this,et,new Map),k(this,Ce,0)}mount(){St(this,Ce)._++,l(this,Ce)===1&&(k(this,tt,Un.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onFocus())})),k(this,at,kt.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onOnline())})))}unmount(){var e,t;St(this,Ce)._--,l(this,Ce)===0&&((e=l(this,tt))==null||e.call(this),k(this,tt,void 0),(t=l(this,at))==null||t.call(this),k(this,at,void 0))}isFetching(e){return l(this,F).findAll({...e,fetchStatus:"fetching"}).length}isMutating(e){return l(this,_e).findAll({...e,status:"pending"}).length}getQueryData(e){var a;const t=this.defaultQueryOptions({queryKey:e});return(a=l(this,F).get(t.queryHash))==null?void 0:a.state.data}ensureQueryData(e){const t=this.defaultQueryOptions(e),a=l(this,F).build(this,t),n=a.state.data;return n===void 0?this.fetchQuery(e):(e.revalidateIfStale&&a.isStaleByTime(Gt(t.staleTime,a))&&this.prefetchQuery(t),Promise.resolve(n))}getQueriesData(e){return l(this,F).findAll(e).map(({queryKey:t,state:a})=>{const n=a.data;return[t,n]})}setQueryData(e,t,a){const n=this.defaultQueryOptions({queryKey:e}),r=l(this,F).get(n.queryHash),s=r==null?void 0:r.state.data,i=ni(t,s);if(i!==void 0)return l(this,F).build(this,n).setData(i,{...a,manual:!0})}setQueriesData(e,t,a){return z.batch(()=>l(this,F).findAll(e).map(({queryKey:n})=>[n,this.setQueryData(n,t,a)]))}getQueryState(e){var a;const t=this.defaultQueryOptions({queryKey:e});return(a=l(this,F).get(t.queryHash))==null?void 0:a.state}removeQueries(e){const t=l(this,F);z.batch(()=>{t.findAll(e).forEach(a=>{t.remove(a)})})}resetQueries(e,t){const a=l(this,F);return z.batch(()=>(a.findAll(e).forEach(n=>{n.reset()}),this.refetchQueries({type:"active",...e},t)))}cancelQueries(e,t={}){const a={revert:!0,...t},n=z.batch(()=>l(this,F).findAll(e).map(r=>r.cancel(a)));return Promise.all(n).then(ae).catch(ae)}invalidateQueries(e,t={}){return z.batch(()=>(l(this,F).findAll(e).forEach(a=>{a.invalidate()}),(e==null?void 0:e.refetchType)==="none"?Promise.resolve():this.refetchQueries({...e,type:(e==null?void 0:e.refetchType)??(e==null?void 0:e.type)??"active"},t)))}refetchQueries(e,t={}){const a={...t,cancelRefetch:t.cancelRefetch??!0},n=z.batch(()=>l(this,F).findAll(e).filter(r=>!r.isDisabled()&&!r.isStatic()).map(r=>{let s=r.fetch(void 0,a);return a.throwOnError||(s=s.catch(ae)),r.state.fetchStatus==="paused"?Promise.resolve():s}));return Promise.all(n).then(ae)}fetchQuery(e){const t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);const a=l(this,F).build(this,t);return a.isStaleByTime(Gt(t.staleTime,a))?a.fetch(t):Promise.resolve(a.state.data)}prefetchQuery(e){return this.fetchQuery(e).then(ae).catch(ae)}fetchInfiniteQuery(e){return e._type="infinite",this.fetchQuery(e)}prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(ae).catch(ae)}ensureInfiniteQueryData(e){return e._type="infinite",this.ensureQueryData(e)}resumePausedMutations(){return kt.isOnline()?l(this,_e).resumePausedMutations():Promise.resolve()}getQueryCache(){return l(this,F)}getMutationCache(){return l(this,_e)}getDefaultOptions(){return l(this,Se)}setDefaultOptions(e){k(this,Se,e)}setQueryDefaults(e,t){l(this,Ye).set(lt(e),{queryKey:e,defaultOptions:t})}getQueryDefaults(e){const t=[...l(this,Ye).values()],a={};return t.forEach(n=>{ut(e,n.queryKey)&&Object.assign(a,n.defaultOptions)}),a}setMutationDefaults(e,t){l(this,et).set(lt(e),{mutationKey:e,defaultOptions:t})}getMutationDefaults(e){const t=[...l(this,et).values()],a={};return t.forEach(n=>{ut(e,n.mutationKey)&&Object.assign(a,n.defaultOptions)}),a}defaultQueryOptions(e){if(e._defaulted)return e;const t={...l(this,Se).queries,...this.getQueryDefaults(e.queryKey),...e,_defaulted:!0};return t.queryHash||(t.queryHash=ua(t.queryKey,t)),t.refetchOnReconnect===void 0&&(t.refetchOnReconnect=t.networkMode!=="always"),t.throwOnError===void 0&&(t.throwOnError=!!t.suspense),!t.networkMode&&t.persister&&(t.networkMode="offlineFirst"),t.queryFn===da&&(t.enabled=!1),t}defaultMutationOptions(e){return e!=null&&e._defaulted?e:{...l(this,Se).mutations,...(e==null?void 0:e.mutationKey)&&this.getMutationDefaults(e.mutationKey),...e,_defaulted:!0}}clear(){l(this,F).clear(),l(this,_e).clear()}},F=new WeakMap,_e=new WeakMap,Se=new WeakMap,Ye=new WeakMap,et=new WeakMap,Ce=new WeakMap,tt=new WeakMap,at=new WeakMap,An),Gn=C.createContext(void 0),Il=e=>{const t=C.useContext(Gn);if(!t)throw new Error("No QueryClient set, use QueryClientProvider to set one");return t},Li=({client:e,children:t})=>(C.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),c.jsx(Gn.Provider,{value:e,children:t}));function Ri(e,t=window.location.href){var n;const a=(n=new URL(t).searchParams.get("record"))==null?void 0:n.trim();if(a){const r=e.calls.find(s=>s.id===a);return r?[r]:[]}return e.calls[0]?[e.calls[0]]:[]}function $l({calls:e,recordId:t,detail:a}){const n=e.findIndex(b=>b.id===t),r=n>=0?n:!t&&e.length?0:-1,s=(a==null?void 0:a.record.id)===t?a:null,i=(s==null?void 0:s.record)??(r>=0?e[r]:null),o=(s==null?void 0:s.previousRecord)??(r>0?e[r-1]:null),h=(s==null?void 0:s.nextRecord)??(r>=0&&r=0?`${r+1} of ${e.length} loaded calls`:"Record outside loaded snapshot";return{modelIndex:n,activeIndex:r,hydratedDetail:s,call:i,previous:o,next:h,threadCalls:f,positionLabel:d}}function Mi(e,t,a){const n=e.filter(i=>i.thread===t.thread),r=[a==null?void 0:a.previousRecord,a==null?void 0:a.record,a==null?void 0:a.nextRecord].filter(Pi),s=new Map;for(const i of[...n,...r,t])s.set(i.id,i);return[...s.values()].sort(ji)}function Pi(e){return!!(e!=null&&e.id)}function ji(e,t){return Date.parse(t.rawTime||t.time)-Date.parse(e.rawTime||e.time)}function Ai(e,t){const a=t.map(r=>Ja(r.header)).join(","),n=e.map(r=>t.map(s=>Ja(s.value(r))).join(","));return[a,...n].join(` +`)}function Ni(e,t){const a=new Blob([t],{type:"text/csv;charset=utf-8"}),n=typeof URL.createObjectURL=="function"?URL.createObjectURL(a):`data:text/csv;charset=utf-8,${encodeURIComponent(t)}`,r=document.createElement("a");r.href=n,r.download=e,r.rel="noopener",document.body.append(r),r.click(),r.remove(),n.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(n)}function Ei(e=new Date){return e.toISOString().slice(0,10)}function Ja(e){const t=String(e??"");return/[",\n\r]/.test(t)?`"${t.replaceAll('"','""')}"`:t}function Jn(e){return e.fast===!0?"Fast":e.fast===!1?"Standard":"Unknown"}function Ol(e){return e.fast!==null?`confirmed ${Jn(e)} · ${e.serviceTierConfidence||"exact"}`:e.fastProxyCandidate?"tier unknown · Fast proxy candidate":"tier unknown · normal throughput proxy"}function Te(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Le(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Xt(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function Lt(e){return`${e.toFixed(1)}%`}const Ul=[{id:"time",accessorFn:e=>Number(Date.parse(e.eventTimestamp||e.callStartedAt||e.rawTime||e.time))||0,header:"Time",cell:e=>e.row.original.time},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:e=>c.jsx("span",{className:`pill effort-${String(e.getValue())}`,children:String(e.getValue())})},{accessorKey:"input",header:"Input Tokens",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"output",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:e=>c.jsx("span",{className:"cache-pill",children:Lt(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"contextWindowPct",header:"Context %",cell:e=>{const t=e.getValue(),a=typeof t=="number"?t:Number.NaN;return c.jsx("span",{className:"num",children:Number.isFinite(a)?Lt(a):"-"})}},{accessorKey:"duration",header:"Duration"},{id:"serviceTier",accessorFn:e=>Jn(e),header:"Service Tier",cell:e=>{const t=String(e.getValue()),a=t==="Fast"?"green":t==="Standard"?"blue":"";return c.jsx("span",{className:`status-badge ${a}`.trim(),children:t})}},{accessorKey:"previousCallGap",header:"Prev Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiator",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"signal",header:"Signals",cell:e=>c.jsx(Fi,{call:e.row.original})}],ce=[{header:"timestamp",value:e=>e.eventTimestamp||e.rawTime||e.time},{header:"thread",value:e=>e.thread},{header:"call_started_at",value:e=>e.callStartedAt||e.rawTime||e.time},{header:"call_duration_seconds",value:e=>e.durationSeconds},{header:"previous_call_event_timestamp",value:e=>e.previousCallEventTimestamp},{header:"previous_call_delta_seconds",value:e=>e.previousCallGapSeconds},{header:"initiated",value:e=>e.initiator},{header:"initiated_reason",value:e=>e.initiatorReason},{header:"project",value:e=>e.project},{header:"model",value:e=>e.model},{header:"effort",value:e=>e.effort},{header:"total_tokens",value:e=>e.totalTokens},{header:"input_tokens",value:e=>e.input},{header:"cached_input_tokens",value:e=>e.cachedInput},{header:"uncached_input_tokens",value:e=>e.uncachedInput},{header:"output_tokens",value:e=>e.output},{header:"reasoning_output_tokens",value:e=>e.reasoningOutput},{header:"estimated_cost_usd",value:e=>e.cost.toFixed(6)},{header:"usage_credits",value:e=>e.credits.toFixed(6)},{header:"standard_usage_credits",value:e=>e.standardUsageCredits.toFixed(6)},{header:"service_tier",value:e=>e.serviceTier},{header:"fast",value:e=>e.fast===null?"":e.fast?1:0},{header:"service_tier_source",value:e=>e.serviceTierSource},{header:"service_tier_confidence",value:e=>e.serviceTierConfidence},{header:"fast_proxy_candidate",value:e=>String(e.fastProxyCandidate)},{header:"usage_credit_multiplier",value:e=>e.usageCreditMultiplier},{header:"usage_credit_multiplier_source",value:e=>e.usageCreditMultiplierSource},{header:"cache_ratio",value:e=>e.cachedPct.toFixed(2)},{header:"context_window_percent",value:e=>{var t;return((t=e.contextWindowPct)==null?void 0:t.toFixed(2))??""}},{header:"pricing_model",value:e=>e.pricingModel},{header:"usage_credit_confidence",value:e=>e.usageCreditConfidence},{header:"recommendation",value:e=>e.recommendation},{header:"record_id",value:e=>e.id},{header:"thread_attachment",value:e=>e.threadAttachmentLabel},{header:"thread_source",value:e=>e.threadSource},{header:"parent_thread",value:e=>e.parentThread},{header:"session_id",value:e=>e.sessionId},{header:"turn_id",value:e=>e.turnId},{header:"parent_session_id",value:e=>e.parentSessionId},{header:"parent_session_updated_at",value:e=>e.parentSessionUpdatedAt},{header:"project_relative_cwd",value:e=>e.projectRelativeCwd},{header:"cwd",value:e=>e.cwd},{header:"source_file",value:e=>e.sourceFile},{header:"source_line",value:e=>e.lineNumber??""},{header:"git_branch",value:e=>e.gitBranch},{header:"git_remote_label",value:e=>e.gitRemoteLabel},{header:"git_remote_hash",value:e=>e.gitRemoteHash},{header:"pricing_estimated",value:e=>String(e.pricingEstimated)},{header:"usage_credit_model",value:e=>e.usageCreditModel},{header:"usage_credit_source",value:e=>e.usageCreditSource},{header:"usage_credit_tier",value:e=>e.usageCreditTier},{header:"usage_credit_fetched_at",value:e=>e.usageCreditFetchedAt},{header:"usage_credit_note",value:e=>e.usageCreditNote},{header:"model_context_window",value:e=>e.modelContextWindow??""},{header:"cumulative_total_tokens",value:e=>e.cumulativeTotalTokens??""},{header:"estimated_cache_savings_usd",value:e=>e.estimatedCacheSavings.toFixed(6)},{header:"initiated_confidence",value:e=>e.initiatorConfidence},{header:"signal",value:e=>e.signal},{header:"tags",value:e=>e.tags.join("|")},{header:"efficiency_flags",value:e=>e.efficiencyFlags.join("|")}];function Di(e,t=3){const n=Ii([e.signal,...e.efficiencyFlags]).map((r,s)=>({key:`${r}-${s}`,label:Zn(r),shortLabel:$i(r)}));return{visible:n.slice(0,t),hidden:n.slice(t)}}function Fi({call:e}){const t=On(),{visible:a,hidden:n}=Di(e);if(!a.length)return c.jsx("span",{className:"muted",children:"None"});const r=a.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),s=n.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),i=s.map(o=>o.label).join("、");return c.jsxs("span",{className:"flags compact-flags","aria-label":t.language==="zh-Hans"?`信号:${[...r,...s].map(o=>o.label).join("、")}`:`Signals: ${[...a,...n].map(o=>o.label).join(", ")}`,children:[r.map(o=>c.jsx("span",{className:"flag signal-puck",title:o.label,children:o.shortLabel},o.key)),s.length?c.jsxs("span",{className:"flag signal-puck more",title:i,children:["+",s.length]}):null]})}function Ii(e){const t=new Set;return e.map(a=>a.trim()).filter(a=>a&&a!=="aggregate").filter(a=>{const n=a.toLowerCase();return t.has(n)?!1:(t.add(n),!0)})}function Zn(e){return e.replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function $i(e){const t=e.toLowerCase().replace(/[_\s]+/g,"-"),a={"cache-drop":"CACHE","cache-risk":"CACHE","context-bloat":"CTX","context-heavy":"CTX","elevated-context":"CTX","elevated-context-use":"CTX","estimated-pricing":"EST","expensive-low-output-call":"LO","high-context-use":"CTX","high-cost":"$","high-estimated-cost":"$","high-reasoning-share":"RSN","large-thread":"BIG","low-cache":"CACHE","low-cache-reuse":"CACHE","low-output":"LO","pricing-gap":"PRICE","reasoning-spike":"RSN","subagent-attribution":"SUB"};if(a[t])return a[t];const n=Zn(e).split(/\s+/).filter(Boolean);return n.length?n.length===1?n[0].slice(0,4).toUpperCase():n.slice(0,3).map(r=>r[0]).join("").toUpperCase():"?"}const Vl=[{accessorKey:"name",header:"Thread"},{accessorKey:"latestActivity",header:"Latest"},{accessorKey:"turns",header:"Turns",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"totalDuration",header:"Duration"},{accessorKey:"averageGap",header:"Avg Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiatorSummary",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"modelSummary",header:"Models",cell:e=>c.jsx("span",{className:"pill model-pill",children:String(e.getValue())})},{accessorKey:"effortSummary",header:"Effort Mix"},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"outputTokens",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachePct",header:"Cache %",cell:e=>c.jsx("span",{className:"cache-pill",children:Lt(Number(e.getValue()))})},{accessorKey:"contextPct",header:"Context %",cell:e=>{const t=e.getValue();return c.jsx("span",{className:"num",children:typeof t=="number"?Lt(t):"-"})}},{accessorKey:"costPerCall",header:"Cost / Call",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"coldResumeRisk",header:"Cold Resume Risk",cell:e=>c.jsx("span",{className:`status-badge ${Oi(String(e.getValue()))}`,children:String(e.getValue())})},{accessorKey:"productivity",header:"Productivity",cell:e=>c.jsx("span",{className:"score",children:Number(e.getValue())})}],Kl=[{id:"name",label:"Thread",locked:!0},{id:"latestActivity",label:"Latest"},{id:"turns",label:"Turns"},{id:"totalDuration",label:"Duration"},{id:"averageGap",label:"Avg Gap"},{id:"initiatorSummary",label:"Initiated"},{id:"modelSummary",label:"Models"},{id:"effortSummary",label:"Effort Mix"},{id:"totalTokens",label:"Total Tokens"},{id:"cachedInput",label:"Cached Input"},{id:"uncachedInput",label:"Uncached Input"},{id:"outputTokens",label:"Output Tokens"},{id:"reasoningOutput",label:"Reasoning Output"},{id:"cost",label:"Est. Cost"},{id:"credits",label:"Codex Credits"},{id:"cachePct",label:"Cache %"},{id:"contextPct",label:"Context %"},{id:"costPerCall",label:"Cost / Call"},{id:"coldResumeRisk",label:"Cold Resume Risk"},{id:"productivity",label:"Productivity"},{id:"investigate",label:"Investigate",locked:!0}];function Oi(e){return e==="High"?"red":e==="Medium"?"orange":e==="Low"?"green":"neutral"}const dt=1,re=0,qt=100,Xn=1e3,Yn=500,er="codexUsageDashboardLoadSettings",Ui={day:1440*60*1e3,week:10080*60*1e3};function ct(e,t=Yn){if((e==null?void 0:e.limit_label)==="All"||t===re&&(e==null?void 0:e.limit)==null)return re;const a=Number((e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??t);return Number.isFinite(a)&&a>=0?a:t}function gt(e){return Number.isFinite(e)?e<=re?re:Math.max(dt,Math.round(e)):dt}function je(...e){const t=e.find(a=>typeof a=="number"&&Number.isFinite(a)&&a>0);return t?Math.max(dt,Math.round(t)):dt}function Vi(e,t,a=null,n="rows"){const r=gt(e);return{historyScope:t,loadWindow:n,limit:r===re?null:r,since:a}}function Ki(e){return e.limit??re}function ha(e){return fa(e==null?void 0:e.load_window)?e.load_window:e!=null&&e.since?"week":(e==null?void 0:e.limit_label)==="All"||(e==null?void 0:e.limit)==null?"all":"rows"}function qi(e){return fa(e==null?void 0:e.default_load_window)?e.default_load_window:ha(e)}function Ht(e,t=new Date){const a=Ui[e];if(!a)return null;const n=Math.floor(t.getTime()/6e4)*6e4;return new Date(n-a).toISOString()}function Re(e,t=Yn){return e==="day"?"Last 24 hours":e==="week"?"Last 7 days":e==="all"?"All time":`Most recent ${gt(t).toLocaleString()}`}function Hi(e=tr()){if(!e)return null;try{const t=e.getItem(er);if(!t)return null;const a=JSON.parse(t),n=typeof a.loadLimit=="number"&&Number.isFinite(a.loadLimit)?gt(a.loadLimit):void 0,r=a.historyScope==="active"||a.historyScope==="all"?a.historyScope:void 0,s=fa(a.loadWindow)?a.loadWindow:void 0;return n===void 0&&r===void 0&&s===void 0?null:{loadLimit:n,historyScope:r,loadWindow:s}}catch{return null}}function Qi(e,t,a="rows",n=tr()){if(n)try{n.setItem(er,JSON.stringify({loadLimit:gt(e),historyScope:t,loadWindow:a}))}catch{}}function fa(e){return e==="day"||e==="week"||e==="rows"||e==="all"}function Wi({currentLimit:e,loadedRows:t,pendingLimit:a}){const n=a===re?0:a+qt,s=Math.max(dt,e===re?0:e,n,t);return Math.ceil((s+Xn)/qt)*qt}function zi({currentLimit:e,loadedRows:t,pendingLimit:a}){return Math.max(je(e),je(a),je(t))+Xn}function Bi({loadedRows:e,limit:t,totalRows:a}){return t===re&&e>0?`Loaded all ${e.toLocaleString()}`:a>e?`Loaded ${e.toLocaleString()} of ${a.toLocaleString()}`:`Loaded ${e.toLocaleString()} rows`}function tr(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}async function Gi(e,t,a,n="",r=""){const s=Ei();switch(e){case"threads":{const{threadCallsForCurrentUrl:i}=await O(async()=>{const{threadCallsForCurrentUrl:o}=await import("./ThreadsPage.js");return{threadCallsForCurrentUrl:o}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]));return te(`codex-thread-filtered-calls-${s}.csv`,i(t,n),ce,"call rows")}case"cache-context":{const{cacheContextCallsForCurrentUrl:i}=await O(async()=>{const{cacheContextCallsForCurrentUrl:o}=await import("./CacheContextPage.js");return{cacheContextCallsForCurrentUrl:o}},__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12]));return te(`codex-${e}-calls-${s}.csv`,i(t),ce,"call rows")}case"usage-drain":{const{usageDrainCallsForCurrentUrl:i}=await O(async()=>{const{usageDrainCallsForCurrentUrl:o}=await import("./UsageDrainPage.js");return{usageDrainCallsForCurrentUrl:o}},__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39]));return te(`codex-usage-drain-calls-${s}.csv`,i(t),ce,"call rows")}case"diagnostics":{const{diagnosticsCallsForCurrentUrl:i}=await O(async()=>{const{diagnosticsCallsForCurrentUrl:o}=await import("./DiagnosticsPage.js");return{diagnosticsCallsForCurrentUrl:o}},__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12]));return te(`codex-diagnostics-calls-${s}.csv`,i(t),ce,"call rows")}case"reports":{const{reportCallsForCurrentUrl:i}=await O(async()=>{const{reportCallsForCurrentUrl:o}=await import("./ReportsPage.js");return{reportCallsForCurrentUrl:o}},__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43]));return te(`codex-reports-evidence-${s}.csv`,i(t),ce,"call rows")}case"settings":return te(`codex-dashboard-settings-${s}.csv`,Zi(t,a),Ji,"settings rows");case"calls":{const{callsForCurrentUrl:i}=await O(async()=>{const{callsForCurrentUrl:o}=await import("./CallsPage.js");return{callsForCurrentUrl:o}},__vite__mapDeps([44,1,2,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48]));return te(`codex-calls-${s}.csv`,i(t.calls,n,r),ce,"call rows")}case"overview":{const{overviewCallsForQuery:i}=await O(async()=>{const{overviewCallsForQuery:o}=await import("./OverviewPage.js");return{overviewCallsForQuery:o}},__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50]));return te(`codex-overview-calls-${s}.csv`,i(t.calls,n),ce,"call rows")}case"investigator":{const{investigatorCallsForCurrentUrl:i}=await O(async()=>{const{investigatorCallsForCurrentUrl:o}=await import("./InvestigatorPage.js");return{investigatorCallsForCurrentUrl:o}},__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52]));return te(`codex-investigator-calls-${s}.csv`,i(t),ce,"call rows")}case"compression-lab":return te(`codex-compression-lab-scope-${s}.csv`,t.calls,ce,"call rows");case"call":return te(`codex-call-calls-${s}.csv`,Ri(t),ce,"call rows")}}function te(e,t,a,n){return{filename:e,csv:Ai(t,a),rowCount:t.length,label:n}}const Ji=[{header:"Field",value:e=>e.field},{header:"Value",value:e=>e.value}];function Zi(e,t){return[{field:"live_api",value:t.canUseLiveApi?"available":"static snapshot"},{field:"context_api",value:t.contextRuntime.contextApiEnabled?"enabled":"gated"},{field:"history_scope",value:t.historyScope},{field:"data_window",value:Re(t.loadWindow,t.loadLimit)},{field:"scope_since",value:t.scopeSince??"none"},{field:"row_request",value:t.loadLimit===re?"no cap":String(t.loadLimit)},{field:"loaded_rows",value:String(t.loadedRowCount)},{field:"total_available_rows",value:String(t.totalAvailableRows)},{field:"auto_refresh",value:t.autoRefreshEnabled?"enabled":"paused"},{field:"refresh_state",value:t.refreshState},{field:"visible_calls",value:String(e.calls.length)},{field:"visible_threads",value:String(e.threads.length)}]}function Xi(e){return e instanceof Error?e.message:String(e)}function Za(e,t){const a=t==="all"?"all history":"active history",n=e.message||"Refreshing usage index",r=typeof e.percent=="number"?` ${Math.round(e.percent)}%`:"";return`${n}${r} (${a})`}function Qt(e,t="active"){return e?typeof e.include_archived=="boolean"?e.include_archived?"all":"active":e.history_scope==="all-history"||e.history_scope==="all"?"all":e.history_scope==="active"?"active":t:t}function Yi({historyScope:e,activeRows:t,allRows:a,archivedRows:n}){const r=eo({activeRows:t,allRows:a,archivedRows:n});return e==="all"?r===null?"All history selected":r>0?`All history includes ${r.toLocaleString()} archived calls`:"All history selected; no archived calls are indexed yet":r===null||r<=0?"Active sessions only":`Active sessions only; ${r.toLocaleString()} archived calls hidden`}function eo({activeRows:e,allRows:t,archivedRows:a}){const n=Wt(a);if(n!==null)return n;const r=Wt(e),s=Wt(t);return r!==null&&s!==null?Math.max(s-r,0):null}function Wt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.round(e):null}const ar=["aria-description","aria-label","aria-valuetext","title","placeholder","alt"],to="data-localization-attributes",ao=new Set(["CODE","KBD","PRE","SAMP","SCRIPT","STYLE","TEXTAREA"]),Yt=new WeakMap,ea=new WeakMap;function no({value:e,children:t}){return c.jsxs(Zs,{value:e,children:[c.jsx(ro,{}),t]})}function ro(){const e=On();return C.useLayoutEffect(()=>{const t=document.querySelector("[data-dashboard-localization-root]");if(!t)return;if(e.language!=="zh-Hans"){io(t),document.title="Codex Usage Tracker React Dashboard";return}document.title="Codex Usage Tracker · 用量仪表盘",Xa(t,e.translateText);const a=new MutationObserver(n=>{for(const r of n){if(r.type==="characterData"&&r.target instanceof Text){ta(r.target,e.translateText);continue}if(r.type==="attributes"&&r.target instanceof Element){aa(r.target,e.translateText);continue}for(const s of r.addedNodes)s instanceof Text?ta(s,e.translateText):s instanceof Element&&Xa(s,e.translateText)}});return a.observe(t,{attributes:!0,attributeFilter:[...ar],characterData:!0,childList:!0,subtree:!0}),()=>a.disconnect()},[e]),null}function Xa(e,t){if(Rt(e))return;aa(e,t);const a=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);let n=a.nextNode();for(;n;){if(n instanceof Element){if(Rt(n)){n=so(a,n,e);continue}aa(n,t)}else n instanceof Text&&ta(n,t);n=a.nextNode()}}function so(e,t,a){let n=t;for(;n&&n!==a;){const r=e.nextSibling();if(r)return r;n=n.parentNode,n&&(e.currentNode=n)}return null}function ta(e,t){const a=e.parentElement;if(!a||Rt(a))return;const n=e.nodeValue??"",r=Yt.get(e),s=r&&(n===r.source||n===r.translated)?r.source:n,i=s.match(/^(\s*)([\s\S]*?)(\s*)$/u);if(!i||!i[2])return;const o=t(i[2]),h=`${i[1]}${o}${i[3]}`;Yt.set(e,{source:s,translated:h}),h!==n&&(e.nodeValue=h)}function aa(e,t){if(Rt(e))return;const a=new Set((e.getAttribute(to)??"").split(/[\s,]+/u).filter(Boolean));if(!a.size)return;const n=ea.get(e)??new Map;for(const r of ar){if(!a.has(r))continue;const s=e.getAttribute(r);if(!s)continue;const i=n.get(r),o=i&&(s===i.source||s===i.translated)?i.source:s,h=t(o);n.set(r,{source:o,translated:h}),h!==s&&e.setAttribute(r,h)}n.size&&ea.set(e,n)}function io(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);Ya(e);let a=t.nextNode();for(;a;){if(a instanceof Text){const n=Yt.get(a);n&&a.nodeValue===n.translated&&(a.nodeValue=n.source)}else a instanceof Element&&Ya(a);a=t.nextNode()}}function Ya(e){const t=ea.get(e);if(t)for(const[a,n]of t)e.getAttribute(a)===n.translated&&e.setAttribute(a,n.source)}function Rt(e){return ao.has(e.tagName)||!!e.closest('[data-localization-skip="true"]')}const Mt=["May 12","May 19","May 26","Jun 02","Jun 09","Jun 16","Jun 23","Jun 30"],it=Mt.slice(2),nr={contextRuntime:{apiToken:"",contextApiEnabled:!1,fileMode:!1},cards:[{label:"Total Tokens",value:"24.83M",detail:"7-day total: 12.56M",trend:"up 18.7% vs prior 7 days",tone:"blue"},{label:"Estimated Cost",value:"$42.67",detail:"7-day total: $24.81",trend:"up 14.2% vs prior 7 days",tone:"green"},{label:"Cache Hit Rate",value:"38.7%",detail:"7-day average: 42.3%",trend:"down 3.6pp vs prior 7 days",tone:"purple"},{label:"Total Calls",value:"1,342",detail:"678 calls in last 7 days",trend:"up 11.3% vs prior 7 days",tone:"blue"},{label:"Usage Remaining",value:"32.4%",detail:"~15.9K credits estimated",trend:"resets in 4d 12h",tone:"green"}],tokenSeries:[Q("input","Input","#2563eb",[5.2,6.4,7.5,9.2,6.7,7.5,6.6,9],1e6),Q("output","Output","#059669",[2.5,3,3.6,5.1,3.7,5,4,5.4],1e6),Q("cached","Cached","#7c3aed",[1.1,1.4,1.7,2.4,1.8,2.3,1.8,2.6],1e6,!0)],costSeries:[Q("cost","Estimated Cost","#2563eb",[8.4,10.1,14.3,9.9,11.4,7.8,12.7,16.5])],cacheSeries:[Q("cache","Cache Hit Rate","#059669",[58,61,39,45,50,44,48,41])],weeklyCreditSeries:[{id:"pro",label:"Pro observed",color:"#2563eb",points:Mt.map((e,t)=>({label:e,value:[59800,44900,45e3,40500,42800,38900,31400,35900][t]??0,low:[52100,38800,38900,34700,36200,32200,26100,29900][t]??0,high:[67400,51200,51100,46800,49200,45100,37300,41900][t]??0}))},Q("pro-trend","Pro trend","#1d4ed8",[54.2,51,47.8,44.6,41.4,38.2,35,31.8],1e3,!0),Q("prolite","Prolite observed","#0f766e",[15.9,15.8,15.9,16.1,15.7,15.6,15.9,15.8],1e3)],usageRemainingSeries:[Q("remaining","Usage remaining","#059669",[87,71,63,56,56,48,50,54]),Q("allowance","Allowance guide","#0f766e",[86,85,84,83,82,81,80,79],1,!0)],actualVsPredictedSeries:[Q("observed","Observed drain","#2563eb",[18.7,22.1,45.3,31,34.8],1e3),Q("predicted","Predicted baseline","#1d4ed8",[17.9,21.4,41.2,29.6,33.9],1e3,!0)],findings:[{rank:1,title:"Long Thread: data-engine-refactor",severity:"High",credits:12847,share:25.6,summary:"Very long duration with high model effort."},{rank:2,title:"Cache Misses (Large Inputs)",severity:"High",credits:9612,share:19.1,summary:"Large uncached inputs across 214 calls."},{rank:3,title:"High Model Effort",severity:"Medium",credits:7404,share:14.7,summary:"Reasoning and output token volume are concentrated."},{rank:4,title:"Tool Output Volume",severity:"Medium",credits:5231,share:10.4,summary:"Large tool outputs returned to the model."}],calls:[["2026-06-01T10:24:00Z","Jun 1, 10:24 AM","thread-9f3a1c","codex-1","high",128542,45231,62,.42,"18.4s",!1,["review"]],["2026-06-01T10:18:00Z","Jun 1, 10:18 AM","thread-7b2e91","o4-mini","medium",98731,32104,41,.31,"12.7s",!0,["analysis"]],["2026-06-01T10:12:00Z","Jun 1, 10:12 AM","thread-3c8d4e","o3","high",64221,18903,28,.12,"9.3s",!0,["uncached"]],["2026-06-01T10:06:00Z","Jun 1, 10:06 AM","thread-1a2b3c","codex-1","high",245123,98112,71,.87,"27.6s",!1,["large"]],["2026-06-01T10:01:00Z","Jun 1, 10:01 AM","thread-8d7c6b","gpt-4.1","low",12543,4231,12,.03,"3.6s",!0,["quick"]],["2026-06-01T09:55:00Z","Jun 1, 09:55 AM","thread-2f9e7d","o4-mini","medium",76881,28442,39,.24,"11.2s",!1,["subagent"]],["2026-06-01T09:50:00Z","Jun 1, 09:50 AM","thread-6a5b4c","codex-1","high",312654,112991,67,1.12,"31.8s",!1,["file-heavy"]],["2026-06-01T09:47:00Z","Jun 1, 09:47 AM","thread-0f1e2d","o3","low",8221,2903,15,.02,"2.8s",!0,["fast"]]].map(([e,t,a,n,r,s,i,o,h,f,d,b],u)=>{const p=Number(s),g=Number(i),v=Number(o),w=Math.round(p*Math.max(100-v,0)/100);return{id:`fixture-call-${u}`,rawTime:String(e),eventTimestamp:String(e),callStartedAt:String(e),time:String(t),thread:String(a),model:String(n),effort:String(r),input:p,output:g,reasoningOutput:Math.round(g*.2),totalTokens:p+g,cachedInput:Math.round(p*v/100),uncachedInput:w,cachedPct:v,cost:u===4?0:Number(h),credits:(u===4?0:Number(h))*25,duration:String(f),durationSeconds:Number.parseFloat(String(f))||0,previousCallGap:u===0?"-":`${u*7}m 0s`,previousCallEventTimestamp:u===0?"":`2026-06-01T09:${String(40+u).padStart(2,"0")}:00Z`,previousCallGapSeconds:u*420,initiator:u%3===0?"user":u%3===1?"assistant":"tool",initiatorReason:u%3===0?"direct user request":u%3===1?"assistant follow-up":"tool-driven continuation",initiatorConfidence:u%2===0?"exact":"estimated",serviceTier:"",fast:null,serviceTierSource:"",serviceTierConfidence:"",fastProxyCandidate:!!d,standardUsageCredits:(u===4?0:Number(h))*25,usageCreditMultiplier:1,usageCreditMultiplierSource:"tier_unknown",usageCreditConfidence:u===7?"user_override":u%4===0?"exact":u%4===1?"estimated":u%4===2?"missing":"fixture",usageCreditModel:u===4?"":`${n}-credits`,usageCreditSource:u===4?"":"fixture-rate-card",usageCreditFetchedAt:u===4?"":"2026-06-01T10:00:00Z",usageCreditTier:u%2===0?"standard":"estimated",usageCreditNote:u===2?"fixture inherited rate card":"",pricingModel:u===4?"":`${n}-pricing`,pricingEstimated:u===1||u===5,signal:w>5e4?"cache-risk":"aggregate",recommendation:w>5e4?"Review uncached aggregate input before continuing this thread.":"",tags:b,sessionId:`fixture-session-${u}`,turnId:`fixture-turn-${u}`,parentSessionId:u%3===0?"fixture-parent-session":"",parentSessionUpdatedAt:u%3===0?"2026-06-01T09:30:00Z":"",parentThread:u%3===0?"parent-thread-analysis":"",threadAttachmentLabel:u%3===0?"spawned child thread":"direct active thread",threadSource:u%3===0?"subagent":"user",subagentType:u%3===0?"analysis":"",agentRole:u%3===0?"reviewer":"",agentNickname:u%3===0?"usage-reviewer":"",project:u%2===0?"codex-usage-tracker":"local-ops",projectRelativeCwd:u%2===0?"frontend/dashboard":".",projectTags:u%2===0?["dashboard","rewrite"]:["local"],cwd:`/fixtures/${u%2===0?"codex-usage-tracker":"local-ops"}`,sourceFile:`fixture-thread-${u}.jsonl`,lineNumber:120+u,gitBranch:"experiment/frontend-rewrite",gitRemoteLabel:"origin",gitRemoteHash:`fixture-${u}`,contextWindowPct:Math.min(18+v,96),modelContextWindow:128e3,cumulativeTotalTokens:p+g+u*1e4,estimatedCacheSavings:Math.round((p-w)*1e-5*100)/100,efficiencyFlags:w>5e4?["cache-risk"]:[]}}),threads:[["thread-9f3a",142,58400,8.76,12,1.38,"High",42],["thread-7c2b",87,31200,4.21,22,1.12,"Medium",55],["thread-1a8c",64,22700,3.02,18,.98,"High",48],["thread-d3e1",53,18100,2.11,41,.81,"Low",72],["thread-b7f0",41,13600,1.65,47,.73,"Low",75],["thread-3c5d",36,9900,1.18,35,.66,"Medium",63],["thread-0e16",28,6400,.72,56,.58,"Low",82]].map(([e,t,a,n,r,s,i,o],h)=>{const f=Number(t),d=Number(a),b=Number(r),u=f*48,p=(h+1)*420;return{name:String(e),latestCallId:`fixture-call-${h}`,latestActivity:`Jun ${h+1}, 10:${String(24-h).padStart(2,"0")} AM`,latestActivityRaw:`2026-06-${String(h+1).padStart(2,"0")}T10:${String(24-h).padStart(2,"0")}:00Z`,turns:f,totalDurationSeconds:u,totalDuration:`${Math.floor(u/60)}m ${u%60}s`,averageGapSeconds:p,averageGap:`${Math.floor(p/60)}m ${p%60}s`,initiatorSummary:h%2===0?"user x4, assistant x2":"assistant x3, tool x1",modelSummary:h%2===0?"codex-1 x5, o4-mini x2":"o4-mini x3, o3 x1",effortSummary:h%2===0?"high x5, medium x2":"medium x3, low x1",totalTokens:d,cachedInput:Math.round(d*b/100),uncachedInput:Math.round(d*Math.max(100-b,0)/100),outputTokens:Math.round(d*.28),reasoningOutput:Math.round(d*.08),cost:Number(n),credits:Number(n)*25,cachePct:b,contextPct:Math.min(96,28+h*7),costPerCall:Number(s),coldResumeRisk:i,productivity:Number(o)}}),weeklyWindows:Mt.map((e,t)=>({week:e,plan:t===0?"Prolite":"Pro",observedPct:[61.4,49.2,47.7,48.3,44.5,37.4,40.1,35.8][t]??0,credits:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,projected:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,ciLow:[42156,34892,33424,34021,31241,26164,28234,29450][t]??0,ciHigh:[57467,47657,46349,47105,43326,36676,39450,41900][t]??0,confidence:t===0?"Medium":"High",note:["Prolite baseline","Drop in credits","Stable","Slight uptick","Down again","Lowest window","Recovery","Latest"][t]??""})),modelCosts:[{label:"codex-1",value:16.21,color:"#2563eb"},{label:"o3",value:12.43,color:"#1d4ed8"},{label:"o4-mini",value:7.62,color:"#059669"},{label:"gpt-4.1",value:4.91,color:"#f59e0b"},{label:"other",value:1.5,color:"#94a3b8"}],commandActions:[{title:"Show highest uncached calls",status:"Ready",owner:"Calls",description:"214 calls above the uncached threshold."},{title:"Compare Pro weeks",status:"Ready",owner:"Usage Drain",description:"Allowance windows with confidence intervals."},{title:"Find cold resumes",status:"Ready",owner:"Cache",description:"14 threads with long idle gaps."},{title:"Export support bundle",status:"Planned",owner:"Reports",description:"Local aggregate artifacts only."}],cacheSegments:[{label:"Cache read",value:38.7,color:"#2563eb"},{label:"Cache write",value:29.6,color:"#059669"},{label:"Uncached",value:31.7,color:"#7c3aed"}],cacheHeatmap:[{thread:"thread-8c1e",labels:it,values:[62,71,89,82,74,31]},{thread:"thread-2b9d",labels:it,values:[42,58,77,61,51,24]},{thread:"thread-713a",labels:it,values:[78,81,83,66,59,37]},{thread:"thread-4af2",labels:it,values:[24,36,63,54,71,44]},{thread:"thread-f9c3",labels:it,values:[18,25,41,38,52,22]}],diagnostics:[{title:"Usage Drain",status:"Ready",finding:"Projected weekly credits declined from the baseline and partially recovered in the latest window.",confidence:"High",metric:"33,842 credits / week",series:[Q("usage-drain","Projected credits","#2563eb",[41.8,46.7,45.9,32.1,33.8],1e3)]},{title:"Cache Behavior",status:"Ready",finding:"Cache hit rate is healthy overall, with spikes aligned to large cache misses and cold resumes.",confidence:"Medium",metric:"41.1% hit rate",series:[Q("cache","Cache hit %","#059669",[44,48,38,33,40])]},{title:"Thread Efficiency",status:"Ready",finding:"Long threads account for most estimated cost and are the clearest optimization target.",confidence:"High",metric:"65% cost share",series:[Q("threads","Cost share","#1d4ed8",[65,23,8,4])]},{title:"Tool And Command Activity",status:"Stale",finding:"Command volume is stable with a slight upward trend; read and shell commands dominate.",confidence:"Medium",metric:"912 commands",series:[Q("commands","Commands","#7c3aed",[542,488,611,883,912])]}],reports:[{title:"Weekly Credits",status:"Ready",owner:"Usage Drain",description:"Plan-specific weekly credits, trend lines, and confidence intervals."},{title:"Usage Remaining",status:"Ready",owner:"Usage Drain",description:"Observed remaining usage over time with reset handling."},{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Cumulative estimated cost by thread and concentration metrics."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Actual-vs-predicted drain and feature group comparisons."},{title:"Fast Mode Proxy",status:"Planned",owner:"Calls",description:"Candidate detection, speedup histogram, and confidence breakdowns."},{title:"Allowance Change",status:"Planned",owner:"Reports",description:"Week-to-week allowance estimate changes with careful language."}]};function Q(e,t,a,n,r=1,s=!1){return{id:e,label:t,color:a,dashed:s,points:n.map((i,o)=>({label:Mt[o]??`Point ${o+1}`,value:i*r}))}}function rr(e){if(window.location.protocol==="file:")throw new Error("Live refresh requires the localhost dashboard server.");if(!(e!=null&&e.api_token))throw new Error("Live refresh requires localhost dashboard API token.")}function ma(e){return{Accept:"application/json","X-Codex-Usage-Token":e.api_token||""}}function oo(e,t){return new Promise((a,n)=>{if(t!=null&&t.aborted){n(en(t));return}const r=window.setTimeout(()=>{t==null||t.removeEventListener("abort",s),a()},e);function s(){window.clearTimeout(r),n(en(t))}t==null||t.addEventListener("abort",s,{once:!0})})}function sr(e){return(e instanceof DOMException||e instanceof Error)&&e.name==="AbortError"}function en(e){return(e==null?void 0:e.reason)instanceof Error?e.reason:new DOMException("The request was cancelled.","AbortError")}const co=["#2563eb","#1d4ed8","#059669","#f59e0b","#94a3b8"];function ir(e){const t=new Map;e.forEach(r=>{const s=r.model||"unknown";t.set(s,(t.get(s)??0)+r.cost)});const a=[...t.entries()].sort((r,s)=>s[1]-r[1]||r[0].localeCompare(s[0]));return(a.length>5?[...a.slice(0,4),["other",a.slice(4).reduce((r,s)=>r+s[1],0)]]:a).map(([r,s],i)=>({label:r,value:s,color:co[i]??"#94a3b8"}))}function or(e){if(!e.length)return[];const t=Math.max(e.reduce((a,n)=>a+pt(n),0),1);return[lo(e,t),uo(e,t),ho(e,t),fo(e,t)].filter(a=>!!a).sort((a,n)=>n.credits-a.credits).map((a,n)=>({...a,rank:n+1}))}function cr(e){if(!e.length)return[];const t=[{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Estimated cost concentration by loaded aggregate thread."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Highest estimated credit-impact calls from loaded aggregate rows."}];return e.some(a=>a.fastProxyCandidate||a.effort.toLowerCase()==="low")&&t.push({title:"Fast Mode Proxy",status:"Ready",owner:"Calls",description:"Low-effort and fast-call candidates inferred from aggregate rows."}),t}function lo(e,t){const a=new Map;e.forEach(i=>a.set(i.thread,[...a.get(i.thread)??[],i]));const[n,r]=[...a.entries()].sort((i,o)=>Ae(o[1],f=>f.totalTokens)-Ae(i[1],f=>f.totalTokens)||o[1].length-i[1].length)[0]??[];if(!n||!(r!=null&&r.length)||r.length<2)return null;const s=Ae(r,pt);return{rank:0,title:`Long Thread: ${n}`,severity:s/t>=.25||r.length>=8?"High":"Medium",credits:Math.round(s),share:s/t*100,summary:`${r.length.toLocaleString()} loaded calls and ${Ae(r,i=>i.totalTokens).toLocaleString()} tokens in this thread.`}}function uo(e,t){const a=e.filter(r=>r.signal==="cache-risk"||r.cachedPct<35||r.uncachedInput>5e4);if(!a.length)return null;const n=Ae(a,pt);return{rank:0,title:"Cache Misses (Large Inputs)",severity:a.some(r=>r.cachedPct<20||r.uncachedInput>5e4)?"High":"Medium",credits:Math.round(n),share:n/t*100,summary:`${a.length.toLocaleString()} loaded calls show low cache reuse or large uncached input.`}}function ho(e,t){const a=e.filter(r=>r.effort.toLowerCase()==="high"||r.reasoningOutput>0);if(!a.length)return null;const n=Ae(a,pt);return{rank:0,title:"High Model Effort",severity:n/t>=.25?"High":"Medium",credits:Math.round(n),share:n/t*100,summary:`${a.length.toLocaleString()} loaded calls use high effort or report reasoning output.`}}function fo(e,t){const a=Math.max(25e3,mo(e.map(s=>s.output),.75)),n=e.filter(s=>s.output>=a||s.tags.some(i=>["file-heavy","subagent","large"].includes(i)));if(!n.length)return null;const r=Ae(n,pt);return{rank:0,title:"Tool Output Volume",severity:n.some(s=>s.output>5e4)?"High":"Medium",credits:Math.round(r),share:r/t*100,summary:`${n.length.toLocaleString()} loaded calls have high output volume or file-heavy/subagent tags.`}}function pt(e){return e.credits>0?e.credits:e.cost*25}function Ae(e,t){return e.reduce((a,n)=>a+t(n),0)}function mo(e,t){const a=e.filter(n=>Number.isFinite(n)).sort((n,r)=>n-r);return a.length?a[Math.min(a.length-1,Math.max(0,Math.floor((a.length-1)*t)))]??0:0}function lr(e){const t=new Map;for(const n of e){if(!Number.isFinite(n.timestamp))continue;const r=ur(n.timestamp),s=t.get(r)??{label:dr(n.timestamp),timestamp:po(n.timestamp),cached:0,cost:0,input:0,output:0};s.cached+=n.cached,s.cost+=n.cost,s.input+=n.input,s.output+=n.output,t.set(r,s)}const a=go(t);return a.length?{tokenSeries:[{id:"input",label:"Input",color:"#2563eb",points:a.map(n=>({label:n.label,value:n.input}))},{id:"output",label:"Output",color:"#059669",points:a.map(n=>({label:n.label,value:n.output}))},{id:"cached",label:"Cached",color:"#7c3aed",dashed:!0,points:a.map(n=>({label:n.label,value:n.cached}))}],costSeries:[{id:"cost",label:"Estimated Cost",color:"#f59e0b",points:a.map(n=>({label:n.label,value:n.cost}))}],cacheSeries:[{id:"cache",label:"Cache hit %",color:"#2563eb",points:a.map(n=>({label:n.label,value:n.input>0?n.cached/n.input*100:0}))}]}:{tokenSeries:[],costSeries:[],cacheSeries:[]}}function go(e){const t=[...e.values()].sort((s,i)=>s.timestamp-i.timestamp),a=t.at(0),n=t.at(-1);if(!a||!n)return[];const r=[];for(const s=new Date(a.timestamp);s.getTime()<=n.timestamp;s.setDate(s.getDate()+1)){const i=s.getTime(),o=ur(i);r.push(e.get(o)??{label:dr(i),timestamp:i,cached:0,cost:0,input:0,output:0})}return r}function ur(e){const t=new Date(e),a=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${a}-${n}`}function po(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}function dr(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function W(e,t){var n;const a=Number(((n=e.summary)==null?void 0:n[t])??0);return Number.isFinite(a)?a:0}function vo(e){if(!(!e.summary||e.load_window==="rows"))return{visibleCalls:W(e,"visible_calls"),inputTokens:W(e,"input_tokens"),cachedInputTokens:W(e,"cached_input_tokens"),uncachedInputTokens:W(e,"uncached_input_tokens"),outputTokens:W(e,"output_tokens"),reasoningOutputTokens:W(e,"reasoning_output_tokens"),totalTokens:W(e,"total_tokens"),estimatedCostUsd:W(e,"estimated_cost_usd"),usageCredits:W(e,"usage_credits")}}const bo=1e4,wo=500;async function tn(e,t,a){var s,i;const n=t.limit&&t.limit>0?t.limit:wo,r=await a(e,{...t,limit:n});return(i=t.onProgress)==null||i.call(t,{status:"completed",phase:"loading_rows",message:`Loaded ${t.loadWindow==="all"?"all-history":t.loadWindow} evidence window`,completed:Number(r.loaded_row_count??((s=r.rows)==null?void 0:s.length)??0),total:Number(r.total_available_rows??r.loaded_row_count??0),percent:100}),r}async function an(e,t,a){var o,h;const n=[];let r=0,s=null,i=Number((e==null?void 0:e.total_available_rows)??0);for(let f=0;f<1e3;f+=1){(o=t.signal)==null||o.throwIfAborted();const d=await a(e,{...t,refresh:f===0?t.refresh:!1,limit:bo,offset:r}),b=d.rows??[];s=d,n.push(...b),i=Number(d.total_available_rows??i??n.length);const u=n.length>=i||!d.has_more;if((h=t.onProgress)==null||h.call(t,{status:u?"completed":"running",phase:"loading_rows",message:"Loading all rows",completed:n.length,total:i,percent:u?100:i>0?Math.min(99,Math.floor(n.length/i*100)):0}),r+=b.length,!d.has_more||b.length===0||n.length>=i)break}return{...s??e??{},rows:n,loaded_row_count:n.length,limit:null,limit_label:"All",has_more:!1,total_available_rows:i||n.length}}function yo(){if(window.__CODEX_USAGE_BOOT__)return window.__CODEX_USAGE_BOOT__;const e=document.getElementById("usage-data");if(!(e!=null&&e.textContent))return null;try{return JSON.parse(e.textContent)}catch{return null}}async function _o(e,t={}){if(t.refresh&&(e!=null&&e.refresh_jobs_available)){const a=await So(e,t),n={...t,refresh:!a};return n.loadWindow&&n.loadWindow!=="rows"?tn(e,n,He):n.limit===0?an(e,n,He):He(e,n)}return t.loadWindow&&t.loadWindow!=="rows"?tn(e,t,He):t.limit===0?an(e,t,He):He(e,t)}async function So(e,t){try{return await Co(e,t),!0}catch(a){if(sr(a)||a instanceof hr)throw a;return!1}}async function He(e,t={}){rr(e);const a=new URLSearchParams({refresh:t.refresh?"1":"0",limit:String(t.limit??(e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??500),_:String(Date.now())});t.loadWindow&&a.set("load_window",t.loadWindow),t.since&&a.set("since",t.since),t.offset&&t.offset>0&&a.set("offset",String(t.offset)),(t.includeArchived??wr(e))&&a.set("include_archived","1");const r=await fetch(`/api/usage?${a.toString()}`,{headers:ma(e),cache:"no-store",signal:t.signal});return await ga(r,"Usage refresh")}async function Co(e,t){var o;rr(e);const a=new URLSearchParams({_:String(Date.now())});(t.includeArchived??wr(e))&&a.set("include_archived","1");const r=await fetch(`/api/refresh/start?${a.toString()}`,{headers:ma(e),cache:"no-store",signal:t.signal}),s=await ga(r,"Usage refresh start");(o=t.onProgress)==null||o.call(t,s);const i=typeof s.job_id=="string"?s.job_id:"";if(!i)throw new Error("Usage refresh start did not return a job id.");return xo(e,i,t.onProgress,t.signal)}async function xo(e,t,a,n){for(let r=0;r<600;r+=1){n==null||n.throwIfAborted();const s=new URLSearchParams({job_id:t,_:String(Date.now())}),i=await fetch(`/api/refresh/status?${s.toString()}`,{headers:ma(e),cache:"no-store",signal:n}),o=await ga(i,"Usage refresh status");if(a==null||a(o),o.status==="completed")return o;if(o.status==="failed")throw new hr(o.error||o.message||"Usage refresh failed.");await oo(Math.min(1e3,150+r*50),n)}throw new Error("Usage refresh did not complete before the polling timeout.")}class hr extends Error{}function nn(e){if(!e)return{...nr,contextRuntime:ra(e)};const t=e.rows??[],a=t.map(mr),n=t.length?ke(t,v=>Number(v.total_tokens??0)):W(e,"total_tokens"),r=t.length?ke(t,v=>Number(v.estimated_cost_usd??0)):W(e,"estimated_cost_usd"),s=t.length?ke(t,v=>Number(v.cached_input_tokens??0)):W(e,"cached_input_tokens"),i=t.length?ke(t,v=>Number(v.input_tokens??0)):W(e,"input_tokens"),o=t.length?ke(t,v=>{const w=Number(v.input_tokens??0),T=Number(v.cached_input_tokens??0);return Number(v.uncached_input_tokens??Math.max(w-T,0))}):Math.max(i-s,0),h=t.length?ke(t,v=>Number(v.output_tokens??0)):W(e,"output_tokens"),f=t.length?ke(t,v=>Number(v.reasoning_output_tokens??0)):W(e,"reasoning_output_tokens"),d=i>0?s/i*100:0,b=a.length||Math.max(0,Number(e.loaded_row_count??0)),u=To(t),p=Lo(t),g=jo({cachePct:d,cachedTokens:s,estimatedCost:r,historyScope:e.history_scope??"active",totalCalls:b,totalTokens:n,tokenBreakdown:{cachedInput:s,uncachedInput:o,output:h,reasoningOutput:f},usageRemainingCard:Ao(e)});return{...ko(e),contextRuntime:ra(e),scopeSummary:vo(e),cards:g,...u,...p,calls:a,threads:yr(a),findings:or(a),modelCosts:ir(a),reports:cr(a),cacheSegments:[{label:"Cache read",value:d,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-d,0),color:"#7c3aed"}]}}function ko(e){return{...nr,contextRuntime:ra(e),tokenSeries:[],costSeries:[],cacheSeries:[],weeklyCreditSeries:[],usageRemainingSeries:[],actualVsPredictedSeries:[],calls:[],threads:[],findings:[],weeklyWindows:[],modelCosts:[],commandActions:[],cacheSegments:[],cacheHeatmap:[],diagnostics:[],reports:[]}}function To(e){return lr(e.map(t=>({timestamp:va(t),cached:Number(t.cached_input_tokens??0),cost:Number(t.estimated_cost_usd??0),input:Number(t.input_tokens??0),output:Number(t.output_tokens??0)})))}function Lo(e){const t=[...e].map(f=>({row:f,timestamp:va(f)})).filter(f=>Number.isFinite(f.timestamp)).sort((f,d)=>f.timestamp-d.timestamp),a=new Map;for(const{row:f,timestamp:d}of t){const b=na(d),u=a.get(b)??{timestamp:d,credits:0,weeklyUsedPercent:null};u.credits+=Math.max(0,Number(f.usage_credits??0));const p=Oe(f.rate_limit_secondary_used_percent);p!==null&&(u.weeklyUsedPercent=p),a.set(b,u)}const n=[...a.entries()].map(([f,d])=>({label:f,...d}));let r=0;const s=n.map(f=>(r+=f.credits,{label:f.label,value:r})),i=s.map((f,d)=>{var b;return{label:f.label,value:s.length>1?(((b=s.at(-1))==null?void 0:b.value)??0)*((d+1)/s.length):f.value}}),o=n.filter(f=>f.weeklyUsedPercent!==null).map(f=>({label:f.label,value:Pt(100-(f.weeklyUsedPercent??0))})),h=Ro(e);return{weeklyCreditSeries:Mo(h),usageRemainingSeries:o.length?[{id:"weekly-remaining",label:"Weekly remaining",color:"#059669",points:o}]:[],actualVsPredictedSeries:s.length?[{id:"observed-drain",label:"Observed drain",color:"#2563eb",points:s},{id:"loaded-baseline",label:"Loaded-row baseline",color:"#1d4ed8",dashed:!0,points:i}]:[],weeklyWindows:h}}function Ro(e){const t=new Map;for(const a of e){const n=va(a);if(!Number.isFinite(n))continue;const r=Po(a,n),s=t.get(r)??{rows:[],latestTimestamp:0,latestUsedPercent:null};s.rows.push(a),n>=s.latestTimestamp&&(s.latestTimestamp=n,s.latestUsedPercent=Oe(a.rate_limit_secondary_used_percent)),t.set(r,s)}return[...t.entries()].map(([a,n])=>{var i;const r=n.rows.reduce((o,h)=>o+Math.max(0,Number(h.usage_credits??0)),0),s=n.latestUsedPercent??0;return{week:a,plan:String(((i=n.rows[0])==null?void 0:i.rate_limit_plan_type)??"unknown"),observedPct:s,credits:r,projected:s>0?r/(s/100):r,ciLow:s>0?r/(s/100)*.85:r,ciHigh:s>0?r/(s/100)*1.15:r,confidence:n.rows.length>=20?"Medium":"Low",note:`Loaded ${pa(n.rows.length)} rows`}}).sort((a,n)=>a.week.localeCompare(n.week))}function Mo(e){return e.length?[{id:"weekly-projected",label:"Projected weekly credits",color:"#2563eb",points:e.map(t=>({label:t.week,value:t.projected,low:t.ciLow,high:t.ciHigh}))},{id:"loaded-credits",label:"Loaded-row credits",color:"#0f766e",dashed:!0,points:e.map(t=>({label:t.week,value:t.credits}))}]:[]}function Po(e,t){const a=We(e.rate_limit_secondary_resets_at);return a!==null&&a>0?na(a*1e3):na(t)}function na(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function ra(e){return{apiToken:String((e==null?void 0:e.api_token)??""),contextApiEnabled:!!(e!=null&&e.context_api_enabled),fileMode:window.location.protocol==="file:"}}function jo(e){return[{label:"Total Tokens",value:Me(e.totalTokens),detail:`${e.historyScope} history scope`,trend:"loaded aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Me(e.tokenBreakdown.cachedInput)},{label:"Uncached",value:Me(e.tokenBreakdown.uncachedInput)},{label:"Output",value:Me(e.tokenBreakdown.output)},{label:"Reasoning",value:Me(e.tokenBreakdown.reasoningOutput)}]},{label:"Estimated Cost",value:Oo(e.estimatedCost),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.cachePct.toFixed(1)}%`,detail:`${Me(e.cachedTokens)} cached input`,trend:e.cachePct>=40?"healthy cache reuse":"cache risk",tone:e.cachePct>=40?"purple":"orange"},{label:"Total Calls",value:pa(e.totalCalls),detail:"loaded calls in this dashboard",trend:"privacy-safe",tone:"blue"},e.usageRemainingCard]}function Ao(e){const t=No(e.observed_usage);if(t)return t;const a=Eo(e.allowance_windows);return a||{label:"Usage Remaining",value:"Unknown",detail:e.allowance_configured?"allowance configured; no current window":"no observed usage or allowance window",trend:e.allowance_error?`config issue: ${e.allowance_error}`:"not available in payload",tone:e.allowance_error?"red":"orange"}}function No(e){const t=Array.isArray(e==null?void 0:e.windows)?e.windows:[];if(!(e!=null&&e.available)||!t.length)return null;const a=fr(t,s=>Oe(s.used_percent)!==null);if(!a)return null;const n=Oe(a.used_percent)??0,r=Pt(100-n);return{label:"Usage Remaining",value:gr(r),detail:`${vr(a.label||a.key,"Observed usage")} observed usage`,trend:pr(a.resets_at)||e.source||"observed locally",tone:br(r)}}function Eo(e){if(!Array.isArray(e)||!e.length)return null;const t=fr(e,o=>{const h=Oe(o.remaining_percent),f=We(o.remaining_credits),d=We(o.total_credits);return h!==null||f!==null||d!==null&&d>0});if(!t)return null;const a=We(t.remaining_credits),n=We(t.total_credits),r=a!==null&&n!==null&&n>0?a/n*100:null,s=Oe(t.remaining_percent)??r;return{label:"Usage Remaining",value:s!==null?gr(Pt(s)):`${rn(a??0)} left`,detail:`${vr(t.label||t.key,"Allowance")} allowance window`,trend:[a===null?"":`${rn(a)} left`,pr(t.reset_at)].filter(Boolean).join(" · ")||"configured allowance",tone:s===null?"green":br(Pt(s))}}function fr(e,t){const a=e.filter(t);return a.find(Do)??a[0]??null}function Do(e){const t=We(e.window_minutes),a=`${e.key??""} ${e.label??""}`.toLowerCase();return t===10080||/\b(weekly|week|7d|7-day|7 day)\b/.test(a)}function mr(e,t=0){const a=String(e.event_timestamp??e.time??e.turn_timestamp??e.started_at??e.call_started_at??""),n=a,r=String(e.call_started_at??e.started_at??a),s=Number(e.input_tokens??0),i=Number(e.output_tokens??0),o=Number(e.reasoning_output_tokens??0),h=Number(e.cached_input_tokens??0),f=Number(e.cache_hit_ratio??e.cache_ratio??0),d=s>0?h/s*100:f*100,b=Number(e.total_tokens??s+i),u=Number(e.duration_seconds??e.call_duration_seconds??0),p=String(e.previous_call_event_timestamp??""),g=Number(e.previous_call_delta_seconds??0),v=Number(e.uncached_input_tokens??Math.max(s-h,0)),w=String(e.record_id??e.id??`${n||"row"}-${t}`),T=String(e.primary_signal??"").trim(),N=Number(e.line_number),R=Oe(e.context_window_percent),_=Number(e.model_context_window),L=Number(e.cumulative_total_tokens),y=e.fast,x=y===!0||y===1?!0:y===!1||y===0?!1:null;return{id:w,threadKey:String(e.thread_key??""),rawTime:n,eventTimestamp:a,callStartedAt:r,time:_r(n),thread:Io(e),model:String(e.model??"unknown"),effort:String(e.effort??"blank"),input:s,output:i,reasoningOutput:o,totalTokens:b,cachedInput:h,uncachedInput:v,cachedPct:d,cost:Number(e.estimated_cost_usd??0),credits:Number(e.usage_credits??0),duration:jt(u),durationSeconds:u,previousCallGap:jt(g),previousCallEventTimestamp:p,previousCallGapSeconds:Number.isFinite(g)?g:0,initiator:String(e.call_initiator??"unknown"),initiatorReason:String(e.call_initiator_reason??""),initiatorConfidence:String(e.call_initiator_confidence??""),serviceTier:String(e.service_tier??""),fast:x,serviceTierSource:String(e.service_tier_source??""),serviceTierConfidence:String(e.service_tier_confidence??""),fastProxyCandidate:u>0&&b/Math.max(u,1)>4e3,standardUsageCredits:Number(e.standard_usage_credits??e.usage_credits??0),usageCreditMultiplier:Number(e.usage_credit_multiplier??1),usageCreditMultiplierSource:String(e.usage_credit_multiplier_source??""),usageCreditConfidence:String(e.usage_credit_confidence??"unknown"),usageCreditModel:String(e.usage_credit_model??""),usageCreditSource:String(e.usage_credit_source??""),usageCreditFetchedAt:String(e.usage_credit_fetched_at??""),usageCreditTier:String(e.usage_credit_tier??""),usageCreditNote:String(e.usage_credit_note??""),pricingModel:String(e.pricing_model??""),pricingEstimated:!!e.pricing_estimated,signal:T||(d<25?"cache-risk":"aggregate"),recommendation:String(e.recommended_action??""),tags:d<25?["uncached"]:d>60?["healthy-cache"]:[],sessionId:String(e.session_id??""),turnId:String(e.turn_id??""),parentSessionId:String(e.parent_session_id??""),parentSessionUpdatedAt:String(e.resolved_parent_session_updated_at??e.parent_session_updated_at??""),parentThread:String(e.resolved_parent_thread_name??e.parent_thread_name??""),threadAttachmentLabel:String(e.thread_attachment_label??""),threadSource:String(e.thread_source??""),subagentType:String(e.subagent_type??""),agentRole:String(e.agent_role??""),agentNickname:String(e.agent_nickname??""),project:String(e.project_name??""),projectRelativeCwd:String(e.project_relative_cwd??""),projectTags:Array.isArray(e.project_tags)?e.project_tags.map(M=>String(M)):[],cwd:String(e.cwd??""),sourceFile:String(e.source_file??""),lineNumber:Number.isFinite(N)&&N>0?N:null,gitBranch:String(e.git_branch??""),gitRemoteLabel:String(e.git_remote_label??""),gitRemoteHash:String(e.git_remote_hash??""),contextWindowPct:R,modelContextWindow:Number.isFinite(_)&&_>0?_:null,cumulativeTotalTokens:Number.isFinite(L)&&L>0?L:null,estimatedCacheSavings:Number(e.estimated_cache_savings_usd??0),efficiencyFlags:Array.isArray(e.efficiency_flags)?e.efficiency_flags.map(M=>String(M)):[]}}function Oe(e){const t=Number(e);return Number.isFinite(t)?t<=1?t*100:t:null}function We(e){const t=Number(e);return Number.isFinite(t)?t:null}function Pt(e){return Math.max(0,Math.min(100,e))}function gr(e){const t=Math.abs(e)>=10?0:1;return`${e.toFixed(t)}%`}function rn(e){return`${Me(e)} cr`}function pr(e){if(e==null||e==="")return"";const t=typeof e=="number"?e*1e3:Date.parse(e);return Number.isFinite(t)?`resets ${Fo(t)}`:""}function Fo(e){const t=new Date(e);return Number.isNaN(t.getTime())?String(e):`${t.toISOString().slice(0,16).replace("T"," ")} UTC`}function vr(e,t){return(e==null?void 0:e.trim())||t}function br(e){return e<20?"red":e<40?"orange":"green"}function wr(e){return typeof e.include_archived=="boolean"?e.include_archived:e.history_scope==="all-history"||e.history_scope==="all"}function Io(e){const t=e.thread_name??e.thread??e.resolved_parent_thread_name??e.parent_thread_name;if(t&&String(t).trim())return String(t);const a=e.project_name??e.project_relative_cwd,n=e.session_id?e.session_id.slice(-6):"";return a&&n?`${a} ${n}`:e.thread_attachment_label?String(e.thread_attachment_label):"Untitled thread"}function yr(e){const t=new Map;for(const a of e)t.set(a.thread,[...t.get(a.thread)??[],a]);return[...t.entries()].map(([a,n])=>{const r=n.length,i=[...n].sort((y,x)=>sn(x)-sn(y))[0]??null,o=(i==null?void 0:i.rawTime)||(i==null?void 0:i.time)||"",h=n.reduce((y,x)=>y+x.totalTokens,0),f=n.reduce((y,x)=>y+x.cachedInput,0),d=n.reduce((y,x)=>y+x.uncachedInput,0),b=n.reduce((y,x)=>y+x.output,0),u=n.reduce((y,x)=>y+x.reasoningOutput,0),p=n.reduce((y,x)=>y+x.cost,0),g=n.reduce((y,x)=>y+x.credits,0),v=n.reduce((y,x)=>y+x.durationSeconds,0),w=n.filter(y=>y.previousCallGapSeconds>0),T=w.reduce((y,x)=>y+x.previousCallGapSeconds,0)/Math.max(w.length,1),N=f+d,R=N>0?f/N*100:n.reduce((y,x)=>y+x.cachedPct,0)/Math.max(r,1),_=n.map(y=>y.contextWindowPct).filter(y=>typeof y=="number"&&Number.isFinite(y)),L=R<25?"High":R<45?"Medium":"Low";return{name:a,latestCallId:(i==null?void 0:i.id)??"",latestActivity:_r(o),latestActivityRaw:o,turns:r,totalDurationSeconds:v,totalDuration:jt(v),averageGapSeconds:T,averageGap:jt(T),initiatorSummary:zt(n.map(y=>y.initiator)),modelSummary:zt(n.map(y=>y.model)),effortSummary:zt(n.map(y=>y.effort)),totalTokens:h,cachedInput:f,uncachedInput:d,outputTokens:b,reasoningOutput:u,cost:p,credits:g,cachePct:R,contextPct:_.length?Math.max(..._):null,costPerCall:p/Math.max(r,1),coldResumeRisk:L,productivity:Math.max(20,Math.round(R-p/Math.max(r,1)*4))}}).sort((a,n)=>n.cost-a.cost).slice(0,20)}function sn(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function zt(e,t=3){const a=new Map;for(const n of e){const r=n.trim()||"unknown";a.set(r,(a.get(r)??0)+1)}return[...a.entries()].sort((n,r)=>r[1]-n[1]||n[0].localeCompare(r[0])).slice(0,t).map(([n,r])=>`${n} x${pa(r)}`).join(", ")||"unknown"}function ke(e,t){return e.reduce((a,n)=>a+t(n),0)}async function ga(e,t){let a;try{a=await e.json()}catch(n){if(e.ok)throw new Error(`${t} response could not be read as JSON: ${$o(n)}`);a={}}if(!e.ok){const n=typeof a.error=="string"?a.error:`${t} request failed (${e.status})`;throw new Error(n)}return a}function $o(e){return e instanceof Error?e.message:String(e)}function pa(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Me(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Oo(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function jt(e){if(!Number.isFinite(e)||e<=0)return"-";if(e<60)return`${e.toFixed(0)}s`;const t=Math.floor(e/60),a=Math.round(e%60);return`${t}m ${a}s`}function _r(e){const t=new Date(e);return Number.isNaN(t.getTime())?e||"-":new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).format(t)}function va(e){return Date.parse(String(e.started_at??e.call_started_at??e.time??e.event_timestamp??e.turn_timestamp??""))}const Pe=1440*60*1e3;function Uo(e,t,a=window.location.search){const n=Sr(a);if(!n.active)return e;const r=e.calls.filter(s=>Vo(s,n));return r.length===e.calls.length?e:zo(e,r,`${t} filtered`)}function Sr(e){var h,f,d,b,u,p;const t=new URLSearchParams(e),a=((h=t.get("model"))==null?void 0:h.trim())??"",n=((f=t.get("effort"))==null?void 0:f.trim())??"",r=((d=t.get("confidence")||t.get("pricing"))==null?void 0:d.trim())??"",s=((b=t.get("date")||t.get("time"))==null?void 0:b.trim())??"",i=((u=t.get("from"))==null?void 0:u.trim())??"",o=((p=t.get("to"))==null?void 0:p.trim())??"";return{model:a,effort:n,confidence:r,datePreset:s,dateStart:i,dateEnd:o,active:!!(a||n||r||s||i||o)}}function Vo(e,t){return!(t.model&&e.model!==t.model||t.effort&&e.effort!==t.effort||t.confidence&&!Ko(e,t.confidence)||!qo(e,t))}function Ko(e,t){return t==="official"||t==="cost-exact"?!!(e.pricingModel&&!e.pricingEstimated):t==="estimated"||t==="cost-estimated"?e.pricingEstimated:t==="unpriced"||t==="cost-unpriced"?!e.pricingModel:t==="credit-exact"?e.usageCreditConfidence==="exact":t==="credit-estimated"?e.usageCreditConfidence==="estimated":t==="credit-override"?e.usageCreditConfidence==="user_override":t==="credit-missing"?e.usageCreditConfidence==="missing"||e.usageCreditConfidence==="unknown":!0}function qo(e,t){const a=Ho(t);if(!a.active)return!0;if(a.invalid)return!1;const n=Date.parse(e.rawTime||e.time);return!(!Number.isFinite(n)||a.start!==null&&n=a.endExclusive)}function Ho(e){if(e.datePreset&&e.datePreset!=="all"&&e.datePreset!=="custom"){const n=Qo(e.datePreset);return n?{active:!0,invalid:!1,...n}:{active:!1,invalid:!1,start:null,endExclusive:null}}const t=on(e.dateStart),a=on(e.dateEnd);return t!==null&&a!==null&&t>a?{active:!0,invalid:!0,start:t,endExclusive:a+Pe}:{active:t!==null||a!==null,invalid:!1,start:t,endExclusive:a===null?null:a+Pe}}function Qo(e){const t=Wo(new Date);if(e==="today")return{start:t,endExclusive:t+Pe};if(e==="last-7-days")return{start:t-6*Pe,endExclusive:t+Pe};if(e==="this-week"){const n=new Date(t).getDay(),r=n===0?-6:1-n,s=t+r*Pe;return{start:s,endExclusive:s+7*Pe}}if(e==="this-month"){const a=new Date(t),n=new Date(a.getFullYear(),a.getMonth(),1).getTime(),r=new Date(a.getFullYear(),a.getMonth()+1,1).getTime();return{start:n,endExclusive:r}}return null}function on(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,a,n]=e.split("-").map(Number),r=new Date(t,a-1,n);return r.getFullYear()!==t||r.getMonth()!==a-1||r.getDate()!==n?null:r.getTime()}function Wo(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function zo(e,t,a="filtered"){const n=t.reduce((u,p)=>u+p.totalTokens,0),r=t.reduce((u,p)=>u+p.cost,0),s=t.reduce((u,p)=>u+p.cachedInput,0),i=t.reduce((u,p)=>u+p.uncachedInput,0),o=t.reduce((u,p)=>u+p.output,0),h=t.reduce((u,p)=>u+p.reasoningOutput,0),f=t.reduce((u,p)=>u+p.input,0),d=f>0?s/f*100:0,b=e.cards.find(u=>u.label==="Usage Remaining")??{label:"Usage Remaining",value:"Unknown",detail:"not available in filtered view",trend:"not available in payload",tone:"orange"};return{...e,cards:Bo({cachePct:d,cachedTokens:s,estimatedCost:r,historyScope:a,totalCalls:t.length,totalTokens:n,tokenBreakdown:{cachedInput:s,uncachedInput:i,output:o,reasoningOutput:h},usageRemainingCard:b}),...Go(t),calls:t,threads:yr(t),findings:or(t),modelCosts:ir(t),reports:cr(t),cacheSegments:[{label:"Cache read",value:d,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-d,0),color:"#7c3aed"}]}}function Bo({cachePct:e,cachedTokens:t,estimatedCost:a,historyScope:n,totalCalls:r,totalTokens:s,tokenBreakdown:i,usageRemainingCard:o}){return[{label:"Total Tokens",value:Qe(s),detail:`${n} history scope`,trend:"filtered aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Qe(i.cachedInput)},{label:"Uncached",value:Qe(i.uncachedInput)},{label:"Output",value:Qe(i.output)},{label:"Reasoning",value:Qe(i.reasoningOutput)}]},{label:"Estimated Cost",value:Zo(a),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.toFixed(1)}%`,detail:`${Qe(t)} cached input`,trend:e>=40?"healthy cache reuse":"cache risk",tone:e>=40?"purple":"orange"},{label:"Total Calls",value:Jo(r),detail:"loaded calls matching filters",trend:"legacy shell filters",tone:"blue"},o]}function Go(e){return lr(e.map(t=>({timestamp:Date.parse(t.rawTime||t.time),cached:t.cachedInput,cost:t.cost,input:t.input,output:t.output})))}function Qe(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Jo(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Zo(e){return new Intl.NumberFormat("en-US",{currency:"USD",maximumFractionDigits:2,minimumFractionDigits:2,style:"currency"}).format(e)}const Cr=[{id:"overview",label:"Overview",description:"High-level telemetry",icon:Ds},{id:"investigator",label:"Investigate",description:"Root-cause evidence",icon:Es},{id:"compression-lab",label:"Compression Lab",description:"Context savings",icon:Ls},{id:"calls",label:"Calls",description:"Model-call table",icon:Os},{id:"threads",label:"Threads",description:"Thread efficiency",icon:Ks},{id:"usage-drain",label:"Limits",description:"Allowance intelligence",icon:Vs},{id:"cache-context",label:"Cache And Context",description:"Cache and cold resumes",icon:Ps},{id:"diagnostics",label:"Diagnostics Notebook",description:"Technical report",icon:ks},{id:"reports",label:"Reports",description:"Generated analyses",icon:Rs},{id:"settings",label:"Settings",description:"Local configuration",icon:Is}],xr=[{label:"Files",icon:As,target:"settings"},{label:"Commands",icon:Cs,target:"investigator"},{label:"Models",icon:Ts,target:"calls"}];function kr(e){return ws(e)}const Xo=[{value:"day",label:"24 hours",ariaLabel:"Last 24h"},{value:"week",label:"7 days",ariaLabel:"Last 7 days"},{value:"rows",label:"Recent",ariaLabel:"Recent rows"},{value:"all",label:"All time",ariaLabel:"All time"}];function Yo(e){const t=e.refreshing||!e.canUseLiveApi,a=e.loadWindow==="rows",n=`${e.loadedRowCount.toLocaleString()} detail row${e.loadedRowCount===1?"":"s"} cached`,r=a?`${e.loadedRowCount.toLocaleString()} loaded / ${e.totalAvailableRows.toLocaleString()} total`:`${e.totalAvailableRows.toLocaleString()} calls analyzed · ${n}`,s=a?`${e.loadedRowCount.toLocaleString()} of ${e.totalAvailableRows.toLocaleString()} evidence rows loaded`:`Focused pages analyze all ${e.totalAvailableRows.toLocaleString()} calls in scope; ${e.loadedRowCount.toLocaleString()} call rows are cached for immediate detail views.`,i=a?e.rowLoadStatus:`${e.rowLoadModeLabel} analysis uses ${e.totalAvailableRows.toLocaleString()} calls; ${n}`;return c.jsxs("section",{className:"data-window-control","aria-label":"Analysis scope",children:[c.jsxs("div",{className:"data-window-summary",children:[c.jsx("span",{children:"Analysis scope"}),c.jsx("strong",{children:e.rowLoadModeLabel}),c.jsx("small",{title:s,children:r})]}),c.jsx("div",{className:"data-window-options",role:"group","aria-label":"Choose loaded call window",children:Xo.map(o=>c.jsx("button",{type:"button","aria-label":o.ariaLabel,"aria-pressed":e.loadWindow===o.value,disabled:t,onClick:()=>e.onWindowChange(o.value),children:o.label},o.value))}),e.loadWindow==="rows"?c.jsxs("div",{className:"row-window-editor",children:[c.jsx("input",{"aria-label":"Rows to load slider","aria-valuetext":`${e.finitePendingLoadLimit.toLocaleString()} recent rows`,type:"range",min:1,max:e.rowLimitSliderMax,step:100,value:e.rowLimitSliderValue,onChange:o=>e.onSliderChange(o.target.value),disabled:t}),c.jsx("input",{"aria-label":"Rows to load",type:"number",min:1,step:100,value:e.pendingLoadLimit,onChange:o=>e.onDraftChange(o.target.value),disabled:t}),c.jsx("button",{type:"button","data-primary":"true",onClick:e.onApply,disabled:t||!e.rowLimitChanged,children:e.loadLabel}),c.jsx("button",{type:"button",onClick:e.onLoadMore,disabled:t||!e.hasMoreRows,children:e.loadMoreLabel})]}):null,e.refreshing?c.jsxs("div",{className:"row-load-progress","aria-label":"Row loading progress",children:[c.jsx("div",{className:"row-load-progress-track",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":e.refreshProgressPercent??void 0,children:c.jsx("span",{style:{width:`${e.refreshProgressPercent??8}%`}})}),c.jsxs("span",{children:[e.refreshProgressPercent===null?e.refreshProgressText:`${Math.round(e.refreshProgressPercent)}% loaded`,c.jsx("button",{className:"icon-button",type:"button",onClick:()=>void e.onCancel(),"aria-label":"Cancel refresh",title:"Cancel refresh",children:c.jsx(la,{size:13})})]})]}):null,c.jsx("span",{className:"sr-only",role:"status","aria-live":"polite",children:i})]})}const ba=[{value:"all",label:"All time"},{value:"today",label:"Today"},{value:"this-week",label:"This week"},{value:"last-7-days",label:"Last 7 days"},{value:"this-month",label:"This month"},{value:"custom",label:"Custom"}],Tr=[{value:"all",label:"All confidence"},{value:"cost-exact",label:"Exact cost"},{value:"cost-estimated",label:"Estimated cost"},{value:"cost-unpriced",label:"Unpriced cost"},{value:"credit-exact",label:"Exact credit"},{value:"credit-estimated",label:"Estimated credit"},{value:"credit-override",label:"Credit override"},{value:"credit-missing",label:"Missing credit"}];function ec({activeView:e,locationSearch:t,model:a,onUrlChange:n}){const r=Sr(t),s=C.useMemo(()=>cn(a.calls.map(g=>g.model)),[a.calls]),i=C.useMemo(()=>cn(a.calls.map(g=>g.effort)),[a.calls]),o=r.dateStart||r.dateEnd?"custom":tc(r.datePreset),h=nc(r,o);if(e==="calls"||e==="call"||!a.calls.length)return null;function f(g){const v=new URL(window.location.href);g(v),n(v)}function d(g,v){f(w=>{g==="confidence"&&w.searchParams.delete("pricing"),!v||v==="all"?w.searchParams.delete(g):w.searchParams.set(g,v)})}function b(g){f(v=>{if(!g||g==="all"){v.searchParams.delete("date"),v.searchParams.delete("time"),v.searchParams.delete("from"),v.searchParams.delete("to");return}v.searchParams.set("date",g),v.searchParams.set("time",g),g!=="custom"&&(v.searchParams.delete("from"),v.searchParams.delete("to"))})}function u(g,v){f(w=>{v?(w.searchParams.set(g,v),w.searchParams.set("date","custom"),w.searchParams.set("time","custom")):(w.searchParams.delete(g),!w.searchParams.get("from")&&!w.searchParams.get("to")&&(w.searchParams.delete("date"),w.searchParams.delete("time")))})}function p(){f(g=>{for(const v of["model","effort","confidence","pricing","date","time","from","to"])g.searchParams.delete(v)})}return c.jsxs("section",{className:"global-filter-strip span-all","aria-label":"Dashboard filters",children:[c.jsxs("strong",{children:[c.jsx(Ns,{size:15}),"Filters"]}),c.jsxs("label",{children:[c.jsx("span",{children:"Model"}),c.jsxs("select",{"aria-label":"Global model filter",value:r.model||"all",onChange:g=>d("model",g.target.value),children:[c.jsx("option",{value:"all",children:"All models"}),s.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Effort"}),c.jsxs("select",{"aria-label":"Global effort filter",value:r.effort||"all",onChange:g=>d("effort",g.target.value),children:[c.jsx("option",{value:"all",children:"All effort"}),i.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Confidence"}),c.jsx("select",{"aria-label":"Global confidence filter",value:ac(r.confidence),onChange:g=>d("confidence",g.target.value),children:Tr.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Time"}),c.jsx("select",{"aria-label":"Global time filter",value:o,onChange:g=>b(g.target.value),children:ba.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))}),h?c.jsx("span",{className:"filter-status","data-state":h.state,"aria-live":"polite",children:h.label}):null]}),c.jsxs("label",{children:[c.jsx("span",{children:"Start"}),c.jsx("input",{"aria-label":"Global start date",type:"date",value:r.dateStart,onChange:g=>u("from",g.target.value)})]}),c.jsxs("label",{children:[c.jsx("span",{children:"End"}),c.jsx("input",{"aria-label":"Global end date",type:"date",value:r.dateEnd,onChange:g=>u("to",g.target.value)})]}),c.jsxs("button",{className:"toolbar-button",type:"button",disabled:!r.active,onClick:p,children:[c.jsx(la,{size:15}),"Clear filters"]})]})}function cn(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean))).sort((t,a)=>t.localeCompare(a))}function tc(e){return ba.some(t=>t.value===e)?e:"all"}function ac(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":Tr.some(t=>t.value===e)?e:"all"}function nc(e,t){var r;const a=un(e.dateStart),n=un(e.dateEnd);if(a!==null&&n!==null&&a>n)return{label:"Invalid date range",state:"error"};if(t==="custom"&&(e.dateStart||e.dateEnd))return{label:rc(e.dateStart,e.dateEnd),state:"active"};if(t!=="all"){const s=((r=ba.find(o=>o.value===t))==null?void 0:r.label)??t,i=sc(t);return{label:i?`${s}: ${ln(i.start)} to ${ln(ze(i.endExclusive,-1))}`:s,state:"active"}}return null}function rc(e,t){return e&&t?`Custom: ${e} to ${t}`:e?`Custom: from ${e}`:t?`Custom: through ${t}`:"Custom range"}function sc(e){const t=ic();if(e==="today")return{start:t,endExclusive:ze(t,1)};if(e==="this-week"){const a=oc(t);return{start:a,endExclusive:ze(a,7)}}return e==="last-7-days"?{start:ze(t,-6),endExclusive:ze(t,1)}:e==="this-month"?{start:new Date(t.getFullYear(),t.getMonth(),1),endExclusive:new Date(t.getFullYear(),t.getMonth()+1,1)}:null}function ic(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function oc(e){const t=e.getDay();return ze(e,t===0?-6:1-t)}function ze(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function ln(e){const t=String(e.getMonth()+1).padStart(2,"0"),a=String(e.getDate()).padStart(2,"0");return`${e.getFullYear()}-${t}-${a}`}function un(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,a,n]=e.split("-").map(Number),r=new Date(t,a-1,n);return r.getFullYear()!==t||r.getMonth()!==a-1||r.getDate()!==n?null:r.getTime()}function cc(e){return kr(e)&&e!=="call"}function sa(e,t="overview"){return e==="insights"?"overview":kr(e)?e:t}function dn(e=window.location.search,t="calls"){const a=new URLSearchParams(e).get("return"),n=sa(a,t);return cc(n)?n:t}function hn(e=window.location.search){return new URLSearchParams(e).has("return")}function lc(e){var t,a;return((t=Cr.find(n=>n.id===e))==null?void 0:t.label)??((a=xr.find(n=>n.target===e))==null?void 0:a.label)??"Calls"}function fn(e,t=window.location.search){return new URLSearchParams(t).get("history")==="all"?"all":e}function mn(e,t=window.location.href){const a=new URL(t);return e==="all"?a.searchParams.set("history","all"):a.searchParams.delete("history"),a}const uc={investigator:["finding"],threads:["thread","expand","threads","thread_q","risk","thread_call_sort","thread_call_page"],"cache-context":["cache_thread"],reports:["report"],"usage-drain":["usage_plan","usage_effort","usage_subagents","usage_sample","usage_confidence","limit_window","limit_hypothesis"],diagnostics:["diagnostic_source","diagnostic_fact"],calls:["explore","detail","call_q","source","sort","direction","density","page"],call:["record","return","mode","max_entries","max_chars","include_tool_output","include_compaction_history"]};function xt(e,t,a=[]){const n=new Set([t,...Array.isArray(a)?a:[a]]);for(const[r,s]of Object.entries(uc))if(!n.has(r))for(const i of s)e.searchParams.delete(i)}function gn(e){let t=!1;return e.searchParams.get("view")==="insights"&&(e.searchParams.set("view","overview"),t=!0),e.searchParams.get("return")==="insights"&&(e.searchParams.set("return","overview"),t=!0),t}const Lr=[{key:"overview",title:"Overview",path:"/api/diagnostics/overview",refreshPath:"/api/diagnostics/overview/refresh"},{key:"toolOutput",title:"Tool Output",path:"/api/diagnostics/tool-output",refreshPath:"/api/diagnostics/tool-output/refresh"},{key:"commands",title:"Commands",path:"/api/diagnostics/commands",refreshPath:"/api/diagnostics/commands/refresh"},{key:"gitInteractions",title:"Git Interactions",path:"/api/diagnostics/git-interactions",refreshPath:"/api/diagnostics/git-interactions/refresh"},{key:"fileReads",title:"File Reads",path:"/api/diagnostics/file-reads",refreshPath:"/api/diagnostics/file-reads/refresh"},{key:"fileModifications",title:"File Modifications",path:"/api/diagnostics/file-modifications",refreshPath:"/api/diagnostics/file-modifications/refresh"},{key:"readProductivity",title:"Read Productivity",path:"/api/diagnostics/read-productivity",refreshPath:"/api/diagnostics/read-productivity/refresh"},{key:"concentration",title:"Concentration",path:"/api/diagnostics/concentration",refreshPath:"/api/diagnostics/concentration/refresh"},{key:"guidedSummary",title:"What Is Driving Usage?",path:"/api/diagnostics/guided-summary",refreshPath:"/api/diagnostics/guided-summary/refresh"},{key:"usageDrain",title:"Usage Drain",path:"/api/diagnostics/usage-drain",refreshPath:"/api/diagnostics/usage-drain/refresh"}],At=new Map,Dt=new Map;function dc(){At.clear(),Dt.clear()}async function ql(e,t,a={}){_a(t);const n=pc(e);return a.signal?Nt(n,t,a.signal):gc(Dt,ya(e,t,a.cacheKey),()=>Nt(n,t))}async function Hl(e,t={}){_a(e);const a=await fetch(`/api/diagnostics/refresh?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:t.signal}),n=await Ft(a,"Diagnostic snapshot refresh"),r=n.sections??(Mr(n)?await hc(e,await Rr(n,e,t),t.signal):{});At.set(wa(e),r);for(const[s,i]of Object.entries(r))Dt.set(ya(s,e),i);return r}async function Ql(e,t,a={}){_a(t);const n=await fetch(`${e.refreshPath}?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal}),r=await Ft(n,e.title),s=Mr(r)?await fc(t,e,await Rr(r,t,a),a.signal):r,i=wa(t),o=At.get(i),h=o?await Promise.resolve(o):{};return At.set(i,{...h,[e.key]:s}),Dt.set(ya(e.key,t),s),s}async function Rr(e,t,a){var r,s,i,o;let n=e;for((r=a.onProgress)==null||r.call(a,n);n.status==="pending"||n.status==="running";){const h=a.pollIntervalMs??((s=n.next)==null?void 0:s.poll_after_ms)??250;await mc(h,a.signal);const f=new URLSearchParams({job_id:n.job_id,_:String(Date.now())}),d=await fetch(`/api/diagnostics/refresh/status?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal});n=await Ft(d,"Diagnostic refresh status"),(i=a.onProgress)==null||i.call(a,n)}if(n.status!=="completed")throw new Error(`Diagnostic refresh failed: ${((o=n.error)==null?void 0:o.code)??n.status}`);return n}async function hc(e,t,a){const n=await Promise.all(Lr.map(async r=>[r.key,await Nt(r,e,a)]));return Object.fromEntries(n)}async function fc(e,t,a,n){return Nt(t,e,n)}function Mr(e){if(!e||typeof e!="object")return!1;const t=e;return t.schema==="codex-usage-tracker-analysis-job-v1"&&t.job_kind==="diagnostic-refresh"&&typeof t.job_id=="string"}function mc(e,t){return t!=null&&t.aborted?Promise.reject(t.reason??new DOMException("Aborted","AbortError")):e<=0?Promise.resolve():new Promise((a,n)=>{const r=()=>{window.clearTimeout(s),t==null||t.removeEventListener("abort",r),n((t==null?void 0:t.reason)??new DOMException("Aborted","AbortError"))},s=window.setTimeout(()=>{t==null||t.removeEventListener("abort",r),a()},e);t==null||t.addEventListener("abort",r,{once:!0})})}function gc(e,t,a){const n=e.get(t);if(n!==void 0)return Promise.resolve(n);const r=a().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function wa(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function ya(e,t,a=""){return`snapshot:${wa(t)}:${a}:${e}`}function pc(e){const t=Lr.find(a=>a.key===e);if(!t)throw new Error(`Unknown diagnostic snapshot: ${e}`);return t}async function Nt(e,t,a){const n=await fetch(`${e.path}?_=${Date.now()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a});return await Ft(n,e.title)}function _a(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Ft(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const a=await e.json();if(typeof a.error=="string"&&a.error)throw new Error(a.error);return a}const pn=[{key:"facts",label:"Top Facts",title:"Top Diagnostic Facts",path:"/api/diagnostics/facts",limit:50},{key:"tools",label:"Tools",title:"Tool and Function Activity",path:"/api/diagnostics/tools",limit:25},{key:"compactions",label:"Compactions",title:"Compaction Activity",path:"/api/diagnostics/compactions",limit:25}],Pr=new Map,jr=new Map;function vc(){dc(),Pr.clear(),jr.clear()}async function Wl(e,t,a={}){Dr(t);const n=pn.find(f=>f.key===e)??pn[0],r=wc(a.sort??"uncached"),s=a.direction??"desc",i=Math.max(1,Math.round(a.limit??n.limit)),o=Math.max(0,Math.round(a.offset??0)),h=async()=>{const f=new URLSearchParams({limit:String(i),offset:String(o),sort:r,direction:s});Er(f,"include_archived",a.includeArchived);const d=await fetch(`${n.path}?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal});return await Fr(d,n.title)};return a.signal?h():Ar(Pr,bc(n.key,t,i,o,r,s,a.cacheKey,a.includeArchived),h)}async function zl(e,t,a={}){Dr(t);const n=Math.max(1,Math.round(a.limit??8)),r=Math.max(0,Math.round(a.offset??0)),s=a.sort??"tokens",i=a.direction??"desc",o=async()=>{const h=String(e.fact_type??""),f=String(e.fact_name??"");if(!h||!f)throw new Error("Diagnostic fact type and name are required.");const d=new URLSearchParams({fact_type:h,fact_name:f,limit:String(n),offset:String(r),sort:s,direction:i});Er(d,"include_archived",a.includeArchived);const b=await fetch(`/api/diagnostics/fact-calls?${d.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal}),u=await Fr(b,"Diagnostic fact calls");return{calls:(u.rows??[]).map((p,g)=>mr(p,g)),rawPayload:u}};return a.signal?o():Ar(jr,yc(e,t,n,r,s,i,a.cacheKey,a.includeArchived),o)}function Ar(e,t,a){const n=e.get(t);if(n!==void 0)return Promise.resolve(n);const r=a().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function Nr(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function bc(e,t,a,n,r,s,i="",o){return["facts",e,Nr(t),i,o??"default",a,n,r,s].join(":")}function wc(e){return e==="total"?"tokens":e==="latest"?"time":e}function yc(e,t,a,n,r,s,i="",o){return["fact-calls",Nr(t),i,o??"default",String(e.fact_type??""),String(e.fact_name??""),a,n,r,s].join(":")}function Er(e,t,a){a!==void 0&&e.set(t,String(a))}function Dr(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Fr(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const a=await e.json();if(a.error)throw new Error(a.error);return a}const _c=[{id:"usage-snapshot",endpoint:"/api/usage",dataClass:"snapshot",schema:"codex-usage-tracker-dashboard-v1"},{id:"overview-summary",endpoint:"/api/summary",dataClass:"aggregate",schema:"codex-usage-tracker-summary-v1"},{id:"overview-recommendations",endpoint:"/api/recommendations",dataClass:"aggregate",schema:"codex-usage-tracker-recommendations-v1"},{id:"calls",endpoint:"/api/calls",dataClass:"aggregate",schema:"codex-usage-tracker-calls-v1"},{id:"threads",endpoint:"/api/threads",dataClass:"aggregate",schema:"codex-usage-tracker-threads-v1"},{id:"thread-calls",endpoint:"/api/thread-calls",dataClass:"detail",schema:"codex-usage-tracker-thread-calls-v1"},{id:"investigator-agentic",endpoint:"/api/investigations/agentic",dataClass:"aggregate",schema:"codex-usage-tracker-agentic-investigation-v1"},{id:"investigator-walk",endpoint:"/api/investigations/walk",dataClass:"userAction",schema:"codex-usage-tracker-investigation-walk-v1"},{id:"diagnostics-facts",endpoint:"/api/diagnostics/facts",dataClass:"aggregate",schema:null},{id:"diagnostics-fact-calls",endpoint:"/api/diagnostics/fact-calls",dataClass:"detail",schema:null},{id:"diagnostics-dedupe",endpoint:"/api/diagnostics/dedupe",dataClass:"aggregate",schema:"codex-usage-tracker-dedupe-diagnostics-v1"},{id:"diagnostics-snapshot",endpoint:"/api/diagnostics/{snapshot}",dataClass:"aggregate",schema:null},{id:"compression-profile",endpoint:"/api/compression/profile",dataClass:"aggregate",schema:"codex-usage-tracker-compression-api-v1"},{id:"reports",endpoint:"/api/reports/pack",dataClass:"aggregate",schema:"codex-usage-tracker-reports-pack-v1"}],Sc=_c,Cc=new Map(Sc.map(e=>[e.id,e])),xc=15*6e4,kc=3e4,Ir={snapshot:ot({persistedCache:"aggregate-only"}),aggregate:ot({persistedCache:"aggregate-only"}),detail:ot(),heavyJob:ot({cancellation:"shared-job",staleTime:1e3}),userAction:ot({retry:0,staleTime:0})};function Tc({sourceKey:e,sourceRevision:t}){return{sourceKey:vn(e,"local-api"),sourceRevision:vn(t,"unversioned")}}function Lc(e,t,a={},...n){return["dashboard",e.id,t.sourceKey,t.sourceRevision,Pc(a),...n]}function Rc(e){return["dashboard",e.id]}function Mc(e){const t=Cc.get(e);if(!t)throw new Error(`Unknown dashboard query definition: ${e}`);return t}function $r(e){const t=Ir[e];return{gcTime:t.gcTime,refetchOnReconnect:t.refetchOnReconnect,refetchOnWindowFocus:t.refetchOnWindowFocus,retry:t.retry,staleTime:t.staleTime}}function Bl({enabled:e,hasData:t,isError:a,isFetching:n,isPending:r}){return e?t?n?"updating":"ready":a?"error":n||r?"loading":"waiting":"waiting"}function Gl(e){const t=e.filter(n=>n==="ready"||n==="updating").length,a=e.length;return{ready:t,total:a,percent:a===0?100:Math.round(t/a*100),loading:e.filter(n=>n==="loading").length,errors:e.filter(n=>n==="error").length}}function Pc(e){return{historyScope:e.historyScope??"active",loadWindow:e.loadWindow??"all",limit:e.limit??null,since:e.since??""}}function vn(e,t){return(e==null?void 0:e.trim())||t}function ot(e={}){return{staleTime:kc,gcTime:xc,retry:1,refetchOnReconnect:!1,refetchOnWindowFocus:!1,cancellation:"observer",persistedCache:"none",...e}}const jc=new Set(["command_text","content_fragment","content_fragments","excerpt","indexed_content","indexed_fragment","indexed_fragments","prompt","raw_context","raw_output","snippet","tool_output"]),Ac=new Set(["includes_indexed_content","includes_raw_fragment","includes_raw_fragments","indexed_content_included","raw_content_included","raw_context_included"]),Nc=new Set(["codex-usage-tracker-context-v1"]);function bn(e){return ia(e,new WeakSet)}function ia(e,t){if(!e||typeof e!="object")return!0;if(t.has(e))return!1;t.add(e);const a=Array.isArray(e)?e.every(n=>ia(n,t)):Object.entries(e).every(([n,r])=>{const s=n.toLowerCase();return jc.has(s)||Ac.has(s)&&r===!0||s==="schema"&&typeof r=="string"&&Nc.has(r)?!1:ia(r,t)});return t.delete(e),a}const Ec="codexUsageDashboard",Dc=1,Y="usageSnapshots",Fc=6,Ic=10080*60*1e3,$c={async read(e){if(!e.sourceRevision)return null;try{const t=await yn();if(!t)return null;const a=await Or(t.transaction(Y,"readonly").objectStore(Y).get(wn(e)));return!a||a.sourceRevision!==e.sourceRevision||Date.now()-a.storedAt>Ic?null:bn(a.payload)?a.payload:(await Oc(t,a.cacheKey),null)}catch{return null}},async write(e,t){if(!(!e.sourceRevision||!bn(t)))try{const a=await yn();if(!a)return;const n=a.transaction(Y,"readwrite");n.objectStore(Y).put({...e,cacheKey:wn(e),payload:t,storedAt:Date.now()}),await Sa(n),await Uc(a)}catch{}}};async function Oc(e,t){const a=e.transaction(Y,"readwrite");a.objectStore(Y).delete(t),await Sa(a)}function wn(e){const{historyScope:t,loadWindow:a,limit:n,since:r}=e.scope;return JSON.stringify([e.sourceKey,t,a,n,r])}function yn(){return typeof indexedDB>"u"?Promise.resolve(null):new Promise(e=>{const t=indexedDB.open(Ec,Dc);t.onupgradeneeded=()=>{t.result.objectStoreNames.contains(Y)||t.result.createObjectStore(Y,{keyPath:"cacheKey"})},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)})}function Or(e){return new Promise((t,a)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>a(e.error??new Error("IndexedDB request failed"))})}function Sa(e){return new Promise((t,a)=>{e.oncomplete=()=>t(),e.onerror=()=>a(e.error??new Error("IndexedDB transaction failed")),e.onabort=()=>a(e.error??new Error("IndexedDB transaction aborted"))})}async function Uc(e){const t=e.transaction(Y,"readonly"),n=(await Or(t.objectStore(Y).getAll())).sort((i,o)=>o.storedAt-i.storedAt).slice(Fc);if(!n.length)return;const r=e.transaction(Y,"readwrite"),s=r.objectStore(Y);n.forEach(i=>s.delete(i.cacheKey)),await Sa(r)}const Vc={kind:"production",load:_o},Kc="codexUsageDashboardRuntimeMetadata",qc=2048,oa=Mc("usage-snapshot"),Ur={all:Rc(oa),snapshot:(e,t,a)=>Lc(oa,Tc({sourceKey:e,sourceRevision:t}),a)};function Hc(){return new Ti({defaultOptions:{queries:{...$r("aggregate")}}})}const Ca=Hc();async function Qc({currentPayload:e,historyScope:t,loadWindow:a,loadLimit:n,since:r=null,onProgress:s,queryClient:i=Ca,refresh:o=!1,snapshotStore:h=$c,transport:f=Vc}){const d=Vi(n,t,r,a),b=xa(e),u=Ur.snapshot(b.sourceKey,b.sourceRevision,d);!i.getQueryData(u)&&Jc(e,d)&&i.setQueryData(u,e),o&&await i.invalidateQueries({queryKey:u,exact:!0});const p=_n(e,d),g=await i.fetchQuery({queryKey:u,...$r(oa.dataClass),queryFn:async({signal:v})=>{var R;const w=!o&&p?await h.read(p):null;if(w)return s==null||s({status:"completed",phase:"loading_rows",message:"Loaded cached dashboard snapshot",completed:Number(w.loaded_row_count??((R=w.rows)==null?void 0:R.length)??0),total:Number(w.total_available_rows??w.loaded_row_count??0),percent:100}),w;const T=await f.load(e,{refresh:o,limit:Ki(d),includeArchived:d.historyScope==="all",loadWindow:a,since:d.since,onProgress:s,signal:v}),N=p?{...p,sourceRevision:String(T.latest_refresh_at??p.sourceRevision)}:_n(T,d);return N&&await h.write(N,T),T},staleTime:o?0:Ir.snapshot.staleTime});return Gc(Bc(g,d)),g}function _n(e,t){if(!(e!=null&&e.api_token))return null;const a=String(e.latest_refresh_at??"");return a?{sourceKey:Vr(e),sourceRevision:a,scope:t}:null}async function Wc(e=Ca){await e.cancelQueries({queryKey:Ur.all})}function zc(e){return bi(e)||sr(e)}function Bc(e,t){return{schema:"codex-usage-dashboard-runtime-v1",...xa(e),scope:t,updatedAt:Date.now()}}function xa(e){return{sourceKey:Vr(e),sourceRevision:Zc(e)}}function Gc(e,t=Xc()){if(t)try{const a=JSON.stringify(e);a.length<=qc&&t.setItem(Kc,a)}catch{}}function Jc(e,t){var o;if(!e||!(((o=e.rows)==null?void 0:o.length)??0))return!1;const a=ct(e),n=t.limit===null?a===0:a===t.limit,r=(e.since??null)===t.since,s=ha(e)===t.loadWindow,i=e.include_archived||e.history_scope==="all-history"?"all":"active";return n&&r&&s&&i===t.historyScope}function Vr(e){const t=e,a=Number((t==null?void 0:t.payload_cache_version)??0),n=String((t==null?void 0:t.payload_cache_key)??(e!=null&&e.api_token?"live":"static"));return`${a}:${n}`}function Zc(e){return String((e==null?void 0:e.latest_refresh_at)??"unversioned")}function Xc(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}const Yc=new Set(["duplicate_cumulative_total"]);function el({canUseLiveApi:e,payload:t,shellI18n:a}){const n=tl(t,e,a);return c.jsxs("section",{className:"environment-status","aria-label":a.t("aria.dashboard_status","Dashboard status"),children:[c.jsx("span",{className:"environment-status-title",children:a.t("aria.dashboard_status","Dashboard status")}),c.jsx("div",{className:"environment-status-grid",children:n.map(r=>c.jsx("span",{className:"environment-chip","data-state":r.state,title:r.title,children:r.label},r.label))})]})}function tl(e,t,a){const n=il(e==null?void 0:e.parser_diagnostics,a);return[{label:a.t("badge.unofficial_project","Unofficial project"),state:"neutral",title:a.t("badge.unofficial_project_title","Codex Usage Tracker is independent and is not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI. OpenAI and Codex are trademarks of OpenAI.")},{label:t?`${a.t("badge.live","Live")} API`:a.t("badge.static","Static"),state:t?"ready":"warn",title:t?"Local API token present for refresh actions.":"Static embedded snapshot; live refresh is unavailable."},nl(e,a),rl(e,a),sl(e,a),al(e),...n?[n]:[]]}function al(e){const t=e==null?void 0:e.dedupe,a=Number((t==null?void 0:t.excluded_copied_rows)||0),n=Number((t==null?void 0:t.canonical_rows)||0),r=Number((t==null?void 0:t.physical_rows)||0);return{label:`Deduped · ${a.toLocaleString()} copied excluded`,state:"ready",title:`Billable totals use ${n.toLocaleString()} canonical rows while preserving ${r.toLocaleString()} physical source rows.`}}function nl(e,t){var s;const a=!!(e!=null&&e.pricing_configured),n=((s=e==null?void 0:e.pricing_snapshot_warning)==null?void 0:s.trim())??"",r=Kr(e==null?void 0:e.pricing_source);return{label:a?t.t("badge.costs","Costs"):t.t("badge.no_costs","No costs"),state:a?n?"warn":"ready":"missing",title:a?[r||"Pricing configured",n].filter(Boolean).join(" - "):t.t("pricing.configure_hint","Run codex-usage-tracker update-pricing to configure estimated costs.")}}function rl(e,t){var s,i;const a=((s=e==null?void 0:e.allowance_error)==null?void 0:s.trim())??"",n=((i=e==null?void 0:e.rate_card_error)==null?void 0:i.trim())??"",r=Kr(e==null?void 0:e.allowance_source)||"Codex credit rates";return a?{label:t.t("state.allowance_config_error","Allowance config error"),state:"missing",title:`Config error: ${a}`}:n?{label:"Rate-card error",state:"missing",title:`Rate-card error: ${n}`}:e!=null&&e.allowance_configured?{label:t.t("state.allowance_configured","Allowance configured"),state:"ready",title:r}:e!=null&&e.rate_card_configured?{label:"Credit rates loaded",state:"ready",title:r}:{label:t.t("action.set_limits","Set limits"),state:"warn",title:"No local allowance windows are configured."}}function sl(e,t){const a=e==null?void 0:e.project_metadata_privacy,n=(a==null?void 0:a.mode)||(e==null?void 0:e.privacy_mode)||"normal",r=n==="normal",s=[a!=null&&a.cwd_redacted?"cwd redacted":"",a!=null&&a.project_names_redacted?"project names redacted":"",a!=null&&a.git_remote_label_hidden?"git remote hidden":"",a!=null&&a.relative_cwd_hidden?"relative cwd hidden":"",a!=null&&a.git_branch_hidden?"git branch hidden":"",a!=null&&a.tags_hidden?"tags hidden":""].filter(Boolean);return{label:r?t.t("badge.metadata_normal","Metadata normal"):qr(t.t("badge.metadata_mode","Metadata {mode}"),{mode:n}),state:r?"ready":"warn",title:r?"Project metadata is shown normally.":[`Metadata mode: ${n}`,...s].join(" - ")}}function il(e,t){const a=Object.entries(e??{}).filter(([s,i])=>Number(i||0)>0&&!Yc.has(s));if(!a.length)return null;const n=a.reduce((s,[,i])=>s+Number(i||0),0),r=a.map(([s,i])=>`${s}=${Number(i||0)}`).join(", ");return{label:t.t("badge.parser_warnings","Parser warnings"),state:"missing",title:qr(t.t("parser.warnings_title","Latest refresh reported {count} parser diagnostics: {entries}. Run codex-usage-tracker inspect-log to investigate schema drift."),{count:n.toLocaleString(),entries:r})}}function Kr(e){if(!e)return"";if(typeof e=="string")return e;const t=e.label??e.name??e.type??e.path??"";return typeof t=="string"?t:""}function qr(e,t){return e.replace(/\{([a-zA-Z0-9_]+)\}/g,(a,n)=>t[n]??a)}async function Sn(e){var a;if((a=navigator.clipboard)!=null&&a.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly","readonly"),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}const ol={"highest-cost":"Highest Cost Threads","context-bloat":"Context Bloat","cache-misses":"Cache Misses","pricing-gaps":"Pricing Gaps","codex-credits":"Codex Credits","reasoning-spike":"Reasoning Spike"};function Jl(e,t){return t==="context-bloat"?Number(e.contextWindowPct??0)>=60||e.totalTokens>=2e5:t==="cache-misses"?e.signal==="cache-risk"||e.cachedPct<30||e.uncachedInput>=5e4:t==="pricing-gaps"?e.pricingEstimated||!Number.isFinite(e.cost):t==="codex-credits"?e.credits>0:t==="reasoning-spike"?e.reasoningOutput>0:!0}function cl(e){return ol[e]??e}const ll=se(()=>O(()=>import("./OverviewPage.js"),__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50])),"OverviewPage"),ul=se(()=>O(()=>import("./InvestigatorPage.js"),__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52])),"InvestigatorPage"),dl=se(()=>O(()=>import("./CompressionLabPage.js"),__vite__mapDeps([53,1,2,34,4,6,9,10,17,25,26,12,54])),"CompressionLabPage"),hl=se(()=>O(()=>import("./ExploreRoutePage.js"),__vite__mapDeps([55,1,2,44,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48,8,9,10,56])),"ExploreRoutePage"),fl=se(()=>O(()=>import("./CallInvestigatorPage.js"),__vite__mapDeps([57,1,2,46,33,19,37,38,47,25,26,12])),"CallInvestigatorPage"),ml=se(()=>O(()=>import("./ThreadsPage.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27])),"ThreadsPage"),gl=se(()=>O(()=>import("./UsageDrainPage.js"),__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39])),"UsageDrainPage"),pl=se(()=>O(()=>import("./CacheContextPage.js"),__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12])),"CacheContextPage"),vl=se(()=>O(()=>import("./DiagnosticsPage.js"),__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12])),"DiagnosticsPage"),bl=se(()=>O(()=>import("./ReportsPage.js"),__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43])),"ReportsPage"),wl=se(()=>O(()=>import("./SettingsPage.js"),__vite__mapDeps([58,1,2,33,19,32,38,47,17,25,26,12,59])),"SettingsPage");function yl(e){return c.jsx(C.Suspense,{fallback:c.jsx(Sl,{activeView:e.activeView}),children:_l(e)})}function _l(e){const{activePreset:t,activeRecordId:a,activeView:n,autoRefreshEnabled:r,applicationI18n:s,backFromCallInvestigator:i,callBackLabel:o,canLoadAllRows:h,canUseLiveApi:f,contextRuntime:d,copyCallInvestigatorLink:b,dashboardPayload:u,globalFilters:p,globalQuery:g,hasMoreRows:v,historyScope:w,loadWindow:T,loadAllRows:N,loadedRowCount:R,loadLimit:_,loadMoreRows:L,scopeSince:y,model:x,navigateView:M,onRefresh:E,openCallInvestigator:D,refreshing:me,refreshState:vt,setContextApiEnabled:bt,sourceIdentity:$,totalAvailableRows:nt}=e;switch(n){case"overview":return c.jsx(ll,{model:x,contextRuntime:d,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onRefresh:E,globalQuery:g,runtime:{historyScope:w,loadLimit:_,loadWindow:T,loadedRowCount:R,scopeSince:y,totalAvailableRows:nt},refreshing:me,canLoadMoreRows:f&&v,onLoadMoreRows:L,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:M,globalFilters:p});case"investigator":return c.jsx(ul,{model:x,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:M});case"compression-lab":return c.jsx(dl,{contextRuntime:d,includeArchived:w==="all",since:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision});case"calls":return c.jsx(hl,{model:x,globalQuery:g,activePreset:t,onRefresh:E,contextRuntime:d,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onContextApiEnabledChange:bt,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:M});case"call":return c.jsx(fl,{model:x,recordId:a,contextRuntime:d,onContextApiEnabledChange:bt,onNavigateRecord:D,onCopyCallLink:b,onBackToCalls:i,backLabel:o});case"threads":return c.jsx(ml,{model:x,globalQuery:g,onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onNavigateView:M});case"usage-drain":return c.jsx(gl,{model:x,contextRuntime:d,includeArchived:w==="all",sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"cache-context":return c.jsx(pl,{model:x,contextRuntime:d,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"diagnostics":return c.jsx(vl,{model:x,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,rowLoadControls:{loadedRowCount:R,totalAvailableRows:nt,canLoadMoreRows:f&&v,canLoadAllRows:h,refreshing:me,onLoadMoreRows:L,onLoadAllRows:N},onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p});case"reports":return c.jsx(bl,{model:x,refreshState:vt,includeArchived:w==="all",loadWindow:T,loadLimit:_,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"settings":return c.jsx(wl,{model:x,payload:u,historyScope:w,loadWindow:T,loadLimit:_,scopeSince:y,loadedRowCount:R,totalAvailableRows:nt,canUseLiveApi:f,autoRefreshEnabled:r,refreshState:vt,applicationI18n:s})}}function Sl({activeView:e}){return c.jsxs("section",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:["Loading ",e.replace("-"," "),"..."]})}const Cn=1e4,Cl={1:"overview",2:"calls",3:"threads",4:"diagnostics"},xl=new Set(["call","compression-lab","diagnostics","investigator"]);function Hr(e){return!xl.has(e)}function kl(e){return e instanceof Element?!!e.closest('input, select, textarea, button, [contenteditable="true"]'):!1}function Qr(){var Oa;const e=C.useRef(null),t=C.useMemo(()=>yo(),[]),[a,n]=C.useState(t),[r,s]=C.useState(()=>nn(t)),[i,o]=C.useState(()=>{const m=new URLSearchParams(window.location.search);return sa(m.get("view"))}),[h,f]=C.useState(()=>new URLSearchParams(window.location.search).get("record")??""),[d,b]=C.useState(()=>dn()),[u,p]=C.useState(()=>hn()),[g,v]=C.useState(()=>new URLSearchParams(window.location.search).get("q")??""),[w,T]=C.useState(()=>new URLSearchParams(window.location.search).get("preset")??""),[N,R]=C.useState(()=>window.location.search),[_,L]=C.useState("Stored snapshot loaded just now"),[y,x]=C.useState(null),[M,E]=C.useState(!1),[D,me]=C.useState(!1),[vt,bt]=C.useState(!1),[$,nt]=C.useState(()=>zs(t)),It=C.useRef(!1),[G,ka]=C.useState(()=>je(ct(t),500)),[Ue,wt]=C.useState(()=>je(ct(t),500)),[q,Ta]=C.useState(()=>qi(t)),[J,yt]=C.useState(()=>fn(Qt(t))),[La,Ra]=C.useState(r.contextRuntime.contextApiEnabled),H=!!(a!=null&&a.api_token),Wr=C.useMemo(()=>xa(a),[a]),A=C.useMemo(()=>Dn(a,$),[a,$]),Ma=C.useMemo(()=>({...r.contextRuntime,contextApiEnabled:La}),[La,r.contextRuntime]),zr=C.useMemo(()=>Uo(r,J,N),[J,N,r]),Pa=i==="calls"||i==="call"?r:zr,rt=Hr(i),$t=je(Ue,G,500),ge=Math.max(0,Number((a==null?void 0:a.loaded_row_count)??((Oa=a==null?void 0:a.rows)==null?void 0:Oa.length)??r.calls.length??0)),Ve=Math.max(0,Number((a==null?void 0:a.total_available_rows)??ge)),Br=Ue!==G,ja=Wi({currentLimit:G,loadedRows:ge,pendingLimit:Ue}),Gr=Math.min($t,ja),Aa=!!(a!=null&&a.has_more)||Ve>0&&ge{const m=new URL(window.location.href);gn(m)&&Ke(m)},[]),C.useEffect(()=>{function m(){const S=window.location.search,P=new URLSearchParams(S);o(sa(P.get("view"))),f(P.get("record")??""),b(dn(S)),p(hn(S)),v(P.get("q")??""),T(P.get("preset")??""),yt(fn(Qt(a),S)),R(S)}return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[a]),C.useEffect(()=>{function m(S){var oe;if(kl(S.target))return;if(S.key==="/"){S.preventDefault(),(oe=e.current)==null||oe.focus();return}const P=Cl[S.key];P&&(S.preventDefault(),st(P))}return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[]),C.useEffect(()=>{function m(){bt(window.scrollY>320)}return m(),window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]);function as(m){const S=i==="call"?d:i;b(S),p(i==="call"?u:!0),o("call"),f(m);const P=new URL(window.location.href);xt(P,i,i==="call"?d:[]),P.searchParams.set("view","call"),P.searchParams.set("record",m),P.searchParams.set("return",S),Da(P)}function ns(){st(d)}function rs(m){v(m),T("");const S=new URL(window.location.href);S.searchParams.delete("preset"),m?S.searchParams.set("q",m):S.searchParams.delete("q"),Ke(S)}async function ie(m={}){var _t;if(M)return;It.current=!0;const S=m.loadLimit??G,P=m.loadWindow??q,oe=Ht(P),pe=m.historyScope??J,ee=m.refresh??!0,Ot=!!(a!=null&&a.refresh_jobs_available);E(!0),x(Ot?{status:"running",phase:ee?"refreshing_index":"loading_rows",message:`${ee?"Refreshing":"Loading"} ${Re(P,S)}`}:null),L(`${ee?"Refreshing index for":"Loading"} ${Re(P,S)}...`);let qe=!1;try{const B=await Qc({currentPayload:a,refresh:ee,loadLimit:S,loadWindow:P,since:oe,historyScope:pe,onProgress:Vt=>{qe||(qe=Vt.message==="Loaded cached dashboard snapshot"),x(Vt),L(Za(Vt,pe))}});vc(),n(B),s(nn(B)),Ra(!!B.context_api_enabled);const xe=P==="rows"?je(ct(B,S),S):S;ka(xe),wt(xe),Ta(P);const Ua=Qt(B,pe);yt(Ua),Qi(xe,Ua,P);const Ut=B.loaded_row_count??((_t=B.rows)==null?void 0:_t.length)??0,Va=B.total_available_rows??Ut;L(P==="rows"?`${qe?"Cache hit; l":ee?"Refreshed index; l":"L"}oaded ${Ut.toLocaleString()} of ${Va.toLocaleString()} calls from ${Re(P,xe)}`:`${qe?"Cache hit; ":ee?"Refreshed index; ":""}${Re(P,xe)} analysis ready across ${Va.toLocaleString()} calls; ${Ut.toLocaleString()} detail rows cached`)}catch(B){if(x(null),zc(B)){L("Refresh cancelled; stored snapshot remains visible");return}const xe=new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});L(`${Xi(B)} Stored snapshot kept at ${xe}`)}finally{x(null),E(!1)}}async function ss(){await Wc(),x(null),E(!1),L("Refresh cancelled; stored snapshot remains visible")}C.useEffect(()=>{document.documentElement.lang=A.language,document.documentElement.dir=A.direction},[A.direction,A.language]),C.useEffect(()=>{var B;const m=Number((a==null?void 0:a.total_available_rows)??0),S=Number((a==null?void 0:a.loaded_row_count)??((B=a==null?void 0:a.rows)==null?void 0:B.length)??0),P=Hi(),oe=(P==null?void 0:P.historyScope)??J,pe=(P==null?void 0:P.loadLimit)??G,ee=(P==null?void 0:P.loadWindow)??q,Ot=ha(a),qe=oe!==J||ee!==Ot||ee==="rows"&&pe!==ct(a),_t=S>0;!H||!qe&&_t||m<=0||M||It.current||(It.current=!0,qe&&(yt(oe),ka(pe),wt(pe),Ta(ee),Ke(mn(oe))),ie({refresh:!1,historyScope:oe,loadLimit:pe,loadWindow:ee}))},[H,a,J,G,q,M]),C.useEffect(()=>{!H&&D&&me(!1)},[D,H]),C.useEffect(()=>{if(!D||!H||!rt)return;const m=window.setInterval(()=>{ie()},Cn);return()=>window.clearInterval(m)},[D,rt,H,a,J,G,q,M]),C.useEffect(()=>{if(!D||!H||!rt)return;function m(){document.visibilityState==="visible"&&ie()}return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[D,rt,H,a,J,G,q,M]);function Fa(m){const S=m.trim();wt(Math.max(1,gt(S===""?Number.NaN:Number(S))))}function is(m){Fa(m)}function os(){ie({refresh:!1,loadLimit:Ue,loadWindow:"rows"})}function cs(){ie({refresh:!1,loadWindow:"all"})}function Ia(){wt(Na),ie({refresh:!1,loadLimit:Na,loadWindow:q})}function ls(m){m!==q&&ie({refresh:!1,loadWindow:m})}function us(m){const S=m==="all"?"all":"active";yt(S),Ke(mn(S)),ie({refresh:!1,historyScope:S})}function ds(m){if(me(m),m){if(!rt){L("Auto refresh pauses on this evidence-heavy view");return}L(`Auto refresh every ${Cn/1e3}s`),ie()}else L("Auto refresh paused")}function hs(m){nt(m),Bs(m)}async function fs(){try{const m=new URL(window.location.href);if(gn(m),xt(m,i,i==="call"?d:[]),!await Sn(m.toString()))throw new Error("Clipboard unavailable");L("Copied current view link")}catch{L("Copy unavailable in browser")}}async function ms(m){try{const S=new URL(window.location.href);xt(S,i,i==="call"?d:[]);const P=i==="call"?d:i;if(S.searchParams.set("view","call"),S.searchParams.set("record",m),S.searchParams.set("return",P),!await Sn(S.toString()))throw new Error("Clipboard unavailable");L("Copied call investigator link")}catch{L("Copy unavailable in browser")}}async function gs(){const m=await Gi(i,Pa,{contextRuntime:Ma,historyScope:J,loadWindow:q,loadLimit:G,scopeSince:(a==null?void 0:a.since)??Ht(q),loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,refreshState:_},g,w);if(!m.rowCount){L(`No ${m.label} to export`);return}Ni(m.filename,m.csv),L(`Exported ${m.rowCount} ${m.label}`)}function ps(){T("");const m=new URL(window.location.href);m.searchParams.delete("preset"),Ke(m),L("Investigation preset cleared")}function vs(){window.scrollTo({top:0,behavior:"smooth"})}return c.jsx(no,{value:A,children:c.jsxs("div",{className:"app-shell","data-dashboard-localization-root":!0,children:[c.jsxs("aside",{className:"sidebar",children:[c.jsxs("div",{className:"brand",children:[c.jsx("div",{className:"brand-mark",children:c.jsx(Us,{size:22})}),c.jsxs("div",{children:[c.jsx("strong",{children:"Codex Usage Tracker"}),c.jsx("span",{children:A.t("dashboard.eyebrow","Local telemetry console")})]})]}),c.jsxs("div",{className:"local-pill",children:[c.jsx("span",{"aria-hidden":"true"}),"Local data only"]}),c.jsx(el,{payload:a,canUseLiveApi:H,shellI18n:A}),c.jsx("nav",{className:"primary-nav","aria-label":"Primary",children:Cr.map(m=>{const S=m.icon,P=i===m.id||i==="call"&&m.id==="calls";return c.jsxs("button",{type:"button","aria-pressed":P,className:P?"active":"",onClick:()=>st(m.id),children:[c.jsx(S,{size:18}),c.jsx("span",{children:A.navLabel(m.id,m.label)})]},m.id)})}),c.jsxs("div",{className:"secondary-block",role:"group","aria-label":"Quick Links",children:[c.jsx("span",{children:"Quick Links"}),xr.map(m=>{const S=m.icon;return c.jsxs("button",{type:"button",onClick:()=>st(m.target),children:[c.jsx(S,{size:16}),m.label]},m.label)})]})]}),c.jsxs("main",{className:"workspace",children:[c.jsxs("div",{className:"unofficial-banner",role:"note","aria-label":"Unofficial project notice",children:[c.jsx($s,{size:16}),c.jsxs("span",{children:[c.jsx("strong",{children:"Unofficial project."})," Not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI."]})]}),c.jsxs("header",{className:"topbar","aria-label":"Dashboard toolbar",children:[c.jsxs("label",{className:"global-search",children:[c.jsx("span",{className:"sr-only",children:A.t("filter.search","Search dashboard")}),c.jsx("input",{ref:e,"aria-label":A.t("filter.search","Search dashboard"),value:g,onChange:m=>rs(m.target.value),placeholder:A.t("filter.search_placeholder","Search calls, threads, models, diagnostics...")})]}),c.jsxs("div",{className:"topbar-actions",children:[c.jsxs("div",{className:"topbar-scope-controls",children:[A.languages.length>1?c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("language.label","Language")}),c.jsx("select",{"data-localization-skip":"true","aria-label":A.t("language.label","Language"),value:A.language,onChange:m=>hs(m.target.value),children:A.languages.map(m=>c.jsx("option",{value:m.code,children:m.native_name||m.english_name||m.code},m.code))})]}):null,c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("nav.history","History")}),c.jsxs("select",{"aria-label":"History scope",title:Ea,value:J,onChange:m=>us(m.target.value),disabled:M||!H,children:[c.jsx("option",{value:"active",children:A.t("option.active_sessions_only","Active")}),c.jsx("option",{value:"all",children:A.t("option.all_history","All history")})]}),c.jsx("small",{className:"sr-only",children:Ea})]})]}),c.jsx(Yo,{canUseLiveApi:H,finitePendingLoadLimit:$t,hasMoreRows:Aa,loadLabel:A.t("nav.load","Load"),loadMoreLabel:A.t("button.load_more","Load more"),loadWindow:q,loadedRowCount:ge,pendingLoadLimit:Ue,refreshProgressPercent:Yr,refreshProgressText:es,refreshing:M,rowLimitChanged:Br,rowLimitSliderMax:ja,rowLimitSliderValue:Gr,rowLoadModeLabel:Zr,rowLoadStatus:Jr,totalAvailableRows:Ve,onApply:os,onCancel:ss,onDraftChange:Fa,onLoadMore:Ia,onSliderChange:is,onWindowChange:ls}),c.jsxs("div",{className:"topbar-meta",children:[c.jsxs("div",{className:"topbar-statuses",children:[w?c.jsxs("button",{className:"toolbar-button",type:"button",onClick:ps,children:[c.jsx(la,{size:15}),A.t("button.clear","Clear")," ",cl(w)]}):null,c.jsxs("label",{className:"topbar-toggle",children:[c.jsx("input",{"aria-label":"Auto refresh",type:"checkbox",checked:D,onChange:m=>ds(m.target.checked),disabled:M||!H}),c.jsx("span",{children:"Auto"})]})]}),c.jsxs("div",{className:"topbar-icon-actions",children:[c.jsx("button",{className:"icon-button",type:"button",onClick:fs,"aria-label":A.t("button.copy_link","Copy link"),title:A.t("button.copy_link","Copy link"),children:c.jsx(Ms,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:gs,"aria-label":A.t("button.export_csv","Export CSV"),title:A.t("button.export_csv","Export CSV"),children:c.jsx(js,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:$a,"aria-label":A.t("button.refresh","Refresh"),title:A.t("button.refresh","Refresh"),disabled:M,children:c.jsx(Fs,{size:17})})]})]})]})]}),c.jsx("p",{className:"sr-only",role:"status","aria-live":"polite",children:_}),c.jsx(yl,{activeView:i,model:Pa,navigateView:st,onRefresh:$a,refreshState:_,globalQuery:g,activePreset:w,activeRecordId:h,contextRuntime:Ma,setContextApiEnabled:Ra,openCallInvestigator:as,copyCallInvestigatorLink:ms,callBackLabel:u?`Back to ${lc(d)}`:A.t("button.back_to_dashboard","Back to dashboard"),backFromCallInvestigator:ns,dashboardPayload:a,sourceIdentity:Wr,historyScope:J,loadWindow:q,scopeSince:(a==null?void 0:a.since)??Ht(q),loadLimit:G,loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,applicationI18n:A,refreshing:M,hasMoreRows:Aa,canLoadAllRows:ts,loadMoreRows:Ia,loadAllRows:cs,globalFilters:c.jsx(ec,{activeView:i,locationSearch:N,model:r,onUrlChange:Ke})})]}),vt?c.jsxs("button",{className:"to-top-button",type:"button",onClick:vs,"aria-label":"Back to top",children:[c.jsx(xs,{size:18}),A.t("button.top","Top")]}):null]})});function $a(){ie()}}function Tl(){return c.jsx(Li,{client:Ca,children:c.jsx(Qr,{})})}const Zl=Object.freeze(Object.defineProperty({__proto__:null,App:Qr,RoutedApp:Tl,shouldAutoRefreshUsageView:Hr},Symbol.toStringTag,{value:"Module"}));export{cl as $,xs as A,Al as B,Fi as C,js as D,Ul as E,Es as F,Cs as G,Ps as H,bn as I,Et as J,z as K,Nl as L,Vn as M,ae as N,Wl as O,wc as P,ql as Q,Fs as R,Is as S,zl as T,Rs as U,Os as V,Jl as W,Sn as X,Ol as Y,Ns as Z,la as _,Ms as a,Fl as a0,Dl as a1,fi as a2,ii as a3,Gt as a4,qn as a5,ri as a6,si as a7,Bt as a8,Un as a9,_i as aa,li as ab,El as ac,$l as ad,xt as ae,dn as af,Re as ag,Zl as ah,Vl as b,I as c,Ni as d,ce as e,Le as f,Ei as g,Gl as h,Bl as i,Te as j,lr as k,Il as l,Xt as m,Lr as n,Ql as o,Lt as p,Hl as q,Ai as r,pn as s,Kl as t,On as u,mr as v,$r as w,Lc as x,Tc as y,Mc as z}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js index 28188d15..3de619f2 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js @@ -1,6 +1,6 @@ -import{r as C,j as e}from"./dashboard-react.js";import{c as Z,v as R,p as U,j as h,u as A,ac as ee,a as te,C as ae,f as F,m as Q,ad as ne,ae as se,X as le}from"./App.js";import{f as q,t as oe,u as ie,T as ce,w as re,C as de,z as ue,v as he,x as O,y as xe,A as me,B as pe,c as be,d as K,a as B,r as $,l as ge,g as je,D as V,b as ve,e as fe,h as ye,i as J,j as W,k as Ce,m as we,n as ke,o as _e,p as Ne,q as Ee,s as Se}from"./contextEvidenceState.js";import{P as T}from"./Panel.js";import{S as z}from"./StatusBadge.js";import{C as Te,a as Ie}from"./chevron-right.js";import{S as Ae}from"./shield-check.js";import{L as Le}from"./lock-keyhole.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** +import{r as C,j as e}from"./dashboard-react.js";import{c as Z,v as R,p as U,j as h,u as A,ad as ee,a as te,C as ae,f as F,m as Q,Y as ne,ae as se,af as le,X as oe}from"./App.js";import{f as q,t as ie,u as ce,T as re,w as de,C as ue,z as he,v as xe,x as O,y as me,A as pe,B as be,c as ge,d as K,a as B,r as $,l as je,g as ve,D as V,b as fe,e as ye,h as Ce,i as J,j as W,k as we,m as ke,n as _e,o as Ne,p as Ee,q as Se,s as Te}from"./contextEvidenceState.js";import{P as T}from"./Panel.js";import{S as z}from"./StatusBadge.js";import{C as Ie,a as Ae}from"./chevron-right.js";import{S as Le}from"./shield-check.js";import{L as Pe}from"./lock-keyhole.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const X=Z("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]),D=new Map;function Pe(t,n){ze(t,n);const s=`${n.apiToken}:${t}`,i=D.get(s);if(i)return i;const l=Re(t,n).finally(()=>{D.delete(s)});return D.set(s,l),l}async function Re(t,n){var o;const s=new URLSearchParams({record_id:t,_:String(Date.now())}),i=await fetch(`/api/call?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":n.apiToken},cache:"no-store"}),l=await Me(i,"Call detail");if(!((o=l.record)!=null&&o.record_id))throw new Error("Call detail response did not include the requested aggregate record.");const u=Array.isArray(l.adjacent_records)&&l.adjacent_records.length?l.adjacent_records:[l.previous_record,l.record,l.next_record].filter(p=>!!p);return{record:R(l.record,0),previousRecord:l.previous_record?R(l.previous_record,-1):null,nextRecord:l.next_record?R(l.next_record,1):null,adjacentRecords:u.map((p,c)=>R(p,c)),rawPayload:l}}function ze(t,n){if(!t)throw new Error("record_id is required for call detail loading.");if(n.fileMode)throw new Error("Call detail hydration requires the localhost dashboard server.");if(!n.apiToken)throw new Error("Call detail hydration requires a localhost dashboard API token.")}async function Me(t,n){let s={};try{s=await t.json()}catch{s={}}if(!t.ok){const i=typeof s.error=="string"?s.error:`${n} request failed (${t.status})`;throw new Error(i)}return s}function Oe(t,n){return H(n.t("call.readout.exact_body","{input} input tokens = {cached} cached + {uncached} uncached; {output} output tokens; {cache} cache reuse."),{input:h(t.input),cached:h(t.cachedInput),uncached:h(t.uncachedInput),output:h(t.output),cache:U(t.cachedPct)})}function $e(t){return t.t("call.readout.previous_unavailable","No previous call is loaded in resolved thread, call-to-call deltas unavailable.")}function De(t,n){const s=t.uncachedInput-n.uncachedInput,i=t.cachedInput-n.cachedInput;return s>0&&i<0?`Fresh input rose by ${h(s)} while cached input fell by ${h(Math.abs(i))}; classic cache-drop profile.`:s>0?`Fresh input increased by ${h(s)} from previous call; inspect evidence new files, tool results, or rewritten context.`:s<0&&i>=0?`Fresh input fell by ${h(Math.abs(s))} while cached input increased, so this call reused context more efficiently previous one.`:"Token accounting broadly stable compared previous call in resolved thread."}function qe(t,n){var s;if(t.status==="loaded"){const i=((s=t.payload.entries)==null?void 0:s.length)??0,l=Number(t.payload.visible_char_count??0),u=Number(t.payload.visible_token_estimate??0),o=Ue(t.payload,n);return H(n.t("call.readout.evidence_analyzed","Evidence analyzed: {totalEntries} selected-turn entries, {visibleChars} visible redacted chars, {visibleTokens} visible tokens.{serializedDetail}"),{totalEntries:h(i),visibleChars:h(l),visibleTokens:h(u),estimator:t.payload.visible_token_estimator??"visible-token estimate",serializedDetail:o,renderedEntries:h(i)})}return t.status==="loading"?n.t("call.readout.evidence_loading",t.message):t.status==="error"?`Evidence request failed: ${t.message}`:"Evidence is not loaded yet. Aggregate token counts are exact, but visible-context attribution needs runtime evidence."}function Ue(t,n){const s=t.serialized_evidence??{};if(s.deferred||s.deferred_buckets)return n.t("call.readout.evidence_serialized_deferred","Fast serialized estimate only; full serialized grouping deferred.");const i=Ke(t);return i<=0?"":H(n.t("call.readout.evidence_serialized_bound"," Serialized local upper bound: {tokens} tokens."),{tokens:h(i),chars:h(Number(s.raw_json_char_count??s.total_chars??0))})}function Fe(t,n){const s=t.input>0?t.cachedInput/t.input:t.cachedPct/100,i=n&&n.input>0?n.cachedInput/n.input:n?n.cachedPct/100:null,l=(n==null?void 0:n.uncachedInput)??0;return n&&i!==null&&i>=.8&&s<=.05&&t.input>=1e3?"Compare previous call, then inspect loaded evidence see fresh context was sent after cache miss.":n&&t.uncachedInput>Math.max(l*2,1e3)?"Inspect most recent evidence entries first; spike is in fresh uncached input, not cached history.":s>=.85?`Cache reuse is healthy; focus on ${h(t.uncachedInput)} uncached tokens were still billed as fresh input.`:n?"Use delta cards to locate whether change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough understand this isolated call."}function He(t){return t==="Hydrated from /api/call"?"Position: hydrated live record outside loaded snapshot":`Position: ${t}`}function H(t,n){return t.replace(/\{(\w+)\}/g,(s,i)=>n[i]??s)}function Ke(t){const n=t.serialized_evidence??{};return Number(n.raw_json_token_estimate??n.token_estimate??0)}function ct({model:t,recordId:n,contextRuntime:s,onContextApiEnabledChange:i,onNavigateRecord:l,onCopyCallLink:u,onBackToCalls:o,backLabel:p}){const c=A(),[j,b]=C.useState(""),[x,k]=C.useState({status:"idle"}),[d,w]=C.useState({status:"idle"}),[S,L]=C.useState({recordId:"",nonce:0}),I=x.status==="loaded"&&x.recordId===n?x.detail:null,{modelIndex:N,hydratedDetail:E,call:a,previous:r,next:g,threadCalls:m,positionLabel:v}=C.useMemo(()=>ee({calls:t.calls,recordId:n,detail:I}),[I,t.calls,n]),G=d.status==="loaded"?d.payload:null;if(C.useEffect(()=>{w({status:"idle"})},[n]),C.useEffect(()=>{if(!n||N>=0){k({status:"idle"});return}if(s.fileMode||!s.apiToken){k({status:"error",recordId:n,message:"This call is outside the loaded snapshot. Serve the dashboard with its localhost API token to hydrate it."});return}let _=!1;return k({status:"loading",recordId:n,message:"Loading call detail from localhost..."}),Pe(n,s).then(P=>{_||k({status:"loaded",recordId:n,detail:P})}).catch(P=>{_||k({status:"error",recordId:n,message:q(P)})}),()=>{_=!0}},[s,N,n]),!a){const _=x.status==="loading"||x.status==="error"?x.message:n?"Selected call is not present in the loaded dashboard rows.":"No aggregate call rows are loaded.";return e.jsx("div",{className:"page-grid",children:e.jsxs("div",{className:"page-title-row",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsx("p",{children:_})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]})]})})}async function Y(){try{const _=new URL(window.location.href);if(ne(_,"call",se(_.search)),!await le(_.toString()))throw new Error("Clipboard unavailable");b("Copied investigator link")}catch{b("Copy unavailable in this browser")}}return e.jsxs("div",{className:"call-investigator-layout",children:[e.jsxs("div",{className:"page-title-row span-all",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsxs("p",{children:[a.thread," / ",a.model]})]}),e.jsxs("div",{className:"toolbar",children:[e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>r&&l(r.id),disabled:!r,children:[e.jsx(Te,{size:16})," ",c.t("button.previous_call","Previous call")]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>g&&l(g.id),disabled:!g,children:[c.t("button.next_call","Next call")," ",e.jsx(Ie,{size:16})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:Y,"aria-label":c.t("button.copy_investigator_link","Copy investigator link"),children:[e.jsx(te,{size:16})," ",c.t("button.copy_link","Copy link")]})]})]}),e.jsxs(T,{title:c.t("call.readout.title","Investigation Readout"),subtitle:j||v,className:"span-all",action:e.jsx(z,{label:c.t("call.readout.badge","Aggregate + on-demand evidence"),tone:"blue"}),children:[e.jsxs("div",{className:"call-summary",children:[e.jsx(z,{label:"Aggregate only",tone:"green"}),E?e.jsx(z,{label:"Hydrated live",tone:"blue"}):null,e.jsx(ae,{call:a}),e.jsx(z,{label:"Raw context gated",tone:"blue"}),e.jsx("span",{className:"call-id",children:a.id.slice(0,16)})]}),e.jsx(Be,{call:a,previous:r,evidenceState:d,positionLabel:v}),e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Total tokens",value:h(a.totalTokens),detail:`${F(a.input)} input`}),e.jsx(f,{label:"Uncached input",value:h(a.uncachedInput),detail:"fresh billed input"}),e.jsx(f,{label:"Cache hit rate",value:U(a.cachedPct),detail:oe(a)}),e.jsx(f,{label:"Estimated cost",value:Q(a.cost),detail:a.pricingEstimated?"estimated pricing":"configured pricing"}),e.jsx(f,{label:"Duration",value:a.duration,detail:a.fast?"fast candidate":"normal throughput"}),e.jsx(f,{label:"Usage credits",value:a.credits?a.credits.toFixed(3):"-",detail:a.usageCreditConfidence})]}),e.jsx(ie,{call:a})]}),e.jsxs(T,{title:"Token Accounting",subtitle:"Exact aggregate row fields",children:[e.jsx(Qe,{call:a}),e.jsx(ce,{call:a})]}),e.jsx(T,{title:"Cache Accounting",subtitle:"Derived from adjacent aggregate call",children:e.jsx(re,{call:a,calls:m})}),e.jsx(T,{title:"Context Attribution",subtitle:"Estimated from visible log volume",className:"span-all",children:e.jsx(de,{call:a,payload:G,onRunFullAnalysis:()=>L(_=>({recordId:a.id,nonce:_.nonce+1})),showHeading:!1})}),e.jsxs(T,{title:"Aggregate Identity",subtitle:"Local metadata only",children:[e.jsxs("dl",{className:"detail-list",children:[e.jsx(y,{label:"Record id",value:a.id}),e.jsx(y,{label:"Time",value:a.time}),e.jsx(y,{label:"Thread",value:a.thread}),e.jsx(y,{label:"Model",value:a.model}),e.jsx(y,{label:"Effort",value:a.effort}),e.jsx(y,{label:"Project",value:a.project||"Unknown"}),e.jsx(y,{label:"Context window",value:ue(a)}),e.jsx(y,{label:"Recommendation",value:a.recommendation||"No aggregate recommendation"})]}),e.jsx(he,{call:a}),a.recommendation?e.jsxs("div",{className:"recommendation-box",children:[e.jsx(Ae,{size:16}),e.jsx("p",{children:a.recommendation})]}):null]}),e.jsx(T,{title:"Thread Context",subtitle:`${m.length} loaded related calls`,className:"span-all",children:e.jsx(Xe,{call:a,calls:m,onNavigateRecord:l,onCopyCallLink:u})}),e.jsx(T,{title:"Raw Evidence",subtitle:"Explicit localhost request only",className:"span-all",children:e.jsx(Ve,{call:a,contextRuntime:s,onContextApiEnabledChange:i,onEvidenceStateChange:w,fullAnalysisRequestNonce:S.recordId===a.id?S.nonce:0},a.id)})]})}function Be({call:t,previous:n,evidenceState:s,positionLabel:i}){const l=A();return e.jsxs("div",{className:"investigation-readout-grid",children:[e.jsx(M,{label:l.t("call.readout.exact_label","Exact callback accounting"),body:Oe(t,l)}),e.jsx(M,{label:l.t("call.readout.previous_label","Compared previous call"),body:n?De(t,n):$e(l)}),e.jsx(M,{label:l.t("call.readout.evidence_label","Evidence state"),body:qe(s,l)}),e.jsx(M,{label:l.t("call.readout.next_label","Next diagnostic move"),body:Fe(t,n),detail:He(i)})]})}function M({label:t,body:n,detail:s}){return e.jsxs("div",{className:"investigation-readout-card",children:[e.jsx("span",{children:t}),e.jsx("p",{children:n}),s?e.jsx("small",{children:s}):null]})}function Ve({call:t,contextRuntime:n,onContextApiEnabledChange:s,onEvidenceStateChange:i,fullAnalysisRequestNonce:l}){const u=A(),[o,p]=C.useState(()=>pe(window.location.search,be(t.id)??K)),[c,j]=C.useState({status:"idle"}),b=!!n.apiToken&&!n.fileMode,x=b&&n.contextApiEnabled;C.useEffect(()=>{const a=B(t.id,o);j(a?{status:"loaded",payload:a}:{status:"idle"})},[t.id,o.includeToolOutput,o.includeCompactionHistory,o.maxChars,o.maxEntries,o.mode]),C.useEffect(()=>{i(c)},[c,i]),C.useEffect(()=>{if(l<=0||!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")},[l]);async function k(){j({status:"loading",message:"Enabling localhost context API..."});try{const a=await fe(n);s(a),j({status:"idle",message:a?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(a){j({status:"error",message:q(a)})}}async function d(a=o,r="Loading selected-turn evidence..."){$(t.id,a);const g=B(t.id,a);if(g){j({status:"loaded",payload:g});return}j({status:"loading",message:r});try{const m=await ge(t.id,n,a);je(t.id,a,m),j({status:"loaded",payload:m})}catch(m){j({status:"error",message:q(m)})}}function w(){if(!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")}function S(a){const r=Ne(a,o);N(r),d(r,"Loading older context...")}function L(){const a={...o,includeToolOutput:!0};N(a),d(a,"Loading omitted tool output...")}function I(){const a={...o,includeCompactionHistory:!0};N(a),d(a,"Loading compacted replacement...")}function N(a){p(a),$(t.id,a);const r=new URL(window.location.href);V(r,a),window.history.replaceState(null,"",r)}function E(a,r){p(g=>{const m={...g,[a]:r};$(t.id,m);const v=new URL(window.location.href);return V(v,m),window.history.replaceState(null,"",v),m})}return e.jsxs("div",{className:"investigator-evidence",children:[e.jsxs("div",{className:"locked-context-card",children:[e.jsx(Le,{size:20}),e.jsxs("div",{children:[e.jsx("strong",{children:"Raw context is gated"}),e.jsx("p",{children:ve(n)})]})]}),e.jsxs("div",{className:"context-action-grid",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:k,disabled:!b||n.contextApiEnabled||c.status==="loading",children:u.t("button.enable_context_loading","Enable context loading")}),e.jsx("button",{className:"primary-button",type:"button",onClick:()=>d(),disabled:!x||c.status==="loading",children:u.t("button.show_turn_evidence","Show turn log evidence")}),e.jsx("button",{className:"toolbar-button",type:"button",onClick:w,disabled:!x||c.status==="loading",children:u.t("button.full_serialized_analysis","Run full serialized analysis")}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Mode"}),e.jsxs("select",{"aria-label":"Context mode",value:o.mode,disabled:!x||c.status==="loading",onChange:a=>E("mode",a.target.value==="full"?"full":"quick"),children:[e.jsx("option",{value:"quick",children:"Quick"}),e.jsx("option",{value:"full",children:"Full"})]})]}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Entries"}),e.jsxs("select",{"aria-label":"Context entries",value:String(o.maxEntries),disabled:!x||c.status==="loading",onChange:a=>E("maxEntries",Number(a.target.value)),children:[e.jsx("option",{value:"20",children:"20"}),e.jsx("option",{value:"50",children:"50"}),e.jsx("option",{value:"100",children:"100"}),e.jsx("option",{value:"0",children:"All"})]})]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeToolOutput,disabled:!x||c.status==="loading",onChange:a=>E("includeToolOutput",a.target.checked)}),u.t("button.include_tool_output","Include tool output")]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeCompactionHistory,disabled:!x||c.status==="loading",onChange:a=>E("includeCompactionHistory",a.target.checked)}),"Include compaction history"]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.maxChars===0,disabled:!x||c.status==="loading",onChange:a=>E("maxChars",a.target.checked?0:K.maxChars)}),u.t("button.no_char_limit","No char limit")]})]}),c.status==="idle"&&c.message?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="loading"?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="error"?e.jsx("p",{className:"context-state-note error",children:c.message}):null,c.status==="loaded"?e.jsx(Je,{payload:c.payload,onLoadOlder:S,onLoadCompactionHistory:I,onLoadToolOutput:L}):null,e.jsx("p",{className:"privacy-note",children:"Raw context is read from the local JSONL source only after this explicit action and is not embedded in static dashboard HTML."})]})}function Je({payload:t,onLoadOlder:n,onLoadCompactionHistory:s,onLoadToolOutput:i}){var E,a;const l=A(),u=t.entries??[],o=t.omitted??{},p=Number(o.older_entries??0),c=ye(t),j=10,b=String(t.record_id??""),[x,k]=C.useState(()=>J(b)),[d,w]=C.useState(()=>W(b,u));C.useEffect(()=>{k(J(b)),w(W(b,u))},[u.length,t.context_mode,t.include_compaction_history,t.include_tool_output,(E=t.omitted)==null?void 0:E.max_chars,(a=t.omitted)==null?void 0:a.max_entries,t.record_id,b]);const S=x?u:u.slice(0,j),L=Math.max(u.length-S.length,0);function I(){k(r=>{const g=!r;return Se(b,g),g})}function N(r,g){Ee(b,r,g),w(m=>{const v=new Set(m);return g?v.add(r):v.delete(r),v})}return e.jsxs("div",{className:"context-evidence",children:[e.jsxs("div",{className:"context-evidence-summary",children:[e.jsx(f,{label:"Entries",value:h(u.length),detail:String(t.context_mode??"quick")}),e.jsx(f,{label:"Visible chars",value:h(Number(t.visible_char_count??0)),detail:"redacted local text"}),e.jsx(f,{label:"Visible tokens",value:h(Number(t.visible_token_estimate??0)),detail:"estimator"}),e.jsx(f,{label:"Older omitted",value:h(p),detail:"entry budget"})]}),c.length?e.jsx("p",{className:"context-note",children:c.join(" ")}):null,p>0?e.jsx("div",{className:"context-followup-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>n(t),children:l.t("button.load_older_context","Load older entries")})}):null,e.jsxs("div",{className:"context-entry-list",children:[S.map((r,g)=>{const m=Ce(r,g);return e.jsxs("details",{className:"context-entry",open:d.has(m),onToggle:v=>N(m,v.currentTarget.open),children:[e.jsx("summary",{className:"context-entry-summary",children:e.jsxs("div",{className:"context-entry-meta",children:[e.jsx("strong",{children:r.label||r.role||r.type||`Entry ${g+1}`}),e.jsx("span",{children:r.line_number?`line ${r.line_number}`:r.timestamp||"local evidence"})]})}),e.jsx(we,{entry:r}),r.tool_output_omitted?e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:i,children:l.t("button.show_tool_output","Show tool output")})}):null,e.jsx(We,{entry:r,onLoadCompactionHistory:s}),e.jsx("pre",{ref:v=>{v&&(v.scrollTop=_e(b,m))},onScroll:v=>ke(b,m,v.currentTarget.scrollTop),children:r.text||"[no visible text]"})]},m)}),u.length?null:e.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),u.length>j?e.jsxs("div",{className:"context-followup-actions",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:I,children:x?`Show first ${h(j)} entries`:`Show all ${h(u.length)} returned entries`}),x?null:e.jsxs("span",{className:"context-entry-count-note",children:[h(L)," entries hidden in compact view"]})]}):null]})}function We({entry:t,onLoadCompactionHistory:n}){const s=A(),i=t.compaction;if(!(i!=null&&i.replacement_history_available))return null;const l=i.replacement_history??[],u=Number(i.replacement_entry_count??l.length);return e.jsxs("div",{className:"context-entry-compaction",children:[e.jsx("strong",{children:"Compaction detected"}),e.jsxs("span",{children:[h(u)," replacement history entries available."]}),l.length?e.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:l.map((o,p)=>e.jsxs("div",{className:"context-replacement-entry",children:[e.jsx("strong",{children:o.label||`Replacement item ${p+1}`}),e.jsx("pre",{children:o.text||"[no visible replacement text]"})]},`${o.label??"replacement"}-${p}`))}):e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}function Xe({call:t,calls:n,onNavigateRecord:s,onCopyCallLink:i}){const u=A().t("button.copy_link","Copy link"),o=n.length?n:[t],p=Math.max(o.findIndex(d=>d.id===t.id),0),c=o.reduce((d,w)=>d+w.totalTokens,0),j=o.reduce((d,w)=>d+w.cost,0),b=o.reduce((d,w)=>d+w.cachedPct,0)/Math.max(o.length,1),x=o.filter(d=>Number(d.contextWindowPct??0)>=60).length,k=o.filter(d=>d.cachedPct<25||d.signal==="cache-risk").length;return e.jsxs("div",{className:"thread-context-module",children:[e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Thread calls",value:h(o.length),detail:`selected ${p+1} of ${o.length}`}),e.jsx(f,{label:"Thread tokens",value:F(c),detail:"loaded aggregate rows"}),e.jsx(f,{label:"Thread cost",value:Q(j),detail:"estimated aggregate"}),e.jsx(f,{label:"Avg cache",value:U(b),detail:O(o.map(d=>d.model))}),e.jsx(f,{label:"Cache risks",value:h(k),detail:"weak reuse or flagged"}),e.jsx(f,{label:"Context pressure",value:h(x),detail:">=60% context window"})]}),e.jsxs("div",{className:"thread-context-grid",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Thread timeline"}),e.jsx(xe,{selectedCall:t,calls:o,onOpenInvestigator:s,onCopyCallLink:i,className:"investigator-thread-timeline",copyAriaContext:"thread context call",copyLabel:u})]}),e.jsxs("dl",{className:"detail-list compact",children:[e.jsx(y,{label:"Project",value:t.project||"Unknown"}),e.jsx(y,{label:"Project path",value:t.projectRelativeCwd||t.cwd||"."}),e.jsx(y,{label:"Source line",value:me(t)}),e.jsx(y,{label:"Session",value:t.sessionId||"Not available"}),e.jsx(y,{label:"Parent thread",value:t.parentThread||"None"}),e.jsx(y,{label:"Models in thread",value:O(o.map(d=>d.model),{limit:3})}),e.jsx(y,{label:"Effort mix",value:O(o.map(d=>d.effort),{limit:3})})]})]})]})}function f({label:t,value:n,detail:s}){return e.jsxs("span",{className:"drilldown-metric",children:[e.jsx("small",{children:t}),e.jsx("strong",{children:n}),e.jsx("em",{children:s})]})}function y({label:t,value:n}){return e.jsxs("div",{children:[e.jsx("dt",{children:t}),e.jsx("dd",{children:n})]})}function Qe({call:t}){const s=[{label:"Cached input",value:Math.max(t.input-t.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:t.uncachedInput,color:"#f59e0b"},{label:"Output",value:t.output,color:"#059669"},{label:"Reasoning",value:t.reasoningOutput,color:"#7c3aed"}].filter(l=>l.value>0),i=Math.max(s.reduce((l,u)=>l+u.value,0),1);return e.jsxs("div",{className:"composition-card",children:[e.jsxs("div",{className:"composition-head",children:[e.jsx("strong",{children:"Token composition"}),e.jsxs("span",{children:[F(i)," visible tokens"]})]}),e.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(l=>e.jsx("i",{style:{width:`${Math.max(l.value/i*100,3)}%`,background:l.color}},l.label))}),e.jsx("div",{className:"composition-legend",children:s.map(l=>e.jsxs("span",{children:[e.jsx("i",{style:{background:l.color}}),l.label]},l.label))})]})}export{ct as CallInvestigatorPage}; + */const X=Z("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]),D=new Map;function Re(t,n){Me(t,n);const s=`${n.apiToken}:${t}`,i=D.get(s);if(i)return i;const l=ze(t,n).finally(()=>{D.delete(s)});return D.set(s,l),l}async function ze(t,n){var o;const s=new URLSearchParams({record_id:t,_:String(Date.now())}),i=await fetch(`/api/call?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":n.apiToken},cache:"no-store"}),l=await Oe(i,"Call detail");if(!((o=l.record)!=null&&o.record_id))throw new Error("Call detail response did not include the requested aggregate record.");const u=Array.isArray(l.adjacent_records)&&l.adjacent_records.length?l.adjacent_records:[l.previous_record,l.record,l.next_record].filter(p=>!!p);return{record:R(l.record,0),previousRecord:l.previous_record?R(l.previous_record,-1):null,nextRecord:l.next_record?R(l.next_record,1):null,adjacentRecords:u.map((p,c)=>R(p,c)),rawPayload:l}}function Me(t,n){if(!t)throw new Error("record_id is required for call detail loading.");if(n.fileMode)throw new Error("Call detail hydration requires the localhost dashboard server.");if(!n.apiToken)throw new Error("Call detail hydration requires a localhost dashboard API token.")}async function Oe(t,n){let s={};try{s=await t.json()}catch{s={}}if(!t.ok){const i=typeof s.error=="string"?s.error:`${n} request failed (${t.status})`;throw new Error(i)}return s}function $e(t,n){return H(n.t("call.readout.exact_body","{input} input tokens = {cached} cached + {uncached} uncached; {output} output tokens; {cache} cache reuse."),{input:h(t.input),cached:h(t.cachedInput),uncached:h(t.uncachedInput),output:h(t.output),cache:U(t.cachedPct)})}function De(t){return t.t("call.readout.previous_unavailable","No previous call is loaded in resolved thread, call-to-call deltas unavailable.")}function qe(t,n){const s=t.uncachedInput-n.uncachedInput,i=t.cachedInput-n.cachedInput;return s>0&&i<0?`Fresh input rose by ${h(s)} while cached input fell by ${h(Math.abs(i))}; classic cache-drop profile.`:s>0?`Fresh input increased by ${h(s)} from previous call; inspect evidence new files, tool results, or rewritten context.`:s<0&&i>=0?`Fresh input fell by ${h(Math.abs(s))} while cached input increased, so this call reused context more efficiently previous one.`:"Token accounting broadly stable compared previous call in resolved thread."}function Ue(t,n){var s;if(t.status==="loaded"){const i=((s=t.payload.entries)==null?void 0:s.length)??0,l=Number(t.payload.visible_char_count??0),u=Number(t.payload.visible_token_estimate??0),o=Fe(t.payload,n);return H(n.t("call.readout.evidence_analyzed","Evidence analyzed: {totalEntries} selected-turn entries, {visibleChars} visible redacted chars, {visibleTokens} visible tokens.{serializedDetail}"),{totalEntries:h(i),visibleChars:h(l),visibleTokens:h(u),estimator:t.payload.visible_token_estimator??"visible-token estimate",serializedDetail:o,renderedEntries:h(i)})}return t.status==="loading"?n.t("call.readout.evidence_loading",t.message):t.status==="error"?`Evidence request failed: ${t.message}`:"Evidence is not loaded yet. Aggregate token counts are exact, but visible-context attribution needs runtime evidence."}function Fe(t,n){const s=t.serialized_evidence??{};if(s.deferred||s.deferred_buckets)return n.t("call.readout.evidence_serialized_deferred","Fast serialized estimate only; full serialized grouping deferred.");const i=Be(t);return i<=0?"":H(n.t("call.readout.evidence_serialized_bound"," Serialized local upper bound: {tokens} tokens."),{tokens:h(i),chars:h(Number(s.raw_json_char_count??s.total_chars??0))})}function He(t,n){const s=t.input>0?t.cachedInput/t.input:t.cachedPct/100,i=n&&n.input>0?n.cachedInput/n.input:n?n.cachedPct/100:null,l=(n==null?void 0:n.uncachedInput)??0;return n&&i!==null&&i>=.8&&s<=.05&&t.input>=1e3?"Compare previous call, then inspect loaded evidence see fresh context was sent after cache miss.":n&&t.uncachedInput>Math.max(l*2,1e3)?"Inspect most recent evidence entries first; spike is in fresh uncached input, not cached history.":s>=.85?`Cache reuse is healthy; focus on ${h(t.uncachedInput)} uncached tokens were still billed as fresh input.`:n?"Use delta cards to locate whether change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough understand this isolated call."}function Ke(t){return t==="Hydrated from /api/call"?"Position: hydrated live record outside loaded snapshot":`Position: ${t}`}function H(t,n){return t.replace(/\{(\w+)\}/g,(s,i)=>n[i]??s)}function Be(t){const n=t.serialized_evidence??{};return Number(n.raw_json_token_estimate??n.token_estimate??0)}function rt({model:t,recordId:n,contextRuntime:s,onContextApiEnabledChange:i,onNavigateRecord:l,onCopyCallLink:u,onBackToCalls:o,backLabel:p}){const c=A(),[j,b]=C.useState(""),[x,k]=C.useState({status:"idle"}),[d,w]=C.useState({status:"idle"}),[S,L]=C.useState({recordId:"",nonce:0}),I=x.status==="loaded"&&x.recordId===n?x.detail:null,{modelIndex:N,hydratedDetail:E,call:a,previous:r,next:g,threadCalls:m,positionLabel:v}=C.useMemo(()=>ee({calls:t.calls,recordId:n,detail:I}),[I,t.calls,n]),Y=d.status==="loaded"?d.payload:null;if(C.useEffect(()=>{w({status:"idle"})},[n]),C.useEffect(()=>{if(!n||N>=0){k({status:"idle"});return}if(s.fileMode||!s.apiToken){k({status:"error",recordId:n,message:"This call is outside the loaded snapshot. Serve the dashboard with its localhost API token to hydrate it."});return}let _=!1;return k({status:"loading",recordId:n,message:"Loading call detail from localhost..."}),Re(n,s).then(P=>{_||k({status:"loaded",recordId:n,detail:P})}).catch(P=>{_||k({status:"error",recordId:n,message:q(P)})}),()=>{_=!0}},[s,N,n]),!a){const _=x.status==="loading"||x.status==="error"?x.message:n?"Selected call is not present in the loaded dashboard rows.":"No aggregate call rows are loaded.";return e.jsx("div",{className:"page-grid",children:e.jsxs("div",{className:"page-title-row",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsx("p",{children:_})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]})]})})}async function G(){try{const _=new URL(window.location.href);if(se(_,"call",le(_.search)),!await oe(_.toString()))throw new Error("Clipboard unavailable");b("Copied investigator link")}catch{b("Copy unavailable in this browser")}}return e.jsxs("div",{className:"call-investigator-layout",children:[e.jsxs("div",{className:"page-title-row span-all",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsxs("p",{children:[a.thread," / ",a.model]})]}),e.jsxs("div",{className:"toolbar",children:[e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>r&&l(r.id),disabled:!r,children:[e.jsx(Ie,{size:16})," ",c.t("button.previous_call","Previous call")]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>g&&l(g.id),disabled:!g,children:[c.t("button.next_call","Next call")," ",e.jsx(Ae,{size:16})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:G,"aria-label":c.t("button.copy_investigator_link","Copy investigator link"),children:[e.jsx(te,{size:16})," ",c.t("button.copy_link","Copy link")]})]})]}),e.jsxs(T,{title:c.t("call.readout.title","Investigation Readout"),subtitle:j||v,className:"span-all",action:e.jsx(z,{label:c.t("call.readout.badge","Aggregate + on-demand evidence"),tone:"blue"}),children:[e.jsxs("div",{className:"call-summary",children:[e.jsx(z,{label:"Aggregate only",tone:"green"}),E?e.jsx(z,{label:"Hydrated live",tone:"blue"}):null,e.jsx(ae,{call:a}),e.jsx(z,{label:"Raw context gated",tone:"blue"}),e.jsx("span",{className:"call-id",children:a.id.slice(0,16)})]}),e.jsx(Ve,{call:a,previous:r,evidenceState:d,positionLabel:v}),e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Total tokens",value:h(a.totalTokens),detail:`${F(a.input)} input`}),e.jsx(f,{label:"Uncached input",value:h(a.uncachedInput),detail:"fresh billed input"}),e.jsx(f,{label:"Cache hit rate",value:U(a.cachedPct),detail:ie(a)}),e.jsx(f,{label:"Estimated cost",value:Q(a.cost),detail:a.pricingEstimated?"estimated pricing":"configured pricing"}),e.jsx(f,{label:"Duration",value:a.duration,detail:ne(a)}),e.jsx(f,{label:"Usage credits",value:a.credits?a.credits.toFixed(3):"-",detail:a.usageCreditConfidence})]}),e.jsx(ce,{call:a})]}),e.jsxs(T,{title:"Token Accounting",subtitle:"Exact aggregate row fields",children:[e.jsx(Ye,{call:a}),e.jsx(re,{call:a})]}),e.jsx(T,{title:"Cache Accounting",subtitle:"Derived from adjacent aggregate call",children:e.jsx(de,{call:a,calls:m})}),e.jsx(T,{title:"Context Attribution",subtitle:"Estimated from visible log volume",className:"span-all",children:e.jsx(ue,{call:a,payload:Y,onRunFullAnalysis:()=>L(_=>({recordId:a.id,nonce:_.nonce+1})),showHeading:!1})}),e.jsxs(T,{title:"Aggregate Identity",subtitle:"Local metadata only",children:[e.jsxs("dl",{className:"detail-list",children:[e.jsx(y,{label:"Record id",value:a.id}),e.jsx(y,{label:"Time",value:a.time}),e.jsx(y,{label:"Thread",value:a.thread}),e.jsx(y,{label:"Model",value:a.model}),e.jsx(y,{label:"Effort",value:a.effort}),e.jsx(y,{label:"Project",value:a.project||"Unknown"}),e.jsx(y,{label:"Context window",value:he(a)}),e.jsx(y,{label:"Recommendation",value:a.recommendation||"No aggregate recommendation"})]}),e.jsx(xe,{call:a}),a.recommendation?e.jsxs("div",{className:"recommendation-box",children:[e.jsx(Le,{size:16}),e.jsx("p",{children:a.recommendation})]}):null]}),e.jsx(T,{title:"Thread Context",subtitle:`${m.length} loaded related calls`,className:"span-all",children:e.jsx(Qe,{call:a,calls:m,onNavigateRecord:l,onCopyCallLink:u})}),e.jsx(T,{title:"Raw Evidence",subtitle:"Explicit localhost request only",className:"span-all",children:e.jsx(Je,{call:a,contextRuntime:s,onContextApiEnabledChange:i,onEvidenceStateChange:w,fullAnalysisRequestNonce:S.recordId===a.id?S.nonce:0},a.id)})]})}function Ve({call:t,previous:n,evidenceState:s,positionLabel:i}){const l=A();return e.jsxs("div",{className:"investigation-readout-grid",children:[e.jsx(M,{label:l.t("call.readout.exact_label","Exact callback accounting"),body:$e(t,l)}),e.jsx(M,{label:l.t("call.readout.previous_label","Compared previous call"),body:n?qe(t,n):De(l)}),e.jsx(M,{label:l.t("call.readout.evidence_label","Evidence state"),body:Ue(s,l)}),e.jsx(M,{label:l.t("call.readout.next_label","Next diagnostic move"),body:He(t,n),detail:Ke(i)})]})}function M({label:t,body:n,detail:s}){return e.jsxs("div",{className:"investigation-readout-card",children:[e.jsx("span",{children:t}),e.jsx("p",{children:n}),s?e.jsx("small",{children:s}):null]})}function Je({call:t,contextRuntime:n,onContextApiEnabledChange:s,onEvidenceStateChange:i,fullAnalysisRequestNonce:l}){const u=A(),[o,p]=C.useState(()=>be(window.location.search,ge(t.id)??K)),[c,j]=C.useState({status:"idle"}),b=!!n.apiToken&&!n.fileMode,x=b&&n.contextApiEnabled;C.useEffect(()=>{const a=B(t.id,o);j(a?{status:"loaded",payload:a}:{status:"idle"})},[t.id,o.includeToolOutput,o.includeCompactionHistory,o.maxChars,o.maxEntries,o.mode]),C.useEffect(()=>{i(c)},[c,i]),C.useEffect(()=>{if(l<=0||!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")},[l]);async function k(){j({status:"loading",message:"Enabling localhost context API..."});try{const a=await ye(n);s(a),j({status:"idle",message:a?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(a){j({status:"error",message:q(a)})}}async function d(a=o,r="Loading selected-turn evidence..."){$(t.id,a);const g=B(t.id,a);if(g){j({status:"loaded",payload:g});return}j({status:"loading",message:r});try{const m=await je(t.id,n,a);ve(t.id,a,m),j({status:"loaded",payload:m})}catch(m){j({status:"error",message:q(m)})}}function w(){if(!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")}function S(a){const r=Ee(a,o);N(r),d(r,"Loading older context...")}function L(){const a={...o,includeToolOutput:!0};N(a),d(a,"Loading omitted tool output...")}function I(){const a={...o,includeCompactionHistory:!0};N(a),d(a,"Loading compacted replacement...")}function N(a){p(a),$(t.id,a);const r=new URL(window.location.href);V(r,a),window.history.replaceState(null,"",r)}function E(a,r){p(g=>{const m={...g,[a]:r};$(t.id,m);const v=new URL(window.location.href);return V(v,m),window.history.replaceState(null,"",v),m})}return e.jsxs("div",{className:"investigator-evidence",children:[e.jsxs("div",{className:"locked-context-card",children:[e.jsx(Pe,{size:20}),e.jsxs("div",{children:[e.jsx("strong",{children:"Raw context is gated"}),e.jsx("p",{children:fe(n)})]})]}),e.jsxs("div",{className:"context-action-grid",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:k,disabled:!b||n.contextApiEnabled||c.status==="loading",children:u.t("button.enable_context_loading","Enable context loading")}),e.jsx("button",{className:"primary-button",type:"button",onClick:()=>d(),disabled:!x||c.status==="loading",children:u.t("button.show_turn_evidence","Show turn log evidence")}),e.jsx("button",{className:"toolbar-button",type:"button",onClick:w,disabled:!x||c.status==="loading",children:u.t("button.full_serialized_analysis","Run full serialized analysis")}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Mode"}),e.jsxs("select",{"aria-label":"Context mode",value:o.mode,disabled:!x||c.status==="loading",onChange:a=>E("mode",a.target.value==="full"?"full":"quick"),children:[e.jsx("option",{value:"quick",children:"Quick"}),e.jsx("option",{value:"full",children:"Full"})]})]}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Entries"}),e.jsxs("select",{"aria-label":"Context entries",value:String(o.maxEntries),disabled:!x||c.status==="loading",onChange:a=>E("maxEntries",Number(a.target.value)),children:[e.jsx("option",{value:"20",children:"20"}),e.jsx("option",{value:"50",children:"50"}),e.jsx("option",{value:"100",children:"100"}),e.jsx("option",{value:"0",children:"All"})]})]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeToolOutput,disabled:!x||c.status==="loading",onChange:a=>E("includeToolOutput",a.target.checked)}),u.t("button.include_tool_output","Include tool output")]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeCompactionHistory,disabled:!x||c.status==="loading",onChange:a=>E("includeCompactionHistory",a.target.checked)}),"Include compaction history"]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.maxChars===0,disabled:!x||c.status==="loading",onChange:a=>E("maxChars",a.target.checked?0:K.maxChars)}),u.t("button.no_char_limit","No char limit")]})]}),c.status==="idle"&&c.message?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="loading"?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="error"?e.jsx("p",{className:"context-state-note error",children:c.message}):null,c.status==="loaded"?e.jsx(We,{payload:c.payload,onLoadOlder:S,onLoadCompactionHistory:I,onLoadToolOutput:L}):null,e.jsx("p",{className:"privacy-note",children:"Raw context is read from the local JSONL source only after this explicit action and is not embedded in static dashboard HTML."})]})}function We({payload:t,onLoadOlder:n,onLoadCompactionHistory:s,onLoadToolOutput:i}){var E,a;const l=A(),u=t.entries??[],o=t.omitted??{},p=Number(o.older_entries??0),c=Ce(t),j=10,b=String(t.record_id??""),[x,k]=C.useState(()=>J(b)),[d,w]=C.useState(()=>W(b,u));C.useEffect(()=>{k(J(b)),w(W(b,u))},[u.length,t.context_mode,t.include_compaction_history,t.include_tool_output,(E=t.omitted)==null?void 0:E.max_chars,(a=t.omitted)==null?void 0:a.max_entries,t.record_id,b]);const S=x?u:u.slice(0,j),L=Math.max(u.length-S.length,0);function I(){k(r=>{const g=!r;return Te(b,g),g})}function N(r,g){Se(b,r,g),w(m=>{const v=new Set(m);return g?v.add(r):v.delete(r),v})}return e.jsxs("div",{className:"context-evidence",children:[e.jsxs("div",{className:"context-evidence-summary",children:[e.jsx(f,{label:"Entries",value:h(u.length),detail:String(t.context_mode??"quick")}),e.jsx(f,{label:"Visible chars",value:h(Number(t.visible_char_count??0)),detail:"redacted local text"}),e.jsx(f,{label:"Visible tokens",value:h(Number(t.visible_token_estimate??0)),detail:"estimator"}),e.jsx(f,{label:"Older omitted",value:h(p),detail:"entry budget"})]}),c.length?e.jsx("p",{className:"context-note",children:c.join(" ")}):null,p>0?e.jsx("div",{className:"context-followup-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>n(t),children:l.t("button.load_older_context","Load older entries")})}):null,e.jsxs("div",{className:"context-entry-list",children:[S.map((r,g)=>{const m=we(r,g);return e.jsxs("details",{className:"context-entry",open:d.has(m),onToggle:v=>N(m,v.currentTarget.open),children:[e.jsx("summary",{className:"context-entry-summary",children:e.jsxs("div",{className:"context-entry-meta",children:[e.jsx("strong",{children:r.label||r.role||r.type||`Entry ${g+1}`}),e.jsx("span",{children:r.line_number?`line ${r.line_number}`:r.timestamp||"local evidence"})]})}),e.jsx(ke,{entry:r}),r.tool_output_omitted?e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:i,children:l.t("button.show_tool_output","Show tool output")})}):null,e.jsx(Xe,{entry:r,onLoadCompactionHistory:s}),e.jsx("pre",{ref:v=>{v&&(v.scrollTop=Ne(b,m))},onScroll:v=>_e(b,m,v.currentTarget.scrollTop),children:r.text||"[no visible text]"})]},m)}),u.length?null:e.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),u.length>j?e.jsxs("div",{className:"context-followup-actions",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:I,children:x?`Show first ${h(j)} entries`:`Show all ${h(u.length)} returned entries`}),x?null:e.jsxs("span",{className:"context-entry-count-note",children:[h(L)," entries hidden in compact view"]})]}):null]})}function Xe({entry:t,onLoadCompactionHistory:n}){const s=A(),i=t.compaction;if(!(i!=null&&i.replacement_history_available))return null;const l=i.replacement_history??[],u=Number(i.replacement_entry_count??l.length);return e.jsxs("div",{className:"context-entry-compaction",children:[e.jsx("strong",{children:"Compaction detected"}),e.jsxs("span",{children:[h(u)," replacement history entries available."]}),l.length?e.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:l.map((o,p)=>e.jsxs("div",{className:"context-replacement-entry",children:[e.jsx("strong",{children:o.label||`Replacement item ${p+1}`}),e.jsx("pre",{children:o.text||"[no visible replacement text]"})]},`${o.label??"replacement"}-${p}`))}):e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}function Qe({call:t,calls:n,onNavigateRecord:s,onCopyCallLink:i}){const u=A().t("button.copy_link","Copy link"),o=n.length?n:[t],p=Math.max(o.findIndex(d=>d.id===t.id),0),c=o.reduce((d,w)=>d+w.totalTokens,0),j=o.reduce((d,w)=>d+w.cost,0),b=o.reduce((d,w)=>d+w.cachedPct,0)/Math.max(o.length,1),x=o.filter(d=>Number(d.contextWindowPct??0)>=60).length,k=o.filter(d=>d.cachedPct<25||d.signal==="cache-risk").length;return e.jsxs("div",{className:"thread-context-module",children:[e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Thread calls",value:h(o.length),detail:`selected ${p+1} of ${o.length}`}),e.jsx(f,{label:"Thread tokens",value:F(c),detail:"loaded aggregate rows"}),e.jsx(f,{label:"Thread cost",value:Q(j),detail:"estimated aggregate"}),e.jsx(f,{label:"Avg cache",value:U(b),detail:O(o.map(d=>d.model))}),e.jsx(f,{label:"Cache risks",value:h(k),detail:"weak reuse or flagged"}),e.jsx(f,{label:"Context pressure",value:h(x),detail:">=60% context window"})]}),e.jsxs("div",{className:"thread-context-grid",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Thread timeline"}),e.jsx(me,{selectedCall:t,calls:o,onOpenInvestigator:s,onCopyCallLink:i,className:"investigator-thread-timeline",copyAriaContext:"thread context call",copyLabel:u})]}),e.jsxs("dl",{className:"detail-list compact",children:[e.jsx(y,{label:"Project",value:t.project||"Unknown"}),e.jsx(y,{label:"Project path",value:t.projectRelativeCwd||t.cwd||"."}),e.jsx(y,{label:"Source line",value:pe(t)}),e.jsx(y,{label:"Session",value:t.sessionId||"Not available"}),e.jsx(y,{label:"Parent thread",value:t.parentThread||"None"}),e.jsx(y,{label:"Models in thread",value:O(o.map(d=>d.model),{limit:3})}),e.jsx(y,{label:"Effort mix",value:O(o.map(d=>d.effort),{limit:3})})]})]})]})}function f({label:t,value:n,detail:s}){return e.jsxs("span",{className:"drilldown-metric",children:[e.jsx("small",{children:t}),e.jsx("strong",{children:n}),e.jsx("em",{children:s})]})}function y({label:t,value:n}){return e.jsxs("div",{children:[e.jsx("dt",{children:t}),e.jsx("dd",{children:n})]})}function Ye({call:t}){const s=[{label:"Cached input",value:Math.max(t.input-t.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:t.uncachedInput,color:"#f59e0b"},{label:"Output",value:t.output,color:"#059669"},{label:"Reasoning",value:t.reasoningOutput,color:"#7c3aed"}].filter(l=>l.value>0),i=Math.max(s.reduce((l,u)=>l+u.value,0),1);return e.jsxs("div",{className:"composition-card",children:[e.jsxs("div",{className:"composition-head",children:[e.jsx("strong",{children:"Token composition"}),e.jsxs("span",{children:[F(i)," visible tokens"]})]}),e.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(l=>e.jsx("i",{style:{width:`${Math.max(l.value/i*100,3)}%`,background:l.color}},l.label))}),e.jsx("div",{className:"composition-legend",children:s.map(l=>e.jsxs("span",{children:[e.jsx("i",{style:{background:l.color}}),l.label]},l.label))})]})}export{rt as CallInvestigatorPage}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js index 2c78fd7d..55c655c3 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js @@ -1,16 +1,16 @@ -import{j as t,r as c}from"./dashboard-react.js";import{u as Lt}from"./useInfiniteQuery.js";import{c as kt,d as It}from"./exploreQueries.js";import{c as Re,W as $t,u as ce,j as O,C as Rt,a as dt,G as At,U as ut,H as Ot,X as ht,f as ee,p as q,m as Ae,Y as Bt,Z as Vt,D as Ht,R as Kt,_ as mt,E as zt,d as Ut,r as qt,e as Gt,g as Qt}from"./App.js";import{r as Wt,u as Ze}from"./filtering.js";import{L as et}from"./LineChart.js";import{P as Z}from"./Panel.js";import{S as re}from"./StatusBadge.js";import{E as Yt}from"./EvidenceGrid.js";import{b as Xt,c as Jt}from"./tableActions.js";import{u as Zt}from"./useQuery.js";import{d as tt,c as en,a as nt,b as tn,e as nn,f as st,r as at,l as sn,g as an,h as on,i as it,j as ot,C as rn,k as ln,m as cn,n as dn,o as un,p as hn,q as mn,s as xn,t as Oe,u as pn,v as fn,T as xt,w as gn,x as jn,y as vn}from"./contextEvidenceState.js";import{L as pt}from"./lock-keyhole.js";import{S as bn}from"./search.js";import{S as Cn}from"./shield-check.js";import{a as yn}from"./EvidenceGridControls.js";import"./useBaseQuery.js";import"./queryOptions.js";import"./infiniteQueryOptions.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./index2.js";import"./rowActionEvents.js";/** +import{j as t,r as c}from"./dashboard-react.js";import{u as Lt}from"./useInfiniteQuery.js";import{c as kt,d as It}from"./exploreQueries.js";import{c as Re,W as $t,u as ce,j as O,C as Rt,a as dt,G as At,U as ut,H as Ot,X as ht,f as ee,p as q,m as Ae,Y as Bt,Z as Vt,_ as Ht,D as Kt,R as zt,$ as mt,E as Ut,d as qt,r as Gt,e as Qt,g as Wt}from"./App.js";import{r as Yt,u as Ze}from"./filtering.js";import{L as et}from"./LineChart.js";import{P as Z}from"./Panel.js";import{S as re}from"./StatusBadge.js";import{E as Xt}from"./EvidenceGrid.js";import{b as Jt,c as Zt}from"./tableActions.js";import{u as en}from"./useQuery.js";import{d as tt,c as tn,a as nt,b as nn,e as sn,f as st,r as at,l as an,g as on,h as rn,i as it,j as ot,C as ln,k as cn,m as dn,n as un,o as hn,p as mn,q as xn,s as pn,t as Oe,u as fn,v as gn,T as xt,w as jn,x as vn,y as bn}from"./contextEvidenceState.js";import{L as pt}from"./lock-keyhole.js";import{S as Cn}from"./search.js";import{S as yn}from"./shield-check.js";import{a as Sn}from"./EvidenceGridControls.js";import"./useBaseQuery.js";import"./queryOptions.js";import"./infiniteQueryOptions.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./index2.js";import"./rowActionEvents.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Sn=Re("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]);/** + */const wn=Re("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const wn=Re("PanelRightClose",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m8 9 3 3-3 3",key:"12hl5m"}]]);/** + */const Fn=Re("PanelRightClose",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m8 9 3 3-3 3",key:"12hl5m"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Fn=Re("PanelRightOpen",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m10 15-3-3 3-3",key:"1pgupc"}]]);function Nn(e){const n=[],s=[e.localQuery.trim(),e.globalQuery.trim()].filter(Boolean);s.length&&n.push(`Search ${s.map(i=>`"${i}"`).join(" + ")}`),e.modelFilter!=="all"&&n.push(`Model ${e.modelFilter}`),e.effortFilter!=="all"&&n.push(`Effort ${e.effortFilter}`),e.confidenceFilter!=="all"&&n.push(`Confidence ${Pn(e.confidenceFilter)}`),e.sourceFilter!=="all"&&n.push(`Source ${_n(e.sourceFilter)}`),e.dateRangeStatus.invalid?n.push("Date range invalid"):(e.dateRangeStatus.active||e.timeFilter!=="all")&&n.push(e.dateRangeStatus.label||Ln(e.timeFilter)),e.activePresetLabel&&n.push(`Preset ${e.activePresetLabel}`);const a=`Showing ${e.shownCount.toLocaleString()} of ${e.totalCount.toLocaleString()} aggregate rows`;return n.length?`${a} - Filters: ${n.join("; ")}`:a}function En(e,n){return n==="project"?`${e.project.toLocaleString()} project/cwd rows`:n==="session"?`${e.session.toLocaleString()} session-linked rows`:n==="git"?`${e.git.toLocaleString()} git rows`:n==="source-file"?`${e.sourceFile.toLocaleString()} source-file rows`:n==="missing"?`${e.missing.toLocaleString()} rows missing source`:`${e.project.toLocaleString()} project, ${e.session.toLocaleString()} session, ${e.git.toLocaleString()} git`}function Tn(e,n){return n==="all"?!0:n==="project"?Be(e):n==="session"?Ve(e):n==="git"?He(e):n==="source-file"?Ke(e):!ft(e)}function Mn(e,n){if(n==="all")return!0;if(n==="cost-exact")return!e.pricingEstimated&&Number.isFinite(e.cost)&&e.cost>0;if(n==="cost-estimated")return e.pricingEstimated;if(n==="cost-unpriced")return!e.pricingEstimated&&(!Number.isFinite(e.cost)||e.cost<=0);const s=e.usageCreditConfidence.toLowerCase();return n==="credit-exact"?s.includes("exact"):n==="credit-override"?s.includes("override"):n==="credit-estimated"?s.includes("estimated"):s.includes("missing")||s.includes("unpriced")}function Dn(e){return e.reduce((n,s)=>({project:n.project+(Be(s)?1:0),session:n.session+(Ve(s)?1:0),git:n.git+(He(s)?1:0),sourceFile:n.sourceFile+(Ke(s)?1:0),missing:n.missing+(ft(s)?0:1),total:n.total+1}),{project:0,session:0,git:0,sourceFile:0,missing:0,total:0})}function Be(e){return!!(e.project||e.projectRelativeCwd||e.cwd||e.projectTags.length)}function Ve(e){return!!(e.sessionId||e.turnId||e.parentSessionId)}function He(e){return!!(e.gitBranch||e.gitRemoteLabel||e.gitRemoteHash)}function Ke(e){return!!(e.sourceFile||e.lineNumber!==null)}function ft(e){return Be(e)||Ve(e)||He(e)||Ke(e)}function Pn(e){return e==="cost-exact"?"exact cost":e==="cost-estimated"?"estimated cost":e==="cost-unpriced"?"unpriced cost":e==="credit-exact"?"exact credit rate":e==="credit-estimated"?"estimated credit mapping":e==="credit-override"?"user credit override":"missing credit rate"}function _n(e){return e==="project"?"project/cwd":e==="session"?"session-linked":e==="git"?"git metadata":e==="source-file"?"source file":"missing source"}function Ln(e){return e==="today"?"Today":e==="this-week"?"This week":e==="last-7-days"?"Last 7 days":e==="this-month"?"This month":e==="custom"?"Custom date range":"All time"}const oe="__detail_first__",kn=new Set(["all","cost-exact","cost-estimated","cost-unpriced","credit-exact","credit-estimated","credit-override","credit-missing"]),In=new Set(["all","today","this-week","last-7-days","this-month","custom"]),$n=new Set(["all","project","session","git","source-file","missing"]),Rn=new Set(["time","duration","gap","attention","thread","initiator","model","effort","total","cached","uncached","output","reasoning","cost","usage","cache","context"]);function E(e,n=window.location.href){var s;return((s=new URL(n).searchParams.get(e))==null?void 0:s.trim())??""}function gt(e=window.location.href){const n=E("confidence",e)||E("pricing",e),s=Hn(n);return kn.has(s)?s:"all"}function jt(e=window.location.href){const n=E("source",e);return $n.has(n)?n:"all"}function vt(e=window.location.href){const n=E("date",e)||E("time",e);return In.has(n)?n:"all"}function le(e,n=window.location.href){return Le(E(e,n))}function An(e=window.location.href){const n=E("record",e);return n||(E("detail",e)==="first"?oe:null)}function Pe(e=window.location.href){const n=E("sort",e);return bt(n)}function bt(e){return Rn.has(e)?e:"time"}function Ct(e,n=window.location.href){const s=E("direction",n);return s==="asc"||s==="desc"?s:U(e)}function On(e=window.location.href){return E("density",e)==="roomy"?"roomy":"dense"}function Bn(e,n=window.location.href){const s=Number(E("page",n)||1);return Number.isFinite(s)&&s>1?Math.floor(s)*e:e}function _e(e,n=window.location.href){const s=new URL(n);return s.searchParams.set("view","calls"),s.searchParams.delete("detail"),s.searchParams.delete("pricing"),k(s,"record",e.selectedRecordId,""),k(s,"call_q",e.localQuery.trim(),""),k(s,"model",e.modelFilter,"all"),k(s,"effort",e.effortFilter,"all"),k(s,"confidence",e.confidenceFilter,"all"),k(s,"source",e.sourceFilter,"all"),k(s,"time",e.timeFilter,"all"),k(s,"date",e.timeFilter,"all"),k(s,"from",e.timeFilter==="custom"?e.dateStart:"",""),k(s,"to",e.timeFilter==="custom"?e.dateEnd:"",""),k(s,"sort",e.sortKey,"time"),k(s,"direction",e.sortDirection,U(e.sortKey)),k(s,"density",e.density,"dense"),k(s,"page",String(Vn(e.visibleRowCount,e.pageSize)),"1"),s}function U(e){return e==="cache"||e==="effort"||e==="initiator"||e==="model"||e==="thread"?"asc":"desc"}function Le(e){const n=Kn(e);return n?zn(n):""}function Vn(e,n){return Math.max(1,Math.ceil(Math.max(e,n)/n))}function k(e,n,s,a){if(!s||s===a){e.searchParams.delete(n);return}e.searchParams.set(n,s)}function Hn(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":e}function Kn(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function zn(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(e,n){return e.filter(s=>Un(s,n))}function ke(e,n,s){return[...e].sort((a,i)=>qn(a,i,n,s))}function ze(e,n,s,a){const i=Wn(a);if(e==="custom"){const o=lt(n),r=lt(s);return o&&r&&o>r?{active:!0,invalid:!0,start:o,endExclusive:K(r,1),label:"Invalid date range"}:{active:!!(o||r),invalid:!1,start:o,endExclusive:r?K(r,1):null,label:J("Custom",o,r)}}if(e==="today")return{active:!0,invalid:!1,start:i,endExclusive:K(i,1),label:J("Today",i,i)};if(e==="this-week"){const o=Yn(i);return{active:!0,invalid:!1,start:o,endExclusive:K(o,7),label:J("This week",o,K(o,6))}}if(e==="last-7-days"){const o=K(i,-6);return{active:!0,invalid:!1,start:o,endExclusive:K(i,1),label:J("Last 7 days",o,i)}}if(e==="this-month"){const o=new Date(i.getFullYear(),i.getMonth(),1),r=new Date(i.getFullYear(),i.getMonth()+1,1);return{active:!0,invalid:!1,start:o,endExclusive:r,label:J("This month",o,K(r,-1))}}return{active:!1,invalid:!1,start:null,endExclusive:null,label:"All time"}}function Un(e,n){if(n.modelFilter!=="all"&&e.model!==n.modelFilter||n.effortFilter!=="all"&&e.effort!==n.effortFilter||!Mn(e,n.confidenceFilter)||!Tn(e,n.sourceFilter)||!Xn(e,n.timeFilter,n.dateStart,n.dateEnd)||n.activePreset&&!$t(e,n.activePreset))return!1;const s=[e.thread,e.cwd,e.project,e.projectRelativeCwd,e.gitBranch,e.gitRemoteLabel,e.sessionId,e.model,e.effort,e.initiator,e.initiatorReason,e.signal,e.recommendation,e.rawTime,e.sourceFile,e.lineNumber,e.tags.join(" ")];return[n.globalQuery,n.localQuery].every(a=>Wt(s,a))}function qn(e,n,s,a){const i=rt(e,s),o=rt(n,s);if(i===null&&o!==null)return 1;if(o===null&&i!==null)return-1;const r=Qn(i,o);return r!==0?a==="asc"?r:-r:Ie(e,n)||e.id.localeCompare(n.id)}function rt(e,n){return n==="time"?$e(e):n==="duration"?e.durationSeconds:n==="gap"?e.previousCallGapSeconds:n==="attention"?Gn(e):n==="thread"?e.thread.toLowerCase():n==="initiator"?e.initiator.toLowerCase():n==="model"?e.model.toLowerCase():n==="effort"?e.effort.toLowerCase():n==="total"?e.totalTokens:n==="cached"?e.input*(e.cachedPct/100):n==="uncached"?e.uncachedInput:n==="output"?e.output:n==="reasoning"?e.reasoningOutput:n==="cost"?e.cost:n==="usage"?e.credits:n==="cache"?e.cachedPct:e.contextWindowPct}function Gn(e){const n=e.signal&&e.signal!=="aggregate"?1e3:0,s=e.recommendation?750:0,a=e.contextWindowPct??0,i=Math.min(e.uncachedInput/1e3,250),o=Math.min(e.cost*25,200),r=Math.min(e.credits,200),h=Math.min(e.durationSeconds/60,120);return n+s+a+i+o+r+h}function Qn(e,n){return e===null&&n===null?0:e===null?1:n===null?-1:typeof e=="string"||typeof n=="string"?String(e).localeCompare(String(n)):e-n}function Ie(e,n){return $e(n)-$e(e)}function $e(e){const n=Date.parse(e.rawTime);return Number.isFinite(n)?n:0}function lt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function ct(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function J(e,n,s){const a=n?ct(n):"",i=s?ct(s):"";return a&&i&&a===i?`${e}: ${a}`:a&&i?`${e}: ${a} to ${i}`:a?`${e}: from ${a}`:i?`${e}: through ${i}`:e}function Wn(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function K(e,n){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+n)}function Yn(e){const n=e.getDay();return K(e,n===0?-6:1-n)}function Xn(e,n,s="",a="",i=new Date){if(n==="all")return!0;const o=ze(n,s,a,i);if(o.invalid)return!1;if(!o.active)return!0;const r=Date.parse(e.rawTime);return!(!Number.isFinite(r)||o.start&&r=o.endExclusive.getTime())}const Jn={time:"time",duration:"duration",gap:"gap",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"tokens",cached:"cached",uncached:"uncached",output:"output",reasoning:"reasoning",cache:"cache"};function Zn(e){const n=Jn[e.sortKey],s=ze(e.timeFilter,e.dateStart,e.dateEnd,new Date),a=es(e,n,s.invalid);return{enabled:!a,reason:a,sort:n??"time",filters:{query:[e.globalQuery.trim(),e.localQuery.trim()].filter(Boolean).join(" "),model:e.modelFilter==="all"?void 0:e.modelFilter,effort:e.effortFilter==="all"?void 0:e.effortFilter,...ts(e.confidenceFilter),...ns(s.start,s.endExclusive,e.scopeSince)}}}function es(e,n,s){return!e.enabled||e.runtime.fileMode||!e.runtime.apiToken?"Stored snapshot":e.globalQuery.trim()&&e.localQuery.trim()?"Multiple searches use loaded snapshot":e.activePreset?"Preset uses loaded snapshot":e.sourceFilter!=="all"?"Source filter uses loaded snapshot":n?s?"Invalid date range":"":"This sort uses loaded snapshot"}function ts(e){return e==="cost-exact"?{pricingStatus:"priced"}:e==="cost-estimated"?{pricingStatus:"estimated"}:e==="cost-unpriced"?{pricingStatus:"unpriced"}:e==="credit-exact"?{creditConfidence:"exact"}:e==="credit-estimated"?{creditConfidence:"estimated"}:e==="credit-override"?{creditConfidence:"user_override"}:e==="credit-missing"?{creditConfidence:"unpriced"}:{}}function ns(e,n,s){return{since:(e==null?void 0:e.toISOString())??s??void 0,until:n?new Date(n.getTime()-1).toISOString():void 0}}function ss({data:e,valueLabel:n=s=>String(s)}){const s=Math.max(...e.map(a=>a.value),1);return t.jsx("div",{className:"bar-list",children:e.map(a=>t.jsxs("div",{className:"bar-row",children:[t.jsx("span",{children:a.label}),t.jsx("div",{className:"bar-track","aria-hidden":"true",children:t.jsx("i",{style:{width:`${a.value/s*100}%`,backgroundColor:a.color??"#2563eb"}})}),t.jsx("strong",{children:n(a.value)})]},a.label))})}function P({label:e,value:n,detail:s}){return t.jsxs("span",{className:"drilldown-metric",children:[t.jsx("small",{children:e}),t.jsx("strong",{children:n}),t.jsx("em",{children:s})]})}function S({label:e,value:n}){return t.jsxs("div",{children:[t.jsx("dt",{children:e}),t.jsx("dd",{children:n})]})}function as({call:e,contextRuntime:n,onContextApiEnabledChange:s}){const a=ce(),[i,o]=c.useState(()=>en(e.id)??tt),[r,h]=c.useState({status:"idle"}),F=!!n.apiToken&&!n.fileMode,d=F&&n.contextApiEnabled;c.useEffect(()=>{const l=nt(e.id,i);h(l?{status:"loaded",payload:l}:{status:"idle"})},[e.id,i.includeCompactionHistory,i.includeToolOutput,i.maxChars,i.maxEntries,i.mode]);async function b(){h({status:"loading",message:"Enabling localhost context API..."});try{const l=await nn(n);s(l),h({status:"idle",message:l?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(l){h({status:"error",message:st(l)})}}async function j(l=i,p="Loading selected-turn evidence..."){at(e.id,l);const w=nt(e.id,l);if(w){h({status:"loaded",payload:w});return}h({status:"loading",message:p});try{const g=await sn(e.id,n,l);an(e.id,l,g),h({status:"loaded",payload:g})}catch(g){h({status:"error",message:st(g)})}}function C(){const l={...i,mode:"full"};o(l),j(l,"Loading full turn analysis...")}function D(l){const p=hn(l,i);o(p),j(p,"Loading older context...")}function N(){const l={...i,includeToolOutput:!0};o(l),j(l,"Loading omitted tool output...")}function y(){const l={...i,includeCompactionHistory:!0};o(l),j(l,"Loading compacted replacement...")}function m(l,p){o(w=>{const g={...w,[l]:p};return at(e.id,g),g})}return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"locked-context-card",children:[t.jsx(pt,{size:20}),t.jsxs("div",{children:[t.jsx("strong",{children:"Raw context is gated"}),t.jsx("p",{children:tn(n)})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Record id",value:e.id}),t.jsx(S,{label:"Time",value:e.time}),t.jsx(S,{label:"Thread",value:e.thread}),t.jsx(S,{label:"Model",value:e.model}),t.jsx(S,{label:"Effort",value:e.effort})]}),t.jsxs("div",{className:"context-action-grid",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:b,disabled:!F||n.contextApiEnabled||r.status==="loading",children:a.t("button.enable_context_loading","Enable context loading")}),t.jsx("button",{className:"primary-button",type:"button",onClick:()=>j(),disabled:!d||r.status==="loading",children:a.t("button.show_turn_evidence","Show turn log evidence")}),t.jsx("button",{className:"toolbar-button",type:"button",onClick:C,disabled:!d||r.status==="loading",children:a.t("button.full_serialized_analysis","Run full serialized analysis")}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Mode"}),t.jsxs("select",{"aria-label":"Side panel context mode",value:i.mode,disabled:!d||r.status==="loading",onChange:l=>m("mode",l.target.value==="full"?"full":"quick"),children:[t.jsx("option",{value:"quick",children:"Quick"}),t.jsx("option",{value:"full",children:"Full"})]})]}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Entries"}),t.jsxs("select",{"aria-label":"Side panel context entries",value:String(i.maxEntries),disabled:!d||r.status==="loading",onChange:l=>m("maxEntries",Number(l.target.value)),children:[t.jsx("option",{value:"20",children:"20"}),t.jsx("option",{value:"50",children:"50"}),t.jsx("option",{value:"100",children:"100"}),t.jsx("option",{value:"0",children:"All"})]})]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeToolOutput,disabled:!d||r.status==="loading",onChange:l=>m("includeToolOutput",l.target.checked)}),a.t("button.include_tool_output","Include tool output")]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeCompactionHistory,disabled:!d||r.status==="loading",onChange:l=>m("includeCompactionHistory",l.target.checked)}),"Include compaction history"]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.maxChars===0,disabled:!d||r.status==="loading",onChange:l=>m("maxChars",l.target.checked?0:tt.maxChars)}),a.t("button.no_char_limit","No char limit")]})]}),r.status==="idle"&&r.message?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="loading"?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="error"?t.jsx("p",{className:"context-state-note error",children:r.message}):null,r.status==="loaded"?t.jsx(is,{call:e,payload:r.payload,onLoadOlder:D,onRunFullAnalysis:C,onLoadCompactionHistory:y,onLoadToolOutput:N}):null,t.jsx("p",{className:"privacy-note",children:"Raw context is never embedded in the dashboard HTML. This view reads the selected local JSONL turn only after an explicit request."})]})}function is({call:e,payload:n,onLoadOlder:s,onRunFullAnalysis:a,onLoadCompactionHistory:i,onLoadToolOutput:o}){var _,T;const r=ce(),h=n.entries??[],F=n.omitted??{},d=Number(F.older_entries??0),b=on(n),j=8,C=e.id||String(n.record_id??""),[D,N]=c.useState(()=>it(C)),[y,m]=c.useState(()=>ot(C,h));c.useEffect(()=>{N(it(C)),m(ot(C,h))},[h.length,n.context_mode,n.include_compaction_history,n.include_tool_output,(_=n.omitted)==null?void 0:_.max_chars,(T=n.omitted)==null?void 0:T.max_entries,n.record_id,C]);const l=D?h:h.slice(0,j),p=Math.max(h.length-l.length,0);function w(){N(x=>{const L=!x;return xn(C,L),L})}function g(x,L){mn(C,x,L),m(v=>{const u=new Set(v);return L?u.add(x):u.delete(x),u})}return t.jsxs("div",{className:"context-evidence",children:[t.jsxs("div",{className:"context-evidence-summary",children:[t.jsx(P,{label:"Entries",value:O(h.length),detail:String(n.context_mode??"quick")}),t.jsx(P,{label:"Visible chars",value:O(Number(n.visible_char_count??0)),detail:"redacted local text"}),t.jsx(P,{label:"Visible tokens",value:O(Number(n.visible_token_estimate??0)),detail:"estimator"}),t.jsx(P,{label:"Older omitted",value:O(d),detail:"entry budget"})]}),b.length?t.jsx("p",{className:"context-note",children:b.join(" ")}):null,t.jsx(rn,{call:e,payload:n,onRunFullAnalysis:a}),d>0?t.jsx("div",{className:"context-followup-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>s(n),children:r.t("button.load_older_context","Load older entries")})}):null,t.jsxs("div",{className:"context-entry-list",children:[l.map((x,L)=>{const v=ln(x,L);return t.jsxs("details",{className:"context-entry",open:y.has(v),onToggle:u=>g(v,u.currentTarget.open),children:[t.jsx("summary",{className:"context-entry-summary",children:t.jsxs("div",{className:"context-entry-meta",children:[t.jsx("strong",{children:x.label||x.role||x.type||`Entry ${L+1}`}),t.jsx("span",{children:x.line_number?`line ${x.line_number}`:x.timestamp||"local evidence"})]})}),t.jsx(cn,{entry:x}),x.tool_output_omitted?t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:o,children:r.t("button.show_tool_output","Show tool output")})}):null,t.jsx(os,{entry:x,onLoadCompactionHistory:i}),t.jsx("pre",{ref:u=>{u&&(u.scrollTop=un(C,v))},onScroll:u=>dn(C,v,u.currentTarget.scrollTop),children:x.text||"[no visible text]"})]},v)}),h.length?null:t.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),h.length>j?t.jsxs("div",{className:"context-followup-actions",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:w,children:D?`Show first ${O(j)} entries`:`Show all ${O(h.length)} returned entries`}),D?null:t.jsxs("span",{className:"context-entry-count-note",children:[O(p)," entries hidden in compact view"]})]}):null]})}function os({entry:e,onLoadCompactionHistory:n}){const s=ce(),a=e.compaction;if(!(a!=null&&a.replacement_history_available))return null;const i=a.replacement_history??[],o=Number(a.replacement_entry_count??i.length);return t.jsxs("div",{className:"context-entry-compaction",children:[t.jsx("strong",{children:"Compaction detected"}),t.jsxs("span",{children:[O(o)," replacement history entries available."]}),i.length?t.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:i.map((r,h)=>t.jsxs("div",{className:"context-replacement-entry",children:[t.jsx("strong",{children:r.label||`Replacement item ${h+1}`}),t.jsx("pre",{children:r.text||"[no visible replacement text]"})]},`${r.label??"replacement"}-${h}`))}):t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}const rs=[{id:"summary",label:"Summary",icon:At},{id:"tokens",label:"Tokens",icon:ut},{id:"cache",label:"Cache",icon:Ot},{id:"thread",label:"Thread",icon:Sn},{id:"evidence",label:"Evidence",icon:pt}];function ls({call:e,calls:n,contextRuntime:s,includeArchived:a,sourceRevision:i,hydrateThreadCalls:o,onContextApiEnabledChange:r,onOpenInvestigator:h,onCopyCallLink:F}){const[d,b]=c.useState("summary"),[j,C]=c.useState(""),D=c.useMemo(()=>e?n.filter(m=>m.thread===e.thread).sort(Ie):[],[e,n]),N=Zt({...kt({runtime:s,includeArchived:a,sourceRevision:i,threadKey:(e==null?void 0:e.threadKey)||(e==null?void 0:e.thread)||"",selectedRecordId:(e==null?void 0:e.id)??"",selectedEventTimestamp:(e==null?void 0:e.eventTimestamp)??""}),enabled:o&&!s.fileMode&&!!s.apiToken&&!!e,placeholderData:m=>m}),y=c.useMemo(()=>{var l;const m=((l=N.data)==null?void 0:l.rows)??D;return!e||m.some(p=>p.id===e.id)?m:[...m,e].sort(Ie)},[e,D,N.data]);return e?t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsxs(Z,{title:"Call Drill-Down",subtitle:`${e.thread} / ${e.model}`,children:[t.jsxs("div",{className:"call-summary",children:[t.jsx(re,{label:"Aggregate only",tone:"green"}),t.jsx(Rt,{call:e}),t.jsx(re,{label:"Raw context gated",tone:"blue"}),t.jsx("span",{className:"call-id",children:e.id.slice(0,12)})]}),t.jsxs("div",{className:"action-row",children:[t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>h(e.id),children:[t.jsx(bn,{size:16}),"Open investigator"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>xs(e,C),children:[t.jsx(dt,{size:16}),"Copy link"]})]}),j?t.jsx("p",{className:"context-state-note",children:j}):null,t.jsx("div",{className:"drilldown-tabs",role:"tablist","aria-label":"Call drill-down sections",children:rs.map(m=>{const l=m.icon,p=d===m.id;return t.jsxs("button",{type:"button",role:"tab","aria-selected":p,className:p?"active":"",onClick:()=>b(m.id),children:[t.jsx(l,{size:14}),m.label]},m.id)})}),t.jsxs("div",{className:"drilldown-tab-panel",role:"tabpanel",children:[d==="summary"?t.jsx(cs,{call:e}):null,d==="tokens"?t.jsx(us,{call:e}):null,d==="cache"?t.jsx(hs,{call:e,calls:y}):null,d==="thread"?t.jsx(ms,{call:e,calls:y,onOpenInvestigator:h,onCopyCallLink:F}):null,d==="evidence"?t.jsx(as,{call:e,contextRuntime:s,onContextApiEnabledChange:r},e.id):null]})]})}):t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsx(Z,{title:"Call Drill-Down",subtitle:"No matching call",children:t.jsx("p",{className:"empty-state",children:"No aggregate row matches the active filters."})})})}function cs({call:e}){return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Total tokens",value:O(e.totalTokens),detail:`${ee(e.input)} input`}),t.jsx(P,{label:"Uncached input",value:O(e.uncachedInput),detail:"fresh billed input"}),t.jsx(P,{label:"Cache hit rate",value:q(e.cachedPct),detail:Oe(e)}),t.jsx(P,{label:"Estimated cost",value:Ae(e.cost),detail:e.pricingEstimated?"estimated pricing":"configured pricing"}),t.jsx(P,{label:"Duration",value:e.duration,detail:e.fast?"fast candidate":"normal throughput"}),t.jsx(P,{label:"Usage credits",value:e.credits?e.credits.toFixed(3):"-",detail:e.usageCreditConfidence})]}),t.jsx(pn,{call:e}),t.jsx(fn,{call:e}),t.jsx(ds,{call:e}),t.jsx(St,{call:e}),t.jsx(wt,{call:e}),e.recommendation?t.jsxs("div",{className:"recommendation-box",children:[t.jsx(Cn,{size:16}),t.jsx("p",{children:e.recommendation})]}):null]})}function ds({call:e}){return t.jsxs("div",{className:"composition-card accounting-snapshot-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Accounting Snapshot"}),t.jsx("span",{children:"pricing, credits, and cache savings"})]}),t.jsx(xt,{call:e})]})}function us({call:e}){return t.jsxs(t.Fragment,{children:[t.jsx(St,{call:e}),t.jsx(xt,{call:e})]})}function hs({call:e,calls:n}){return t.jsxs(t.Fragment,{children:[t.jsx(wt,{call:e}),t.jsx(gn,{call:e,calls:n}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Cache state",value:Oe(e)}),t.jsx(S,{label:"Cache hit rate",value:q(e.cachedPct)}),t.jsx(S,{label:"Fresh share",value:q(Math.max(100-e.cachedPct,0))}),t.jsx(S,{label:"Signal",value:e.signal})]}),t.jsx("p",{className:"privacy-note",children:"Use this readout to decide whether the aggregate call needs deeper raw-context investigation."})]})}function ms({call:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a}){const i=n.reduce((b,j)=>b+j.totalTokens,0),o=n.reduce((b,j)=>b+j.cost,0),r=n.reduce((b,j)=>b+j.cachedPct,0)/Math.max(n.length,1),h=Math.max(n.findIndex(b=>b.id===e.id),0),F=Math.min(Math.max(n.length,1),5),d=e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available";return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Loaded thread calls",value:O(n.length),detail:`selected ${h+1} of ${n.length}`}),t.jsx(P,{label:"Thread tokens",value:ee(i),detail:"loaded aggregate rows"}),t.jsx(P,{label:"Thread cost",value:Ae(o),detail:"estimated aggregate"}),t.jsx(P,{label:"Avg cache",value:q(r),detail:jn(n.map(b=>b.model),{style:"x",emptyLabel:"no model mix"})}),t.jsx(P,{label:"Context window",value:e.contextWindowPct===null?"-":q(e.contextWindowPct),detail:e.modelContextWindow?`${ee(e.modelContextWindow)} window`:"not reported"}),t.jsx(P,{label:"Parent thread",value:e.parentThread||"-",detail:e.parentSessionId||"no parent session"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Thread timeline"}),t.jsxs("span",{children:[F," nearby loaded calls"]})]}),t.jsx(vn,{selectedCall:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a,copyAriaContext:"side-panel thread call"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Call Narrative"}),t.jsx("span",{children:e.initiatorConfidence||"aggregate inference"})]}),t.jsxs("dl",{className:"detail-list compact",children:[t.jsx(S,{label:"Initiated by",value:e.initiator||"unknown"}),t.jsx(S,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),t.jsx(S,{label:"Parent thread",value:e.parentThread||"None"}),t.jsx(S,{label:"Parent session",value:e.parentSessionId||"None"}),t.jsx(S,{label:"Timestamp",value:e.time}),t.jsx(S,{label:"Duration",value:e.duration}),t.jsx(S,{label:"Previous gap",value:e.previousCallGap})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Project",value:e.project||"Unknown"}),t.jsx(S,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),t.jsx(S,{label:"Source line",value:d}),t.jsx(S,{label:"Session",value:e.sessionId||"Not available"}),t.jsx(S,{label:"Git branch",value:e.gitBranch||"Unknown"}),t.jsx(S,{label:"Remote",value:e.gitRemoteLabel||e.gitRemoteHash||"None"})]})]})}function St({call:e}){const s=[{label:"Cached input",value:Math.max(e.input-e.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:e.uncachedInput,color:"#f59e0b"},{label:"Output",value:e.output,color:"#059669"},{label:"Reasoning",value:e.reasoningOutput,color:"#7c3aed"}].filter(i=>i.value>0),a=Math.max(s.reduce((i,o)=>i+o.value,0),1);return t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Token composition"}),t.jsxs("span",{children:[ee(a)," visible tokens"]})]}),t.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(i=>t.jsx("i",{style:{width:`${Math.max(i.value/a*100,3)}%`,background:i.color}},i.label))}),t.jsx("div",{className:"composition-legend",children:s.map(i=>t.jsxs("span",{children:[t.jsx("i",{style:{background:i.color}}),i.label]},i.label))})]})}function wt({call:e}){const n=[{label:"Cache",value:Math.min(Math.max(e.cachedPct,0),100),color:"#2563eb"},{label:"Fresh",value:Math.min(Math.max(100-e.cachedPct,0),100),color:"#f59e0b"},{label:"Output",value:Math.min(Math.max(e.output/Math.max(e.totalTokens,1)*100,0),100),color:"#059669"}];return t.jsxs("div",{className:"cache-mini-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"Cache delta readout"}),t.jsx("span",{children:Oe(e)})]}),t.jsx("div",{className:"cache-bars","aria-label":"Cache delta readout",children:n.map(s=>t.jsxs("span",{children:[t.jsx("i",{style:{height:`${Math.max(s.value,4)}%`,background:s.color}}),t.jsx("em",{children:s.label})]},s.label))})]})}async function xs(e,n){try{const s=new URL(window.location.href);if(s.searchParams.set("view","call"),s.searchParams.set("record",e.id),s.searchParams.set("return","calls"),!await ht(s.toString()))throw new Error("Clipboard unavailable");n("Copied investigator link")}catch{n("Copy unavailable in this browser")}}const ps="_page_gyxvc_1",fs="_pageHeader_gyxvc_5",gs="_tableHeading_gyxvc_13",js="_eyebrow_gyxvc_22",vs="_headerActions_gyxvc_36",bs="_tableActions_gyxvc_37",Cs="_gridFooter_gyxvc_38",ys="_queryBar_gyxvc_46",Ss="_advancedFilters_gyxvc_80",ws="_patternsDisclosure_gyxvc_85",Fs="_advancedFilterGrid_gyxvc_107",Ns="_gridColumn_gyxvc_138",$={page:ps,pageHeader:fs,tableHeading:gs,eyebrow:js,headerActions:vs,tableActions:bs,gridFooter:Cs,queryBar:ys,advancedFilters:Ss,patternsDisclosure:ws,advancedFilterGrid:Fs,gridColumn:Ns};function Es({searchInputRef:e,localQuery:n,modelFilter:s,effortFilter:a,confidenceFilter:i,sourceFilter:o,timeFilter:r,dateStart:h,dateEnd:F,sortKey:d,sortDirection:b,modelOptions:j,effortOptions:C,sourceCoverage:D,dateRangeStatus:N,onLocalQueryChange:y,onModelFilterChange:m,onEffortFilterChange:l,onConfidenceFilterChange:p,onSourceFilterChange:w,onTimeFilterChange:g,onDateStartChange:_,onDateEndChange:T,onSortKeyChange:x,onSortDirectionChange:L,onClear:v}){return t.jsxs("section",{className:$.queryBar,"aria-label":"Call filters",children:[t.jsxs("label",{className:"search-box",children:[t.jsx("span",{className:"sr-only",children:"Search calls"}),t.jsx("input",{ref:e,value:n,onChange:u=>y(u.target.value),placeholder:"Search calls, cwd, projects, models..."})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Model"}),t.jsxs("select",{value:s,onChange:u=>m(u.target.value),children:[t.jsx("option",{value:"all",children:"All models"}),j.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Effort"}),t.jsxs("select",{value:a,onChange:u=>l(u.target.value),children:[t.jsx("option",{value:"all",children:"All effort"}),C.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Confidence"}),t.jsxs("select",{"aria-label":"Confidence filter",value:i,onChange:u=>p(u.target.value),children:[t.jsx("option",{value:"all",children:"All confidence"}),t.jsx("option",{value:"cost-exact",children:"Exact cost"}),t.jsx("option",{value:"cost-estimated",children:"Estimated cost"}),t.jsx("option",{value:"cost-unpriced",children:"Unpriced cost"}),t.jsx("option",{value:"credit-exact",children:"Exact credit rate"}),t.jsx("option",{value:"credit-estimated",children:"Estimated credit mapping"}),t.jsx("option",{value:"credit-override",children:"User credit override"}),t.jsx("option",{value:"credit-missing",children:"Missing credit rate"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Time"}),t.jsxs("select",{"aria-label":"Time filter",value:r,onChange:u=>g(u.target.value),children:[t.jsx("option",{value:"all",children:"All time"}),t.jsx("option",{value:"today",children:"Today"}),t.jsx("option",{value:"this-week",children:"This week"}),t.jsx("option",{value:"last-7-days",children:"Last 7 days"}),t.jsx("option",{value:"this-month",children:"This month"}),t.jsx("option",{value:"custom",children:"Custom range"})]}),N.active||N.invalid?t.jsx("span",{className:"filter-status","data-state":N.invalid?"error":"active","aria-live":"polite",children:N.label}):null]}),t.jsxs("details",{className:$.advancedFilters,children:[t.jsxs("summary",{children:[t.jsx(Bt,{size:16}),"More filters"]}),t.jsxs("div",{className:$.advancedFilterGrid,children:[t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Source"}),t.jsxs("select",{"aria-label":"Source filter",value:o,onChange:u=>w(u.target.value),children:[t.jsx("option",{value:"all",children:"All sources"}),t.jsx("option",{value:"project",children:"Project / cwd"}),t.jsx("option",{value:"session",children:"Session-linked"}),t.jsx("option",{value:"git",children:"Git metadata"}),t.jsx("option",{value:"source-file",children:"Source file"}),t.jsx("option",{value:"missing",children:"Missing source"})]}),t.jsx("span",{className:"filter-status","data-state":o==="all"?"active":"filtered","aria-live":"polite",children:En(D,o)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Start"}),t.jsx("input",{"aria-label":"Start date",type:"date",value:h,onChange:u=>_(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"End"}),t.jsx("input",{"aria-label":"End date",type:"date",value:F,onChange:u=>T(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Sort"}),t.jsxs("select",{"aria-label":"Sort calls",value:d,onChange:u=>x(u.target.value),children:[t.jsx("option",{value:"time",children:"Newest calls"}),t.jsx("option",{value:"duration",children:"Longest duration"}),t.jsx("option",{value:"gap",children:"Longest gap"}),t.jsx("option",{value:"attention",children:"Needs attention"}),t.jsx("option",{value:"thread",children:"Thread name"}),t.jsx("option",{value:"initiator",children:"Initiated"}),t.jsx("option",{value:"model",children:"Model"}),t.jsx("option",{value:"effort",children:"Reasoning"}),t.jsx("option",{value:"total",children:"Most tokens"}),t.jsx("option",{value:"cached",children:"Cached"}),t.jsx("option",{value:"uncached",children:"Uncached"}),t.jsx("option",{value:"output",children:"Output"}),t.jsx("option",{value:"reasoning",children:"Reasoning output"}),t.jsx("option",{value:"cost",children:"Highest estimated cost"}),t.jsx("option",{value:"usage",children:"Highest Codex credits"}),t.jsx("option",{value:"cache",children:"Lowest cache ratio"}),t.jsx("option",{value:"context",children:"Highest context use"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Direction"}),t.jsxs("select",{"aria-label":"Sort direction",value:b,onChange:u=>L(u.target.value),children:[t.jsx("option",{value:"desc",children:"Descending"}),t.jsx("option",{value:"asc",children:"Ascending"})]})]})]})]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:v,children:[t.jsx(Vt,{size:16}),"Clear filters"]})]})}function Ts({workspaceSwitcher:e,canExport:n,onExport:s,onCopyView:a,onRefresh:i}){return t.jsxs("header",{className:$.pageHeader,children:[t.jsxs("div",{children:[t.jsx("p",{className:$.eyebrow,children:"Evidence explorer"}),t.jsx("h1",{children:"Calls"}),t.jsx("p",{children:"Find expensive, cold, or context-heavy calls and move directly into their evidence."})]}),t.jsxs("div",{className:$.headerActions,children:[e,t.jsxs("button",{className:"toolbar-button",type:"button",onClick:s,disabled:!n,children:[t.jsx(Ht,{size:16}),"Export"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:a,children:[t.jsx(dt,{size:16}),"Copy view"]}),t.jsxs("button",{className:"primary-button",type:"button",onClick:i,children:[t.jsx(Kt,{size:16}),"Refresh"]})]})]})}const Ft="codexUsageDetailPanel";function Ms(e=!1){var n;try{const s=(n=window.sessionStorage)==null?void 0:n.getItem(Ft);return s?s==="expanded":e}catch{return e}}function Ds(e){var n;try{(n=window.sessionStorage)==null||n.setItem(Ft,e?"expanded":"collapsed")}catch{}}const B=250;function Ps(e,n){const s=E("density"),[a,i]=c.useState(()=>E("call_q")),[o,r]=c.useState(()=>E("model")||"all"),[h,F]=c.useState(()=>E("effort")||"all"),[d,b]=c.useState(()=>gt()),[j,C]=c.useState(()=>jt()),[D,N]=c.useState(()=>vt()),[y,m]=c.useState(()=>le("from")),[l,p]=c.useState(()=>le("to")),[w,g]=c.useState(()=>Pe()),[_,T]=c.useState(()=>Ct(Pe())),x=yn("codexUsageCallsEvidenceGrid",{density:On()==="dense"?"compact":"comfortable",columnVisibility:{}},s==="roomy"?"comfortable":s==="dense"?"compact":void 0),L=x.density==="compact"?"dense":"roomy",v=c.useMemo(()=>An(),[]),[u,te]=c.useState(v),[G,R]=c.useState(()=>Bn(B)),[ne,Q]=c.useState(""),[de,ue]=c.useState(""),[W,he]=c.useState(()=>Ms(!!v)),me=c.useRef(null),se=c.useRef(n),xe=c.useMemo(()=>Ze(e.calls.map(f=>f.model)),[e.calls]),pe=c.useMemo(()=>Ze(e.calls.map(f=>f.effort)),[e.calls]),fe=c.useMemo(()=>Dn(e.calls),[e.calls]),Y=c.useMemo(()=>ze(D,y,l,new Date),[l,y,D]);c.useEffect(()=>{se.current!==n&&(se.current=n,R(B))},[n]);function I(){R(B)}function ge(f){i(f),I()}function je(f){r(f),I()}function ve(f){F(f),I()}function be(f){b(f),I()}function Ce(f){C(f),I()}function ye(f){N(f),I()}function Se(f){m(Le(f)),N("custom"),I()}function we(f){p(Le(f)),N("custom"),I()}function Fe(f){const A=bt(f);g(A),T(U(A)),I()}function Ne(f){T(f==="asc"?"asc":"desc"),I()}function Ee(){i(""),r("all"),F("all"),b("all"),C("all"),N("all"),m(""),p(""),g("time"),T(U("time")),x.setDensity("compact"),x.setColumnVisibility({}),te(null),R(B),window.history.replaceState(null,"",_e({localQuery:"",modelFilter:"all",effortFilter:"all",confidenceFilter:"all",sourceFilter:"all",timeFilter:"all",dateStart:"",dateEnd:"",sortKey:"time",sortDirection:U("time"),density:"dense",selectedRecordId:"",visibleRowCount:B,pageSize:B})),ue("Calls filters cleared")}function Te(){he(f=>{const A=!f;return Ds(A),A})}return{localQuery:a,modelFilter:o,effortFilter:h,confidenceFilter:d,sourceFilter:j,timeFilter:D,dateStart:y,dateEnd:l,sortKey:w,setSortKey:g,sortDirection:_,setSortDirection:T,gridPreferences:x,density:L,initialSelectedCallId:v,selectedCallId:u,setSelectedCallId:te,visibleCallRows:G,setVisibleCallRows:R,exportStatus:ne,setExportStatus:Q,filterStatus:de,detailsExpanded:W,searchInputRef:me,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Ee,toggleCallDetails:Te}}function _s({model:e,header:n,filters:s,table:a,inspector:i}){var F;const o=ce(),r=o.t("dashboard.model_calls","Model Calls"),h=o.t("dashboard.model_calls","Model calls");return t.jsxs("div",{className:`${$.page} page-grid`,children:[t.jsx(Ts,{...n}),t.jsx(Es,{...s}),t.jsxs("div",{className:$.tableHeading,children:[t.jsxs("div",{children:[t.jsx("h2",{children:r}),t.jsx("p",{children:a.exportStatus||a.filterStatus||a.subtitle})]}),t.jsxs("div",{className:$.tableActions,children:[t.jsx(re,{label:Ls(a.isFetching,a.focused,a.focusedReason),tone:a.focused?"green":"blue"}),t.jsx(re,{label:a.activePreset?`Preset: ${mt(a.activePreset)}`:"Raw context gated",tone:a.activePreset?"green":"blue"}),t.jsxs("button",{className:"toolbar-button",type:"button","aria-expanded":a.detailsExpanded,onClick:a.onToggleDetails,children:[a.detailsExpanded?t.jsx(wn,{size:16}):t.jsx(Fn,{size:16}),a.detailsExpanded?o.t("button.hide_details","Hide details"):o.t("dashboard.call_details","Call Details")]})]})]}),t.jsxs("div",{className:a.detailsExpanded?"table-detail-layout":"table-detail-layout detail-collapsed",children:[t.jsxs("div",{className:$.gridColumn,children:[t.jsx(Yt,{ariaLabel:h,columns:a.columns,data:a.calls,identityColumnId:"thread",lockedColumnIds:["investigate"],getRowId:d=>d.id,mobile:{primary:d=>d.thread,secondary:d=>o.translateText(`${d.time} · ${d.model} · ${ee(d.totalTokens)} tokens · ${q(d.cachedPct)} cache`),actionLabel:d=>Xt(d)},sorting:a.sorting,onSortingChange:a.onSortingChange,manualSorting:!0,columnVisibility:a.gridPreferences.columnVisibility,onColumnVisibilityChange:a.gridPreferences.setColumnVisibility,density:a.gridPreferences.density,onDensityChange:a.gridPreferences.setDensity,onRestoreDefaults:a.gridPreferences.restoreDefaults,selectedRowId:(F=a.selectedCall)==null?void 0:F.id,onRowSelect:d=>a.onSelectCall(d.id),onRowActivate:d=>i.onOpenInvestigator(d.id),activateOnClick:!0,selectOnHover:!0,viewportHeight:560,emptyLabel:"No rows match current filters."}),t.jsxs("div",{className:$.gridFooter,"aria-live":"polite",children:[t.jsx("span",{children:o.translateText(`${a.calls.length.toLocaleString()} loaded / ${a.totalMatchedCalls.toLocaleString()} matched`)}),a.focused&&a.hasNextPage?t.jsx("button",{className:"toolbar-button",type:"button",onClick:a.onLoadMore,disabled:a.isFetchingNextPage,children:a.isFetchingNextPage?"Loading more...":`Load ${B.toLocaleString()} more`}):null]})]}),a.detailsExpanded?t.jsx(ls,{call:a.selectedCall,calls:e.calls,...i}):null]}),t.jsxs("details",{className:$.patternsDisclosure,children:[t.jsxs("summary",{children:[t.jsx(ut,{size:17}),"Usage patterns"]}),t.jsxs("div",{className:"dashboard-grid three",children:[t.jsx(Z,{title:"Usage Over Time",subtitle:"Tokens",children:t.jsx(et,{series:e.tokenSeries,yLabel:"Tokens",height:220})}),t.jsx(Z,{title:"Cost by Model",subtitle:"Estimated USD",children:t.jsx(ss,{data:e.modelCosts,valueLabel:Ae})}),t.jsx(Z,{title:"Cache Hit Rate Over Time",subtitle:o.translateText("Daily"),children:t.jsx(et,{series:e.cacheSeries,yLabel:"Cache %",height:220,valueFormatter:d=>`${d}%`})})]})]})]})}function Ls(e,n,s){return e&&n?"Updating focused rows":e?"Loading focused rows":n?"Focused paged API":s||"Stored snapshot"}function ia(e,n="",s=""){const a=Pe();return ke(yt(e,{globalQuery:n,localQuery:E("call_q"),modelFilter:E("model")||"all",effortFilter:E("effort")||"all",confidenceFilter:gt(),sourceFilter:jt(),timeFilter:vt(),dateStart:le("from"),dateEnd:le("to"),activePreset:s}),a,Ct(a))}const Nt={time:"time",duration:"duration",gap:"previousCallGap",attention:"signal",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"totalTokens",cached:"cachedInput",uncached:"uncachedInput",output:"output",reasoning:"reasoningOutput",cost:"cost",usage:"credits",cache:"cachedPct",context:"contextWindowPct"},ks=Object.fromEntries(Object.entries(Nt).map(([e,n])=>[n,e]));function oa({model:e,globalQuery:n,activePreset:s,onRefresh:a,contextRuntime:i,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h,includeArchived:F=!1,sourceKey:d,sourceRevision:b="",scopeSince:j=null,focusedEndpointsEnabled:C=!0,workspaceSwitcher:D}){var We,Ye;const N=Ps(e,n),{localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:T,sortKey:x,setSortKey:L,sortDirection:v,setSortDirection:u,gridPreferences:te,density:G,selectedCallId:R,setSelectedCallId:ne,visibleCallRows:Q,setVisibleCallRows:de,exportStatus:ue,setExportStatus:W,filterStatus:he,detailsExpanded:me,searchInputRef:se,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Ee,toggleCallDetails:Te}=N,f=c.useMemo(()=>[...zt,Jt({onOpenInvestigator:r,onCopyCallLink:h})],[h,r]),A=c.useMemo(()=>Zn({runtime:i,enabled:C,activePreset:s,sourceFilter:w,sortKey:x,scopeSince:j,timeFilter:g,dateStart:_,dateEnd:T,confidenceFilter:p,globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l}),[s,p,i,T,_,l,C,n,y,m,x,w,j,g]),V=Lt({...It({runtime:i,includeArchived:F,sourceKey:d,sourceRevision:b,filters:A.filters,sort:A.sort,direction:v,pageSize:B}),enabled:A.enabled,placeholderData:M=>M}),Ue=c.useMemo(()=>yt(e.calls,{globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:T,activePreset:s}),[s,p,T,_,l,n,y,e.calls,m,w,g]),qe=c.useMemo(()=>ke(Ue,x,v),[Ue,v,x]),Ge=c.useMemo(()=>{var M;return((M=V.data)==null?void 0:M.pages.flatMap(X=>X.rows))??[]},[V.data]),ae=A.enabled&&!!V.data,H=c.useMemo(()=>ae?ke(Ge,x,v):qe,[Ge,qe,v,x,ae]),Me=ae?((Ye=(We=V.data)==null?void 0:We.pages[0])==null?void 0:Ye.totalMatchedRows)??H.length:e.calls.length,Et=c.useMemo(()=>Nn({shownCount:H.length,totalCount:Me,localQuery:y,globalQuery:n,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateRangeStatus:Y,activePresetLabel:s?mt(s):""}),[s,p,Y,l,n,y,m,H.length,w,g,Me]),Qe=c.useMemo(()=>[{id:Nt[x],desc:v==="desc"}],[v,x]),ie=R===oe?H[0]??null:H.find(M=>M.id===R)??H[0]??null,z=ie&&(ie.id===R||R===oe)?ie.id:"";c.useEffect(()=>{R===oe&&z&&ne(z)},[R,z]),c.useEffect(()=>{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:T,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});M.toString()!==window.location.href&&window.history.replaceState(null,"",M)},[p,T,_,G,l,y,m,z,v,x,w,g,Q]);function Tt(){Ut(`codex-calls-${Qt()}.csv`,qt(H,Gt)),W(`Exported ${H.length} calls`)}async function Mt(){try{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:T,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});if(!await ht(M.toString()))throw new Error("Clipboard unavailable");W("Copied Calls view link")}catch{W("Copy unavailable in browser")}}function Dt(M){var Xe,Je;const X=typeof M=="function"?M(Qe):M,De=ks[((Xe=X[0])==null?void 0:Xe.id)??""]??"time",_t=De!==x;L(De),u(_t?U(De):(Je=X[0])!=null&&Je.desc?"desc":"asc"),I()}async function Pt(){!V.hasNextPage||V.isFetchingNextPage||(await V.fetchNextPage(),de(M=>M+B))}return t.jsx(_s,{model:e,header:{workspaceSwitcher:D,canExport:!!H.length,onExport:Tt,onCopyView:Mt,onRefresh:a},filters:{searchInputRef:se,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:T,sortKey:x,sortDirection:v,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,onLocalQueryChange:ge,onModelFilterChange:je,onEffortFilterChange:ve,onConfidenceFilterChange:be,onSourceFilterChange:Ce,onTimeFilterChange:ye,onDateStartChange:Se,onDateEndChange:we,onSortKeyChange:Fe,onSortDirectionChange:Ne,onClear:Ee},table:{activePreset:s,exportStatus:ue,filterStatus:he,subtitle:Et,focused:ae,focusedReason:A.reason,isFetching:V.isFetching,isFetchingNextPage:V.isFetchingNextPage,hasNextPage:!!V.hasNextPage,detailsExpanded:me,calls:H,totalMatchedCalls:Me,columns:f,sorting:Qe,gridPreferences:te,selectedCall:ie,onSortingChange:Dt,onSelectCall:ne,onLoadMore:Pt,onToggleDetails:Te},inspector:{contextRuntime:i,includeArchived:F,sourceRevision:b,hydrateThreadCalls:C,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h}})}export{oa as CallsPage,ia as callsForCurrentUrl}; + */const Nn=Re("PanelRightOpen",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m10 15-3-3 3-3",key:"1pgupc"}]]);function Tn(e){const n=[],s=[e.localQuery.trim(),e.globalQuery.trim()].filter(Boolean);s.length&&n.push(`Search ${s.map(i=>`"${i}"`).join(" + ")}`),e.modelFilter!=="all"&&n.push(`Model ${e.modelFilter}`),e.effortFilter!=="all"&&n.push(`Effort ${e.effortFilter}`),e.confidenceFilter!=="all"&&n.push(`Confidence ${_n(e.confidenceFilter)}`),e.sourceFilter!=="all"&&n.push(`Source ${Ln(e.sourceFilter)}`),e.dateRangeStatus.invalid?n.push("Date range invalid"):(e.dateRangeStatus.active||e.timeFilter!=="all")&&n.push(e.dateRangeStatus.label||kn(e.timeFilter)),e.activePresetLabel&&n.push(`Preset ${e.activePresetLabel}`);const a=`Showing ${e.shownCount.toLocaleString()} of ${e.totalCount.toLocaleString()} aggregate rows`;return n.length?`${a} - Filters: ${n.join("; ")}`:a}function En(e,n){return n==="project"?`${e.project.toLocaleString()} project/cwd rows`:n==="session"?`${e.session.toLocaleString()} session-linked rows`:n==="git"?`${e.git.toLocaleString()} git rows`:n==="source-file"?`${e.sourceFile.toLocaleString()} source-file rows`:n==="missing"?`${e.missing.toLocaleString()} rows missing source`:`${e.project.toLocaleString()} project, ${e.session.toLocaleString()} session, ${e.git.toLocaleString()} git`}function Mn(e,n){return n==="all"?!0:n==="project"?Be(e):n==="session"?Ve(e):n==="git"?He(e):n==="source-file"?Ke(e):!ft(e)}function Dn(e,n){if(n==="all")return!0;if(n==="cost-exact")return!e.pricingEstimated&&Number.isFinite(e.cost)&&e.cost>0;if(n==="cost-estimated")return e.pricingEstimated;if(n==="cost-unpriced")return!e.pricingEstimated&&(!Number.isFinite(e.cost)||e.cost<=0);const s=e.usageCreditConfidence.toLowerCase();return n==="credit-exact"?s.includes("exact"):n==="credit-override"?s.includes("override"):n==="credit-estimated"?s.includes("estimated"):s.includes("missing")||s.includes("unpriced")}function Pn(e){return e.reduce((n,s)=>({project:n.project+(Be(s)?1:0),session:n.session+(Ve(s)?1:0),git:n.git+(He(s)?1:0),sourceFile:n.sourceFile+(Ke(s)?1:0),missing:n.missing+(ft(s)?0:1),total:n.total+1}),{project:0,session:0,git:0,sourceFile:0,missing:0,total:0})}function Be(e){return!!(e.project||e.projectRelativeCwd||e.cwd||e.projectTags.length)}function Ve(e){return!!(e.sessionId||e.turnId||e.parentSessionId)}function He(e){return!!(e.gitBranch||e.gitRemoteLabel||e.gitRemoteHash)}function Ke(e){return!!(e.sourceFile||e.lineNumber!==null)}function ft(e){return Be(e)||Ve(e)||He(e)||Ke(e)}function _n(e){return e==="cost-exact"?"exact cost":e==="cost-estimated"?"estimated cost":e==="cost-unpriced"?"unpriced cost":e==="credit-exact"?"exact credit rate":e==="credit-estimated"?"estimated credit mapping":e==="credit-override"?"user credit override":"missing credit rate"}function Ln(e){return e==="project"?"project/cwd":e==="session"?"session-linked":e==="git"?"git metadata":e==="source-file"?"source file":"missing source"}function kn(e){return e==="today"?"Today":e==="this-week"?"This week":e==="last-7-days"?"Last 7 days":e==="this-month"?"This month":e==="custom"?"Custom date range":"All time"}const oe="__detail_first__",In=new Set(["all","cost-exact","cost-estimated","cost-unpriced","credit-exact","credit-estimated","credit-override","credit-missing"]),$n=new Set(["all","today","this-week","last-7-days","this-month","custom"]),Rn=new Set(["all","project","session","git","source-file","missing"]),An=new Set(["time","duration","gap","attention","thread","initiator","model","effort","total","cached","uncached","output","reasoning","cost","usage","cache","context"]);function T(e,n=window.location.href){var s;return((s=new URL(n).searchParams.get(e))==null?void 0:s.trim())??""}function gt(e=window.location.href){const n=T("confidence",e)||T("pricing",e),s=Kn(n);return In.has(s)?s:"all"}function jt(e=window.location.href){const n=T("source",e);return Rn.has(n)?n:"all"}function vt(e=window.location.href){const n=T("date",e)||T("time",e);return $n.has(n)?n:"all"}function le(e,n=window.location.href){return Le(T(e,n))}function On(e=window.location.href){const n=T("record",e);return n||(T("detail",e)==="first"?oe:null)}function Pe(e=window.location.href){const n=T("sort",e);return bt(n)}function bt(e){return An.has(e)?e:"time"}function Ct(e,n=window.location.href){const s=T("direction",n);return s==="asc"||s==="desc"?s:U(e)}function Bn(e=window.location.href){return T("density",e)==="roomy"?"roomy":"dense"}function Vn(e,n=window.location.href){const s=Number(T("page",n)||1);return Number.isFinite(s)&&s>1?Math.floor(s)*e:e}function _e(e,n=window.location.href){const s=new URL(n);return s.searchParams.set("view","calls"),s.searchParams.delete("detail"),s.searchParams.delete("pricing"),k(s,"record",e.selectedRecordId,""),k(s,"call_q",e.localQuery.trim(),""),k(s,"model",e.modelFilter,"all"),k(s,"effort",e.effortFilter,"all"),k(s,"confidence",e.confidenceFilter,"all"),k(s,"source",e.sourceFilter,"all"),k(s,"time",e.timeFilter,"all"),k(s,"date",e.timeFilter,"all"),k(s,"from",e.timeFilter==="custom"?e.dateStart:"",""),k(s,"to",e.timeFilter==="custom"?e.dateEnd:"",""),k(s,"sort",e.sortKey,"time"),k(s,"direction",e.sortDirection,U(e.sortKey)),k(s,"density",e.density,"dense"),k(s,"page",String(Hn(e.visibleRowCount,e.pageSize)),"1"),s}function U(e){return e==="cache"||e==="effort"||e==="initiator"||e==="model"||e==="thread"?"asc":"desc"}function Le(e){const n=zn(e);return n?Un(n):""}function Hn(e,n){return Math.max(1,Math.ceil(Math.max(e,n)/n))}function k(e,n,s,a){if(!s||s===a){e.searchParams.delete(n);return}e.searchParams.set(n,s)}function Kn(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":e}function zn(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function Un(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(e,n){return e.filter(s=>qn(s,n))}function ke(e,n,s){return[...e].sort((a,i)=>Gn(a,i,n,s))}function ze(e,n,s,a){const i=Yn(a);if(e==="custom"){const o=lt(n),r=lt(s);return o&&r&&o>r?{active:!0,invalid:!0,start:o,endExclusive:K(r,1),label:"Invalid date range"}:{active:!!(o||r),invalid:!1,start:o,endExclusive:r?K(r,1):null,label:J("Custom",o,r)}}if(e==="today")return{active:!0,invalid:!1,start:i,endExclusive:K(i,1),label:J("Today",i,i)};if(e==="this-week"){const o=Xn(i);return{active:!0,invalid:!1,start:o,endExclusive:K(o,7),label:J("This week",o,K(o,6))}}if(e==="last-7-days"){const o=K(i,-6);return{active:!0,invalid:!1,start:o,endExclusive:K(i,1),label:J("Last 7 days",o,i)}}if(e==="this-month"){const o=new Date(i.getFullYear(),i.getMonth(),1),r=new Date(i.getFullYear(),i.getMonth()+1,1);return{active:!0,invalid:!1,start:o,endExclusive:r,label:J("This month",o,K(r,-1))}}return{active:!1,invalid:!1,start:null,endExclusive:null,label:"All time"}}function qn(e,n){if(n.modelFilter!=="all"&&e.model!==n.modelFilter||n.effortFilter!=="all"&&e.effort!==n.effortFilter||!Dn(e,n.confidenceFilter)||!Mn(e,n.sourceFilter)||!Jn(e,n.timeFilter,n.dateStart,n.dateEnd)||n.activePreset&&!$t(e,n.activePreset))return!1;const s=[e.thread,e.cwd,e.project,e.projectRelativeCwd,e.gitBranch,e.gitRemoteLabel,e.sessionId,e.model,e.effort,e.initiator,e.initiatorReason,e.signal,e.recommendation,e.rawTime,e.sourceFile,e.lineNumber,e.tags.join(" ")];return[n.globalQuery,n.localQuery].every(a=>Yt(s,a))}function Gn(e,n,s,a){const i=rt(e,s),o=rt(n,s);if(i===null&&o!==null)return 1;if(o===null&&i!==null)return-1;const r=Wn(i,o);return r!==0?a==="asc"?r:-r:Ie(e,n)||e.id.localeCompare(n.id)}function rt(e,n){return n==="time"?$e(e):n==="duration"?e.durationSeconds:n==="gap"?e.previousCallGapSeconds:n==="attention"?Qn(e):n==="thread"?e.thread.toLowerCase():n==="initiator"?e.initiator.toLowerCase():n==="model"?e.model.toLowerCase():n==="effort"?e.effort.toLowerCase():n==="total"?e.totalTokens:n==="cached"?e.input*(e.cachedPct/100):n==="uncached"?e.uncachedInput:n==="output"?e.output:n==="reasoning"?e.reasoningOutput:n==="cost"?e.cost:n==="usage"?e.credits:n==="cache"?e.cachedPct:e.contextWindowPct}function Qn(e){const n=e.signal&&e.signal!=="aggregate"?1e3:0,s=e.recommendation?750:0,a=e.contextWindowPct??0,i=Math.min(e.uncachedInput/1e3,250),o=Math.min(e.cost*25,200),r=Math.min(e.credits,200),h=Math.min(e.durationSeconds/60,120);return n+s+a+i+o+r+h}function Wn(e,n){return e===null&&n===null?0:e===null?1:n===null?-1:typeof e=="string"||typeof n=="string"?String(e).localeCompare(String(n)):e-n}function Ie(e,n){return $e(n)-$e(e)}function $e(e){const n=Date.parse(e.rawTime);return Number.isFinite(n)?n:0}function lt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function ct(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function J(e,n,s){const a=n?ct(n):"",i=s?ct(s):"";return a&&i&&a===i?`${e}: ${a}`:a&&i?`${e}: ${a} to ${i}`:a?`${e}: from ${a}`:i?`${e}: through ${i}`:e}function Yn(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function K(e,n){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+n)}function Xn(e){const n=e.getDay();return K(e,n===0?-6:1-n)}function Jn(e,n,s="",a="",i=new Date){if(n==="all")return!0;const o=ze(n,s,a,i);if(o.invalid)return!1;if(!o.active)return!0;const r=Date.parse(e.rawTime);return!(!Number.isFinite(r)||o.start&&r=o.endExclusive.getTime())}const Zn={time:"time",duration:"duration",gap:"gap",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"tokens",cached:"cached",uncached:"uncached",output:"output",reasoning:"reasoning",cache:"cache"};function es(e){const n=Zn[e.sortKey],s=ze(e.timeFilter,e.dateStart,e.dateEnd,new Date),a=ts(e,n,s.invalid);return{enabled:!a,reason:a,sort:n??"time",filters:{query:[e.globalQuery.trim(),e.localQuery.trim()].filter(Boolean).join(" "),model:e.modelFilter==="all"?void 0:e.modelFilter,effort:e.effortFilter==="all"?void 0:e.effortFilter,...ns(e.confidenceFilter),...ss(s.start,s.endExclusive,e.scopeSince)}}}function ts(e,n,s){return!e.enabled||e.runtime.fileMode||!e.runtime.apiToken?"Stored snapshot":e.globalQuery.trim()&&e.localQuery.trim()?"Multiple searches use loaded snapshot":e.activePreset?"Preset uses loaded snapshot":e.sourceFilter!=="all"?"Source filter uses loaded snapshot":n?s?"Invalid date range":"":"This sort uses loaded snapshot"}function ns(e){return e==="cost-exact"?{pricingStatus:"priced"}:e==="cost-estimated"?{pricingStatus:"estimated"}:e==="cost-unpriced"?{pricingStatus:"unpriced"}:e==="credit-exact"?{creditConfidence:"exact"}:e==="credit-estimated"?{creditConfidence:"estimated"}:e==="credit-override"?{creditConfidence:"user_override"}:e==="credit-missing"?{creditConfidence:"unpriced"}:{}}function ss(e,n,s){return{since:(e==null?void 0:e.toISOString())??s??void 0,until:n?new Date(n.getTime()-1).toISOString():void 0}}function as({data:e,valueLabel:n=s=>String(s)}){const s=Math.max(...e.map(a=>a.value),1);return t.jsx("div",{className:"bar-list",children:e.map(a=>t.jsxs("div",{className:"bar-row",children:[t.jsx("span",{children:a.label}),t.jsx("div",{className:"bar-track","aria-hidden":"true",children:t.jsx("i",{style:{width:`${a.value/s*100}%`,backgroundColor:a.color??"#2563eb"}})}),t.jsx("strong",{children:n(a.value)})]},a.label))})}function P({label:e,value:n,detail:s}){return t.jsxs("span",{className:"drilldown-metric",children:[t.jsx("small",{children:e}),t.jsx("strong",{children:n}),t.jsx("em",{children:s})]})}function S({label:e,value:n}){return t.jsxs("div",{children:[t.jsx("dt",{children:e}),t.jsx("dd",{children:n})]})}function is({call:e,contextRuntime:n,onContextApiEnabledChange:s}){const a=ce(),[i,o]=c.useState(()=>tn(e.id)??tt),[r,h]=c.useState({status:"idle"}),F=!!n.apiToken&&!n.fileMode,d=F&&n.contextApiEnabled;c.useEffect(()=>{const l=nt(e.id,i);h(l?{status:"loaded",payload:l}:{status:"idle"})},[e.id,i.includeCompactionHistory,i.includeToolOutput,i.maxChars,i.maxEntries,i.mode]);async function b(){h({status:"loading",message:"Enabling localhost context API..."});try{const l=await sn(n);s(l),h({status:"idle",message:l?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(l){h({status:"error",message:st(l)})}}async function j(l=i,p="Loading selected-turn evidence..."){at(e.id,l);const w=nt(e.id,l);if(w){h({status:"loaded",payload:w});return}h({status:"loading",message:p});try{const g=await an(e.id,n,l);on(e.id,l,g),h({status:"loaded",payload:g})}catch(g){h({status:"error",message:st(g)})}}function C(){const l={...i,mode:"full"};o(l),j(l,"Loading full turn analysis...")}function D(l){const p=mn(l,i);o(p),j(p,"Loading older context...")}function N(){const l={...i,includeToolOutput:!0};o(l),j(l,"Loading omitted tool output...")}function y(){const l={...i,includeCompactionHistory:!0};o(l),j(l,"Loading compacted replacement...")}function m(l,p){o(w=>{const g={...w,[l]:p};return at(e.id,g),g})}return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"locked-context-card",children:[t.jsx(pt,{size:20}),t.jsxs("div",{children:[t.jsx("strong",{children:"Raw context is gated"}),t.jsx("p",{children:nn(n)})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Record id",value:e.id}),t.jsx(S,{label:"Time",value:e.time}),t.jsx(S,{label:"Thread",value:e.thread}),t.jsx(S,{label:"Model",value:e.model}),t.jsx(S,{label:"Effort",value:e.effort})]}),t.jsxs("div",{className:"context-action-grid",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:b,disabled:!F||n.contextApiEnabled||r.status==="loading",children:a.t("button.enable_context_loading","Enable context loading")}),t.jsx("button",{className:"primary-button",type:"button",onClick:()=>j(),disabled:!d||r.status==="loading",children:a.t("button.show_turn_evidence","Show turn log evidence")}),t.jsx("button",{className:"toolbar-button",type:"button",onClick:C,disabled:!d||r.status==="loading",children:a.t("button.full_serialized_analysis","Run full serialized analysis")}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Mode"}),t.jsxs("select",{"aria-label":"Side panel context mode",value:i.mode,disabled:!d||r.status==="loading",onChange:l=>m("mode",l.target.value==="full"?"full":"quick"),children:[t.jsx("option",{value:"quick",children:"Quick"}),t.jsx("option",{value:"full",children:"Full"})]})]}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Entries"}),t.jsxs("select",{"aria-label":"Side panel context entries",value:String(i.maxEntries),disabled:!d||r.status==="loading",onChange:l=>m("maxEntries",Number(l.target.value)),children:[t.jsx("option",{value:"20",children:"20"}),t.jsx("option",{value:"50",children:"50"}),t.jsx("option",{value:"100",children:"100"}),t.jsx("option",{value:"0",children:"All"})]})]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeToolOutput,disabled:!d||r.status==="loading",onChange:l=>m("includeToolOutput",l.target.checked)}),a.t("button.include_tool_output","Include tool output")]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeCompactionHistory,disabled:!d||r.status==="loading",onChange:l=>m("includeCompactionHistory",l.target.checked)}),"Include compaction history"]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.maxChars===0,disabled:!d||r.status==="loading",onChange:l=>m("maxChars",l.target.checked?0:tt.maxChars)}),a.t("button.no_char_limit","No char limit")]})]}),r.status==="idle"&&r.message?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="loading"?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="error"?t.jsx("p",{className:"context-state-note error",children:r.message}):null,r.status==="loaded"?t.jsx(os,{call:e,payload:r.payload,onLoadOlder:D,onRunFullAnalysis:C,onLoadCompactionHistory:y,onLoadToolOutput:N}):null,t.jsx("p",{className:"privacy-note",children:"Raw context is never embedded in the dashboard HTML. This view reads the selected local JSONL turn only after an explicit request."})]})}function os({call:e,payload:n,onLoadOlder:s,onRunFullAnalysis:a,onLoadCompactionHistory:i,onLoadToolOutput:o}){var _,E;const r=ce(),h=n.entries??[],F=n.omitted??{},d=Number(F.older_entries??0),b=rn(n),j=8,C=e.id||String(n.record_id??""),[D,N]=c.useState(()=>it(C)),[y,m]=c.useState(()=>ot(C,h));c.useEffect(()=>{N(it(C)),m(ot(C,h))},[h.length,n.context_mode,n.include_compaction_history,n.include_tool_output,(_=n.omitted)==null?void 0:_.max_chars,(E=n.omitted)==null?void 0:E.max_entries,n.record_id,C]);const l=D?h:h.slice(0,j),p=Math.max(h.length-l.length,0);function w(){N(x=>{const L=!x;return pn(C,L),L})}function g(x,L){xn(C,x,L),m(v=>{const u=new Set(v);return L?u.add(x):u.delete(x),u})}return t.jsxs("div",{className:"context-evidence",children:[t.jsxs("div",{className:"context-evidence-summary",children:[t.jsx(P,{label:"Entries",value:O(h.length),detail:String(n.context_mode??"quick")}),t.jsx(P,{label:"Visible chars",value:O(Number(n.visible_char_count??0)),detail:"redacted local text"}),t.jsx(P,{label:"Visible tokens",value:O(Number(n.visible_token_estimate??0)),detail:"estimator"}),t.jsx(P,{label:"Older omitted",value:O(d),detail:"entry budget"})]}),b.length?t.jsx("p",{className:"context-note",children:b.join(" ")}):null,t.jsx(ln,{call:e,payload:n,onRunFullAnalysis:a}),d>0?t.jsx("div",{className:"context-followup-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>s(n),children:r.t("button.load_older_context","Load older entries")})}):null,t.jsxs("div",{className:"context-entry-list",children:[l.map((x,L)=>{const v=cn(x,L);return t.jsxs("details",{className:"context-entry",open:y.has(v),onToggle:u=>g(v,u.currentTarget.open),children:[t.jsx("summary",{className:"context-entry-summary",children:t.jsxs("div",{className:"context-entry-meta",children:[t.jsx("strong",{children:x.label||x.role||x.type||`Entry ${L+1}`}),t.jsx("span",{children:x.line_number?`line ${x.line_number}`:x.timestamp||"local evidence"})]})}),t.jsx(dn,{entry:x}),x.tool_output_omitted?t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:o,children:r.t("button.show_tool_output","Show tool output")})}):null,t.jsx(rs,{entry:x,onLoadCompactionHistory:i}),t.jsx("pre",{ref:u=>{u&&(u.scrollTop=hn(C,v))},onScroll:u=>un(C,v,u.currentTarget.scrollTop),children:x.text||"[no visible text]"})]},v)}),h.length?null:t.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),h.length>j?t.jsxs("div",{className:"context-followup-actions",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:w,children:D?`Show first ${O(j)} entries`:`Show all ${O(h.length)} returned entries`}),D?null:t.jsxs("span",{className:"context-entry-count-note",children:[O(p)," entries hidden in compact view"]})]}):null]})}function rs({entry:e,onLoadCompactionHistory:n}){const s=ce(),a=e.compaction;if(!(a!=null&&a.replacement_history_available))return null;const i=a.replacement_history??[],o=Number(a.replacement_entry_count??i.length);return t.jsxs("div",{className:"context-entry-compaction",children:[t.jsx("strong",{children:"Compaction detected"}),t.jsxs("span",{children:[O(o)," replacement history entries available."]}),i.length?t.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:i.map((r,h)=>t.jsxs("div",{className:"context-replacement-entry",children:[t.jsx("strong",{children:r.label||`Replacement item ${h+1}`}),t.jsx("pre",{children:r.text||"[no visible replacement text]"})]},`${r.label??"replacement"}-${h}`))}):t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}const ls=[{id:"summary",label:"Summary",icon:At},{id:"tokens",label:"Tokens",icon:ut},{id:"cache",label:"Cache",icon:Ot},{id:"thread",label:"Thread",icon:wn},{id:"evidence",label:"Evidence",icon:pt}];function cs({call:e,calls:n,contextRuntime:s,includeArchived:a,sourceRevision:i,hydrateThreadCalls:o,onContextApiEnabledChange:r,onOpenInvestigator:h,onCopyCallLink:F}){const[d,b]=c.useState("summary"),[j,C]=c.useState(""),D=c.useMemo(()=>e?n.filter(m=>m.thread===e.thread).sort(Ie):[],[e,n]),N=en({...kt({runtime:s,includeArchived:a,sourceRevision:i,threadKey:(e==null?void 0:e.threadKey)||(e==null?void 0:e.thread)||"",selectedRecordId:(e==null?void 0:e.id)??"",selectedEventTimestamp:(e==null?void 0:e.eventTimestamp)??""}),enabled:o&&!s.fileMode&&!!s.apiToken&&!!e,placeholderData:m=>m}),y=c.useMemo(()=>{var l;const m=((l=N.data)==null?void 0:l.rows)??D;return!e||m.some(p=>p.id===e.id)?m:[...m,e].sort(Ie)},[e,D,N.data]);return e?t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsxs(Z,{title:"Call Drill-Down",subtitle:`${e.thread} / ${e.model}`,children:[t.jsxs("div",{className:"call-summary",children:[t.jsx(re,{label:"Aggregate only",tone:"green"}),t.jsx(Rt,{call:e}),t.jsx(re,{label:"Raw context gated",tone:"blue"}),t.jsx("span",{className:"call-id",children:e.id.slice(0,12)})]}),t.jsxs("div",{className:"action-row",children:[t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>h(e.id),children:[t.jsx(Cn,{size:16}),"Open investigator"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>ps(e,C),children:[t.jsx(dt,{size:16}),"Copy link"]})]}),j?t.jsx("p",{className:"context-state-note",children:j}):null,t.jsx("div",{className:"drilldown-tabs",role:"tablist","aria-label":"Call drill-down sections",children:ls.map(m=>{const l=m.icon,p=d===m.id;return t.jsxs("button",{type:"button",role:"tab","aria-selected":p,className:p?"active":"",onClick:()=>b(m.id),children:[t.jsx(l,{size:14}),m.label]},m.id)})}),t.jsxs("div",{className:"drilldown-tab-panel",role:"tabpanel",children:[d==="summary"?t.jsx(ds,{call:e}):null,d==="tokens"?t.jsx(hs,{call:e}):null,d==="cache"?t.jsx(ms,{call:e,calls:y}):null,d==="thread"?t.jsx(xs,{call:e,calls:y,onOpenInvestigator:h,onCopyCallLink:F}):null,d==="evidence"?t.jsx(is,{call:e,contextRuntime:s,onContextApiEnabledChange:r},e.id):null]})]})}):t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsx(Z,{title:"Call Drill-Down",subtitle:"No matching call",children:t.jsx("p",{className:"empty-state",children:"No aggregate row matches the active filters."})})})}function ds({call:e}){return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Total tokens",value:O(e.totalTokens),detail:`${ee(e.input)} input`}),t.jsx(P,{label:"Uncached input",value:O(e.uncachedInput),detail:"fresh billed input"}),t.jsx(P,{label:"Cache hit rate",value:q(e.cachedPct),detail:Oe(e)}),t.jsx(P,{label:"Estimated cost",value:Ae(e.cost),detail:e.pricingEstimated?"estimated pricing":"configured pricing"}),t.jsx(P,{label:"Duration",value:e.duration,detail:Bt(e)}),t.jsx(P,{label:"Usage credits",value:e.credits?e.credits.toFixed(3):"-",detail:e.usageCreditConfidence})]}),t.jsx(fn,{call:e}),t.jsx(gn,{call:e}),t.jsx(us,{call:e}),t.jsx(St,{call:e}),t.jsx(wt,{call:e}),e.recommendation?t.jsxs("div",{className:"recommendation-box",children:[t.jsx(yn,{size:16}),t.jsx("p",{children:e.recommendation})]}):null]})}function us({call:e}){return t.jsxs("div",{className:"composition-card accounting-snapshot-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Accounting Snapshot"}),t.jsx("span",{children:"pricing, credits, and cache savings"})]}),t.jsx(xt,{call:e})]})}function hs({call:e}){return t.jsxs(t.Fragment,{children:[t.jsx(St,{call:e}),t.jsx(xt,{call:e})]})}function ms({call:e,calls:n}){return t.jsxs(t.Fragment,{children:[t.jsx(wt,{call:e}),t.jsx(jn,{call:e,calls:n}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Cache state",value:Oe(e)}),t.jsx(S,{label:"Cache hit rate",value:q(e.cachedPct)}),t.jsx(S,{label:"Fresh share",value:q(Math.max(100-e.cachedPct,0))}),t.jsx(S,{label:"Signal",value:e.signal})]}),t.jsx("p",{className:"privacy-note",children:"Use this readout to decide whether the aggregate call needs deeper raw-context investigation."})]})}function xs({call:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a}){const i=n.reduce((b,j)=>b+j.totalTokens,0),o=n.reduce((b,j)=>b+j.cost,0),r=n.reduce((b,j)=>b+j.cachedPct,0)/Math.max(n.length,1),h=Math.max(n.findIndex(b=>b.id===e.id),0),F=Math.min(Math.max(n.length,1),5),d=e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available";return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Loaded thread calls",value:O(n.length),detail:`selected ${h+1} of ${n.length}`}),t.jsx(P,{label:"Thread tokens",value:ee(i),detail:"loaded aggregate rows"}),t.jsx(P,{label:"Thread cost",value:Ae(o),detail:"estimated aggregate"}),t.jsx(P,{label:"Avg cache",value:q(r),detail:vn(n.map(b=>b.model),{style:"x",emptyLabel:"no model mix"})}),t.jsx(P,{label:"Context window",value:e.contextWindowPct===null?"-":q(e.contextWindowPct),detail:e.modelContextWindow?`${ee(e.modelContextWindow)} window`:"not reported"}),t.jsx(P,{label:"Parent thread",value:e.parentThread||"-",detail:e.parentSessionId||"no parent session"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Thread timeline"}),t.jsxs("span",{children:[F," nearby loaded calls"]})]}),t.jsx(bn,{selectedCall:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a,copyAriaContext:"side-panel thread call"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Call Narrative"}),t.jsx("span",{children:e.initiatorConfidence||"aggregate inference"})]}),t.jsxs("dl",{className:"detail-list compact",children:[t.jsx(S,{label:"Initiated by",value:e.initiator||"unknown"}),t.jsx(S,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),t.jsx(S,{label:"Parent thread",value:e.parentThread||"None"}),t.jsx(S,{label:"Parent session",value:e.parentSessionId||"None"}),t.jsx(S,{label:"Timestamp",value:e.time}),t.jsx(S,{label:"Duration",value:e.duration}),t.jsx(S,{label:"Previous gap",value:e.previousCallGap})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Project",value:e.project||"Unknown"}),t.jsx(S,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),t.jsx(S,{label:"Source line",value:d}),t.jsx(S,{label:"Session",value:e.sessionId||"Not available"}),t.jsx(S,{label:"Git branch",value:e.gitBranch||"Unknown"}),t.jsx(S,{label:"Remote",value:e.gitRemoteLabel||e.gitRemoteHash||"None"})]})]})}function St({call:e}){const s=[{label:"Cached input",value:Math.max(e.input-e.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:e.uncachedInput,color:"#f59e0b"},{label:"Output",value:e.output,color:"#059669"},{label:"Reasoning",value:e.reasoningOutput,color:"#7c3aed"}].filter(i=>i.value>0),a=Math.max(s.reduce((i,o)=>i+o.value,0),1);return t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Token composition"}),t.jsxs("span",{children:[ee(a)," visible tokens"]})]}),t.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(i=>t.jsx("i",{style:{width:`${Math.max(i.value/a*100,3)}%`,background:i.color}},i.label))}),t.jsx("div",{className:"composition-legend",children:s.map(i=>t.jsxs("span",{children:[t.jsx("i",{style:{background:i.color}}),i.label]},i.label))})]})}function wt({call:e}){const n=[{label:"Cache",value:Math.min(Math.max(e.cachedPct,0),100),color:"#2563eb"},{label:"Fresh",value:Math.min(Math.max(100-e.cachedPct,0),100),color:"#f59e0b"},{label:"Output",value:Math.min(Math.max(e.output/Math.max(e.totalTokens,1)*100,0),100),color:"#059669"}];return t.jsxs("div",{className:"cache-mini-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"Cache delta readout"}),t.jsx("span",{children:Oe(e)})]}),t.jsx("div",{className:"cache-bars","aria-label":"Cache delta readout",children:n.map(s=>t.jsxs("span",{children:[t.jsx("i",{style:{height:`${Math.max(s.value,4)}%`,background:s.color}}),t.jsx("em",{children:s.label})]},s.label))})]})}async function ps(e,n){try{const s=new URL(window.location.href);if(s.searchParams.set("view","call"),s.searchParams.set("record",e.id),s.searchParams.set("return","calls"),!await ht(s.toString()))throw new Error("Clipboard unavailable");n("Copied investigator link")}catch{n("Copy unavailable in this browser")}}const fs="_page_gyxvc_1",gs="_pageHeader_gyxvc_5",js="_tableHeading_gyxvc_13",vs="_eyebrow_gyxvc_22",bs="_headerActions_gyxvc_36",Cs="_tableActions_gyxvc_37",ys="_gridFooter_gyxvc_38",Ss="_queryBar_gyxvc_46",ws="_advancedFilters_gyxvc_80",Fs="_patternsDisclosure_gyxvc_85",Ns="_advancedFilterGrid_gyxvc_107",Ts="_gridColumn_gyxvc_138",$={page:fs,pageHeader:gs,tableHeading:js,eyebrow:vs,headerActions:bs,tableActions:Cs,gridFooter:ys,queryBar:Ss,advancedFilters:ws,patternsDisclosure:Fs,advancedFilterGrid:Ns,gridColumn:Ts};function Es({searchInputRef:e,localQuery:n,modelFilter:s,effortFilter:a,confidenceFilter:i,sourceFilter:o,timeFilter:r,dateStart:h,dateEnd:F,sortKey:d,sortDirection:b,modelOptions:j,effortOptions:C,sourceCoverage:D,dateRangeStatus:N,onLocalQueryChange:y,onModelFilterChange:m,onEffortFilterChange:l,onConfidenceFilterChange:p,onSourceFilterChange:w,onTimeFilterChange:g,onDateStartChange:_,onDateEndChange:E,onSortKeyChange:x,onSortDirectionChange:L,onClear:v}){return t.jsxs("section",{className:$.queryBar,"aria-label":"Call filters",children:[t.jsxs("label",{className:"search-box",children:[t.jsx("span",{className:"sr-only",children:"Search calls"}),t.jsx("input",{ref:e,value:n,onChange:u=>y(u.target.value),placeholder:"Search calls, cwd, projects, models..."})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Model"}),t.jsxs("select",{value:s,onChange:u=>m(u.target.value),children:[t.jsx("option",{value:"all",children:"All models"}),j.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Effort"}),t.jsxs("select",{value:a,onChange:u=>l(u.target.value),children:[t.jsx("option",{value:"all",children:"All effort"}),C.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Confidence"}),t.jsxs("select",{"aria-label":"Confidence filter",value:i,onChange:u=>p(u.target.value),children:[t.jsx("option",{value:"all",children:"All confidence"}),t.jsx("option",{value:"cost-exact",children:"Exact cost"}),t.jsx("option",{value:"cost-estimated",children:"Estimated cost"}),t.jsx("option",{value:"cost-unpriced",children:"Unpriced cost"}),t.jsx("option",{value:"credit-exact",children:"Exact credit rate"}),t.jsx("option",{value:"credit-estimated",children:"Estimated credit mapping"}),t.jsx("option",{value:"credit-override",children:"User credit override"}),t.jsx("option",{value:"credit-missing",children:"Missing credit rate"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Time"}),t.jsxs("select",{"aria-label":"Time filter",value:r,onChange:u=>g(u.target.value),children:[t.jsx("option",{value:"all",children:"All time"}),t.jsx("option",{value:"today",children:"Today"}),t.jsx("option",{value:"this-week",children:"This week"}),t.jsx("option",{value:"last-7-days",children:"Last 7 days"}),t.jsx("option",{value:"this-month",children:"This month"}),t.jsx("option",{value:"custom",children:"Custom range"})]}),N.active||N.invalid?t.jsx("span",{className:"filter-status","data-state":N.invalid?"error":"active","aria-live":"polite",children:N.label}):null]}),t.jsxs("details",{className:$.advancedFilters,children:[t.jsxs("summary",{children:[t.jsx(Vt,{size:16}),"More filters"]}),t.jsxs("div",{className:$.advancedFilterGrid,children:[t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Source"}),t.jsxs("select",{"aria-label":"Source filter",value:o,onChange:u=>w(u.target.value),children:[t.jsx("option",{value:"all",children:"All sources"}),t.jsx("option",{value:"project",children:"Project / cwd"}),t.jsx("option",{value:"session",children:"Session-linked"}),t.jsx("option",{value:"git",children:"Git metadata"}),t.jsx("option",{value:"source-file",children:"Source file"}),t.jsx("option",{value:"missing",children:"Missing source"})]}),t.jsx("span",{className:"filter-status","data-state":o==="all"?"active":"filtered","aria-live":"polite",children:En(D,o)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Start"}),t.jsx("input",{"aria-label":"Start date",type:"date",value:h,onChange:u=>_(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"End"}),t.jsx("input",{"aria-label":"End date",type:"date",value:F,onChange:u=>E(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Sort"}),t.jsxs("select",{"aria-label":"Sort calls",value:d,onChange:u=>x(u.target.value),children:[t.jsx("option",{value:"time",children:"Newest calls"}),t.jsx("option",{value:"duration",children:"Longest duration"}),t.jsx("option",{value:"gap",children:"Longest gap"}),t.jsx("option",{value:"attention",children:"Needs attention"}),t.jsx("option",{value:"thread",children:"Thread name"}),t.jsx("option",{value:"initiator",children:"Initiated"}),t.jsx("option",{value:"model",children:"Model"}),t.jsx("option",{value:"effort",children:"Reasoning"}),t.jsx("option",{value:"total",children:"Most tokens"}),t.jsx("option",{value:"cached",children:"Cached"}),t.jsx("option",{value:"uncached",children:"Uncached"}),t.jsx("option",{value:"output",children:"Output"}),t.jsx("option",{value:"reasoning",children:"Reasoning output"}),t.jsx("option",{value:"cost",children:"Highest estimated cost"}),t.jsx("option",{value:"usage",children:"Highest Codex credits"}),t.jsx("option",{value:"cache",children:"Lowest cache ratio"}),t.jsx("option",{value:"context",children:"Highest context use"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Direction"}),t.jsxs("select",{"aria-label":"Sort direction",value:b,onChange:u=>L(u.target.value),children:[t.jsx("option",{value:"desc",children:"Descending"}),t.jsx("option",{value:"asc",children:"Ascending"})]})]})]})]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:v,children:[t.jsx(Ht,{size:16}),"Clear filters"]})]})}function Ms({workspaceSwitcher:e,canExport:n,onExport:s,onCopyView:a,onRefresh:i}){return t.jsxs("header",{className:$.pageHeader,children:[t.jsxs("div",{children:[t.jsx("p",{className:$.eyebrow,children:"Evidence explorer"}),t.jsx("h1",{children:"Calls"}),t.jsx("p",{children:"Find expensive, cold, or context-heavy calls and move directly into their evidence."})]}),t.jsxs("div",{className:$.headerActions,children:[e,t.jsxs("button",{className:"toolbar-button",type:"button",onClick:s,disabled:!n,children:[t.jsx(Kt,{size:16}),"Export"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:a,children:[t.jsx(dt,{size:16}),"Copy view"]}),t.jsxs("button",{className:"primary-button",type:"button",onClick:i,children:[t.jsx(zt,{size:16}),"Refresh"]})]})]})}const Ft="codexUsageDetailPanel";function Ds(e=!1){var n;try{const s=(n=window.sessionStorage)==null?void 0:n.getItem(Ft);return s?s==="expanded":e}catch{return e}}function Ps(e){var n;try{(n=window.sessionStorage)==null||n.setItem(Ft,e?"expanded":"collapsed")}catch{}}const B=250;function _s(e,n){const s=T("density"),[a,i]=c.useState(()=>T("call_q")),[o,r]=c.useState(()=>T("model")||"all"),[h,F]=c.useState(()=>T("effort")||"all"),[d,b]=c.useState(()=>gt()),[j,C]=c.useState(()=>jt()),[D,N]=c.useState(()=>vt()),[y,m]=c.useState(()=>le("from")),[l,p]=c.useState(()=>le("to")),[w,g]=c.useState(()=>Pe()),[_,E]=c.useState(()=>Ct(Pe())),x=Sn("codexUsageCallsEvidenceGrid",{density:Bn()==="dense"?"compact":"comfortable",columnVisibility:{}},s==="roomy"?"comfortable":s==="dense"?"compact":void 0),L=x.density==="compact"?"dense":"roomy",v=c.useMemo(()=>On(),[]),[u,te]=c.useState(v),[G,R]=c.useState(()=>Vn(B)),[ne,Q]=c.useState(""),[de,ue]=c.useState(""),[W,he]=c.useState(()=>Ds(!!v)),me=c.useRef(null),se=c.useRef(n),xe=c.useMemo(()=>Ze(e.calls.map(f=>f.model)),[e.calls]),pe=c.useMemo(()=>Ze(e.calls.map(f=>f.effort)),[e.calls]),fe=c.useMemo(()=>Pn(e.calls),[e.calls]),Y=c.useMemo(()=>ze(D,y,l,new Date),[l,y,D]);c.useEffect(()=>{se.current!==n&&(se.current=n,R(B))},[n]);function I(){R(B)}function ge(f){i(f),I()}function je(f){r(f),I()}function ve(f){F(f),I()}function be(f){b(f),I()}function Ce(f){C(f),I()}function ye(f){N(f),I()}function Se(f){m(Le(f)),N("custom"),I()}function we(f){p(Le(f)),N("custom"),I()}function Fe(f){const A=bt(f);g(A),E(U(A)),I()}function Ne(f){E(f==="asc"?"asc":"desc"),I()}function Te(){i(""),r("all"),F("all"),b("all"),C("all"),N("all"),m(""),p(""),g("time"),E(U("time")),x.setDensity("compact"),x.setColumnVisibility({}),te(null),R(B),window.history.replaceState(null,"",_e({localQuery:"",modelFilter:"all",effortFilter:"all",confidenceFilter:"all",sourceFilter:"all",timeFilter:"all",dateStart:"",dateEnd:"",sortKey:"time",sortDirection:U("time"),density:"dense",selectedRecordId:"",visibleRowCount:B,pageSize:B})),ue("Calls filters cleared")}function Ee(){he(f=>{const A=!f;return Ps(A),A})}return{localQuery:a,modelFilter:o,effortFilter:h,confidenceFilter:d,sourceFilter:j,timeFilter:D,dateStart:y,dateEnd:l,sortKey:w,setSortKey:g,sortDirection:_,setSortDirection:E,gridPreferences:x,density:L,initialSelectedCallId:v,selectedCallId:u,setSelectedCallId:te,visibleCallRows:G,setVisibleCallRows:R,exportStatus:ne,setExportStatus:Q,filterStatus:de,detailsExpanded:W,searchInputRef:me,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}}function Ls({model:e,header:n,filters:s,table:a,inspector:i}){var F;const o=ce(),r=o.t("dashboard.model_calls","Model Calls"),h=o.t("dashboard.model_calls","Model calls");return t.jsxs("div",{className:`${$.page} page-grid`,children:[t.jsx(Ms,{...n}),t.jsx(Es,{...s}),t.jsxs("div",{className:$.tableHeading,children:[t.jsxs("div",{children:[t.jsx("h2",{children:r}),t.jsx("p",{children:a.exportStatus||a.filterStatus||a.subtitle})]}),t.jsxs("div",{className:$.tableActions,children:[t.jsx(re,{label:ks(a.isFetching,a.focused,a.focusedReason),tone:a.focused?"green":"blue"}),t.jsx(re,{label:a.activePreset?`Preset: ${mt(a.activePreset)}`:"Raw context gated",tone:a.activePreset?"green":"blue"}),t.jsxs("button",{className:"toolbar-button",type:"button","aria-expanded":a.detailsExpanded,onClick:a.onToggleDetails,children:[a.detailsExpanded?t.jsx(Fn,{size:16}):t.jsx(Nn,{size:16}),a.detailsExpanded?o.t("button.hide_details","Hide details"):o.t("dashboard.call_details","Call Details")]})]})]}),t.jsxs("div",{className:a.detailsExpanded?"table-detail-layout":"table-detail-layout detail-collapsed",children:[t.jsxs("div",{className:$.gridColumn,children:[t.jsx(Xt,{ariaLabel:h,columns:a.columns,data:a.calls,identityColumnId:"thread",lockedColumnIds:["investigate"],getRowId:d=>d.id,mobile:{primary:d=>d.thread,secondary:d=>o.translateText(`${d.time} · ${d.model} · ${ee(d.totalTokens)} tokens · ${q(d.cachedPct)} cache`),actionLabel:d=>Jt(d)},sorting:a.sorting,onSortingChange:a.onSortingChange,manualSorting:!0,columnVisibility:a.gridPreferences.columnVisibility,onColumnVisibilityChange:a.gridPreferences.setColumnVisibility,density:a.gridPreferences.density,onDensityChange:a.gridPreferences.setDensity,onRestoreDefaults:a.gridPreferences.restoreDefaults,selectedRowId:(F=a.selectedCall)==null?void 0:F.id,onRowSelect:d=>a.onSelectCall(d.id),onRowActivate:d=>i.onOpenInvestigator(d.id),activateOnClick:!0,selectOnHover:!0,viewportHeight:560,emptyLabel:"No rows match current filters."}),t.jsxs("div",{className:$.gridFooter,"aria-live":"polite",children:[t.jsx("span",{children:o.translateText(`${a.calls.length.toLocaleString()} loaded / ${a.totalMatchedCalls.toLocaleString()} matched`)}),a.focused&&a.hasNextPage?t.jsx("button",{className:"toolbar-button",type:"button",onClick:a.onLoadMore,disabled:a.isFetchingNextPage,children:a.isFetchingNextPage?"Loading more...":`Load ${B.toLocaleString()} more`}):null]})]}),a.detailsExpanded?t.jsx(cs,{call:a.selectedCall,calls:e.calls,...i}):null]}),t.jsxs("details",{className:$.patternsDisclosure,children:[t.jsxs("summary",{children:[t.jsx(ut,{size:17}),"Usage patterns"]}),t.jsxs("div",{className:"dashboard-grid three",children:[t.jsx(Z,{title:"Usage Over Time",subtitle:"Tokens",children:t.jsx(et,{series:e.tokenSeries,yLabel:"Tokens",height:220})}),t.jsx(Z,{title:"Cost by Model",subtitle:"Estimated USD",children:t.jsx(as,{data:e.modelCosts,valueLabel:Ae})}),t.jsx(Z,{title:"Cache Hit Rate Over Time",subtitle:o.translateText("Daily"),children:t.jsx(et,{series:e.cacheSeries,yLabel:"Cache %",height:220,valueFormatter:d=>`${d}%`})})]})]})]})}function ks(e,n,s){return e&&n?"Updating focused rows":e?"Loading focused rows":n?"Focused paged API":s||"Stored snapshot"}function oa(e,n="",s=""){const a=Pe();return ke(yt(e,{globalQuery:n,localQuery:T("call_q"),modelFilter:T("model")||"all",effortFilter:T("effort")||"all",confidenceFilter:gt(),sourceFilter:jt(),timeFilter:vt(),dateStart:le("from"),dateEnd:le("to"),activePreset:s}),a,Ct(a))}const Nt={time:"time",duration:"duration",gap:"previousCallGap",attention:"signal",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"totalTokens",cached:"cachedInput",uncached:"uncachedInput",output:"output",reasoning:"reasoningOutput",cost:"cost",usage:"credits",cache:"cachedPct",context:"contextWindowPct"},Is=Object.fromEntries(Object.entries(Nt).map(([e,n])=>[n,e]));function ra({model:e,globalQuery:n,activePreset:s,onRefresh:a,contextRuntime:i,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h,includeArchived:F=!1,sourceKey:d,sourceRevision:b="",scopeSince:j=null,focusedEndpointsEnabled:C=!0,workspaceSwitcher:D}){var We,Ye;const N=_s(e,n),{localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,setSortKey:L,sortDirection:v,setSortDirection:u,gridPreferences:te,density:G,selectedCallId:R,setSelectedCallId:ne,visibleCallRows:Q,setVisibleCallRows:de,exportStatus:ue,setExportStatus:W,filterStatus:he,detailsExpanded:me,searchInputRef:se,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}=N,f=c.useMemo(()=>[...Ut,Zt({onOpenInvestigator:r,onCopyCallLink:h})],[h,r]),A=c.useMemo(()=>es({runtime:i,enabled:C,activePreset:s,sourceFilter:w,sortKey:x,scopeSince:j,timeFilter:g,dateStart:_,dateEnd:E,confidenceFilter:p,globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l}),[s,p,i,E,_,l,C,n,y,m,x,w,j,g]),V=Lt({...It({runtime:i,includeArchived:F,sourceKey:d,sourceRevision:b,filters:A.filters,sort:A.sort,direction:v,pageSize:B}),enabled:A.enabled,placeholderData:M=>M}),Ue=c.useMemo(()=>yt(e.calls,{globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,activePreset:s}),[s,p,E,_,l,n,y,e.calls,m,w,g]),qe=c.useMemo(()=>ke(Ue,x,v),[Ue,v,x]),Ge=c.useMemo(()=>{var M;return((M=V.data)==null?void 0:M.pages.flatMap(X=>X.rows))??[]},[V.data]),ae=A.enabled&&!!V.data,H=c.useMemo(()=>ae?ke(Ge,x,v):qe,[Ge,qe,v,x,ae]),Me=ae?((Ye=(We=V.data)==null?void 0:We.pages[0])==null?void 0:Ye.totalMatchedRows)??H.length:e.calls.length,Tt=c.useMemo(()=>Tn({shownCount:H.length,totalCount:Me,localQuery:y,globalQuery:n,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateRangeStatus:Y,activePresetLabel:s?mt(s):""}),[s,p,Y,l,n,y,m,H.length,w,g,Me]),Qe=c.useMemo(()=>[{id:Nt[x],desc:v==="desc"}],[v,x]),ie=R===oe?H[0]??null:H.find(M=>M.id===R)??H[0]??null,z=ie&&(ie.id===R||R===oe)?ie.id:"";c.useEffect(()=>{R===oe&&z&&ne(z)},[R,z]),c.useEffect(()=>{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});M.toString()!==window.location.href&&window.history.replaceState(null,"",M)},[p,E,_,G,l,y,m,z,v,x,w,g,Q]);function Et(){qt(`codex-calls-${Wt()}.csv`,Gt(H,Qt)),W(`Exported ${H.length} calls`)}async function Mt(){try{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});if(!await ht(M.toString()))throw new Error("Clipboard unavailable");W("Copied Calls view link")}catch{W("Copy unavailable in browser")}}function Dt(M){var Xe,Je;const X=typeof M=="function"?M(Qe):M,De=Is[((Xe=X[0])==null?void 0:Xe.id)??""]??"time",_t=De!==x;L(De),u(_t?U(De):(Je=X[0])!=null&&Je.desc?"desc":"asc"),I()}async function Pt(){!V.hasNextPage||V.isFetchingNextPage||(await V.fetchNextPage(),de(M=>M+B))}return t.jsx(Ls,{model:e,header:{workspaceSwitcher:D,canExport:!!H.length,onExport:Et,onCopyView:Mt,onRefresh:a},filters:{searchInputRef:se,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,onLocalQueryChange:ge,onModelFilterChange:je,onEffortFilterChange:ve,onConfidenceFilterChange:be,onSourceFilterChange:Ce,onTimeFilterChange:ye,onDateStartChange:Se,onDateEndChange:we,onSortKeyChange:Fe,onSortDirectionChange:Ne,onClear:Te},table:{activePreset:s,exportStatus:ue,filterStatus:he,subtitle:Tt,focused:ae,focusedReason:A.reason,isFetching:V.isFetching,isFetchingNextPage:V.isFetchingNextPage,hasNextPage:!!V.hasNextPage,detailsExpanded:me,calls:H,totalMatchedCalls:Me,columns:f,sorting:Qe,gridPreferences:te,selectedCall:ie,onSortingChange:Dt,onSelectCall:ne,onLoadMore:Pt,onToggleDetails:Ee},inspector:{contextRuntime:i,includeArchived:F,sourceRevision:b,hydrateThreadCalls:C,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h}})}export{ra as CallsPage,oa as callsForCurrentUrl}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/ReportsPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/ReportsPage.js index a64c284a..a1128c12 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/ReportsPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/ReportsPage.js @@ -1 +1 @@ -import{r as _,j as a}from"./dashboard-react.js";import{u as q}from"./useQuery.js";import{v as B,w as H,x as J,y as G,z as W,f as X,m as Y,p as Z,u as ee,i as te,h as re,D as ae,R as se,g as ie}from"./App.js";import{q as oe}from"./queryOptions.js";import{P as U}from"./Panel.js";import{S as P}from"./StatusBadge.js";import{P as ne}from"./PageLoadProgress.js";import"./Primitives.js";import{v as le,V as ce}from"./UsageConstellation.js";import{D as de}from"./DataTable.js";import{c as ue,b as he}from"./tableActions.js";import"./useBaseQuery.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./triangle-alert.js";import"./index2.js";import"./rowActionEvents.js";import"./search.js";const pe="codex-usage-tracker-reports-pack-v1";async function ge(e,r={}){if(window.location.protocol==="file:")throw new Error("Live report pack requires the localhost dashboard server.");if(!e.apiToken)throw new Error("Live report pack requires localhost dashboard API token.");const s=new URLSearchParams({limit:String(r.limit??500),evidence_limit:String(r.evidenceLimit??8),_:String(Date.now())});r.includeArchived&&s.set("include_archived","1");const o=await fetch(`/api/reports/pack?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:r.signal}),t=await fe(o,"Reports pack");if(t.schema!==pe)throw new Error("Reports pack returned an unsupported schema.");return{reports:t.reports??[],evidence:me(t.evidence??{}),rowCount:Number(t.row_count??0),totalMatchedRows:Number(t.total_matched_rows??t.row_count??0),schema:t.schema,generatedAt:t.generated_at??"",rawContextIncluded:t.raw_context_included===!0,rawPayload:t}}function me(e){return Object.fromEntries(Object.entries(e).map(([r,s])=>[r,(s.rows??[]).map((o,t)=>B(o,t))]))}async function fe(e,r){const s=await e.json().catch(()=>({}));if(!e.ok)throw new Error(typeof s.error=="string"?s.error:`${r} failed with HTTP ${e.status}`);return s}const M=W("reports");function be(e){return oe({queryKey:J(M,G({sourceKey:e.sourceKey??(e.runtime.fileMode?"static-file":"local-api"),sourceRevision:e.sourceRevision}),{historyScope:e.includeArchived?"all":"active",loadWindow:e.loadWindow,limit:e.limit},e.evidenceLimit),queryFn:({signal:r})=>ge(e.runtime,{limit:e.limit,evidenceLimit:e.evidenceLimit,includeArchived:e.includeArchived,signal:r}),...H(M.dataClass)})}function f(e){if(e!=null&&e.key)return e.key;const r=L(e);return r.includes("fast")?"fast-mode-proxy":r.includes("cost")||r.includes("thread")?"cost-curves":r.includes("remaining")?"usage-remaining":r.includes("allowance")?"allowance-change":r.includes("weekly")?"weekly-credits":r.includes("drain")?"usage-drain-model":r.replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"")||"report"}function A(e){var s;const r=(s=new URLSearchParams(window.location.search).get("report"))==null?void 0:s.trim();return r?e.find(o=>f(o)===r||o.title===r):void 0}function we(e){const r=new URL(window.location.href);r.searchParams.set("view","reports"),r.searchParams.set("report",f(e)),window.history.replaceState(null,"",r)}function z(e,r){const s=L(e),o=[...r];return s.includes("fast")?o.filter(t=>t.fast||t.effort.toLowerCase()==="low").sort((t,i)=>t.durationSeconds-i.durationSeconds||y(i)-y(t)).slice(0,8):s.includes("cost")||s.includes("thread")?o.sort((t,i)=>i.cost-t.cost||i.totalTokens-t.totalTokens).slice(0,8):o.sort((t,i)=>y(i)-y(t)||i.totalTokens-t.totalTokens).slice(0,8)}function D(e,r){const s=L(e);return s.includes("fast")?{eyebrow:"Speed proxy",finding:`${r.length} loaded calls are fast-tagged or low effort. Duration is a proxy, not a quality score.`,method:"Filter fast-tagged and low-effort calls, then order by shortest duration and credit impact.",caveat:"Aggregate timing cannot distinguish model latency from tool, network, or queue time.",selection:"Fast/low-effort candidates · shortest duration first · top 8",chartLabel:"Calls"}:s.includes("cost")||s.includes("thread")?{eyebrow:"Cost concentration",finding:`${r.length} highest-cost loaded calls anchor this report. Estimates use the local pricing model.`,method:"Rank aggregate calls by estimated cost, breaking ties with total token volume.",caveat:"Estimated local cost may differ from billing and excludes costs not represented in loaded rows.",selection:"Highest estimated cost · token volume tie-break · top 8",chartLabel:"USD"}:{eyebrow:"Usage trajectory",finding:`${r.length} highest credit-impact loaded calls support the selected usage report.`,method:"Rank aggregate calls by estimated Codex credit impact and compare the selected time series.",caveat:"Allowance and credit projections are local observations, not universal account limits.",selection:"Highest credit impact · token volume tie-break · top 8",chartLabel:s.includes("remaining")||s.includes("allowance")?"Percent":"Credits"}}function ve(e,r){const s=L(e);return s.includes("remaining")||s.includes("allowance")?r.usageRemainingSeries:s.includes("drain")?r.actualVsPredictedSeries:r.weeklyCreditSeries}function xe(e,r,s){const o=L(e);if(o.includes("cost")||o.includes("thread"))return{bars:r.threads.slice(0,10).map(i=>({label:i.name,value:i.cost})),labelsAreUiText:!1};if(!o.includes("fast"))return null;const t=s.map(i=>i.durationSeconds).filter(i=>Number.isFinite(i)&&i>=0);return{bars:[{label:"Under 5s",value:t.filter(i=>i<5).length},{label:"5-15s",value:t.filter(i=>i>=5&&i<15).length},{label:"15-30s",value:t.filter(i=>i>=15&&i<30).length},{label:"30s+",value:t.filter(i=>i>=30).length}],labelsAreUiText:!0}}function y(e){return e.credits>0?e.credits:e.cost*25}function L(e){return((e==null?void 0:e.title)??"").toLowerCase()}function ye({calls:e,onOpenInvestigator:r,onCopyCallLink:s}){const o=_.useMemo(()=>[{accessorKey:"time",header:"Time"},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:t=>a.jsx("span",{className:`pill effort-${String(t.getValue())}`,children:String(t.getValue())})},{id:"credits",header:"Credits",cell:t=>a.jsx("span",{className:"num",children:X(y(t.row.original))}),sortingFn:(t,i)=>y(t.original)-y(i.original)},{accessorKey:"cost",header:"Est. Cost",cell:t=>a.jsx("span",{className:"num",children:Y(Number(t.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:t=>a.jsx("span",{className:"cache-pill",children:Z(Number(t.getValue()))})},ue({onOpenInvestigator:r,onCopyCallLink:s,labelPrefix:"report side evidence call"})],[s,r]);return a.jsx(de,{columns:o,data:e,compact:!0,emptyLabel:"No loaded aggregate calls match this selected report.",getRowId:t=>t.id,getRowActionLabel:t=>he(t,"report side evidence call"),onRowActivate:t=>r(t.id),ariaLabel:"Selected report evidence calls"})}function je(e,r,s,o){var w;const t=D(e,s),i=Se(t.chartLabel),c=xe(e,r,s),u=c?ke(c.bars,i,t.chartLabel,c.labelsAreUiText):Re(ve(e,r),i,t.chartLabel),b=(e==null?void 0:e.title)??"Selected report",v=`${t.eyebrow} evidence`;return{schema:le,id:`report-${f(e)}`,title:v,description:t.selection,state:u.rows.length?{kind:"ready"}:{kind:"empty",message:`No loaded aggregate data is available for ${b}.`},scope:{label:`${o.source} · ${t.selection}`,rowCount:u.rows.length,historyScope:o.historyScope},freshness:{generatedAt:o.generatedAt,sourceRevision:o.sourceRevision},caveats:[t.caveat,"Raw context is available only through an explicitly linked Call Investigator record."],accessibility:{summary:u.rows.length?`${b} contains ${u.rows.length} plotted rows. ${t.finding}`:`No plotted rows are available for ${b}.`,details:[t.method,t.caveat],keyboardInstructions:"Use left and right arrow keys to inspect chart values, or switch to the table for exact values."},table:{caption:`${b} report data`,columns:u.columns,defaultSort:{field:"label",direction:"asc"}},interactions:{selection:{keyField:"id",labelField:"label"},...c?{}:{zoom:{axis:"x",startPercent:u.rows.length>12?Math.round(100-12/u.rows.length*100):0,endPercent:100},brush:{axis:"x"}}},kind:"cartesian",data:{rows:u.rows},axes:{x:{field:"label",label:c?"Category":"Observed period",type:"category"},y:{field:((w=u.series[0])==null?void 0:w.yField)??"value",label:t.chartLabel,type:"number",unit:i}},series:u.series}}function ke(e,r,s,o){return{rows:e.map((i,c)=>({id:`bar-${c}`,label:i.label,value:i.value})),columns:[{field:"label",label:"Category",type:"category",align:"left",localizeValues:o},{field:"value",label:s,type:"number",unit:r,align:"right"}],series:[{id:"report-values",label:s,mark:"bar",xField:"label",yField:"value",color:"#2f6fed"}]}}function Re(e,r,s){const o=new Map,t=[],i=[{field:"label",label:"Observed period",type:"category",align:"left"}];return e.forEach((c,u)=>{const b=`value_${u}`,v=`low_${u}`,w=`high_${u}`,S=c.points.some(m=>Number.isFinite(m.low)&&Number.isFinite(m.high));i.push({field:b,label:c.label||s,type:"number",unit:r,align:"right"}),S&&i.push({field:v,label:`${c.label} low`,type:"number",unit:r,align:"right"},{field:w,label:`${c.label} high`,type:"number",unit:r,align:"right"}),c.points.forEach((m,j)=>{const h=m.label||`Point ${j+1}`,k=o.get(h)??{id:`point-${o.size}`,label:h};k[b]=m.value,S&&Number.isFinite(m.low)&&Number.isFinite(m.high)&&(k[v]=Number(m.low),k[w]=Number(m.high)),o.set(h,k)}),t.push({id:c.id||`series-${u}`,label:c.label||s,mark:"line",xField:"label",yField:b,color:c.color,smooth:!1,...S?{lowerField:v,upperField:w}:{}})}),{rows:[...o.values()],columns:i,series:t}}function Se(e){return e==="USD"?"usd":e==="Calls"?"count":e==="Percent"?"percent":"credits"}const _e="_page_p90q5_1",Le="_header_p90q5_7",Ce="_actions_p90q5_8",Ne="_status_p90q5_9",$e="_selectedMeta_p90q5_10",Fe="_switcher_p90q5_11",Ue="_selected_p90q5_10",Pe="_research_p90q5_24",Ee="_action_p90q5_8",Te="_eyebrow_p90q5_109",Me="_workspace_p90q5_166",Ae="_main_p90q5_173",ze="_metadata_p90q5_195",p={page:_e,header:Le,actions:Ce,status:Ne,selectedMeta:$e,switcher:Fe,selected:Ue,research:Pe,action:Ee,eyebrow:Te,workspace:Me,main:Ae,metadata:ze};function ot(e){return z(A(e.reports)??e.reports[0],e.calls)}function nt({model:e,refreshState:r,includeArchived:s,loadWindow:o,loadLimit:t,sourceKey:i,sourceRevision:c,onOpenInvestigator:u,onCopyCallLink:b}){const v=ee(),[w,S]=_.useState(()=>f(A(e.reports)??e.reports[0])),[m,j]=_.useState(""),h=!!e.contextRuntime.apiToken&&!e.contextRuntime.fileMode,k=o==="rows"?t:0,g=q({...be({runtime:e.contextRuntime,includeArchived:s,loadWindow:o,limit:k,evidenceLimit:8,sourceKey:i,sourceRevision:c}),enabled:h,placeholderData:d=>d}),l=h?g.data:void 0,N=l!=null&&l.reports.length?l.reports:e.reports,n=N.find(d=>f(d)===w)??N[0],x=_.useMemo(()=>{const d=n&&l?l.evidence[f(n)]:void 0;return d===void 0?z(n,e.calls):d},[n,e.calls,l]),R=D(n,x),C=l?"Live localhost report pack":"Loaded dashboard aggregates",$=(l==null?void 0:l.generatedAt)||(l?"Server timestamp unavailable":"Current dashboard snapshot"),K=De(h,g,m,r),V=_.useMemo(()=>je(n,e,x,{generatedAt:$,historyScope:s?"all":"active",source:C,sourceRevision:c}),[n,x,$,s,e,C,c]),F={label:"Report pack",status:te({enabled:h,hasData:!!g.data,isError:g.isError,isFetching:g.isFetching,isPending:g.isPending})},T=re([F.status]);async function O(){if(!h)return;j("Refreshing selected report…");const d=await g.refetch();j(d.isError?`Refresh failed: ${E(d.error)}. Showing cached live report pack.`:"Selected report refreshed")}function I(){Ke(`codex-report-${f(n)}-${ie()}.json`,{schema:"codex-usage-tracker-react-selected-report-v1",generated_at:(l==null?void 0:l.generatedAt)??null,source:C,report:n,method:R.method,caveat:R.caveat,evidence:x,raw_context_included:(l==null?void 0:l.rawContextIncluded)??!1}),j(`Exported ${(n==null?void 0:n.title)??"selected report"}`)}function Q(d){S(f(d)),j(`${d.title} selected`),we(d)}return a.jsxs("div",{className:p.page,children:[a.jsxs("header",{className:p.header,children:[a.jsxs("div",{children:[a.jsx("h1",{children:"Reports"}),a.jsx("p",{children:"Focused local research snapshots with their methods, limits, and investigator-linked evidence."})]}),a.jsxs("div",{className:p.actions,children:[a.jsxs("button",{className:p.action,type:"button",onClick:I,disabled:!n,children:[a.jsx(ae,{size:16,"aria-hidden":"true"}),"Export selected"]}),a.jsxs("button",{className:p.action,"data-primary":"true",type:"button",onClick:O,disabled:!h||g.isFetching,title:h?void 0:"Live report refresh requires the localhost server.",children:[a.jsx(se,{size:16,"aria-hidden":"true"}),h?g.isFetching?"Refreshing":"Refresh report":"Live refresh unavailable"]})]})]}),a.jsx(ne,{active:h&&g.isFetching,completed:T.ready,total:T.total,label:"Loading full-scope report pack",error:h&&g.error&&!g.data?`Report pack unavailable: ${E(g.error)}`:null,modules:[F],updating:F.status==="updating"}),a.jsxs("div",{className:p.status,role:"status","aria-live":"polite",children:[a.jsx(P,{label:l?"Live report pack":"Aggregate fallback",tone:l?"green":"orange"}),a.jsx("span",{children:K})]}),a.jsxs("section",{className:p.selected,"aria-labelledby":"selected-report-title",children:[a.jsxs("div",{children:[a.jsx("span",{className:p.eyebrow,children:R.eyebrow}),a.jsx("h2",{id:"selected-report-title",children:(n==null?void 0:n.title)??"No report available"}),a.jsx("p",{children:n==null?void 0:n.description}),a.jsx("p",{children:R.finding})]}),a.jsxs("div",{className:p.selectedMeta,children:[a.jsx(P,{label:(n==null?void 0:n.status)??"Blocked",tone:(n==null?void 0:n.status)==="Ready"?"green":"orange"}),a.jsxs("span",{children:[(n==null?void 0:n.owner)??"No owner"," · ",x.length," evidence rows"]})]})]}),a.jsx("div",{className:p.switcher,role:"group","aria-label":"Select report",children:N.map(d=>a.jsx("button",{type:"button","aria-pressed":f(d)===f(n),onClick:()=>Q(d),children:d.title},f(d)))}),a.jsxs("div",{className:p.workspace,children:[a.jsxs("section",{className:p.main,"aria-label":"Report evidence",children:[a.jsx(ce,{spec:V,height:320}),a.jsx(U,{title:"Report Evidence Calls",subtitle:v.translateText(`${x.length} aggregate rows · select a row to open Call Investigator`),action:a.jsx(P,{label:"Investigator linked",tone:"green"}),children:a.jsx(ye,{calls:x,onOpenInvestigator:u,onCopyCallLink:b})})]}),a.jsxs("aside",{className:p.research,children:[a.jsxs(U,{title:"Research Notes",subtitle:"Interpretation boundary",children:[a.jsxs("section",{children:[a.jsx("h3",{children:"Method"}),a.jsx("p",{children:R.method})]}),a.jsxs("section",{children:[a.jsx("h3",{children:"Caveat"}),a.jsx("p",{children:R.caveat})]}),a.jsxs("section",{children:[a.jsx("h3",{children:"Evidence privacy"}),a.jsx("p",{children:"Raw context is not included here; inspect an explicitly linked call in Call Investigator."})]})]}),a.jsx(U,{title:"Generation Metadata",subtitle:"Provenance for this view",children:a.jsxs("dl",{className:p.metadata,children:[a.jsxs("div",{children:[a.jsx("dt",{children:"Source"}),a.jsx("dd",{children:C})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Generated"}),a.jsx("dd",{children:$})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Schema"}),a.jsx("dd",{children:(l==null?void 0:l.schema)||"dashboard aggregate model"})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Matched"}),a.jsxs("dd",{children:[l?l.totalMatchedRows.toLocaleString():e.calls.length.toLocaleString()," loaded rows"]})]})]})})]})]})]})}function De(e,r,s,o){return s||(e?r.isLoading?"Loading live report pack…":r.error?`Live report pack unavailable: ${E(r.error)}. Using loaded aggregate fallback.`:r.isFetching?"Refreshing live report pack…":r.data&&r.isStale?"Cached live report pack is stale; refresh is available.":"Live report pack ready.":o||"Static mode: using the loaded aggregate snapshot.")}function Ke(e,r){const s=JSON.stringify(r,null,2),o=new Blob([s],{type:"application/json;charset=utf-8"}),t=typeof URL.createObjectURL=="function"?URL.createObjectURL(o):`data:application/json;charset=utf-8,${encodeURIComponent(s)}`,i=document.createElement("a");i.href=t,i.download=e,i.rel="noopener",document.body.append(i),i.click(),i.remove(),t.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(t)}function E(e){return e instanceof Error?e.message:String(e)}export{nt as ReportsPage,ot as reportCallsForCurrentUrl}; +import{r as _,j as a}from"./dashboard-react.js";import{u as q}from"./useQuery.js";import{v as B,w as H,x as J,y as G,z as W,f as X,m as Y,p as Z,u as ee,i as te,h as re,D as ae,R as se,g as ie}from"./App.js";import{q as oe}from"./queryOptions.js";import{P}from"./Panel.js";import{S as U}from"./StatusBadge.js";import{P as ne}from"./PageLoadProgress.js";import"./Primitives.js";import{v as le,V as ce}from"./UsageConstellation.js";import{D as de}from"./DataTable.js";import{c as ue,b as he}from"./tableActions.js";import"./useBaseQuery.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./triangle-alert.js";import"./index2.js";import"./rowActionEvents.js";import"./search.js";const pe="codex-usage-tracker-reports-pack-v1";async function ge(e,r={}){if(window.location.protocol==="file:")throw new Error("Live report pack requires the localhost dashboard server.");if(!e.apiToken)throw new Error("Live report pack requires localhost dashboard API token.");const s=new URLSearchParams({limit:String(r.limit??500),evidence_limit:String(r.evidenceLimit??8),_:String(Date.now())});r.includeArchived&&s.set("include_archived","1");const o=await fetch(`/api/reports/pack?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:r.signal}),t=await fe(o,"Reports pack");if(t.schema!==pe)throw new Error("Reports pack returned an unsupported schema.");return{reports:t.reports??[],evidence:me(t.evidence??{}),rowCount:Number(t.row_count??0),totalMatchedRows:Number(t.total_matched_rows??t.row_count??0),schema:t.schema,generatedAt:t.generated_at??"",rawContextIncluded:t.raw_context_included===!0,rawPayload:t}}function me(e){return Object.fromEntries(Object.entries(e).map(([r,s])=>[r,(s.rows??[]).map((o,t)=>B(o,t))]))}async function fe(e,r){const s=await e.json().catch(()=>({}));if(!e.ok)throw new Error(typeof s.error=="string"?s.error:`${r} failed with HTTP ${e.status}`);return s}const M=W("reports");function be(e){return oe({queryKey:J(M,G({sourceKey:e.sourceKey??(e.runtime.fileMode?"static-file":"local-api"),sourceRevision:e.sourceRevision}),{historyScope:e.includeArchived?"all":"active",loadWindow:e.loadWindow,limit:e.limit},e.evidenceLimit),queryFn:({signal:r})=>ge(e.runtime,{limit:e.limit,evidenceLimit:e.evidenceLimit,includeArchived:e.includeArchived,signal:r}),...H(M.dataClass)})}function f(e){if(e!=null&&e.key)return e.key;const r=L(e);return r.includes("fast")?"fast-mode-proxy":r.includes("cost")||r.includes("thread")?"cost-curves":r.includes("remaining")?"usage-remaining":r.includes("allowance")?"allowance-change":r.includes("weekly")?"weekly-credits":r.includes("drain")?"usage-drain-model":r.replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"")||"report"}function A(e){var s;const r=(s=new URLSearchParams(window.location.search).get("report"))==null?void 0:s.trim();return r?e.find(o=>f(o)===r||o.title===r):void 0}function we(e){const r=new URL(window.location.href);r.searchParams.set("view","reports"),r.searchParams.set("report",f(e)),window.history.replaceState(null,"",r)}function z(e,r){const s=L(e),o=[...r];return s.includes("fast")?o.filter(t=>t.fastProxyCandidate||t.effort.toLowerCase()==="low").sort((t,i)=>t.durationSeconds-i.durationSeconds||y(i)-y(t)).slice(0,8):s.includes("cost")||s.includes("thread")?o.sort((t,i)=>i.cost-t.cost||i.totalTokens-t.totalTokens).slice(0,8):o.sort((t,i)=>y(i)-y(t)||i.totalTokens-t.totalTokens).slice(0,8)}function D(e,r){const s=L(e);return s.includes("fast")?{eyebrow:"Speed proxy",finding:`${r.length} loaded calls are fast-tagged or low effort. Duration is a proxy, not a quality score.`,method:"Filter fast-tagged and low-effort calls, then order by shortest duration and credit impact.",caveat:"Aggregate timing cannot distinguish model latency from tool, network, or queue time.",selection:"Fast/low-effort candidates · shortest duration first · top 8",chartLabel:"Calls"}:s.includes("cost")||s.includes("thread")?{eyebrow:"Cost concentration",finding:`${r.length} highest-cost loaded calls anchor this report. Estimates use the local pricing model.`,method:"Rank aggregate calls by estimated cost, breaking ties with total token volume.",caveat:"Estimated local cost may differ from billing and excludes costs not represented in loaded rows.",selection:"Highest estimated cost · token volume tie-break · top 8",chartLabel:"USD"}:{eyebrow:"Usage trajectory",finding:`${r.length} highest credit-impact loaded calls support the selected usage report.`,method:"Rank aggregate calls by estimated Codex credit impact and compare the selected time series.",caveat:"Allowance and credit projections are local observations, not universal account limits.",selection:"Highest credit impact · token volume tie-break · top 8",chartLabel:s.includes("remaining")||s.includes("allowance")?"Percent":"Credits"}}function ve(e,r){const s=L(e);return s.includes("remaining")||s.includes("allowance")?r.usageRemainingSeries:s.includes("drain")?r.actualVsPredictedSeries:r.weeklyCreditSeries}function xe(e,r,s){const o=L(e);if(o.includes("cost")||o.includes("thread"))return{bars:r.threads.slice(0,10).map(i=>({label:i.name,value:i.cost})),labelsAreUiText:!1};if(!o.includes("fast"))return null;const t=s.map(i=>i.durationSeconds).filter(i=>Number.isFinite(i)&&i>=0);return{bars:[{label:"Under 5s",value:t.filter(i=>i<5).length},{label:"5-15s",value:t.filter(i=>i>=5&&i<15).length},{label:"15-30s",value:t.filter(i=>i>=15&&i<30).length},{label:"30s+",value:t.filter(i=>i>=30).length}],labelsAreUiText:!0}}function y(e){return e.credits>0?e.credits:e.cost*25}function L(e){return((e==null?void 0:e.title)??"").toLowerCase()}function ye({calls:e,onOpenInvestigator:r,onCopyCallLink:s}){const o=_.useMemo(()=>[{accessorKey:"time",header:"Time"},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:t=>a.jsx("span",{className:`pill effort-${String(t.getValue())}`,children:String(t.getValue())})},{id:"credits",header:"Credits",cell:t=>a.jsx("span",{className:"num",children:X(y(t.row.original))}),sortingFn:(t,i)=>y(t.original)-y(i.original)},{accessorKey:"cost",header:"Est. Cost",cell:t=>a.jsx("span",{className:"num",children:Y(Number(t.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:t=>a.jsx("span",{className:"cache-pill",children:Z(Number(t.getValue()))})},ue({onOpenInvestigator:r,onCopyCallLink:s,labelPrefix:"report side evidence call"})],[s,r]);return a.jsx(de,{columns:o,data:e,compact:!0,emptyLabel:"No loaded aggregate calls match this selected report.",getRowId:t=>t.id,getRowActionLabel:t=>he(t,"report side evidence call"),onRowActivate:t=>r(t.id),ariaLabel:"Selected report evidence calls"})}function je(e,r,s,o){var w;const t=D(e,s),i=Se(t.chartLabel),c=xe(e,r,s),u=c?ke(c.bars,i,t.chartLabel,c.labelsAreUiText):Re(ve(e,r),i,t.chartLabel),b=(e==null?void 0:e.title)??"Selected report",v=`${t.eyebrow} evidence`;return{schema:le,id:`report-${f(e)}`,title:v,description:t.selection,state:u.rows.length?{kind:"ready"}:{kind:"empty",message:`No loaded aggregate data is available for ${b}.`},scope:{label:`${o.source} · ${t.selection}`,rowCount:u.rows.length,historyScope:o.historyScope},freshness:{generatedAt:o.generatedAt,sourceRevision:o.sourceRevision},caveats:[t.caveat,"Raw context is available only through an explicitly linked Call Investigator record."],accessibility:{summary:u.rows.length?`${b} contains ${u.rows.length} plotted rows. ${t.finding}`:`No plotted rows are available for ${b}.`,details:[t.method,t.caveat],keyboardInstructions:"Use left and right arrow keys to inspect chart values, or switch to the table for exact values."},table:{caption:`${b} report data`,columns:u.columns,defaultSort:{field:"label",direction:"asc"}},interactions:{selection:{keyField:"id",labelField:"label"},...c?{}:{zoom:{axis:"x",startPercent:u.rows.length>12?Math.round(100-12/u.rows.length*100):0,endPercent:100},brush:{axis:"x"}}},kind:"cartesian",data:{rows:u.rows},axes:{x:{field:"label",label:c?"Category":"Observed period",type:"category"},y:{field:((w=u.series[0])==null?void 0:w.yField)??"value",label:t.chartLabel,type:"number",unit:i}},series:u.series}}function ke(e,r,s,o){return{rows:e.map((i,c)=>({id:`bar-${c}`,label:i.label,value:i.value})),columns:[{field:"label",label:"Category",type:"category",align:"left",localizeValues:o},{field:"value",label:s,type:"number",unit:r,align:"right"}],series:[{id:"report-values",label:s,mark:"bar",xField:"label",yField:"value",color:"#2f6fed"}]}}function Re(e,r,s){const o=new Map,t=[],i=[{field:"label",label:"Observed period",type:"category",align:"left"}];return e.forEach((c,u)=>{const b=`value_${u}`,v=`low_${u}`,w=`high_${u}`,S=c.points.some(m=>Number.isFinite(m.low)&&Number.isFinite(m.high));i.push({field:b,label:c.label||s,type:"number",unit:r,align:"right"}),S&&i.push({field:v,label:`${c.label} low`,type:"number",unit:r,align:"right"},{field:w,label:`${c.label} high`,type:"number",unit:r,align:"right"}),c.points.forEach((m,j)=>{const h=m.label||`Point ${j+1}`,k=o.get(h)??{id:`point-${o.size}`,label:h};k[b]=m.value,S&&Number.isFinite(m.low)&&Number.isFinite(m.high)&&(k[v]=Number(m.low),k[w]=Number(m.high)),o.set(h,k)}),t.push({id:c.id||`series-${u}`,label:c.label||s,mark:"line",xField:"label",yField:b,color:c.color,smooth:!1,...S?{lowerField:v,upperField:w}:{}})}),{rows:[...o.values()],columns:i,series:t}}function Se(e){return e==="USD"?"usd":e==="Calls"?"count":e==="Percent"?"percent":"credits"}const _e="_page_p90q5_1",Le="_header_p90q5_7",Ce="_actions_p90q5_8",Ne="_status_p90q5_9",$e="_selectedMeta_p90q5_10",Fe="_switcher_p90q5_11",Pe="_selected_p90q5_10",Ue="_research_p90q5_24",Ee="_action_p90q5_8",Te="_eyebrow_p90q5_109",Me="_workspace_p90q5_166",Ae="_main_p90q5_173",ze="_metadata_p90q5_195",p={page:_e,header:Le,actions:Ce,status:Ne,selectedMeta:$e,switcher:Fe,selected:Pe,research:Ue,action:Ee,eyebrow:Te,workspace:Me,main:Ae,metadata:ze};function ot(e){return z(A(e.reports)??e.reports[0],e.calls)}function nt({model:e,refreshState:r,includeArchived:s,loadWindow:o,loadLimit:t,sourceKey:i,sourceRevision:c,onOpenInvestigator:u,onCopyCallLink:b}){const v=ee(),[w,S]=_.useState(()=>f(A(e.reports)??e.reports[0])),[m,j]=_.useState(""),h=!!e.contextRuntime.apiToken&&!e.contextRuntime.fileMode,k=o==="rows"?t:0,g=q({...be({runtime:e.contextRuntime,includeArchived:s,loadWindow:o,limit:k,evidenceLimit:8,sourceKey:i,sourceRevision:c}),enabled:h,placeholderData:d=>d}),l=h?g.data:void 0,N=l!=null&&l.reports.length?l.reports:e.reports,n=N.find(d=>f(d)===w)??N[0],x=_.useMemo(()=>{const d=n&&l?l.evidence[f(n)]:void 0;return d===void 0?z(n,e.calls):d},[n,e.calls,l]),R=D(n,x),C=l?"Live localhost report pack":"Loaded dashboard aggregates",$=(l==null?void 0:l.generatedAt)||(l?"Server timestamp unavailable":"Current dashboard snapshot"),K=De(h,g,m,r),V=_.useMemo(()=>je(n,e,x,{generatedAt:$,historyScope:s?"all":"active",source:C,sourceRevision:c}),[n,x,$,s,e,C,c]),F={label:"Report pack",status:te({enabled:h,hasData:!!g.data,isError:g.isError,isFetching:g.isFetching,isPending:g.isPending})},T=re([F.status]);async function O(){if(!h)return;j("Refreshing selected report…");const d=await g.refetch();j(d.isError?`Refresh failed: ${E(d.error)}. Showing cached live report pack.`:"Selected report refreshed")}function I(){Ke(`codex-report-${f(n)}-${ie()}.json`,{schema:"codex-usage-tracker-react-selected-report-v1",generated_at:(l==null?void 0:l.generatedAt)??null,source:C,report:n,method:R.method,caveat:R.caveat,evidence:x,raw_context_included:(l==null?void 0:l.rawContextIncluded)??!1}),j(`Exported ${(n==null?void 0:n.title)??"selected report"}`)}function Q(d){S(f(d)),j(`${d.title} selected`),we(d)}return a.jsxs("div",{className:p.page,children:[a.jsxs("header",{className:p.header,children:[a.jsxs("div",{children:[a.jsx("h1",{children:"Reports"}),a.jsx("p",{children:"Focused local research snapshots with their methods, limits, and investigator-linked evidence."})]}),a.jsxs("div",{className:p.actions,children:[a.jsxs("button",{className:p.action,type:"button",onClick:I,disabled:!n,children:[a.jsx(ae,{size:16,"aria-hidden":"true"}),"Export selected"]}),a.jsxs("button",{className:p.action,"data-primary":"true",type:"button",onClick:O,disabled:!h||g.isFetching,title:h?void 0:"Live report refresh requires the localhost server.",children:[a.jsx(se,{size:16,"aria-hidden":"true"}),h?g.isFetching?"Refreshing":"Refresh report":"Live refresh unavailable"]})]})]}),a.jsx(ne,{active:h&&g.isFetching,completed:T.ready,total:T.total,label:"Loading full-scope report pack",error:h&&g.error&&!g.data?`Report pack unavailable: ${E(g.error)}`:null,modules:[F],updating:F.status==="updating"}),a.jsxs("div",{className:p.status,role:"status","aria-live":"polite",children:[a.jsx(U,{label:l?"Live report pack":"Aggregate fallback",tone:l?"green":"orange"}),a.jsx("span",{children:K})]}),a.jsxs("section",{className:p.selected,"aria-labelledby":"selected-report-title",children:[a.jsxs("div",{children:[a.jsx("span",{className:p.eyebrow,children:R.eyebrow}),a.jsx("h2",{id:"selected-report-title",children:(n==null?void 0:n.title)??"No report available"}),a.jsx("p",{children:n==null?void 0:n.description}),a.jsx("p",{children:R.finding})]}),a.jsxs("div",{className:p.selectedMeta,children:[a.jsx(U,{label:(n==null?void 0:n.status)??"Blocked",tone:(n==null?void 0:n.status)==="Ready"?"green":"orange"}),a.jsxs("span",{children:[(n==null?void 0:n.owner)??"No owner"," · ",x.length," evidence rows"]})]})]}),a.jsx("div",{className:p.switcher,role:"group","aria-label":"Select report",children:N.map(d=>a.jsx("button",{type:"button","aria-pressed":f(d)===f(n),onClick:()=>Q(d),children:d.title},f(d)))}),a.jsxs("div",{className:p.workspace,children:[a.jsxs("section",{className:p.main,"aria-label":"Report evidence",children:[a.jsx(ce,{spec:V,height:320}),a.jsx(P,{title:"Report Evidence Calls",subtitle:v.translateText(`${x.length} aggregate rows · select a row to open Call Investigator`),action:a.jsx(U,{label:"Investigator linked",tone:"green"}),children:a.jsx(ye,{calls:x,onOpenInvestigator:u,onCopyCallLink:b})})]}),a.jsxs("aside",{className:p.research,children:[a.jsxs(P,{title:"Research Notes",subtitle:"Interpretation boundary",children:[a.jsxs("section",{children:[a.jsx("h3",{children:"Method"}),a.jsx("p",{children:R.method})]}),a.jsxs("section",{children:[a.jsx("h3",{children:"Caveat"}),a.jsx("p",{children:R.caveat})]}),a.jsxs("section",{children:[a.jsx("h3",{children:"Evidence privacy"}),a.jsx("p",{children:"Raw context is not included here; inspect an explicitly linked call in Call Investigator."})]})]}),a.jsx(P,{title:"Generation Metadata",subtitle:"Provenance for this view",children:a.jsxs("dl",{className:p.metadata,children:[a.jsxs("div",{children:[a.jsx("dt",{children:"Source"}),a.jsx("dd",{children:C})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Generated"}),a.jsx("dd",{children:$})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Schema"}),a.jsx("dd",{children:(l==null?void 0:l.schema)||"dashboard aggregate model"})]}),a.jsxs("div",{children:[a.jsx("dt",{children:"Matched"}),a.jsxs("dd",{children:[l?l.totalMatchedRows.toLocaleString():e.calls.length.toLocaleString()," loaded rows"]})]})]})})]})]})]})}function De(e,r,s,o){return s||(e?r.isLoading?"Loading live report pack…":r.error?`Live report pack unavailable: ${E(r.error)}. Using loaded aggregate fallback.`:r.isFetching?"Refreshing live report pack…":r.data&&r.isStale?"Cached live report pack is stale; refresh is available.":"Live report pack ready.":o||"Static mode: using the loaded aggregate snapshot.")}function Ke(e,r){const s=JSON.stringify(r,null,2),o=new Blob([s],{type:"application/json;charset=utf-8"}),t=typeof URL.createObjectURL=="function"?URL.createObjectURL(o):`data:application/json;charset=utf-8,${encodeURIComponent(s)}`,i=document.createElement("a");i.href=t,i.download=e,i.rel="noopener",document.body.append(i),i.click(),i.remove(),t.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(t)}function E(e){return e instanceof Error?e.message:String(e)}export{nt as ReportsPage,ot as reportCallsForCurrentUrl}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js index bf084465..8a2f396a 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js @@ -1,4 +1,4 @@ -import{r as j,j as t}from"./dashboard-react.js";import{P as A}from"./Panel.js";import{S as v}from"./StatusBadge.js";import{c as W,H as h,G as B,af as M,R as $}from"./App.js";import{G as f}from"./gauge.js";import{S as _}from"./shield-check.js";import{L as T}from"./lock-keyhole.js";import{T as H}from"./triangle-alert.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** +import{r as j,j as t}from"./dashboard-react.js";import{P as A}from"./Panel.js";import{S as v}from"./StatusBadge.js";import{c as W,H as h,G as B,ag as M,R as $}from"./App.js";import{G as f}from"./gauge.js";import{S as _}from"./shield-check.js";import{L as T}from"./lock-keyhole.js";import{T as H}from"./triangle-alert.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js index 71b8574a..55207088 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js @@ -1,2 +1,2 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/App.js","assets/dashboard-react.js","assets/index.css","assets/locale-zh-Hans.js","assets/router.js"])))=>i.map(i=>d[i]); -import{j as o,_ as u}from"./dashboard-react.js";import{Y as h,$ as f,T as g,a9 as b}from"./router.js";const p=["overview","investigator","compression-lab","calls","call","threads","usage-drain","cache-context","diagnostics","reports","settings"],m=new Set(p);function y(e){return typeof e=="string"&&m.has(e)}function d(e,r="overview"){const t=s(e);return t==="insights"?"overview":y(t)?t:r}function R(e){const r={...e,view:d(e.view)};i(r,"record",e.record),i(r,"q",e.q),i(r,"preset",e.preset);const t=d(e.return,"calls");s(e.return)&&t!=="call"?r.return=t:delete r.return;const n=s(e.history);n==="active"||n==="all"?r.history=n:delete r.history;const a=w(e.finding);return a!==null&&a>0?r.finding=a:delete r.finding,r}function i(e,r,t){const n=s(t);n?e[r]=n:delete e[r]}function s(e){return Array.isArray(e)?s(e[0]):typeof e=="string"?e.trim():""}function w(e){const r=Array.isArray(e)?e[0]:e,t=typeof r=="number"?r:Number.parseInt(s(r),10);return Number.isFinite(t)?Math.trunc(t):null}const _=b(()=>u(()=>import("./App.js").then(e=>e.ag),__vite__mapDeps([0,1,2,3,4])),"RoutedApp");function c(e={}){const r=h({validateSearch:R,component:_,pendingComponent:x,errorComponent:v});return f({routeTree:r,history:e.history??g(),basepath:e.basepath??l(),defaultPreload:"intent",defaultPendingMs:120,defaultPendingMinMs:180,scrollRestoration:!0,search:{strict:!1}})}const j=c();function l(){return"/"}function x(){return o.jsxs("main",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:[o.jsx("strong",{children:"Loading dashboard"}),o.jsx("span",{children:"Restoring the local usage workspace..."})]})}function v({error:e,reset:r}){return o.jsxs("main",{className:"route-state",role:"alert",children:[o.jsx("strong",{children:"Dashboard route could not load"}),o.jsx("span",{children:e instanceof Error?e.message:String(e)}),o.jsx("button",{type:"button",onClick:r,children:"Retry"})]})}const A=Object.freeze(Object.defineProperty({__proto__:null,createDashboardRouter:c,dashboardBasepath:l,dashboardRouter:j},Symbol.toStringTag,{value:"Module"}));export{A as d,y as i}; +import{j as o,_ as u}from"./dashboard-react.js";import{Y as h,$ as f,T as g,a9 as b}from"./router.js";const p=["overview","investigator","compression-lab","calls","call","threads","usage-drain","cache-context","diagnostics","reports","settings"],m=new Set(p);function y(e){return typeof e=="string"&&m.has(e)}function d(e,r="overview"){const t=s(e);return t==="insights"?"overview":y(t)?t:r}function R(e){const r={...e,view:d(e.view)};i(r,"record",e.record),i(r,"q",e.q),i(r,"preset",e.preset);const t=d(e.return,"calls");s(e.return)&&t!=="call"?r.return=t:delete r.return;const n=s(e.history);n==="active"||n==="all"?r.history=n:delete r.history;const a=w(e.finding);return a!==null&&a>0?r.finding=a:delete r.finding,r}function i(e,r,t){const n=s(t);n?e[r]=n:delete e[r]}function s(e){return Array.isArray(e)?s(e[0]):typeof e=="string"?e.trim():""}function w(e){const r=Array.isArray(e)?e[0]:e,t=typeof r=="number"?r:Number.parseInt(s(r),10);return Number.isFinite(t)?Math.trunc(t):null}const _=b(()=>u(()=>import("./App.js").then(e=>e.ah),__vite__mapDeps([0,1,2,3,4])),"RoutedApp");function c(e={}){const r=h({validateSearch:R,component:_,pendingComponent:x,errorComponent:v});return f({routeTree:r,history:e.history??g(),basepath:e.basepath??l(),defaultPreload:"intent",defaultPendingMs:120,defaultPendingMinMs:180,scrollRestoration:!0,search:{strict:!1}})}const j=c();function l(){return"/"}function x(){return o.jsxs("main",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:[o.jsx("strong",{children:"Loading dashboard"}),o.jsx("span",{children:"Restoring the local usage workspace..."})]})}function v({error:e,reset:r}){return o.jsxs("main",{className:"route-state",role:"alert",children:[o.jsx("strong",{children:"Dashboard route could not load"}),o.jsx("span",{children:e instanceof Error?e.message:String(e)}),o.jsx("button",{type:"button",onClick:r,children:"Retry"})]})}const A=Object.freeze(Object.defineProperty({__proto__:null,createDashboardRouter:c,dashboardBasepath:l,dashboardRouter:j},Symbol.toStringTag,{value:"Module"}));export{A as d,y as i}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js index e0ae489b..2a603091 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js @@ -1 +1 @@ -var bt=s=>{throw TypeError(s)};var $=(s,t,e)=>t.has(s)||bt("Cannot "+e);var i=(s,t,e)=>($(s,t,"read from private field"),e?e.call(s):t.get(s)),p=(s,t,e)=>t.has(s)?bt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),l=(s,t,e,r)=>($(s,t,"write to private field"),r?r.call(s,e):t.set(s,e),e),d=(s,t,e)=>($(s,t,"access private method"),e);import{J as Tt,a1 as gt,a2 as R,L as q,a3 as W,N as tt,a4 as et,a5 as mt,a6 as Mt,a7 as X,a8 as Qt,a9 as xt,aa as vt,K as Ct,ab as Ot,l as _t}from"./App.js";import{r as C}from"./dashboard-react.js";var m,a,z,g,x,U,E,w,V,D,P,_,F,T,L,n,H,st,it,rt,at,nt,ht,ot,It,Et,Gt=(Et=class extends Tt{constructor(t,e){super();p(this,n);p(this,m);p(this,a);p(this,z);p(this,g);p(this,x);p(this,U);p(this,E);p(this,w);p(this,V);p(this,D);p(this,P);p(this,_);p(this,F);p(this,T);p(this,L,new Set);this.options=e,l(this,m,t),l(this,w,null),l(this,E,gt()),this.bindMethods(),this.setOptions(e)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(i(this,a).addObserver(this),Rt(i(this,a),this.options)?d(this,n,H).call(this):this.updateResult(),d(this,n,at).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return ct(i(this,a),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return ct(i(this,a),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,d(this,n,nt).call(this),d(this,n,ht).call(this),i(this,a).removeObserver(this)}setOptions(t){const e=this.options,r=i(this,a);if(this.options=i(this,m).defaultQueryOptions(t),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof R(this.options.enabled,i(this,a))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");d(this,n,ot).call(this),i(this,a).setOptions(this.options),e._defaulted&&!q(this.options,e)&&i(this,m).getQueryCache().notify({type:"observerOptionsUpdated",query:i(this,a),observer:this});const h=this.hasListeners();h&&St(i(this,a),r,this.options,e)&&d(this,n,H).call(this),this.updateResult(),h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||W(this.options.staleTime,i(this,a))!==W(e.staleTime,i(this,a)))&&d(this,n,st).call(this);const o=d(this,n,it).call(this);h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||o!==i(this,T))&&d(this,n,rt).call(this,o)}getOptimisticResult(t){const e=i(this,m).getQueryCache().build(i(this,m),t),r=this.createResult(e,t);return Ut(this,r)&&(l(this,g,r),l(this,U,this.options),l(this,x,i(this,a).state)),r}getCurrentResult(){return i(this,g)}trackResult(t,e){return new Proxy(t,{get:(r,h)=>(this.trackProp(h),e==null||e(h),h==="promise"&&(this.trackProp("data"),!this.options.experimental_prefetchInRender&&i(this,E).status==="pending"&&i(this,E).reject(new Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(r,h))})}trackProp(t){i(this,L).add(t)}getCurrentQuery(){return i(this,a)}refetch({...t}={}){return this.fetch({...t})}fetchOptimistic(t){const e=i(this,m).defaultQueryOptions(t),r=i(this,m).getQueryCache().build(i(this,m),e);return r.fetch().then(()=>this.createResult(r,e))}fetch(t){return d(this,n,H).call(this,{...t,cancelRefetch:t.cancelRefetch??!0}).then(()=>(this.updateResult(),i(this,g)))}createResult(t,e){var ft;const r=i(this,a),h=this.options,o=i(this,g),c=i(this,x),S=i(this,U),N=t!==r?t.state:i(this,z),{state:b}=t;let u={...b},B=!1,f;if(e._optimisticResults){const v=this.hasListeners(),j=!v&&Rt(t,e),K=v&&St(t,r,e,h);(j||K)&&(u={...u,...xt(b.data,t.options)}),e._optimisticResults==="isRestoring"&&(u.fetchStatus="idle")}let{error:k,errorUpdatedAt:Q,status:y}=u;f=u.data;let O=!1;if(e.placeholderData!==void 0&&f===void 0&&y==="pending"){let v;o!=null&&o.isPlaceholderData&&e.placeholderData===(S==null?void 0:S.placeholderData)?(v=o.data,O=!0):v=typeof e.placeholderData=="function"?e.placeholderData((ft=i(this,P))==null?void 0:ft.state.data,i(this,P)):e.placeholderData,v!==void 0&&(y="success",f=vt(o==null?void 0:o.data,v,e),B=!0)}if(e.select&&f!==void 0&&!O)if(o&&f===(c==null?void 0:c.data)&&e.select===i(this,V))f=i(this,D);else try{l(this,V,e.select),f=e.select(f),f=vt(o==null?void 0:o.data,f,e),l(this,D,f),l(this,w,null)}catch(v){l(this,w,v)}i(this,w)&&(k=i(this,w),f=i(this,D),Q=Date.now(),y="error");const A=u.fetchStatus==="fetching",Y=y==="pending",Z=y==="error",ut=Y&&A,dt=f!==void 0,I={status:y,fetchStatus:u.fetchStatus,isPending:Y,isSuccess:y==="success",isError:Z,isInitialLoading:ut,isLoading:ut,data:f,dataUpdatedAt:u.dataUpdatedAt,error:k,errorUpdatedAt:Q,failureCount:u.fetchFailureCount,failureReason:u.fetchFailureReason,errorUpdateCount:u.errorUpdateCount,isFetched:t.isFetched(),isFetchedAfterMount:u.dataUpdateCount>N.dataUpdateCount||u.errorUpdateCount>N.errorUpdateCount,isFetching:A,isRefetching:A&&!Y,isLoadingError:Z&&!dt,isPaused:u.fetchStatus==="paused",isPlaceholderData:B,isRefetchError:Z&&dt,isStale:lt(t,e),refetch:this.refetch,promise:i(this,E),isEnabled:R(e.enabled,t)!==!1};if(this.options.experimental_prefetchInRender){const v=I.data!==void 0,j=I.status==="error"&&!v,K=G=>{j?G.reject(I.error):v&&G.resolve(I.data)},pt=()=>{const G=l(this,E,I.promise=gt());K(G)},J=i(this,E);switch(J.status){case"pending":t.queryHash===r.queryHash&&K(J);break;case"fulfilled":(j||I.data!==J.value)&&pt();break;case"rejected":(!j||I.error!==J.reason)&&pt();break}}return I}updateResult(){const t=i(this,g),e=this.createResult(i(this,a),this.options);if(l(this,x,i(this,a).state),l(this,U,this.options),i(this,x).data!==void 0&&l(this,P,i(this,a)),q(e,t))return;l(this,g,e);const r=()=>{if(!t)return!0;const{notifyOnChangeProps:h}=this.options,o=typeof h=="function"?h():h;if(o==="all"||!o&&!i(this,L).size)return!0;const c=new Set(o??i(this,L));return this.options.throwOnError&&c.add("error"),Object.keys(i(this,g)).some(S=>{const M=S;return i(this,g)[M]!==t[M]&&c.has(M)})};d(this,n,It).call(this,{listeners:r()})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&d(this,n,at).call(this)}},m=new WeakMap,a=new WeakMap,z=new WeakMap,g=new WeakMap,x=new WeakMap,U=new WeakMap,E=new WeakMap,w=new WeakMap,V=new WeakMap,D=new WeakMap,P=new WeakMap,_=new WeakMap,F=new WeakMap,T=new WeakMap,L=new WeakMap,n=new WeakSet,H=function(t){d(this,n,ot).call(this);let e=i(this,a).fetch(this.options,t);return t!=null&&t.throwOnError||(e=e.catch(tt)),e},st=function(){d(this,n,nt).call(this);const t=W(this.options.staleTime,i(this,a));if(et.isServer()||i(this,g).isStale||!mt(t))return;const r=Mt(i(this,g).dataUpdatedAt,t)+1;l(this,_,X.setTimeout(()=>{i(this,g).isStale||this.updateResult()},r))},it=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(i(this,a)):this.options.refetchInterval)??!1},rt=function(t){d(this,n,ht).call(this),l(this,T,t),!(et.isServer()||R(this.options.enabled,i(this,a))===!1||!mt(i(this,T))||i(this,T)===0)&&l(this,F,X.setInterval(()=>{(this.options.refetchIntervalInBackground||Qt.isFocused())&&d(this,n,H).call(this)},i(this,T)))},at=function(){d(this,n,st).call(this),d(this,n,rt).call(this,d(this,n,it).call(this))},nt=function(){i(this,_)!==void 0&&(X.clearTimeout(i(this,_)),l(this,_,void 0))},ht=function(){i(this,F)!==void 0&&(X.clearInterval(i(this,F)),l(this,F,void 0))},ot=function(){const t=i(this,m).getQueryCache().build(i(this,m),this.options);if(t===i(this,a))return;const e=i(this,a);l(this,a,t),l(this,z,t.state),this.hasListeners()&&(e==null||e.removeObserver(this),t.addObserver(this))},It=function(t){Ct.batch(()=>{t.listeners&&this.listeners.forEach(e=>{e(i(this,g))}),i(this,m).getQueryCache().notify({query:i(this,a),type:"observerResultsUpdated"})})},Et);function Ft(s,t){return R(t.enabled,s)!==!1&&s.state.data===void 0&&!(s.state.status==="error"&&R(t.retryOnMount,s)===!1)}function Rt(s,t){return Ft(s,t)||s.state.data!==void 0&&ct(s,t,t.refetchOnMount)}function ct(s,t,e){if(R(t.enabled,s)!==!1&&W(t.staleTime,s)!=="static"){const r=typeof e=="function"?e(s):e;return r==="always"||r!==!1&<(s,t)}return!1}function St(s,t,e,r){return(s!==t||R(r.enabled,s)===!1)&&(!e.suspense||s.state.status!=="error")&<(s,e)}function lt(s,t){return R(t.enabled,s)!==!1&&s.isStaleByTime(W(t.staleTime,s))}function Ut(s,t){return!q(s.getCurrentResult(),t)}var wt=C.createContext(!1),Dt=()=>C.useContext(wt);wt.Provider;function Pt(){let s=!1;return{clearReset:()=>{s=!1},reset:()=>{s=!0},isReset:()=>s}}var Lt=C.createContext(Pt()),Nt=()=>C.useContext(Lt),Bt=(s,t,e)=>{const r=e!=null&&e.state.error&&typeof s.throwOnError=="function"?Ot(s.throwOnError,[e.state.error,e]):s.throwOnError;(s.suspense||s.experimental_prefetchInRender||r)&&(t.isReset()||(s.retryOnMount=!1))},kt=s=>{C.useEffect(()=>{s.clearReset()},[s])},At=({result:s,errorResetBoundary:t,throwOnError:e,query:r,suspense:h})=>s.isError&&!t.isReset()&&!s.isFetching&&r&&(h&&s.data===void 0||Ot(e,[s.error,r])),jt=s=>{if(s.suspense){const e=h=>h==="static"?h:Math.max(h??1e3,1e3),r=s.staleTime;s.staleTime=typeof r=="function"?(...h)=>e(r(...h)):e(r),typeof s.gcTime=="number"&&(s.gcTime=Math.max(s.gcTime,1e3))}},Ht=(s,t)=>s.isLoading&&s.isFetching&&!t,Wt=(s,t)=>(s==null?void 0:s.suspense)&&t.isPending,yt=(s,t,e)=>t.fetchOptimistic(s).catch(()=>{e.clearReset()});function Xt(s,t,e){var f,k,Q,y;const r=Dt(),h=Nt(),o=_t(),c=o.defaultQueryOptions(s);(k=(f=o.getDefaultOptions().queries)==null?void 0:f._experimental_beforeQuery)==null||k.call(f,c);const S=o.getQueryCache().get(c.queryHash),M=s.subscribed!==!1;c._optimisticResults=r?"isRestoring":M?"optimistic":void 0,jt(c),Bt(c,h,S),kt(h);const N=!o.getQueryCache().get(c.queryHash),[b]=C.useState(()=>new t(o,c)),u=b.getOptimisticResult(c),B=!r&&M;if(C.useSyncExternalStore(C.useCallback(O=>{const A=B?b.subscribe(Ct.batchCalls(O)):tt;return b.updateResult(),A},[b,B]),()=>b.getCurrentResult(),()=>b.getCurrentResult()),C.useEffect(()=>{b.setOptions(c)},[c,b]),Wt(c,u))throw yt(c,b,h);if(At({result:u,errorResetBoundary:h,throwOnError:c.throwOnError,query:S,suspense:c.suspense}))throw u.error;if((y=(Q=o.getDefaultOptions().queries)==null?void 0:Q._experimental_afterQuery)==null||y.call(Q,c,u),c.experimental_prefetchInRender&&!et.isServer()&&Ht(u,r)){const O=N?yt(c,b,h):S==null?void 0:S.promise;O==null||O.catch(tt).finally(()=>{b.updateResult()})}return c.notifyOnChangeProps?u:b.trackResult(u)}export{Gt as Q,Nt as a,Bt as b,kt as c,Xt as d,jt as e,yt as f,At as g,Wt as s,Dt as u}; +var bt=s=>{throw TypeError(s)};var $=(s,t,e)=>t.has(s)||bt("Cannot "+e);var i=(s,t,e)=>($(s,t,"read from private field"),e?e.call(s):t.get(s)),p=(s,t,e)=>t.has(s)?bt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),l=(s,t,e,r)=>($(s,t,"write to private field"),r?r.call(s,e):t.set(s,e),e),d=(s,t,e)=>($(s,t,"access private method"),e);import{J as Tt,a2 as gt,a3 as R,L as q,a4 as W,N as tt,a5 as et,a6 as mt,a7 as Mt,a8 as X,a9 as Qt,aa as xt,ab as vt,K as Ct,ac as Ot,l as _t}from"./App.js";import{r as C}from"./dashboard-react.js";var m,a,z,g,x,U,E,w,V,D,P,_,F,T,L,n,H,st,it,rt,at,nt,ht,ot,It,Et,Gt=(Et=class extends Tt{constructor(t,e){super();p(this,n);p(this,m);p(this,a);p(this,z);p(this,g);p(this,x);p(this,U);p(this,E);p(this,w);p(this,V);p(this,D);p(this,P);p(this,_);p(this,F);p(this,T);p(this,L,new Set);this.options=e,l(this,m,t),l(this,w,null),l(this,E,gt()),this.bindMethods(),this.setOptions(e)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(i(this,a).addObserver(this),Rt(i(this,a),this.options)?d(this,n,H).call(this):this.updateResult(),d(this,n,at).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return ct(i(this,a),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return ct(i(this,a),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,d(this,n,nt).call(this),d(this,n,ht).call(this),i(this,a).removeObserver(this)}setOptions(t){const e=this.options,r=i(this,a);if(this.options=i(this,m).defaultQueryOptions(t),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof R(this.options.enabled,i(this,a))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");d(this,n,ot).call(this),i(this,a).setOptions(this.options),e._defaulted&&!q(this.options,e)&&i(this,m).getQueryCache().notify({type:"observerOptionsUpdated",query:i(this,a),observer:this});const h=this.hasListeners();h&&St(i(this,a),r,this.options,e)&&d(this,n,H).call(this),this.updateResult(),h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||W(this.options.staleTime,i(this,a))!==W(e.staleTime,i(this,a)))&&d(this,n,st).call(this);const o=d(this,n,it).call(this);h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||o!==i(this,T))&&d(this,n,rt).call(this,o)}getOptimisticResult(t){const e=i(this,m).getQueryCache().build(i(this,m),t),r=this.createResult(e,t);return Ut(this,r)&&(l(this,g,r),l(this,U,this.options),l(this,x,i(this,a).state)),r}getCurrentResult(){return i(this,g)}trackResult(t,e){return new Proxy(t,{get:(r,h)=>(this.trackProp(h),e==null||e(h),h==="promise"&&(this.trackProp("data"),!this.options.experimental_prefetchInRender&&i(this,E).status==="pending"&&i(this,E).reject(new Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(r,h))})}trackProp(t){i(this,L).add(t)}getCurrentQuery(){return i(this,a)}refetch({...t}={}){return this.fetch({...t})}fetchOptimistic(t){const e=i(this,m).defaultQueryOptions(t),r=i(this,m).getQueryCache().build(i(this,m),e);return r.fetch().then(()=>this.createResult(r,e))}fetch(t){return d(this,n,H).call(this,{...t,cancelRefetch:t.cancelRefetch??!0}).then(()=>(this.updateResult(),i(this,g)))}createResult(t,e){var ft;const r=i(this,a),h=this.options,o=i(this,g),c=i(this,x),S=i(this,U),N=t!==r?t.state:i(this,z),{state:b}=t;let u={...b},B=!1,f;if(e._optimisticResults){const v=this.hasListeners(),j=!v&&Rt(t,e),K=v&&St(t,r,e,h);(j||K)&&(u={...u,...xt(b.data,t.options)}),e._optimisticResults==="isRestoring"&&(u.fetchStatus="idle")}let{error:k,errorUpdatedAt:Q,status:y}=u;f=u.data;let O=!1;if(e.placeholderData!==void 0&&f===void 0&&y==="pending"){let v;o!=null&&o.isPlaceholderData&&e.placeholderData===(S==null?void 0:S.placeholderData)?(v=o.data,O=!0):v=typeof e.placeholderData=="function"?e.placeholderData((ft=i(this,P))==null?void 0:ft.state.data,i(this,P)):e.placeholderData,v!==void 0&&(y="success",f=vt(o==null?void 0:o.data,v,e),B=!0)}if(e.select&&f!==void 0&&!O)if(o&&f===(c==null?void 0:c.data)&&e.select===i(this,V))f=i(this,D);else try{l(this,V,e.select),f=e.select(f),f=vt(o==null?void 0:o.data,f,e),l(this,D,f),l(this,w,null)}catch(v){l(this,w,v)}i(this,w)&&(k=i(this,w),f=i(this,D),Q=Date.now(),y="error");const A=u.fetchStatus==="fetching",Y=y==="pending",Z=y==="error",ut=Y&&A,dt=f!==void 0,I={status:y,fetchStatus:u.fetchStatus,isPending:Y,isSuccess:y==="success",isError:Z,isInitialLoading:ut,isLoading:ut,data:f,dataUpdatedAt:u.dataUpdatedAt,error:k,errorUpdatedAt:Q,failureCount:u.fetchFailureCount,failureReason:u.fetchFailureReason,errorUpdateCount:u.errorUpdateCount,isFetched:t.isFetched(),isFetchedAfterMount:u.dataUpdateCount>N.dataUpdateCount||u.errorUpdateCount>N.errorUpdateCount,isFetching:A,isRefetching:A&&!Y,isLoadingError:Z&&!dt,isPaused:u.fetchStatus==="paused",isPlaceholderData:B,isRefetchError:Z&&dt,isStale:lt(t,e),refetch:this.refetch,promise:i(this,E),isEnabled:R(e.enabled,t)!==!1};if(this.options.experimental_prefetchInRender){const v=I.data!==void 0,j=I.status==="error"&&!v,K=G=>{j?G.reject(I.error):v&&G.resolve(I.data)},pt=()=>{const G=l(this,E,I.promise=gt());K(G)},J=i(this,E);switch(J.status){case"pending":t.queryHash===r.queryHash&&K(J);break;case"fulfilled":(j||I.data!==J.value)&&pt();break;case"rejected":(!j||I.error!==J.reason)&&pt();break}}return I}updateResult(){const t=i(this,g),e=this.createResult(i(this,a),this.options);if(l(this,x,i(this,a).state),l(this,U,this.options),i(this,x).data!==void 0&&l(this,P,i(this,a)),q(e,t))return;l(this,g,e);const r=()=>{if(!t)return!0;const{notifyOnChangeProps:h}=this.options,o=typeof h=="function"?h():h;if(o==="all"||!o&&!i(this,L).size)return!0;const c=new Set(o??i(this,L));return this.options.throwOnError&&c.add("error"),Object.keys(i(this,g)).some(S=>{const M=S;return i(this,g)[M]!==t[M]&&c.has(M)})};d(this,n,It).call(this,{listeners:r()})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&d(this,n,at).call(this)}},m=new WeakMap,a=new WeakMap,z=new WeakMap,g=new WeakMap,x=new WeakMap,U=new WeakMap,E=new WeakMap,w=new WeakMap,V=new WeakMap,D=new WeakMap,P=new WeakMap,_=new WeakMap,F=new WeakMap,T=new WeakMap,L=new WeakMap,n=new WeakSet,H=function(t){d(this,n,ot).call(this);let e=i(this,a).fetch(this.options,t);return t!=null&&t.throwOnError||(e=e.catch(tt)),e},st=function(){d(this,n,nt).call(this);const t=W(this.options.staleTime,i(this,a));if(et.isServer()||i(this,g).isStale||!mt(t))return;const r=Mt(i(this,g).dataUpdatedAt,t)+1;l(this,_,X.setTimeout(()=>{i(this,g).isStale||this.updateResult()},r))},it=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(i(this,a)):this.options.refetchInterval)??!1},rt=function(t){d(this,n,ht).call(this),l(this,T,t),!(et.isServer()||R(this.options.enabled,i(this,a))===!1||!mt(i(this,T))||i(this,T)===0)&&l(this,F,X.setInterval(()=>{(this.options.refetchIntervalInBackground||Qt.isFocused())&&d(this,n,H).call(this)},i(this,T)))},at=function(){d(this,n,st).call(this),d(this,n,rt).call(this,d(this,n,it).call(this))},nt=function(){i(this,_)!==void 0&&(X.clearTimeout(i(this,_)),l(this,_,void 0))},ht=function(){i(this,F)!==void 0&&(X.clearInterval(i(this,F)),l(this,F,void 0))},ot=function(){const t=i(this,m).getQueryCache().build(i(this,m),this.options);if(t===i(this,a))return;const e=i(this,a);l(this,a,t),l(this,z,t.state),this.hasListeners()&&(e==null||e.removeObserver(this),t.addObserver(this))},It=function(t){Ct.batch(()=>{t.listeners&&this.listeners.forEach(e=>{e(i(this,g))}),i(this,m).getQueryCache().notify({query:i(this,a),type:"observerResultsUpdated"})})},Et);function Ft(s,t){return R(t.enabled,s)!==!1&&s.state.data===void 0&&!(s.state.status==="error"&&R(t.retryOnMount,s)===!1)}function Rt(s,t){return Ft(s,t)||s.state.data!==void 0&&ct(s,t,t.refetchOnMount)}function ct(s,t,e){if(R(t.enabled,s)!==!1&&W(t.staleTime,s)!=="static"){const r=typeof e=="function"?e(s):e;return r==="always"||r!==!1&<(s,t)}return!1}function St(s,t,e,r){return(s!==t||R(r.enabled,s)===!1)&&(!e.suspense||s.state.status!=="error")&<(s,e)}function lt(s,t){return R(t.enabled,s)!==!1&&s.isStaleByTime(W(t.staleTime,s))}function Ut(s,t){return!q(s.getCurrentResult(),t)}var wt=C.createContext(!1),Dt=()=>C.useContext(wt);wt.Provider;function Pt(){let s=!1;return{clearReset:()=>{s=!1},reset:()=>{s=!0},isReset:()=>s}}var Lt=C.createContext(Pt()),Nt=()=>C.useContext(Lt),Bt=(s,t,e)=>{const r=e!=null&&e.state.error&&typeof s.throwOnError=="function"?Ot(s.throwOnError,[e.state.error,e]):s.throwOnError;(s.suspense||s.experimental_prefetchInRender||r)&&(t.isReset()||(s.retryOnMount=!1))},kt=s=>{C.useEffect(()=>{s.clearReset()},[s])},At=({result:s,errorResetBoundary:t,throwOnError:e,query:r,suspense:h})=>s.isError&&!t.isReset()&&!s.isFetching&&r&&(h&&s.data===void 0||Ot(e,[s.error,r])),jt=s=>{if(s.suspense){const e=h=>h==="static"?h:Math.max(h??1e3,1e3),r=s.staleTime;s.staleTime=typeof r=="function"?(...h)=>e(r(...h)):e(r),typeof s.gcTime=="number"&&(s.gcTime=Math.max(s.gcTime,1e3))}},Ht=(s,t)=>s.isLoading&&s.isFetching&&!t,Wt=(s,t)=>(s==null?void 0:s.suspense)&&t.isPending,yt=(s,t,e)=>t.fetchOptimistic(s).catch(()=>{e.clearReset()});function Xt(s,t,e){var f,k,Q,y;const r=Dt(),h=Nt(),o=_t(),c=o.defaultQueryOptions(s);(k=(f=o.getDefaultOptions().queries)==null?void 0:f._experimental_beforeQuery)==null||k.call(f,c);const S=o.getQueryCache().get(c.queryHash),M=s.subscribed!==!1;c._optimisticResults=r?"isRestoring":M?"optimistic":void 0,jt(c),Bt(c,h,S),kt(h);const N=!o.getQueryCache().get(c.queryHash),[b]=C.useState(()=>new t(o,c)),u=b.getOptimisticResult(c),B=!r&&M;if(C.useSyncExternalStore(C.useCallback(O=>{const A=B?b.subscribe(Ct.batchCalls(O)):tt;return b.updateResult(),A},[b,B]),()=>b.getCurrentResult(),()=>b.getCurrentResult()),C.useEffect(()=>{b.setOptions(c)},[c,b]),Wt(c,u))throw yt(c,b,h);if(At({result:u,errorResetBoundary:h,throwOnError:c.throwOnError,query:S,suspense:c.suspense}))throw u.error;if((y=(Q=o.getDefaultOptions().queries)==null?void 0:Q._experimental_afterQuery)==null||y.call(Q,c,u),c.experimental_prefetchInRender&&!et.isServer()&&Ht(u,r)){const O=N?yt(c,b,h):S==null?void 0:S.promise;O==null||O.catch(tt).finally(()=>{b.updateResult()})}return c.notifyOnChangeProps?u:b.trackResult(u)}export{Gt as Q,Nt as a,Bt as b,kt as c,Xt as d,jt as e,yt as f,At as g,Wt as s,Dt as u}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js index bc2b5c7c..d0aebf54 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js @@ -1 +1 @@ -import{Q as v,d as p}from"./useBaseQuery.js";import{$ as x,a0 as b}from"./App.js";var l=class extends v{constructor(e,t){super(e,t)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){e._type="infinite",super.setOptions(e)}getOptimisticResult(e){return e._type="infinite",super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"backward"}}})}createResult(e,t){var f,P;const{state:s}=e,i=super.createResult(e,t),{isFetching:a,isRefetching:g,isError:c,isRefetchError:d}=i,r=(P=(f=s.fetchMeta)==null?void 0:f.fetchMore)==null?void 0:P.direction,h=c&&r==="forward",n=a&&r==="forward",o=c&&r==="backward",u=a&&r==="backward";return{...i,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:b(t,s.data),hasPreviousPage:x(t,s.data),isFetchNextPageError:h,isFetchingNextPage:n,isFetchPreviousPageError:o,isFetchingPreviousPage:u,isRefetchError:d&&!h&&!o,isRefetching:g&&!n&&!u}}};function w(e,t){return p(e,l)}export{w as u}; +import{Q as v,d as p}from"./useBaseQuery.js";import{a0 as x,a1 as b}from"./App.js";var l=class extends v{constructor(e,t){super(e,t)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){e._type="infinite",super.setOptions(e)}getOptimisticResult(e){return e._type="infinite",super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"backward"}}})}createResult(e,t){var f,P;const{state:s}=e,i=super.createResult(e,t),{isFetching:a,isRefetching:g,isError:c,isRefetchError:d}=i,r=(P=(f=s.fetchMeta)==null?void 0:f.fetchMore)==null?void 0:P.direction,h=c&&r==="forward",n=a&&r==="forward",o=c&&r==="backward",u=a&&r==="backward";return{...i,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:b(t,s.data),hasPreviousPage:x(t,s.data),isFetchNextPageError:h,isFetchingNextPage:n,isFetchPreviousPageError:o,isFetchingPreviousPage:u,isRefetchError:d&&!h&&!o,isRefetching:g&&!n&&!u}}};function w(e,t){return p(e,l)}export{w as u}; diff --git a/tests/dashboard/test_dashboard_payload.py b/tests/dashboard/test_dashboard_payload.py index 78108dd4..fba0b2d1 100644 --- a/tests/dashboard/test_dashboard_payload.py +++ b/tests/dashboard/test_dashboard_payload.py @@ -10,7 +10,9 @@ connect, export_usage_csv, refresh_usage_index, + upsert_usage_events, ) +from tests.otel_helpers import synthetic_usage_event from tests.store_dashboard_helpers import ( _extract_js_function, _make_codex_home, @@ -658,6 +660,24 @@ def test_dashboard_and_csv_are_aggregate_only(tmp_path: Path) -> None: assert "Pricing snapshot changed since the previous dashboard render" in updated_dashboard +def test_dashboard_payload_keeps_tier_fields_aggregate_only(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + upsert_usage_events( + [ + synthetic_usage_event( + "record-a", "conversation-a", (100, 40, 30, 10), fast=1 + ) + ], + db_path=db_path, + ) + + row = dashboard_payload(db_path=db_path)["rows"][0] + + assert row["service_tier"] == "fast" + assert row["fast"] == 1 + assert "otel_source_path" not in row + + def test_dashboard_payload_contract_includes_analysis_metadata(tmp_path: Path) -> None: codex_home = _make_codex_home(tmp_path) db_path = tmp_path / "usage.sqlite3" diff --git a/tests/server/test_server_call_detail.py b/tests/server/test_server_call_detail.py index 8bd9dda5..6b59df76 100644 --- a/tests/server/test_server_call_detail.py +++ b/tests/server/test_server_call_detail.py @@ -8,6 +8,8 @@ import pytest from codex_usage_tracker.server import call_detail as server_call_detail +from codex_usage_tracker.store.api import upsert_usage_events +from tests.otel_helpers import synthetic_usage_event class _RouteSenders: @@ -153,6 +155,27 @@ def test_call_detail_payload_requires_record_id(tmp_path: Path) -> None: ) +def test_call_detail_exposes_tier_without_sidecar_identity(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + upsert_usage_events( + [ + synthetic_usage_event( + "record-a", "conversation-a", (100, 40, 30, 10), fast=1 + ) + ], + db_path=db_path, + ) + + payload = server_call_detail.call_detail_payload( + "record_id=record-a", db_path=db_path, annotate_rows=lambda rows: rows + ) + + record = payload["record"] + assert record["service_tier"] == "fast" + assert record["service_tier_confidence"] == "exact" + assert "source_path" not in record + + def test_call_detail_payload_raises_when_record_missing( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, diff --git a/tests/store/test_content_query_exports.py b/tests/store/test_content_query_exports.py index 8ca2ce01..4fcedec7 100644 --- a/tests/store/test_content_query_exports.py +++ b/tests/store/test_content_query_exports.py @@ -1,4 +1,10 @@ +from __future__ import annotations + +import csv +from pathlib import Path + from codex_usage_tracker.store import content_index +from codex_usage_tracker.store.api import export_usage_csv, upsert_usage_events from codex_usage_tracker.store.content_index_models import ContentIndexPlan, ContentIndexResult from codex_usage_tracker.store.content_persistence import ( clear_content_index_rows, @@ -9,6 +15,7 @@ search_content_fragments, ) from codex_usage_tracker.store.content_trace import ContentTraceResult, trace_thread_content +from tests.otel_helpers import synthetic_usage_event def test_content_index_preserves_query_exports() -> None: @@ -23,3 +30,28 @@ def test_content_index_preserves_query_exports() -> None: content_index.delete_content_index_rows_for_source_files is delete_content_index_rows_for_source_files ) + + +def test_csv_export_includes_additive_service_tier_fields(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + upsert_usage_events( + [ + synthetic_usage_event( + "record-a", "conversation-a", (100, 40, 30, 10), fast=1 + ) + ], + db_path=db_path, + ) + output_path = tmp_path / "usage.csv" + + export_usage_csv(output_path, db_path=db_path) + + header = next(csv.reader(output_path.read_text(encoding="utf-8").splitlines())) + assert [ + name for name in header if name.startswith("service_tier") or name == "fast" + ] == [ + "service_tier", + "fast", + "service_tier_source", + "service_tier_confidence", + ] From 05b7e17abd3ecefd0360c7e9529c1bc1e9ac26ed Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 13:59:57 -0400 Subject: [PATCH 10/24] docs: explain exact Fast usage tracking --- CHANGELOG.md | 10 ++++++++++ docs/architecture.md | 13 +++++++++++++ docs/cli-json-schemas.md | 15 +++++++++++++++ docs/dashboard-guide.md | 11 +++++++++++ docs/database-schema.md | 23 ++++++++++++++++++++++- docs/pricing-and-credits.md | 26 ++++++++++++++++++++++++++ docs/privacy.md | 15 +++++++++++++-- 7 files changed, 110 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c34db2a3..d17f06b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ ## Unreleased +- Ingest aggregate `response.completed` telemetry from local + `codex-completions*.jsonl` exporter files and conservatively reconcile exact + Fast/Standard service-tier evidence to canonical calls without retaining raw + response bodies or arbitrary OTLP attributes. +- Show exact service tier separately from the existing Fast proxy in Calls, + details, and CSV exports; older or unmatched history remains Unknown. +- Apply documented model-family Fast multipliers to confirmed Codex credit + estimates with explicit provenance while leaving USD token-cost estimates and + standard-credit allowance calibration unchanged. + ## 0.20.0 - 2026-07-16 - Reinvent the Threads tab around inline row expansion, progressively loading and virtualizing every call in the selected thread while preserving explicit investigator actions, deep links, responsive layouts, retry recovery, and aggregate-first privacy boundaries. diff --git a/docs/architecture.md b/docs/architecture.md index ca44e1fd..9537fc92 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -17,6 +17,15 @@ Shareable outputs remain aggregate-first and must omit indexed/raw content unles ## Boundaries - `parser.py` converts local JSONL events into aggregate `UsageEvent` records. It also attaches metadata-only call-origin categories, diagnostic facts from `diagnostic_facts.py`, archived-session flags, conservative thread keys, source cursors, and parser diagnostics. +- `parser/otel.py`, `store/otel_ingest.py`, and `store/otel_reconciliation.py` + provide aggregate-only completion enrichment from local + `~/.codex-usage-tracker/otel/codex-completions*.jsonl` files. The importer + retains only approved completion identifiers, token counters, model/effort, + application version, and service-tier metadata; response bodies and arbitrary + OTLP attributes are never persisted. Reconciliation requires one canonical + call group with the same conversation id and all four token counters. Model + and effort narrow a match when both sides provide them, but timestamps are not + identity evidence. - `store/content_index.py` owns normalized local content-index population and cleanup. It may persist bounded local snippets, tool-call metadata, command roots/labels, file path hashes/basenames, parser adapter metadata, source provenance, parse warnings, and FTS5 search rows. Investigation/report builders may persist bounded run summaries in `investigation_runs`. These surfaces must not feed raw/indexed content into default CSV, dashboard HTML, support bundle, or aggregate report payloads. - `call_origin.py` owns the pure call-origin classifier and migrated-row fallback. It must not open source JSONL files; source-log reads belong in refresh/indexing or explicit context loading. - `schema.py` owns persisted SQLite columns and migrations. Add columns or tables there before changing refresh, export, or MCP behavior. @@ -62,6 +71,10 @@ Shareable outputs remain aggregate-first and must omit indexed/raw content unles totals through `canonical_usage_events`. New physical-row investigation surfaces must be bounded, explicitly labeled, and tested against an original/copy/new-call fixture. +15. Treat service tier as exact only when a completion explicitly reports it, or + when Codex `0.143.0` or newer omits it under the documented Standard + protocol. Older or unmatched calls remain Unknown. Latency and reasoning + effort are useful throughput signals, not proof of Fast usage. Normal aggregate responses use a 64-entry, 256-KiB-per-entry process cache. Allowance history and diagnostics use a separate four-entry, 8-MiB-per-entry diff --git a/docs/cli-json-schemas.md b/docs/cli-json-schemas.md index 75ec4f8a..3af9ea6b 100644 --- a/docs/cli-json-schemas.md +++ b/docs/cli-json-schemas.md @@ -1466,4 +1466,19 @@ Most setup and file-writing commands accept `--json` and return a schema-specifi - `init-thresholds --json`, `init-projects --json` - `support-bundle --json` +Refresh and rebuild payloads add bounded OTel counters under +`parser_diagnostics`: `otel_files_scanned`, `otel_imported`, +`otel_duplicates`, `otel_matched`, `otel_pending`, `otel_ambiguous`, and +`otel_conflicts` (zero-valued counters may be omitted from the immediate JSON +payload). Stored refresh metadata keeps the same keys with zero defaults so +localhost status is stable. These surfaces never expose OTel source paths, +semantic fingerprints, response bodies, arbitrary attributes, or staging ids. + +Aggregate call rows may add nullable `service_tier`, `fast`, +`service_tier_source`, and `service_tier_confidence` fields. Credit-annotated +rows may also add `standard_usage_credits`, `usage_credit_multiplier`, and +`usage_credit_multiplier_source`. `fast: null` means Unknown; clients must not +replace it with the separate throughput proxy. CSV export includes both exact +tier fields and the separately named proxy candidate. + `context` already returns JSON because it is an explicit on-demand context request. Treat `codex-usage-tracker-context-v1` output as sensitive local context even though it is redacted and size-limited by default. `max_entries=0` requests all matching entries and `max_chars=0` removes the character cap for that explicit request. Tool output and compacted replacement history are omitted unless explicitly requested. Compaction entries may include metadata such as `replacement_history_available`, `replacement_entry_count`, and `replacement_history_included`; replacement text appears only when `include_compaction_history` is true for that local request. Evidence responses include `action_timing`, derived from timestamps in the same selected-turn source scan, plus per-entry `action_timing` fields such as `since_turn_start_ms`, `since_previous_entry_ms`, and `reported_duration_ms` when available. MCP returns `codex-usage-tracker-context-disabled-v1` when raw context loading has not been explicitly enabled with `CODEX_USAGE_TRACKER_ALLOW_RAW_CONTEXT=1`. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index 59fde34e..3bfe664a 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -117,6 +117,10 @@ Use `Calls` view when you want to inspect individual model calls. - Time values are shown in your browser's local date/time format while sorting and time filtering still use the logged timestamp. - Calls include `Duration`, derived from turn start for a new turn or the previous same-turn call end for continuations, and `Prev gap`, the elapsed time since the previous call in the resolved thread. - Calls view token columns separate total tokens, cached input, uncached input, and output so the accounting can be scanned without expanding a row. +- The `Service Tier` column shows `Fast` or `Standard` only when local completion + telemetry supplies exact/protocol-confirmed evidence; otherwise it shows + `Unknown`. The detail view keeps the older latency/effort heuristic labeled as + a separate Fast proxy candidate rather than presenting it as historical proof. - Source pucks are call-level estimates derived from local event metadata. `User` means the token-count segment included a user message, `Codex` means it followed tool output, compaction, or agent-continuation metadata, and `Unknown` means the source event metadata was unavailable or ambiguous. - Click a column header like `Time`, `Thread`, `Tokens`, `Cost`, or `Cache` to sort. Use the sort menu for `Highest Codex credits`. Click the same header again to reverse the direction. - Hover a row to scan a compact aggregate preview in `Call Details`; click a Calls row to open the dedicated call investigator. @@ -136,6 +140,13 @@ Useful interpretation notes: - `Cached input` and `Uncached input` are split so cache behavior is visible without storing transcript text. - A cost with `*` means the pricing row is marked as a best-guess estimate. - Codex credits are estimated from aggregate input, cached-input, and output token counters. Direct model matches use the bundled OpenAI Codex rate-card snapshot; inferred labels are marked estimated, and local credit-rate overrides are marked user-provided. +- Confirmed Fast rows apply the documented model-family multiplier to Codex + credits and show the multiplier provenance. Standard and Unknown rows remain + at `1.0x`; USD estimates are unchanged. +- CSV exports include `service_tier`, `fast`, tier source/confidence, the separate + Fast proxy flag, standard credits, and credit multiplier provenance. Missing + exact tier evidence remains blank/Unknown instead of being reconstructed from + duration or reasoning effort. - `Usage observed` is not a live account query. It uses the latest local Codex `token_count.rate_limits` snapshot when present; otherwise configure `~/.codex-usage-tracker/allowance.json` with values copied from Codex Settings > Usage, the Codex Usage dashboard, or `/status` when you want current remaining allowance context. ## Threads View diff --git a/docs/database-schema.md b/docs/database-schema.md index 890d465b..54965693 100644 --- a/docs/database-schema.md +++ b/docs/database-schema.md @@ -32,6 +32,27 @@ identity, parser coverage, replacement, and refresh revision. Changing or removi a source causes its owned physical rows/materializations to be replaced in a transaction rather than accumulated blindly. +## OTel Service-Tier Enrichment (Schema 30) + +Schema 30 adds nullable `service_tier`, `fast`, `service_tier_source`, and +`service_tier_confidence` columns to `usage_events`. Null means the tracker does +not have exact tier evidence; it is not interpreted as Standard. + +`otel_completion_sources` records device/inode identity, size, the last complete +byte and line cursor, and an update timestamp for each local +`codex-completions*.jsonl` file. `otel_completion_events` stores one semantic +fingerprint plus aggregate matching fields, normalized tier provenance, a +bounded match status (`pending`, `matched`, `ambiguous`, `conflict`, or +`invalid`), and the matched aggregate record id when available. + +Append refresh resumes after the last complete JSONL line, retries a partial +trailing line, and restarts a cursor after rotation or truncation. Rebuild keeps +the aggregate OTel staging rows, resets their match pointers, and reconciles +them against the rebuilt canonical calls. A match requires conversation id plus +input, cached-input, output, and reasoning-output counters to resolve to exactly +one canonical group. Existing contradictory tier values are preserved and the +completion is marked as a conflict. + ## Allowance Intelligence Materializations `allowance_observations` stores normalized structured weekly and 5-hour snapshots, @@ -68,7 +89,7 @@ Identical keys reuse a completed snapshot or the same in-flight job. ## Privacy And Rebuilds -Allowance materializations and logical identity contain aggregate metadata only. +Allowance materializations, OTel completion staging, and logical identity contain aggregate metadata only. They do not contain prompts, assistant text, tool output, or raw JSONL content. Rebuilds can recreate them from physical aggregate rows and source provenance. The local content index is a separate opt-in investigation layer and is not used diff --git a/docs/pricing-and-credits.md b/docs/pricing-and-credits.md index e6b05f1c..a667d11e 100644 --- a/docs/pricing-and-credits.md +++ b/docs/pricing-and-credits.md @@ -62,6 +62,28 @@ codex-usage-tracker update-rate-card The local snapshot is written to `~/.codex-usage-tracker/rate-card.json`. Each bundled rate and alias includes source URL, fetched date, tier, confidence, and alias rationale where applicable. Use `--source-file` only when you have a reviewed replacement JSON snapshot you want the tracker to validate and use. +### Confirmed Fast Usage + +When a call has exact OTel evidence that `fast=1`, the tracker first computes +`standard_usage_credits`, then applies the documented model-family Fast +multiplier to produce `usage_credits`: + +- GPT-5.6 family: `2.5x` +- GPT-5.5 family: `2.5x` +- GPT-5.4 family: `2.0x` + +The row also exposes `usage_credit_multiplier` and +`usage_credit_multiplier_source` so the adjustment is auditable. A confirmed +Fast call whose model has no documented multiplier stays at `1.0x` and is +marked `no_documented_fast_multiplier`; the tracker does not guess. Standard +and Unknown-tier calls also stay at `1.0x`. + +This adjustment applies only to Codex/ChatGPT usage-credit estimates. It never +changes USD token-cost estimates, because those continue to use the selected +pricing tier and aggregate token counters. Allowance-drain calibration uses the +standard-credit baseline so a newly observed Fast label does not redefine the +historical credit-to-percentage relationship. + ## Usage Observed `Usage observed` is different from `Codex Credits`. The tracker cannot currently read your logged-in ChatGPT plan, live remaining credits, reset windows, or usage from other agentic surfaces automatically. @@ -90,6 +112,10 @@ Configure the usage component: - Codex upstream log formats can change, and parser compatibility may require tracker updates before new event shapes are fully understood. - Pricing and rate-card sources can change outside this project. Refresh or pin local files when reports need a known source snapshot. - Local Codex logs may not include usage from other ChatGPT agentic surfaces that share the same allowance. +- Service tier is exact only when a local completion explicitly reports it or + Codex `0.143.0` or newer establishes Standard through omission. Older or + unmatched history remains Unknown; latency and reasoning effort cannot prove + Fast usage. - Live account allowance cannot be read automatically by this local tracker, and the dashboard does not infer live remaining allowance from the logged-in account plan. - Observed local-log snapshots may be stale until Codex records another model call, and may omit other agentic surfaces that share the same allowance. - Pricing can change after a report is generated. Use `pin-pricing` when you need reproducible historical cost estimates. diff --git a/docs/privacy.md b/docs/privacy.md index 4fca5c42..4f912cb5 100644 --- a/docs/privacy.md +++ b/docs/privacy.md @@ -22,11 +22,22 @@ The local SQLite database is stored at `~/.codex-usage-tracker/usage.sqlite3` by quality/coverage metrics, source revisions, and persisted statistical results - diagnostic fact labels tied to aggregate call records, safe event categories, payload type labels, counts, timestamps, and line ranges - pricing, credit, allowance, recommendation, and project metadata derived from aggregate fields +- aggregate OTel completion identifiers, token counters, normalized service + tier/provenance, application version, semantic fingerprints, source cursors, + and bounded reconciliation status from local + `~/.codex-usage-tracker/otel/codex-completions*.jsonl` files - normalized local content-index rows for local investigation, including conversation turns, bounded content fragments, tool calls, command runs, file events, source provenance, parser adapter metadata, parser warnings, and FTS5 search rows when SQLite supports FTS5 - bounded local investigation run summaries, including run kind, schema id, content-mode flags, strict summary JSON, branch counts, evidence counts, and timestamps The content index is intended for local MCP/API exploration. It is not a hosted collection system and it does not change where the original Codex logs live. Normalized command and file-event rows store command roots/labels plus path hashes/basenames rather than full shell commands or full paths; bounded raw snippets remain confined to `content_fragments`. +The OTel completion reader accepts only `codex.sse_event` / +`response.completed` aggregate fields needed for conservative call matching and +tier classification. It never persists OTLP response bodies or arbitrary +attributes. Default exports do not expose staging fingerprints, source paths, +or matched record pointers. Support bundles report only whether the configured +completion directory exists and bounded aggregate refresh/reconciliation counts. + Cloned Codex tasks can copy historical calls into another local JSONL file. The tracker keeps every physical row and its source metadata in SQLite, but default dashboard, CLI, MCP, report, recommendation, allowance, compression, and export totals use one canonical representative for strict fingerprint matches. Similar calls are never excluded on fuzzy evidence. Deduplication diagnostics expose aggregate totals plus bounded provenance metadata for excluded rows; they never include prompt, response, tool-output, or raw-log content. ## Shareable Outputs @@ -112,7 +123,7 @@ The report pack contains aggregate report definitions, linked aggregate call rows, a schema marker, and a server generation timestamp. It does not include prompts, assistant text, tool output, command output, or indexed content. -Source JSONL reads happen during refresh/indexing, explicit on-demand context loading for one selected call, and explicit synthetic benchmark/diagnostic runs. Live refresh records source metadata and parser cursors so unchanged logs can be skipped and append-only growth can parse from the last indexed byte. Live aggregate APIs do not return indexed content unless an endpoint is explicitly documented as a local content investigation endpoint. +Source JSONL reads happen during refresh/indexing, explicit on-demand context loading for one selected call, and explicit synthetic benchmark/diagnostic runs. Refresh also reads only local `codex-completions*.jsonl` OTLP exporter files for aggregate service-tier enrichment. Live refresh records source metadata and parser cursors so unchanged logs can be skipped and append-only growth can parse from the last indexed byte. Live aggregate APIs do not return indexed content unless an endpoint is explicitly documented as a local content investigation endpoint. ## Privacy Modes @@ -142,7 +153,7 @@ Strict mode redacts local diagnostic path strings in bundle doctor details while Cost estimates are calculated only from aggregate token fields and your local pricing config. They are omitted when no matching model price is configured. Pricing refreshes pull only OpenAI's public pricing markdown and do not send local usage data anywhere. -Codex credit estimates are calculated only from aggregate token fields and bundled or locally configured rate-card values. The optional allowance config stores only remaining percentages, reset times, and credit totals you manually enter. Observed rate-limit snapshots, when present in Codex token-count logs, store only structured percentages, window lengths, reset times, plan type, and limit id. +Codex credit estimates are calculated only from aggregate token fields and bundled or locally configured rate-card values. Confirmed Fast calls may apply the documented model-family credit multiplier; this does not change USD token-cost estimates. The optional allowance config stores only remaining percentages, reset times, and credit totals you manually enter. Observed rate-limit snapshots, when present in Codex token-count logs, store only structured percentages, window lengths, reset times, plan type, and limit id. Allowance calibration and forecasts use canonical aggregate credits and observed percentages. A displayed credits-per-percent value is a personal historical From c9012e9c6d038eabe6908c6920d231f6d53a665b Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 14:02:04 -0400 Subject: [PATCH 11/24] test: track current schema in migration coverage --- tests/store/test_compression_runs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/store/test_compression_runs.py b/tests/store/test_compression_runs.py index 327963a3..c8388079 100644 --- a/tests/store/test_compression_runs.py +++ b/tests/store/test_compression_runs.py @@ -28,7 +28,7 @@ update_compression_run, ) from codex_usage_tracker.store.connection import connect -from codex_usage_tracker.store.schema import init_db +from codex_usage_tracker.store.schema import SCHEMA_VERSION, init_db class CacheKey(TypedDict): @@ -171,7 +171,7 @@ def test_candidate_record_metadata_migration_backfills_existing_claims( conn.execute("PRAGMA user_version = 18") with connect(db_path) as conn: init_db(conn) - assert conn.execute("PRAGMA user_version").fetchone()[0] == 29 + assert conn.execute("PRAGMA user_version").fetchone()[0] == SCHEMA_VERSION with connect(db_path) as conn: conn.execute("DELETE FROM usage_events WHERE record_id = ?", ("record-cmp_old",)) From dd87b10927fbdb0009905ab53fe2c70e46226f15 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 14:09:57 -0400 Subject: [PATCH 12/24] refactor: extract dashboard tier normalization --- .../dashboard-source-baseline.json | 6 +-- frontend/dashboard/src/api/client.ts | 18 +------- frontend/dashboard/src/api/serviceTier.ts | 45 +++++++++++++++++++ frontend/dashboard/src/api/types.ts | 21 ++------- .../CallInvestigatorPage.tsx | 3 +- .../src/features/calls/serviceTier.ts | 17 +------ .../src/features/shared/callPresentation.ts | 21 +++++++++ .../dashboard/src/features/shared/tables.tsx | 2 +- .../plugin_data/dashboard/react/assets/App.js | 12 ++--- .../react/assets/CallInvestigatorPage.js | 4 +- .../dashboard/react/assets/CallsPage.js | 4 +- .../dashboard/react/assets/SettingsPage.js | 2 +- .../react/assets/contextEvidenceState.js | 2 +- .../dashboard/react/assets/dashboardRouter.js | 2 +- .../dashboard/react/assets/useBaseQuery.js | 2 +- .../react/assets/useInfiniteQuery.js | 2 +- 16 files changed, 92 insertions(+), 71 deletions(-) create mode 100644 frontend/dashboard/src/api/serviceTier.ts diff --git a/.agent-maintainer/dashboard-source-baseline.json b/.agent-maintainer/dashboard-source-baseline.json index 5629614b..a127fc36 100644 --- a/.agent-maintainer/dashboard-source-baseline.json +++ b/.agent-maintainer/dashboard-source-baseline.json @@ -13,12 +13,12 @@ "frontend/dashboard/src/api/client.ts": { "group": "source", "nonblank": 765, - "physical": 826 + "physical": 825 }, "frontend/dashboard/src/api/types.ts": { "group": "source", - "nonblank": 424, - "physical": 450 + "nonblank": 423, + "physical": 449 }, "frontend/dashboard/src/app/zh-Hans/advancedPages.ts": { "group": "source", diff --git a/frontend/dashboard/src/api/client.ts b/frontend/dashboard/src/api/client.ts index 33006929..6c27caea 100644 --- a/frontend/dashboard/src/api/client.ts +++ b/frontend/dashboard/src/api/client.ts @@ -8,6 +8,7 @@ import { import { buildFindings, buildModelCosts, buildReports } from './modelInsights'; import { buildOverviewSeriesFromDailyValues } from './overviewSeries'; import { scopeSummaryFromBootPayload, summaryNumber } from './dashboardScopeSummary'; +import { usageServiceTierFields } from './serviceTier'; import type { CallRow, ContextRuntime, DashboardBootPayload, DashboardModel, MetricCard, Series, ThreadRow, UsageRow, WeeklyWindow } from './types'; import { loadAllUsagePayloadPaged, @@ -537,13 +538,6 @@ export function usageRowToCall(row: UsageRow, index = 0): CallRow { const contextWindowPct = percentNumber(row.context_window_percent); const modelContextWindow = Number(row.model_context_window); const cumulativeTotalTokens = Number(row.cumulative_total_tokens); - const rawFast = row.fast; - const exactFast = rawFast === true || rawFast === 1 - ? true - : rawFast === false || rawFast === 0 - ? false - : null; - return { id, threadKey: String(row.thread_key ?? ''), @@ -562,7 +556,6 @@ export function usageRowToCall(row: UsageRow, index = 0): CallRow { uncachedInput, cachedPct, cost: Number(row.estimated_cost_usd ?? 0), - credits: Number(row.usage_credits ?? 0), duration: formatDuration(durationSeconds), durationSeconds, previousCallGap: formatDuration(previousCallGapSeconds), @@ -571,14 +564,7 @@ export function usageRowToCall(row: UsageRow, index = 0): CallRow { initiator: String(row.call_initiator ?? 'unknown'), initiatorReason: String(row.call_initiator_reason ?? ''), initiatorConfidence: String(row.call_initiator_confidence ?? ''), - serviceTier: String(row.service_tier ?? ''), - fast: exactFast, - serviceTierSource: String(row.service_tier_source ?? ''), - serviceTierConfidence: String(row.service_tier_confidence ?? ''), - fastProxyCandidate: durationSeconds > 0 && totalTokens / Math.max(durationSeconds, 1) > 4_000, - standardUsageCredits: Number(row.standard_usage_credits ?? row.usage_credits ?? 0), - usageCreditMultiplier: Number(row.usage_credit_multiplier ?? 1), - usageCreditMultiplierSource: String(row.usage_credit_multiplier_source ?? ''), + ...usageServiceTierFields(row, durationSeconds, totalTokens), usageCreditConfidence: String(row.usage_credit_confidence ?? 'unknown'), usageCreditModel: String(row.usage_credit_model ?? ''), usageCreditSource: String(row.usage_credit_source ?? ''), diff --git a/frontend/dashboard/src/api/serviceTier.ts b/frontend/dashboard/src/api/serviceTier.ts new file mode 100644 index 00000000..f6ec3dc9 --- /dev/null +++ b/frontend/dashboard/src/api/serviceTier.ts @@ -0,0 +1,45 @@ +export type UsageServiceTierFields = { + standard_usage_credits?: number | null; + usage_credit_multiplier?: number | null; + usage_credit_multiplier_source?: string | null; + service_tier?: string | null; + fast?: number | boolean | null; + service_tier_source?: string | null; + service_tier_confidence?: string | null; +}; + +export type CallServiceTierFields = { + credits: number; + serviceTier: string; + fast: boolean | null; + serviceTierSource: string; + serviceTierConfidence: string; + fastProxyCandidate: boolean; + standardUsageCredits: number; + usageCreditMultiplier: number; + usageCreditMultiplierSource: string; +}; + +export function usageServiceTierFields( + row: UsageServiceTierFields & { usage_credits?: number }, + durationSeconds: number, + totalTokens: number, +): CallServiceTierFields { + const rawFast = row.fast; + const fast = rawFast === true || rawFast === 1 + ? true + : rawFast === false || rawFast === 0 + ? false + : null; + return { + credits: Number(row.usage_credits ?? 0), + serviceTier: String(row.service_tier ?? ''), + fast, + serviceTierSource: String(row.service_tier_source ?? ''), + serviceTierConfidence: String(row.service_tier_confidence ?? ''), + fastProxyCandidate: durationSeconds > 0 && totalTokens / Math.max(durationSeconds, 1) > 4_000, + standardUsageCredits: Number(row.standard_usage_credits ?? row.usage_credits ?? 0), + usageCreditMultiplier: Number(row.usage_credit_multiplier ?? 1), + usageCreditMultiplierSource: String(row.usage_credit_multiplier_source ?? ''), + }; +} diff --git a/frontend/dashboard/src/api/types.ts b/frontend/dashboard/src/api/types.ts index 8dc8460b..948f57d5 100644 --- a/frontend/dashboard/src/api/types.ts +++ b/frontend/dashboard/src/api/types.ts @@ -1,6 +1,7 @@ import type { DashboardDataScope, DashboardModelScope } from './dashboardDataScope'; +import type { CallServiceTierFields, UsageServiceTierFields } from './serviceTier'; -export type UsageRow = { +export type UsageRow = UsageServiceTierFields & { id?: string; record_id?: string; session_id?: string; @@ -44,13 +45,6 @@ export type UsageRow = { uncached_input_tokens?: number; estimated_cost_usd?: number; usage_credits?: number; - standard_usage_credits?: number | null; - usage_credit_multiplier?: number | null; - usage_credit_multiplier_source?: string | null; - service_tier?: string | null; - fast?: number | boolean | null; - service_tier_source?: string | null; - service_tier_confidence?: string | null; rate_limit_plan_type?: string | null; rate_limit_limit_id?: string | null; rate_limit_primary_used_percent?: number | null; @@ -297,7 +291,7 @@ export type Finding = { summary: string; }; -export type CallRow = { +export type CallRow = CallServiceTierFields & { id: string; threadKey?: string; rawTime: string; @@ -315,7 +309,6 @@ export type CallRow = { uncachedInput: number; cachedPct: number; cost: number; - credits: number; duration: string; durationSeconds: number; previousCallGap: string; @@ -324,14 +317,6 @@ export type CallRow = { initiator: string; initiatorReason: string; initiatorConfidence: string; - serviceTier: string; - fast: boolean | null; - serviceTierSource: string; - serviceTierConfidence: string; - fastProxyCandidate: boolean; - standardUsageCredits: number; - usageCreditMultiplier: number; - usageCreditMultiplierSource: string; usageCreditConfidence: string; usageCreditModel: string; usageCreditSource: string; diff --git a/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx b/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx index 7c248e7b..40de7fa5 100644 --- a/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx +++ b/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx @@ -7,7 +7,6 @@ import { enableContextApi, loadCallContext, type ContextRequestOptions } from '. import type { CallContextEntry, CallContextPayload, CallRow, ContextRuntime, DashboardModel } from '../../api/types'; import { Panel } from '../../components/Panel'; import { StatusBadge } from '../../components/StatusBadge'; -import { serviceTierDetail } from '../calls/serviceTier'; import { CallCacheDelta } from '../shared/CallCacheDelta'; import { CallDecisionCard } from '../shared/CallDecisionCard'; import { ContextAttributionModule } from '../shared/ContextAttributionModule'; @@ -15,7 +14,7 @@ import { ContextEntryMetadata } from '../shared/ContextEntryMetadata'; import { CallSourceMetadata } from '../shared/CallSourceMetadata'; import { TokenPricingBreakdown } from '../shared/TokenPricingBreakdown'; import { ThreadCallTimeline } from '../shared/ThreadCallTimeline'; -import { cacheState, contextWindowLabel, sourceLine, summarizeTopCounts } from '../shared/callPresentation'; +import { cacheState, contextWindowLabel, serviceTierDetail, sourceLine, summarizeTopCounts } from '../shared/callPresentation'; import { copyText } from '../shared/copyText'; import { CallSignalPucks } from '../shared/tables'; import { diff --git a/frontend/dashboard/src/features/calls/serviceTier.ts b/frontend/dashboard/src/features/calls/serviceTier.ts index eea43f7d..1c693985 100644 --- a/frontend/dashboard/src/features/calls/serviceTier.ts +++ b/frontend/dashboard/src/features/calls/serviceTier.ts @@ -1,16 +1 @@ -import type { CallRow } from '../../api/types'; - -export function serviceTierLabel(call: CallRow): 'Fast' | 'Standard' | 'Unknown' { - if (call.fast === true) return 'Fast'; - if (call.fast === false) return 'Standard'; - return 'Unknown'; -} - -export function serviceTierDetail(call: CallRow): string { - if (call.fast !== null) { - return `confirmed ${serviceTierLabel(call)} · ${call.serviceTierConfidence || 'exact'}`; - } - return call.fastProxyCandidate - ? 'tier unknown · Fast proxy candidate' - : 'tier unknown · normal throughput proxy'; -} +export { serviceTierDetail, serviceTierLabel } from '../shared/callPresentation'; diff --git a/frontend/dashboard/src/features/shared/callPresentation.ts b/frontend/dashboard/src/features/shared/callPresentation.ts index 41b1e0e8..4f881304 100644 --- a/frontend/dashboard/src/features/shared/callPresentation.ts +++ b/frontend/dashboard/src/features/shared/callPresentation.ts @@ -16,6 +16,27 @@ type ContextWindowInput = { type TopCountStyle = 'parenthetical' | 'x'; +type ServiceTierInput = { + fast: boolean | null; + serviceTierConfidence: string; + fastProxyCandidate: boolean; +}; + +export function serviceTierLabel(call: ServiceTierInput): 'Fast' | 'Standard' | 'Unknown' { + if (call.fast === true) return 'Fast'; + if (call.fast === false) return 'Standard'; + return 'Unknown'; +} + +export function serviceTierDetail(call: ServiceTierInput): string { + if (call.fast !== null) { + return `confirmed ${serviceTierLabel(call)} · ${call.serviceTierConfidence || 'exact'}`; + } + return call.fastProxyCandidate + ? 'tier unknown · Fast proxy candidate' + : 'tier unknown · normal throughput proxy'; +} + export function cacheState(call: CacheStateInput): string { if (call.cachedPct < 25) return 'cold or weak cache'; if (call.cachedPct < 50) return 'partial cache reuse'; diff --git a/frontend/dashboard/src/features/shared/tables.tsx b/frontend/dashboard/src/features/shared/tables.tsx index 15a0e310..68281742 100644 --- a/frontend/dashboard/src/features/shared/tables.tsx +++ b/frontend/dashboard/src/features/shared/tables.tsx @@ -2,8 +2,8 @@ import type { ColumnDef } from '@tanstack/react-table'; import { useShellI18n } from '../../app/i18nContext'; import type { CallRow, ThreadRow } from '../../api/types'; import type { ColumnChoice } from '../../components/ColumnChooser'; -import { serviceTierLabel } from '../calls/serviceTier'; import type { CsvColumn } from './exportCsv'; +import { serviceTierLabel } from './callPresentation'; import { formatCompact, formatNumber, money, pct } from './format'; export { callActionColumn, callInvestigatorRowLabel, threadActionColumn, threadInvestigatorRowLabel } from './tableActions'; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js index aea09e6d..a8334962 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js @@ -1,10 +1,10 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ThreadsPage.js","assets/dashboard-react.js","assets/index.css","assets/useInfiniteQuery.js","assets/useBaseQuery.js","assets/exploreQueries.js","assets/queryOptions.js","assets/infiniteQueryOptions.js","assets/ExploreWorkspaceSwitcher.js","assets/Primitives.js","assets/Primitives.css","assets/EvidenceGridControls.js","assets/router.js","assets/EvidenceGridControls.css","assets/filtering.js","assets/threadSummaryAdapter.js","assets/UsageConstellation.js","assets/triangle-alert.js","assets/UsageConstellation.css","assets/StatusBadge.js","assets/PageLoadProgress.js","assets/PageLoadProgress.css","assets/index2.js","assets/rowActionEvents.js","assets/search.js","assets/locale-zh-Hans.js","assets/dashboardRouter.js","assets/ThreadsPage.css","assets/CacheContextPage.js","assets/LineChart.js","assets/DataTable.js","assets/overviewQueries.js","assets/gauge.js","assets/Panel.js","assets/useQuery.js","assets/tableActions.js","assets/UsageDrainPage.js","assets/chevron-right.js","assets/shield-check.js","assets/UsageDrainPage.css","assets/DiagnosticsPage.js","assets/diagnosticsQueries.js","assets/ReportsPage.js","assets/ReportsPage.css","assets/CallsPage.js","assets/EvidenceGrid.js","assets/contextEvidenceState.js","assets/lock-keyhole.js","assets/CallsPage.css","assets/OverviewPage.js","assets/OverviewPage.css","assets/InvestigatorPage.js","assets/InvestigatorPage.css","assets/CompressionLabPage.js","assets/CompressionLabPage.css","assets/ExploreRoutePage.js","assets/ExploreRoutePage.css","assets/CallInvestigatorPage.js","assets/SettingsPage.js","assets/SettingsPage.css"])))=>i.map(i=>d[i]); -var Ka=e=>{throw TypeError(e)};var Kt=(e,t,a)=>t.has(e)||Ka("Cannot "+a);var l=(e,t,a)=>(Kt(e,t,"read from private field"),a?a.call(e):t.get(e)),j=(e,t,a)=>t.has(e)?Ka("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,a),k=(e,t,a,n)=>(Kt(e,t,"write to private field"),n?n.call(e,a):t.set(e,a),a),V=(e,t,a)=>(Kt(e,t,"access private method"),a);var St=(e,t,a,n)=>({set _(r){k(e,t,r,a)},get _(){return l(e,t,n)}});import{r as C,j as c,_ as O}from"./dashboard-react.js";import{t as bs}from"./locale-zh-Hans.js";import{i as ws}from"./dashboardRouter.js";import{a9 as se}from"./router.js";/** +var qn=e=>{throw TypeError(e)};var Kt=(e,t,n)=>t.has(e)||qn("Cannot "+n);var l=(e,t,n)=>(Kt(e,t,"read from private field"),n?n.call(e):t.get(e)),P=(e,t,n)=>t.has(e)?qn("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),x=(e,t,n,a)=>(Kt(e,t,"write to private field"),a?a.call(e,n):t.set(e,n),n),V=(e,t,n)=>(Kt(e,t,"access private method"),n);var Ct=(e,t,n,a)=>({set _(r){x(e,t,r,n)},get _(){return l(e,t,a)}});import{r as C,j as c,_ as O}from"./dashboard-react.js";import{t as bs}from"./locale-zh-Hans.js";import{i as ws}from"./dashboardRouter.js";import{a9 as se}from"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const ys=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),Nn=(...e)=>e.filter((t,a,n)=>!!t&&t.trim()!==""&&n.indexOf(t)===a).join(" ").trim();/** + */const ys=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),Na=(...e)=>e.filter((t,n,a)=>!!t&&t.trim()!==""&&a.indexOf(t)===n).join(" ").trim();/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. @@ -14,12 +14,12 @@ var Ka=e=>{throw TypeError(e)};var Kt=(e,t,a)=>t.has(e)||Ka("Cannot "+a);var l=( * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ss=C.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:a=2,absoluteStrokeWidth:n,className:r="",children:s,iconNode:i,...o},h)=>C.createElement("svg",{ref:h,..._s,width:t,height:t,stroke:e,strokeWidth:n?Number(a)*24/Number(t):a,className:Nn("lucide",r),...o},[...i.map(([f,d])=>C.createElement(f,d)),...Array.isArray(s)?s:[s]]));/** + */const Ss=C.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:n=2,absoluteStrokeWidth:a,className:r="",children:s,iconNode:i,...o},d)=>C.createElement("svg",{ref:d,..._s,width:t,height:t,stroke:e,strokeWidth:a?Number(n)*24/Number(t):n,className:Na("lucide",r),...o},[...i.map(([f,h])=>C.createElement(f,h)),...Array.isArray(s)?s:[s]]));/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const I=(e,t)=>{const a=C.forwardRef(({className:n,...r},s)=>C.createElement(Ss,{ref:s,iconNode:t,className:Nn(`lucide-${ys(e)}`,n),...r}));return a.displayName=`${e}`,a};/** + */const I=(e,t)=>{const n=C.forwardRef(({className:a,...r},s)=>C.createElement(Ss,{ref:s,iconNode:t,className:Na(`lucide-${ys(e)}`,a),...r}));return n.displayName=`${e}`,n};/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. @@ -124,5 +124,5 @@ var Ka=e=>{throw TypeError(e)};var Kt=(e,t,a)=>t.has(e)||Ka("Cannot "+a);var l=( * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const la=I("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),En="codex-usage-dashboard-language",qs={"button.back_to_dashboard":"Back to dashboard","button.clear":"Clear","button.copy_link":"Copy link","button.enable_context_loading":"Enable context loading","button.export_csv":"Export CSV","button.full_serialized_analysis":"Run full serialized analysis","button.hide_details":"Hide details","button.include_tool_output":"Include tool output","button.load_more":"Load more","button.load_older_context":"Load older entries","button.next_call":"Next call","button.no_char_limit":"No char limit","button.open_investigator":"Open investigator","button.previous_call":"Previous call","button.refresh":"Refresh","button.show_compaction_history":"Show compacted replacement","button.show_tool_output":"Show tool output","button.top":"Top","button.show_turn_evidence":"Show turn log evidence","badge.live":"Live","dashboard.eyebrow":"Local Codex analytics","dashboard.call_details":"Call Details","dashboard.title":"Usage Dashboard","dashboard.view.call":"Call Investigator","dashboard.view.calls":"Calls","dashboard.view.insights":"Overview","dashboard.view.overview":"Overview","dashboard.view.threads":"Threads","detail.next_action":"Next action","filter.search":"Search dashboard","filter.search_placeholder":"Search calls, threads, models, diagnostics...","language.label":"Language","nav.history":"History","nav.load":"Load","nav.live":"Live","option.active_sessions_only":"Active","option.all_history":"All history","status.paused":"Paused","status.static":"Static"},Hs={overview:"dashboard.view.overview",calls:"dashboard.view.calls",call:"dashboard.view.call",threads:"dashboard.view.threads"};function Al(e,t){return typeof t=="string"?e.translateText(t):e.formatText(t.template,t.values)}function Dn(e,t){const a=Fn(e),n=In(t,a),r=(e==null?void 0:e.translation_catalog)??{},s=r[n]??((e==null?void 0:e.language)===n?e==null?void 0:e.translations:void 0)??{},i=r.en??((e==null?void 0:e.language)==="en"?e.translations:void 0)??{},o={...qs,...i,...s},h=Ws(i,s),f=Qs(i,s),d=a.find(p=>p.code===n),b=(d==null?void 0:d.dir)==="rtl"||!d&&(e==null?void 0:e.language_direction)==="rtl"?"rtl":"ltr",u=p=>n==="zh-Hans"?bs(p,h,f):h.get(p)??p;return{language:n,direction:b,languages:a,t:(p,g)=>o[p]??g??p,translateText:u,formatText:(p,g)=>u(p).replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu,(v,w)=>String(g[String(w)]??v)),navLabel:(p,g)=>{const v=Hs[p];return v?o[v]??g:g}}}function Qs(e,t){const a=[];for(const[n,r]of Object.entries(e)){const s=t[n];if(!s||s===r||!r.includes("{"))continue;const i=[],o=[];let h=0;for(const f of r.matchAll(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu)){const d=f.index??h;o.push(qa(r.slice(h,d))),o.push("(.+?)"),i.push(f[1]),h=d+f[0].length}o.push(qa(r.slice(h))),a.push({pattern:new RegExp(`^${o.join("")}$`,"u"),placeholders:i,translatedTemplate:s})}return a.sort((n,r)=>r.translatedTemplate.length-n.translatedTemplate.length)}function qa(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function Ws(e,t){const a=new Map;for(const[n,r]of Object.entries(e)){const s=t[n];s&&s!==r&&a.set(r,s)}return a}function Fn(e){var a;const t=((a=e==null?void 0:e.available_languages)==null?void 0:a.filter(n=>n.code))??[];return t.length?t:[{code:"en",english_name:"English",native_name:"English",dir:"ltr"}]}function zs(e){return In(Gs()||(e==null?void 0:e.language)||"en",Fn(e))}function Bs(e){var t;try{(t=window.localStorage)==null||t.setItem(En,e)}catch{}}function Gs(){var e;try{return((e=window.localStorage)==null?void 0:e.getItem(En))??""}catch{return""}}function In(e,t){if(new Set(t.map(s=>s.code)).has(e))return e;const n=e.toLowerCase(),r=t.find(s=>s.code.toLowerCase()===n);return(r==null?void 0:r.code)??"en"}const Js=Dn(null,"en"),$n=C.createContext(Js);function Zs({value:e,children:t}){return c.jsx($n.Provider,{value:e,children:t})}function On(){return C.useContext($n)}var Et=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Ne,be,Be,xn,Xs=(xn=class extends Et{constructor(){super();j(this,Ne);j(this,be);j(this,Be);k(this,Be,t=>{if(typeof window<"u"&&window.addEventListener){const a=()=>t();return window.addEventListener("visibilitychange",a,!1),()=>{window.removeEventListener("visibilitychange",a)}}})}onSubscribe(){l(this,be)||this.setEventListener(l(this,Be))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,be))==null||t.call(this),k(this,be,void 0))}setEventListener(t){var a;k(this,Be,t),(a=l(this,be))==null||a.call(this),k(this,be,t(n=>{typeof n=="boolean"?this.setFocused(n):this.onFocus()}))}setFocused(t){l(this,Ne)!==t&&(k(this,Ne,t),this.onFocus())}onFocus(){const t=this.isFocused();this.listeners.forEach(a=>{a(t)})}isFocused(){var t;return typeof l(this,Ne)=="boolean"?l(this,Ne):((t=globalThis.document)==null?void 0:t.visibilityState)!=="hidden"}},Ne=new WeakMap,be=new WeakMap,Be=new WeakMap,xn),Un=new Xs,Ys={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},we,ca,kn,ei=(kn=class{constructor(){j(this,we,Ys);j(this,ca,!1)}setTimeoutProvider(e){k(this,we,e)}setTimeout(e,t){return l(this,we).setTimeout(e,t)}clearTimeout(e){l(this,we).clearTimeout(e)}setInterval(e,t){return l(this,we).setInterval(e,t)}clearInterval(e){l(this,we).clearInterval(e)}},we=new WeakMap,ca=new WeakMap,kn),Bt=new ei;function ti(e){setTimeout(e,0)}var ai=typeof window>"u"||"Deno"in globalThis;function ae(){}function ni(e,t){return typeof e=="function"?e(t):e}function ri(e){return typeof e=="number"&&e>=0&&e!==1/0}function si(e,t){return Math.max(e+(t||0)-Date.now(),0)}function Gt(e,t){return typeof e=="function"?e(t):e}function ii(e,t){return typeof e=="function"?e(t):e}function Ha(e,t){const{type:a="all",exact:n,fetchStatus:r,predicate:s,queryKey:i,stale:o}=e;if(i){if(n){if(t.queryHash!==ua(i,t.options))return!1}else if(!ut(t.queryKey,i))return!1}if(a!=="all"){const h=t.isActive();if(a==="active"&&!h||a==="inactive"&&h)return!1}return!(typeof o=="boolean"&&t.isStale()!==o||r&&r!==t.state.fetchStatus||s&&!s(t))}function Qa(e,t){const{exact:a,status:n,predicate:r,mutationKey:s}=e;if(s){if(!t.options.mutationKey)return!1;if(a){if(lt(t.options.mutationKey)!==lt(s))return!1}else if(!ut(t.options.mutationKey,s))return!1}return!(n&&t.state.status!==n||r&&!r(t))}function ua(e,t){return((t==null?void 0:t.queryKeyHashFn)||lt)(e)}function lt(e){return JSON.stringify(e,(t,a)=>Jt(a)?Object.keys(a).sort().reduce((n,r)=>(n[r]=a[r],n),{}):a)}function ut(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="object"&&typeof t=="object"?Object.keys(t).every(a=>ut(e[a],t[a])):!1}var oi=Object.prototype.hasOwnProperty;function Vn(e,t,a=0){if(e===t)return e;if(a>500)return t;const n=Wa(e)&&Wa(t);if(!n&&!(Jt(e)&&Jt(t)))return t;const s=(n?e:Object.keys(e)).length,i=n?t:Object.keys(t),o=i.length,h=n?new Array(o):{};let f=0;for(let d=0;d{Bt.setTimeout(t,e)})}function li(e,t,a){return typeof a.structuralSharing=="function"?a.structuralSharing(e,t):a.structuralSharing!==!1?Vn(e,t):t}function ui(e,t,a=0){const n=[...e,t];return a&&n.length>a?n.slice(1):n}function di(e,t,a=0){const n=[t,...e];return a&&n.length>a?n.slice(0,-1):n}var da=Symbol();function Kn(e,t){return!e.queryFn&&(t!=null&&t.initialPromise)?()=>t.initialPromise:!e.queryFn||e.queryFn===da?()=>Promise.reject(new Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function El(e,t){return typeof e=="function"?e(...t):!!e}function hi(e,t,a){let n=!1,r;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(r??(r=t()),n||(n=!0,r.aborted?a():r.addEventListener("abort",a,{once:!0})),r)}),e}var qn=(()=>{let e=()=>ai;return{isServer(){return e()},setIsServer(t){e=t}}})();function fi(){let e,t;const a=new Promise((r,s)=>{e=r,t=s});a.status="pending",a.catch(()=>{});function n(r){Object.assign(a,r),delete a.resolve,delete a.reject}return a.resolve=r=>{n({status:"fulfilled",value:r}),e(r)},a.reject=r=>{n({status:"rejected",reason:r}),t(r)},a}var mi=ti;function gi(){let e=[],t=0,a=o=>{o()},n=o=>{o()},r=mi;const s=o=>{t?e.push(o):r(()=>{a(o)})},i=()=>{const o=e;e=[],o.length&&r(()=>{n(()=>{o.forEach(h=>{a(h)})})})};return{batch:o=>{let h;t++;try{h=o()}finally{t--,t||i()}return h},batchCalls:o=>(...h)=>{s(()=>{o(...h)})},schedule:s,setNotifyFunction:o=>{a=o},setBatchNotifyFunction:o=>{n=o},setScheduler:o=>{r=o}}}var z=gi(),Ge,ye,Je,Tn,pi=(Tn=class extends Et{constructor(){super();j(this,Ge,!0);j(this,ye);j(this,Je);k(this,Je,t=>{if(typeof window<"u"&&window.addEventListener){const a=()=>t(!0),n=()=>t(!1);return window.addEventListener("online",a,!1),window.addEventListener("offline",n,!1),()=>{window.removeEventListener("online",a),window.removeEventListener("offline",n)}}})}onSubscribe(){l(this,ye)||this.setEventListener(l(this,Je))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,ye))==null||t.call(this),k(this,ye,void 0))}setEventListener(t){var a;k(this,Je,t),(a=l(this,ye))==null||a.call(this),k(this,ye,t(this.setOnline.bind(this)))}setOnline(t){l(this,Ge)!==t&&(k(this,Ge,t),this.listeners.forEach(n=>{n(t)}))}isOnline(){return l(this,Ge)}},Ge=new WeakMap,ye=new WeakMap,Je=new WeakMap,Tn),kt=new pi;function vi(e){return Math.min(1e3*2**e,3e4)}function Hn(e){return(e??"online")==="online"?kt.isOnline():!0}var Tt=class extends Error{constructor(e){super("CancelledError"),this.revert=e==null?void 0:e.revert,this.silent=e==null?void 0:e.silent}};function bi(e){return e instanceof Tt}function Qn(e){let t=!1,a=0,n;const r=fi(),s=()=>r.status!=="pending",i=v=>{var w;if(!s()){const T=new Tt(v);u(T),(w=e.onCancel)==null||w.call(e,T)}},o=()=>{t=!0},h=()=>{t=!1},f=()=>Un.isFocused()&&(e.networkMode==="always"||kt.isOnline())&&e.canRun(),d=()=>Hn(e.networkMode)&&e.canRun(),b=v=>{s()||(n==null||n(),r.resolve(v))},u=v=>{s()||(n==null||n(),r.reject(v))},p=()=>new Promise(v=>{var w;n=T=>{(s()||f())&&v(T)},(w=e.onPause)==null||w.call(e)}).then(()=>{var v;n=void 0,s()||(v=e.onContinue)==null||v.call(e)}),g=()=>{if(s())return;let v;const w=a===0?e.initialPromise:void 0;try{v=w??e.fn()}catch(T){v=Promise.reject(T)}Promise.resolve(v).then(b).catch(T=>{var y;if(s())return;const N=e.retry??(qn.isServer()?0:3),R=e.retryDelay??vi,_=typeof R=="function"?R(a,T):R,L=N===!0||typeof N=="number"&&af()?void 0:p()).then(()=>{t?u(T):g()})})};return{promise:r,status:()=>r.status,cancel:i,continue:()=>(n==null||n(),r),cancelRetry:o,continueRetry:h,canStart:d,start:()=>(d()?g():p().then(g),r)}}var Ee,Ln,Wn=(Ln=class{constructor(){j(this,Ee)}destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),ri(this.gcTime)&&k(this,Ee,Bt.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(qn.isServer()?1/0:300*1e3))}clearGcTimeout(){l(this,Ee)!==void 0&&(Bt.clearTimeout(l(this,Ee)),k(this,Ee,void 0))}},Ee=new WeakMap,Ln);function wi(e){return{onFetch:(t,a)=>{var d,b,u,p,g;const n=t.options,r=(u=(b=(d=t.fetchOptions)==null?void 0:d.meta)==null?void 0:b.fetchMore)==null?void 0:u.direction,s=((p=t.state.data)==null?void 0:p.pages)||[],i=((g=t.state.data)==null?void 0:g.pageParams)||[];let o={pages:[],pageParams:[]},h=0;const f=async()=>{let v=!1;const w=R=>{hi(R,()=>t.signal,()=>v=!0)},T=Kn(t.options,t.fetchOptions),N=async(R,_,L)=>{if(v)return Promise.reject(t.signal.reason);if(_==null&&R.pages.length)return Promise.resolve(R);const x=(()=>{const me={client:t.client,queryKey:t.queryKey,pageParam:_,direction:L?"backward":"forward",meta:t.options.meta};return w(me),me})(),M=await T(x),{maxPages:E}=t.options,D=L?di:ui;return{pages:D(R.pages,M,E),pageParams:D(R.pageParams,_,E)}};if(r&&s.length){const R=r==="backward",_=R?zn:Zt,L={pages:s,pageParams:i},y=_(n,L);o=await N(L,y,R)}else{const R=e??s.length;do{const _=h===0?i[0]??n.initialPageParam:Zt(n,o);if(h>0&&_==null)break;o=await N(o,_),h++}while(h{var v,w;return(w=(v=t.options).persister)==null?void 0:w.call(v,f,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},a)}:t.fetchFn=f}}}function Zt(e,{pages:t,pageParams:a}){const n=t.length-1;return t.length>0?e.getNextPageParam(t[n],t,a[n],a):void 0}function zn(e,{pages:t,pageParams:a}){var n;return t.length>0?(n=e.getPreviousPageParam)==null?void 0:n.call(e,t[0],t,a[0],a):void 0}function Dl(e,t){return t?Zt(e,t)!=null:!1}function Fl(e,t){return!t||!e.getPreviousPageParam?!1:zn(e,t)!=null}var Ze,De,Xe,X,Fe,U,ht,Ie,Z,Bn,he,Rn,yi=(Rn=class extends Wn{constructor(t){super();j(this,Z);j(this,Ze);j(this,De);j(this,Xe);j(this,X);j(this,Fe);j(this,U);j(this,ht);j(this,Ie);k(this,Ie,!1),k(this,ht,t.defaultOptions),this.setOptions(t.options),this.observers=[],k(this,Fe,t.client),k(this,X,l(this,Fe).getQueryCache()),this.queryKey=t.queryKey,this.queryHash=t.queryHash,k(this,De,Ga(this.options)),this.state=t.state??l(this,De),this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return l(this,Ze)}get promise(){var t;return(t=l(this,U))==null?void 0:t.promise}setOptions(t){if(this.options={...l(this,ht),...t},t!=null&&t._type&&k(this,Ze,t._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){const a=Ga(this.options);a.data!==void 0&&(this.setState(Ba(a.data,a.dataUpdatedAt)),k(this,De,a))}}optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"&&l(this,X).remove(this)}setData(t,a){const n=li(this.state.data,t,this.options);return V(this,Z,he).call(this,{data:n,type:"success",dataUpdatedAt:a==null?void 0:a.updatedAt,manual:a==null?void 0:a.manual}),n}setState(t){V(this,Z,he).call(this,{type:"setState",state:t})}cancel(t){var n,r;const a=(n=l(this,U))==null?void 0:n.promise;return(r=l(this,U))==null||r.cancel(t),a?a.then(ae).catch(ae):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return l(this,De)}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(t=>ii(t.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===da||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0?this.observers.some(t=>Gt(t.options.staleTime,this)==="static"):!1}isStale(){return this.getObserversCount()>0?this.observers.some(t=>t.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(t=0){return this.state.data===void 0?!0:t==="static"?!1:this.state.isInvalidated?!0:!si(this.state.dataUpdatedAt,t)}onFocus(){var a;const t=this.observers.find(n=>n.shouldFetchOnWindowFocus());t==null||t.refetch({cancelRefetch:!1}),(a=l(this,U))==null||a.continue()}onOnline(){var a;const t=this.observers.find(n=>n.shouldFetchOnReconnect());t==null||t.refetch({cancelRefetch:!1}),(a=l(this,U))==null||a.continue()}addObserver(t){this.observers.includes(t)||(this.observers.push(t),this.clearGcTimeout(),l(this,X).notify({type:"observerAdded",query:this,observer:t}))}removeObserver(t){this.observers.includes(t)&&(this.observers=this.observers.filter(a=>a!==t),this.observers.length||(l(this,U)&&(l(this,Ie)||V(this,Z,Bn).call(this)?l(this,U).cancel({revert:!0}):l(this,U).cancelRetry()),this.scheduleGc()),l(this,X).notify({type:"observerRemoved",query:this,observer:t}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||V(this,Z,he).call(this,{type:"invalidate"})}async fetch(t,a){var f,d,b,u,p,g,v,w,T,N,R;if(this.state.fetchStatus!=="idle"&&((f=l(this,U))==null?void 0:f.status())!=="rejected"){if(this.state.data!==void 0&&(a!=null&&a.cancelRefetch))this.cancel({silent:!0});else if(l(this,U))return l(this,U).continueRetry(),l(this,U).promise}if(t&&this.setOptions(t),!this.options.queryFn){const _=this.observers.find(L=>L.options.queryFn);_&&this.setOptions(_.options)}const n=new AbortController,r=_=>{Object.defineProperty(_,"signal",{enumerable:!0,get:()=>(k(this,Ie,!0),n.signal)})},s=()=>{const _=Kn(this.options,a),y=(()=>{const x={client:l(this,Fe),queryKey:this.queryKey,meta:this.meta};return r(x),x})();return k(this,Ie,!1),this.options.persister?this.options.persister(_,y,this):_(y)},o=(()=>{const _={fetchOptions:a,options:this.options,queryKey:this.queryKey,client:l(this,Fe),state:this.state,fetchFn:s};return r(_),_})(),h=l(this,Ze)==="infinite"?wi(this.options.pages):this.options.behavior;h==null||h.onFetch(o,this),k(this,Xe,this.state),(this.state.fetchStatus==="idle"||this.state.fetchMeta!==((d=o.fetchOptions)==null?void 0:d.meta))&&V(this,Z,he).call(this,{type:"fetch",meta:(b=o.fetchOptions)==null?void 0:b.meta}),k(this,U,Qn({initialPromise:a==null?void 0:a.initialPromise,fn:o.fetchFn,onCancel:_=>{_ instanceof Tt&&_.revert&&this.setState({...l(this,Xe),fetchStatus:"idle"}),n.abort()},onFail:(_,L)=>{V(this,Z,he).call(this,{type:"failed",failureCount:_,error:L})},onPause:()=>{V(this,Z,he).call(this,{type:"pause"})},onContinue:()=>{V(this,Z,he).call(this,{type:"continue"})},retry:o.options.retry,retryDelay:o.options.retryDelay,networkMode:o.options.networkMode,canRun:()=>!0}));try{const _=await l(this,U).start();if(_===void 0)throw new Error(`${this.queryHash} data is undefined`);return this.setData(_),(p=(u=l(this,X).config).onSuccess)==null||p.call(u,_,this),(v=(g=l(this,X).config).onSettled)==null||v.call(g,_,this.state.error,this),_}catch(_){if(_ instanceof Tt){if(_.silent)return l(this,U).promise;if(_.revert){if(this.state.data===void 0)throw _;return this.state.data}}throw V(this,Z,he).call(this,{type:"error",error:_}),(T=(w=l(this,X).config).onError)==null||T.call(w,_,this),(R=(N=l(this,X).config).onSettled)==null||R.call(N,this.state.data,_,this),_}finally{this.scheduleGc()}}},Ze=new WeakMap,De=new WeakMap,Xe=new WeakMap,X=new WeakMap,Fe=new WeakMap,U=new WeakMap,ht=new WeakMap,Ie=new WeakMap,Z=new WeakSet,Bn=function(){return this.state.fetchStatus==="paused"&&this.state.status==="pending"},he=function(t){const a=n=>{switch(t.type){case"failed":return{...n,fetchFailureCount:t.failureCount,fetchFailureReason:t.error};case"pause":return{...n,fetchStatus:"paused"};case"continue":return{...n,fetchStatus:"fetching"};case"fetch":return{...n,..._i(n.data,this.options),fetchMeta:t.meta??null};case"success":const r={...n,...Ba(t.data,t.dataUpdatedAt),dataUpdateCount:n.dataUpdateCount+1,...!t.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return k(this,Xe,t.manual?r:void 0),r;case"error":const s=t.error;return{...n,error:s,errorUpdateCount:n.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:n.fetchFailureCount+1,fetchFailureReason:s,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...n,isInvalidated:!0};case"setState":return{...n,...t.state}}};this.state=a(this.state),z.batch(()=>{this.observers.forEach(n=>{n.onQueryUpdate()}),l(this,X).notify({query:this,type:"updated",action:t})})},Rn);function _i(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Hn(t.networkMode)?"fetching":"paused",...e===void 0&&{error:null,status:"pending"}}}function Ba(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:"success"}}function Ga(e){const t=typeof e.initialData=="function"?e.initialData():e.initialData,a=t!==void 0,n=a?typeof e.initialDataUpdatedAt=="function"?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:a?n??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:a?"success":"pending",fetchStatus:"idle"}}var ft,le,K,$e,ue,ve,Mn,Si=(Mn=class extends Wn{constructor(t){super();j(this,ue);j(this,ft);j(this,le);j(this,K);j(this,$e);k(this,ft,t.client),this.mutationId=t.mutationId,k(this,K,t.mutationCache),k(this,le,[]),this.state=t.state||Ci(),this.setOptions(t.options),this.scheduleGc()}setOptions(t){this.options=t,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(t){l(this,le).includes(t)||(l(this,le).push(t),this.clearGcTimeout(),l(this,K).notify({type:"observerAdded",mutation:this,observer:t}))}removeObserver(t){k(this,le,l(this,le).filter(a=>a!==t)),this.scheduleGc(),l(this,K).notify({type:"observerRemoved",mutation:this,observer:t})}optionalRemove(){l(this,le).length||(this.state.status==="pending"?this.scheduleGc():l(this,K).remove(this))}continue(){var t;return((t=l(this,$e))==null?void 0:t.continue())??this.execute(this.state.variables)}async execute(t){var i,o,h,f,d,b,u,p,g,v,w,T,N,R,_,L,y,x;const a=()=>{V(this,ue,ve).call(this,{type:"continue"})},n={client:l(this,ft),meta:this.options.meta,mutationKey:this.options.mutationKey};k(this,$e,Qn({fn:()=>this.options.mutationFn?this.options.mutationFn(t,n):Promise.reject(new Error("No mutationFn found")),onFail:(M,E)=>{V(this,ue,ve).call(this,{type:"failed",failureCount:M,error:E})},onPause:()=>{V(this,ue,ve).call(this,{type:"pause"})},onContinue:a,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>l(this,K).canRun(this)}));const r=this.state.status==="pending",s=!l(this,$e).canStart();try{if(r)a();else{V(this,ue,ve).call(this,{type:"pending",variables:t,isPaused:s}),l(this,K).config.onMutate&&await l(this,K).config.onMutate(t,this,n);const E=await((o=(i=this.options).onMutate)==null?void 0:o.call(i,t,n));E!==this.state.context&&V(this,ue,ve).call(this,{type:"pending",context:E,variables:t,isPaused:s})}const M=await l(this,$e).start();return await((f=(h=l(this,K).config).onSuccess)==null?void 0:f.call(h,M,t,this.state.context,this,n)),await((b=(d=this.options).onSuccess)==null?void 0:b.call(d,M,t,this.state.context,n)),await((p=(u=l(this,K).config).onSettled)==null?void 0:p.call(u,M,null,this.state.variables,this.state.context,this,n)),await((v=(g=this.options).onSettled)==null?void 0:v.call(g,M,null,t,this.state.context,n)),V(this,ue,ve).call(this,{type:"success",data:M}),M}catch(M){try{await((T=(w=l(this,K).config).onError)==null?void 0:T.call(w,M,t,this.state.context,this,n))}catch(E){Promise.reject(E)}try{await((R=(N=this.options).onError)==null?void 0:R.call(N,M,t,this.state.context,n))}catch(E){Promise.reject(E)}try{await((L=(_=l(this,K).config).onSettled)==null?void 0:L.call(_,void 0,M,this.state.variables,this.state.context,this,n))}catch(E){Promise.reject(E)}try{await((x=(y=this.options).onSettled)==null?void 0:x.call(y,void 0,M,t,this.state.context,n))}catch(E){Promise.reject(E)}throw V(this,ue,ve).call(this,{type:"error",error:M}),M}finally{l(this,K).runNext(this)}}},ft=new WeakMap,le=new WeakMap,K=new WeakMap,$e=new WeakMap,ue=new WeakSet,ve=function(t){const a=n=>{switch(t.type){case"failed":return{...n,failureCount:t.failureCount,failureReason:t.error};case"pause":return{...n,isPaused:!0};case"continue":return{...n,isPaused:!1};case"pending":return{...n,context:t.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:t.isPaused,status:"pending",variables:t.variables,submittedAt:Date.now()};case"success":return{...n,data:t.data,failureCount:0,failureReason:null,error:null,status:"success",isPaused:!1};case"error":return{...n,data:void 0,error:t.error,failureCount:n.failureCount+1,failureReason:t.error,isPaused:!1,status:"error"}}};this.state=a(this.state),z.batch(()=>{l(this,le).forEach(n=>{n.onMutationUpdate(t)}),l(this,K).notify({mutation:this,type:"updated",action:t})})},Mn);function Ci(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:"idle",variables:void 0,submittedAt:0}}var fe,ne,mt,Pn,xi=(Pn=class extends Et{constructor(t={}){super();j(this,fe);j(this,ne);j(this,mt);this.config=t,k(this,fe,new Set),k(this,ne,new Map),k(this,mt,0)}build(t,a,n){const r=new Si({client:t,mutationCache:this,mutationId:++St(this,mt)._,options:t.defaultMutationOptions(a),state:n});return this.add(r),r}add(t){l(this,fe).add(t);const a=Ct(t);if(typeof a=="string"){const n=l(this,ne).get(a);n?n.push(t):l(this,ne).set(a,[t])}this.notify({type:"added",mutation:t})}remove(t){if(l(this,fe).delete(t)){const a=Ct(t);if(typeof a=="string"){const n=l(this,ne).get(a);if(n)if(n.length>1){const r=n.indexOf(t);r!==-1&&n.splice(r,1)}else n[0]===t&&l(this,ne).delete(a)}}this.notify({type:"removed",mutation:t})}canRun(t){const a=Ct(t);if(typeof a=="string"){const n=l(this,ne).get(a),r=n==null?void 0:n.find(s=>s.state.status==="pending");return!r||r===t}else return!0}runNext(t){var n;const a=Ct(t);if(typeof a=="string"){const r=(n=l(this,ne).get(a))==null?void 0:n.find(s=>s!==t&&s.state.isPaused);return(r==null?void 0:r.continue())??Promise.resolve()}else return Promise.resolve()}clear(){z.batch(()=>{l(this,fe).forEach(t=>{this.notify({type:"removed",mutation:t})}),l(this,fe).clear(),l(this,ne).clear()})}getAll(){return Array.from(l(this,fe))}find(t){const a={exact:!0,...t};return this.getAll().find(n=>Qa(a,n))}findAll(t={}){return this.getAll().filter(a=>Qa(t,a))}notify(t){z.batch(()=>{this.listeners.forEach(a=>{a(t)})})}resumePausedMutations(){const t=this.getAll().filter(a=>a.state.isPaused);return z.batch(()=>Promise.all(t.map(a=>a.continue().catch(ae))))}},fe=new WeakMap,ne=new WeakMap,mt=new WeakMap,Pn);function Ct(e){var t;return(t=e.options.scope)==null?void 0:t.id}var de,jn,ki=(jn=class extends Et{constructor(t={}){super();j(this,de);this.config=t,k(this,de,new Map)}build(t,a,n){const r=a.queryKey,s=a.queryHash??ua(r,a);let i=this.get(s);return i||(i=new yi({client:t,queryKey:r,queryHash:s,options:t.defaultQueryOptions(a),state:n,defaultOptions:t.getQueryDefaults(r)}),this.add(i)),i}add(t){l(this,de).has(t.queryHash)||(l(this,de).set(t.queryHash,t),this.notify({type:"added",query:t}))}remove(t){const a=l(this,de).get(t.queryHash);a&&(t.destroy(),a===t&&l(this,de).delete(t.queryHash),this.notify({type:"removed",query:t}))}clear(){z.batch(()=>{this.getAll().forEach(t=>{this.remove(t)})})}get(t){return l(this,de).get(t)}getAll(){return[...l(this,de).values()]}find(t){const a={exact:!0,...t};return this.getAll().find(n=>Ha(a,n))}findAll(t={}){const a=this.getAll();return Object.keys(t).length>0?a.filter(n=>Ha(t,n)):a}notify(t){z.batch(()=>{this.listeners.forEach(a=>{a(t)})})}onFocus(){z.batch(()=>{this.getAll().forEach(t=>{t.onFocus()})})}onOnline(){z.batch(()=>{this.getAll().forEach(t=>{t.onOnline()})})}},de=new WeakMap,jn),F,_e,Se,Ye,et,Ce,tt,at,An,Ti=(An=class{constructor(e={}){j(this,F);j(this,_e);j(this,Se);j(this,Ye);j(this,et);j(this,Ce);j(this,tt);j(this,at);k(this,F,e.queryCache||new ki),k(this,_e,e.mutationCache||new xi),k(this,Se,e.defaultOptions||{}),k(this,Ye,new Map),k(this,et,new Map),k(this,Ce,0)}mount(){St(this,Ce)._++,l(this,Ce)===1&&(k(this,tt,Un.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onFocus())})),k(this,at,kt.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onOnline())})))}unmount(){var e,t;St(this,Ce)._--,l(this,Ce)===0&&((e=l(this,tt))==null||e.call(this),k(this,tt,void 0),(t=l(this,at))==null||t.call(this),k(this,at,void 0))}isFetching(e){return l(this,F).findAll({...e,fetchStatus:"fetching"}).length}isMutating(e){return l(this,_e).findAll({...e,status:"pending"}).length}getQueryData(e){var a;const t=this.defaultQueryOptions({queryKey:e});return(a=l(this,F).get(t.queryHash))==null?void 0:a.state.data}ensureQueryData(e){const t=this.defaultQueryOptions(e),a=l(this,F).build(this,t),n=a.state.data;return n===void 0?this.fetchQuery(e):(e.revalidateIfStale&&a.isStaleByTime(Gt(t.staleTime,a))&&this.prefetchQuery(t),Promise.resolve(n))}getQueriesData(e){return l(this,F).findAll(e).map(({queryKey:t,state:a})=>{const n=a.data;return[t,n]})}setQueryData(e,t,a){const n=this.defaultQueryOptions({queryKey:e}),r=l(this,F).get(n.queryHash),s=r==null?void 0:r.state.data,i=ni(t,s);if(i!==void 0)return l(this,F).build(this,n).setData(i,{...a,manual:!0})}setQueriesData(e,t,a){return z.batch(()=>l(this,F).findAll(e).map(({queryKey:n})=>[n,this.setQueryData(n,t,a)]))}getQueryState(e){var a;const t=this.defaultQueryOptions({queryKey:e});return(a=l(this,F).get(t.queryHash))==null?void 0:a.state}removeQueries(e){const t=l(this,F);z.batch(()=>{t.findAll(e).forEach(a=>{t.remove(a)})})}resetQueries(e,t){const a=l(this,F);return z.batch(()=>(a.findAll(e).forEach(n=>{n.reset()}),this.refetchQueries({type:"active",...e},t)))}cancelQueries(e,t={}){const a={revert:!0,...t},n=z.batch(()=>l(this,F).findAll(e).map(r=>r.cancel(a)));return Promise.all(n).then(ae).catch(ae)}invalidateQueries(e,t={}){return z.batch(()=>(l(this,F).findAll(e).forEach(a=>{a.invalidate()}),(e==null?void 0:e.refetchType)==="none"?Promise.resolve():this.refetchQueries({...e,type:(e==null?void 0:e.refetchType)??(e==null?void 0:e.type)??"active"},t)))}refetchQueries(e,t={}){const a={...t,cancelRefetch:t.cancelRefetch??!0},n=z.batch(()=>l(this,F).findAll(e).filter(r=>!r.isDisabled()&&!r.isStatic()).map(r=>{let s=r.fetch(void 0,a);return a.throwOnError||(s=s.catch(ae)),r.state.fetchStatus==="paused"?Promise.resolve():s}));return Promise.all(n).then(ae)}fetchQuery(e){const t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);const a=l(this,F).build(this,t);return a.isStaleByTime(Gt(t.staleTime,a))?a.fetch(t):Promise.resolve(a.state.data)}prefetchQuery(e){return this.fetchQuery(e).then(ae).catch(ae)}fetchInfiniteQuery(e){return e._type="infinite",this.fetchQuery(e)}prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(ae).catch(ae)}ensureInfiniteQueryData(e){return e._type="infinite",this.ensureQueryData(e)}resumePausedMutations(){return kt.isOnline()?l(this,_e).resumePausedMutations():Promise.resolve()}getQueryCache(){return l(this,F)}getMutationCache(){return l(this,_e)}getDefaultOptions(){return l(this,Se)}setDefaultOptions(e){k(this,Se,e)}setQueryDefaults(e,t){l(this,Ye).set(lt(e),{queryKey:e,defaultOptions:t})}getQueryDefaults(e){const t=[...l(this,Ye).values()],a={};return t.forEach(n=>{ut(e,n.queryKey)&&Object.assign(a,n.defaultOptions)}),a}setMutationDefaults(e,t){l(this,et).set(lt(e),{mutationKey:e,defaultOptions:t})}getMutationDefaults(e){const t=[...l(this,et).values()],a={};return t.forEach(n=>{ut(e,n.mutationKey)&&Object.assign(a,n.defaultOptions)}),a}defaultQueryOptions(e){if(e._defaulted)return e;const t={...l(this,Se).queries,...this.getQueryDefaults(e.queryKey),...e,_defaulted:!0};return t.queryHash||(t.queryHash=ua(t.queryKey,t)),t.refetchOnReconnect===void 0&&(t.refetchOnReconnect=t.networkMode!=="always"),t.throwOnError===void 0&&(t.throwOnError=!!t.suspense),!t.networkMode&&t.persister&&(t.networkMode="offlineFirst"),t.queryFn===da&&(t.enabled=!1),t}defaultMutationOptions(e){return e!=null&&e._defaulted?e:{...l(this,Se).mutations,...(e==null?void 0:e.mutationKey)&&this.getMutationDefaults(e.mutationKey),...e,_defaulted:!0}}clear(){l(this,F).clear(),l(this,_e).clear()}},F=new WeakMap,_e=new WeakMap,Se=new WeakMap,Ye=new WeakMap,et=new WeakMap,Ce=new WeakMap,tt=new WeakMap,at=new WeakMap,An),Gn=C.createContext(void 0),Il=e=>{const t=C.useContext(Gn);if(!t)throw new Error("No QueryClient set, use QueryClientProvider to set one");return t},Li=({client:e,children:t})=>(C.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),c.jsx(Gn.Provider,{value:e,children:t}));function Ri(e,t=window.location.href){var n;const a=(n=new URL(t).searchParams.get("record"))==null?void 0:n.trim();if(a){const r=e.calls.find(s=>s.id===a);return r?[r]:[]}return e.calls[0]?[e.calls[0]]:[]}function $l({calls:e,recordId:t,detail:a}){const n=e.findIndex(b=>b.id===t),r=n>=0?n:!t&&e.length?0:-1,s=(a==null?void 0:a.record.id)===t?a:null,i=(s==null?void 0:s.record)??(r>=0?e[r]:null),o=(s==null?void 0:s.previousRecord)??(r>0?e[r-1]:null),h=(s==null?void 0:s.nextRecord)??(r>=0&&r=0?`${r+1} of ${e.length} loaded calls`:"Record outside loaded snapshot";return{modelIndex:n,activeIndex:r,hydratedDetail:s,call:i,previous:o,next:h,threadCalls:f,positionLabel:d}}function Mi(e,t,a){const n=e.filter(i=>i.thread===t.thread),r=[a==null?void 0:a.previousRecord,a==null?void 0:a.record,a==null?void 0:a.nextRecord].filter(Pi),s=new Map;for(const i of[...n,...r,t])s.set(i.id,i);return[...s.values()].sort(ji)}function Pi(e){return!!(e!=null&&e.id)}function ji(e,t){return Date.parse(t.rawTime||t.time)-Date.parse(e.rawTime||e.time)}function Ai(e,t){const a=t.map(r=>Ja(r.header)).join(","),n=e.map(r=>t.map(s=>Ja(s.value(r))).join(","));return[a,...n].join(` -`)}function Ni(e,t){const a=new Blob([t],{type:"text/csv;charset=utf-8"}),n=typeof URL.createObjectURL=="function"?URL.createObjectURL(a):`data:text/csv;charset=utf-8,${encodeURIComponent(t)}`,r=document.createElement("a");r.href=n,r.download=e,r.rel="noopener",document.body.append(r),r.click(),r.remove(),n.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(n)}function Ei(e=new Date){return e.toISOString().slice(0,10)}function Ja(e){const t=String(e??"");return/[",\n\r]/.test(t)?`"${t.replaceAll('"','""')}"`:t}function Jn(e){return e.fast===!0?"Fast":e.fast===!1?"Standard":"Unknown"}function Ol(e){return e.fast!==null?`confirmed ${Jn(e)} · ${e.serviceTierConfidence||"exact"}`:e.fastProxyCandidate?"tier unknown · Fast proxy candidate":"tier unknown · normal throughput proxy"}function Te(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Le(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Xt(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function Lt(e){return`${e.toFixed(1)}%`}const Ul=[{id:"time",accessorFn:e=>Number(Date.parse(e.eventTimestamp||e.callStartedAt||e.rawTime||e.time))||0,header:"Time",cell:e=>e.row.original.time},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:e=>c.jsx("span",{className:`pill effort-${String(e.getValue())}`,children:String(e.getValue())})},{accessorKey:"input",header:"Input Tokens",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"output",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:e=>c.jsx("span",{className:"cache-pill",children:Lt(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"contextWindowPct",header:"Context %",cell:e=>{const t=e.getValue(),a=typeof t=="number"?t:Number.NaN;return c.jsx("span",{className:"num",children:Number.isFinite(a)?Lt(a):"-"})}},{accessorKey:"duration",header:"Duration"},{id:"serviceTier",accessorFn:e=>Jn(e),header:"Service Tier",cell:e=>{const t=String(e.getValue()),a=t==="Fast"?"green":t==="Standard"?"blue":"";return c.jsx("span",{className:`status-badge ${a}`.trim(),children:t})}},{accessorKey:"previousCallGap",header:"Prev Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiator",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"signal",header:"Signals",cell:e=>c.jsx(Fi,{call:e.row.original})}],ce=[{header:"timestamp",value:e=>e.eventTimestamp||e.rawTime||e.time},{header:"thread",value:e=>e.thread},{header:"call_started_at",value:e=>e.callStartedAt||e.rawTime||e.time},{header:"call_duration_seconds",value:e=>e.durationSeconds},{header:"previous_call_event_timestamp",value:e=>e.previousCallEventTimestamp},{header:"previous_call_delta_seconds",value:e=>e.previousCallGapSeconds},{header:"initiated",value:e=>e.initiator},{header:"initiated_reason",value:e=>e.initiatorReason},{header:"project",value:e=>e.project},{header:"model",value:e=>e.model},{header:"effort",value:e=>e.effort},{header:"total_tokens",value:e=>e.totalTokens},{header:"input_tokens",value:e=>e.input},{header:"cached_input_tokens",value:e=>e.cachedInput},{header:"uncached_input_tokens",value:e=>e.uncachedInput},{header:"output_tokens",value:e=>e.output},{header:"reasoning_output_tokens",value:e=>e.reasoningOutput},{header:"estimated_cost_usd",value:e=>e.cost.toFixed(6)},{header:"usage_credits",value:e=>e.credits.toFixed(6)},{header:"standard_usage_credits",value:e=>e.standardUsageCredits.toFixed(6)},{header:"service_tier",value:e=>e.serviceTier},{header:"fast",value:e=>e.fast===null?"":e.fast?1:0},{header:"service_tier_source",value:e=>e.serviceTierSource},{header:"service_tier_confidence",value:e=>e.serviceTierConfidence},{header:"fast_proxy_candidate",value:e=>String(e.fastProxyCandidate)},{header:"usage_credit_multiplier",value:e=>e.usageCreditMultiplier},{header:"usage_credit_multiplier_source",value:e=>e.usageCreditMultiplierSource},{header:"cache_ratio",value:e=>e.cachedPct.toFixed(2)},{header:"context_window_percent",value:e=>{var t;return((t=e.contextWindowPct)==null?void 0:t.toFixed(2))??""}},{header:"pricing_model",value:e=>e.pricingModel},{header:"usage_credit_confidence",value:e=>e.usageCreditConfidence},{header:"recommendation",value:e=>e.recommendation},{header:"record_id",value:e=>e.id},{header:"thread_attachment",value:e=>e.threadAttachmentLabel},{header:"thread_source",value:e=>e.threadSource},{header:"parent_thread",value:e=>e.parentThread},{header:"session_id",value:e=>e.sessionId},{header:"turn_id",value:e=>e.turnId},{header:"parent_session_id",value:e=>e.parentSessionId},{header:"parent_session_updated_at",value:e=>e.parentSessionUpdatedAt},{header:"project_relative_cwd",value:e=>e.projectRelativeCwd},{header:"cwd",value:e=>e.cwd},{header:"source_file",value:e=>e.sourceFile},{header:"source_line",value:e=>e.lineNumber??""},{header:"git_branch",value:e=>e.gitBranch},{header:"git_remote_label",value:e=>e.gitRemoteLabel},{header:"git_remote_hash",value:e=>e.gitRemoteHash},{header:"pricing_estimated",value:e=>String(e.pricingEstimated)},{header:"usage_credit_model",value:e=>e.usageCreditModel},{header:"usage_credit_source",value:e=>e.usageCreditSource},{header:"usage_credit_tier",value:e=>e.usageCreditTier},{header:"usage_credit_fetched_at",value:e=>e.usageCreditFetchedAt},{header:"usage_credit_note",value:e=>e.usageCreditNote},{header:"model_context_window",value:e=>e.modelContextWindow??""},{header:"cumulative_total_tokens",value:e=>e.cumulativeTotalTokens??""},{header:"estimated_cache_savings_usd",value:e=>e.estimatedCacheSavings.toFixed(6)},{header:"initiated_confidence",value:e=>e.initiatorConfidence},{header:"signal",value:e=>e.signal},{header:"tags",value:e=>e.tags.join("|")},{header:"efficiency_flags",value:e=>e.efficiencyFlags.join("|")}];function Di(e,t=3){const n=Ii([e.signal,...e.efficiencyFlags]).map((r,s)=>({key:`${r}-${s}`,label:Zn(r),shortLabel:$i(r)}));return{visible:n.slice(0,t),hidden:n.slice(t)}}function Fi({call:e}){const t=On(),{visible:a,hidden:n}=Di(e);if(!a.length)return c.jsx("span",{className:"muted",children:"None"});const r=a.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),s=n.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),i=s.map(o=>o.label).join("、");return c.jsxs("span",{className:"flags compact-flags","aria-label":t.language==="zh-Hans"?`信号:${[...r,...s].map(o=>o.label).join("、")}`:`Signals: ${[...a,...n].map(o=>o.label).join(", ")}`,children:[r.map(o=>c.jsx("span",{className:"flag signal-puck",title:o.label,children:o.shortLabel},o.key)),s.length?c.jsxs("span",{className:"flag signal-puck more",title:i,children:["+",s.length]}):null]})}function Ii(e){const t=new Set;return e.map(a=>a.trim()).filter(a=>a&&a!=="aggregate").filter(a=>{const n=a.toLowerCase();return t.has(n)?!1:(t.add(n),!0)})}function Zn(e){return e.replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function $i(e){const t=e.toLowerCase().replace(/[_\s]+/g,"-"),a={"cache-drop":"CACHE","cache-risk":"CACHE","context-bloat":"CTX","context-heavy":"CTX","elevated-context":"CTX","elevated-context-use":"CTX","estimated-pricing":"EST","expensive-low-output-call":"LO","high-context-use":"CTX","high-cost":"$","high-estimated-cost":"$","high-reasoning-share":"RSN","large-thread":"BIG","low-cache":"CACHE","low-cache-reuse":"CACHE","low-output":"LO","pricing-gap":"PRICE","reasoning-spike":"RSN","subagent-attribution":"SUB"};if(a[t])return a[t];const n=Zn(e).split(/\s+/).filter(Boolean);return n.length?n.length===1?n[0].slice(0,4).toUpperCase():n.slice(0,3).map(r=>r[0]).join("").toUpperCase():"?"}const Vl=[{accessorKey:"name",header:"Thread"},{accessorKey:"latestActivity",header:"Latest"},{accessorKey:"turns",header:"Turns",cell:e=>c.jsx("span",{className:"num",children:Te(Number(e.getValue()))})},{accessorKey:"totalDuration",header:"Duration"},{accessorKey:"averageGap",header:"Avg Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiatorSummary",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"modelSummary",header:"Models",cell:e=>c.jsx("span",{className:"pill model-pill",children:String(e.getValue())})},{accessorKey:"effortSummary",header:"Effort Mix"},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"outputTokens",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachePct",header:"Cache %",cell:e=>c.jsx("span",{className:"cache-pill",children:Lt(Number(e.getValue()))})},{accessorKey:"contextPct",header:"Context %",cell:e=>{const t=e.getValue();return c.jsx("span",{className:"num",children:typeof t=="number"?Lt(t):"-"})}},{accessorKey:"costPerCall",header:"Cost / Call",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"coldResumeRisk",header:"Cold Resume Risk",cell:e=>c.jsx("span",{className:`status-badge ${Oi(String(e.getValue()))}`,children:String(e.getValue())})},{accessorKey:"productivity",header:"Productivity",cell:e=>c.jsx("span",{className:"score",children:Number(e.getValue())})}],Kl=[{id:"name",label:"Thread",locked:!0},{id:"latestActivity",label:"Latest"},{id:"turns",label:"Turns"},{id:"totalDuration",label:"Duration"},{id:"averageGap",label:"Avg Gap"},{id:"initiatorSummary",label:"Initiated"},{id:"modelSummary",label:"Models"},{id:"effortSummary",label:"Effort Mix"},{id:"totalTokens",label:"Total Tokens"},{id:"cachedInput",label:"Cached Input"},{id:"uncachedInput",label:"Uncached Input"},{id:"outputTokens",label:"Output Tokens"},{id:"reasoningOutput",label:"Reasoning Output"},{id:"cost",label:"Est. Cost"},{id:"credits",label:"Codex Credits"},{id:"cachePct",label:"Cache %"},{id:"contextPct",label:"Context %"},{id:"costPerCall",label:"Cost / Call"},{id:"coldResumeRisk",label:"Cold Resume Risk"},{id:"productivity",label:"Productivity"},{id:"investigate",label:"Investigate",locked:!0}];function Oi(e){return e==="High"?"red":e==="Medium"?"orange":e==="Low"?"green":"neutral"}const dt=1,re=0,qt=100,Xn=1e3,Yn=500,er="codexUsageDashboardLoadSettings",Ui={day:1440*60*1e3,week:10080*60*1e3};function ct(e,t=Yn){if((e==null?void 0:e.limit_label)==="All"||t===re&&(e==null?void 0:e.limit)==null)return re;const a=Number((e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??t);return Number.isFinite(a)&&a>=0?a:t}function gt(e){return Number.isFinite(e)?e<=re?re:Math.max(dt,Math.round(e)):dt}function je(...e){const t=e.find(a=>typeof a=="number"&&Number.isFinite(a)&&a>0);return t?Math.max(dt,Math.round(t)):dt}function Vi(e,t,a=null,n="rows"){const r=gt(e);return{historyScope:t,loadWindow:n,limit:r===re?null:r,since:a}}function Ki(e){return e.limit??re}function ha(e){return fa(e==null?void 0:e.load_window)?e.load_window:e!=null&&e.since?"week":(e==null?void 0:e.limit_label)==="All"||(e==null?void 0:e.limit)==null?"all":"rows"}function qi(e){return fa(e==null?void 0:e.default_load_window)?e.default_load_window:ha(e)}function Ht(e,t=new Date){const a=Ui[e];if(!a)return null;const n=Math.floor(t.getTime()/6e4)*6e4;return new Date(n-a).toISOString()}function Re(e,t=Yn){return e==="day"?"Last 24 hours":e==="week"?"Last 7 days":e==="all"?"All time":`Most recent ${gt(t).toLocaleString()}`}function Hi(e=tr()){if(!e)return null;try{const t=e.getItem(er);if(!t)return null;const a=JSON.parse(t),n=typeof a.loadLimit=="number"&&Number.isFinite(a.loadLimit)?gt(a.loadLimit):void 0,r=a.historyScope==="active"||a.historyScope==="all"?a.historyScope:void 0,s=fa(a.loadWindow)?a.loadWindow:void 0;return n===void 0&&r===void 0&&s===void 0?null:{loadLimit:n,historyScope:r,loadWindow:s}}catch{return null}}function Qi(e,t,a="rows",n=tr()){if(n)try{n.setItem(er,JSON.stringify({loadLimit:gt(e),historyScope:t,loadWindow:a}))}catch{}}function fa(e){return e==="day"||e==="week"||e==="rows"||e==="all"}function Wi({currentLimit:e,loadedRows:t,pendingLimit:a}){const n=a===re?0:a+qt,s=Math.max(dt,e===re?0:e,n,t);return Math.ceil((s+Xn)/qt)*qt}function zi({currentLimit:e,loadedRows:t,pendingLimit:a}){return Math.max(je(e),je(a),je(t))+Xn}function Bi({loadedRows:e,limit:t,totalRows:a}){return t===re&&e>0?`Loaded all ${e.toLocaleString()}`:a>e?`Loaded ${e.toLocaleString()} of ${a.toLocaleString()}`:`Loaded ${e.toLocaleString()} rows`}function tr(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}async function Gi(e,t,a,n="",r=""){const s=Ei();switch(e){case"threads":{const{threadCallsForCurrentUrl:i}=await O(async()=>{const{threadCallsForCurrentUrl:o}=await import("./ThreadsPage.js");return{threadCallsForCurrentUrl:o}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]));return te(`codex-thread-filtered-calls-${s}.csv`,i(t,n),ce,"call rows")}case"cache-context":{const{cacheContextCallsForCurrentUrl:i}=await O(async()=>{const{cacheContextCallsForCurrentUrl:o}=await import("./CacheContextPage.js");return{cacheContextCallsForCurrentUrl:o}},__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12]));return te(`codex-${e}-calls-${s}.csv`,i(t),ce,"call rows")}case"usage-drain":{const{usageDrainCallsForCurrentUrl:i}=await O(async()=>{const{usageDrainCallsForCurrentUrl:o}=await import("./UsageDrainPage.js");return{usageDrainCallsForCurrentUrl:o}},__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39]));return te(`codex-usage-drain-calls-${s}.csv`,i(t),ce,"call rows")}case"diagnostics":{const{diagnosticsCallsForCurrentUrl:i}=await O(async()=>{const{diagnosticsCallsForCurrentUrl:o}=await import("./DiagnosticsPage.js");return{diagnosticsCallsForCurrentUrl:o}},__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12]));return te(`codex-diagnostics-calls-${s}.csv`,i(t),ce,"call rows")}case"reports":{const{reportCallsForCurrentUrl:i}=await O(async()=>{const{reportCallsForCurrentUrl:o}=await import("./ReportsPage.js");return{reportCallsForCurrentUrl:o}},__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43]));return te(`codex-reports-evidence-${s}.csv`,i(t),ce,"call rows")}case"settings":return te(`codex-dashboard-settings-${s}.csv`,Zi(t,a),Ji,"settings rows");case"calls":{const{callsForCurrentUrl:i}=await O(async()=>{const{callsForCurrentUrl:o}=await import("./CallsPage.js");return{callsForCurrentUrl:o}},__vite__mapDeps([44,1,2,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48]));return te(`codex-calls-${s}.csv`,i(t.calls,n,r),ce,"call rows")}case"overview":{const{overviewCallsForQuery:i}=await O(async()=>{const{overviewCallsForQuery:o}=await import("./OverviewPage.js");return{overviewCallsForQuery:o}},__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50]));return te(`codex-overview-calls-${s}.csv`,i(t.calls,n),ce,"call rows")}case"investigator":{const{investigatorCallsForCurrentUrl:i}=await O(async()=>{const{investigatorCallsForCurrentUrl:o}=await import("./InvestigatorPage.js");return{investigatorCallsForCurrentUrl:o}},__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52]));return te(`codex-investigator-calls-${s}.csv`,i(t),ce,"call rows")}case"compression-lab":return te(`codex-compression-lab-scope-${s}.csv`,t.calls,ce,"call rows");case"call":return te(`codex-call-calls-${s}.csv`,Ri(t),ce,"call rows")}}function te(e,t,a,n){return{filename:e,csv:Ai(t,a),rowCount:t.length,label:n}}const Ji=[{header:"Field",value:e=>e.field},{header:"Value",value:e=>e.value}];function Zi(e,t){return[{field:"live_api",value:t.canUseLiveApi?"available":"static snapshot"},{field:"context_api",value:t.contextRuntime.contextApiEnabled?"enabled":"gated"},{field:"history_scope",value:t.historyScope},{field:"data_window",value:Re(t.loadWindow,t.loadLimit)},{field:"scope_since",value:t.scopeSince??"none"},{field:"row_request",value:t.loadLimit===re?"no cap":String(t.loadLimit)},{field:"loaded_rows",value:String(t.loadedRowCount)},{field:"total_available_rows",value:String(t.totalAvailableRows)},{field:"auto_refresh",value:t.autoRefreshEnabled?"enabled":"paused"},{field:"refresh_state",value:t.refreshState},{field:"visible_calls",value:String(e.calls.length)},{field:"visible_threads",value:String(e.threads.length)}]}function Xi(e){return e instanceof Error?e.message:String(e)}function Za(e,t){const a=t==="all"?"all history":"active history",n=e.message||"Refreshing usage index",r=typeof e.percent=="number"?` ${Math.round(e.percent)}%`:"";return`${n}${r} (${a})`}function Qt(e,t="active"){return e?typeof e.include_archived=="boolean"?e.include_archived?"all":"active":e.history_scope==="all-history"||e.history_scope==="all"?"all":e.history_scope==="active"?"active":t:t}function Yi({historyScope:e,activeRows:t,allRows:a,archivedRows:n}){const r=eo({activeRows:t,allRows:a,archivedRows:n});return e==="all"?r===null?"All history selected":r>0?`All history includes ${r.toLocaleString()} archived calls`:"All history selected; no archived calls are indexed yet":r===null||r<=0?"Active sessions only":`Active sessions only; ${r.toLocaleString()} archived calls hidden`}function eo({activeRows:e,allRows:t,archivedRows:a}){const n=Wt(a);if(n!==null)return n;const r=Wt(e),s=Wt(t);return r!==null&&s!==null?Math.max(s-r,0):null}function Wt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.round(e):null}const ar=["aria-description","aria-label","aria-valuetext","title","placeholder","alt"],to="data-localization-attributes",ao=new Set(["CODE","KBD","PRE","SAMP","SCRIPT","STYLE","TEXTAREA"]),Yt=new WeakMap,ea=new WeakMap;function no({value:e,children:t}){return c.jsxs(Zs,{value:e,children:[c.jsx(ro,{}),t]})}function ro(){const e=On();return C.useLayoutEffect(()=>{const t=document.querySelector("[data-dashboard-localization-root]");if(!t)return;if(e.language!=="zh-Hans"){io(t),document.title="Codex Usage Tracker React Dashboard";return}document.title="Codex Usage Tracker · 用量仪表盘",Xa(t,e.translateText);const a=new MutationObserver(n=>{for(const r of n){if(r.type==="characterData"&&r.target instanceof Text){ta(r.target,e.translateText);continue}if(r.type==="attributes"&&r.target instanceof Element){aa(r.target,e.translateText);continue}for(const s of r.addedNodes)s instanceof Text?ta(s,e.translateText):s instanceof Element&&Xa(s,e.translateText)}});return a.observe(t,{attributes:!0,attributeFilter:[...ar],characterData:!0,childList:!0,subtree:!0}),()=>a.disconnect()},[e]),null}function Xa(e,t){if(Rt(e))return;aa(e,t);const a=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);let n=a.nextNode();for(;n;){if(n instanceof Element){if(Rt(n)){n=so(a,n,e);continue}aa(n,t)}else n instanceof Text&&ta(n,t);n=a.nextNode()}}function so(e,t,a){let n=t;for(;n&&n!==a;){const r=e.nextSibling();if(r)return r;n=n.parentNode,n&&(e.currentNode=n)}return null}function ta(e,t){const a=e.parentElement;if(!a||Rt(a))return;const n=e.nodeValue??"",r=Yt.get(e),s=r&&(n===r.source||n===r.translated)?r.source:n,i=s.match(/^(\s*)([\s\S]*?)(\s*)$/u);if(!i||!i[2])return;const o=t(i[2]),h=`${i[1]}${o}${i[3]}`;Yt.set(e,{source:s,translated:h}),h!==n&&(e.nodeValue=h)}function aa(e,t){if(Rt(e))return;const a=new Set((e.getAttribute(to)??"").split(/[\s,]+/u).filter(Boolean));if(!a.size)return;const n=ea.get(e)??new Map;for(const r of ar){if(!a.has(r))continue;const s=e.getAttribute(r);if(!s)continue;const i=n.get(r),o=i&&(s===i.source||s===i.translated)?i.source:s,h=t(o);n.set(r,{source:o,translated:h}),h!==s&&e.setAttribute(r,h)}n.size&&ea.set(e,n)}function io(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);Ya(e);let a=t.nextNode();for(;a;){if(a instanceof Text){const n=Yt.get(a);n&&a.nodeValue===n.translated&&(a.nodeValue=n.source)}else a instanceof Element&&Ya(a);a=t.nextNode()}}function Ya(e){const t=ea.get(e);if(t)for(const[a,n]of t)e.getAttribute(a)===n.translated&&e.setAttribute(a,n.source)}function Rt(e){return ao.has(e.tagName)||!!e.closest('[data-localization-skip="true"]')}const Mt=["May 12","May 19","May 26","Jun 02","Jun 09","Jun 16","Jun 23","Jun 30"],it=Mt.slice(2),nr={contextRuntime:{apiToken:"",contextApiEnabled:!1,fileMode:!1},cards:[{label:"Total Tokens",value:"24.83M",detail:"7-day total: 12.56M",trend:"up 18.7% vs prior 7 days",tone:"blue"},{label:"Estimated Cost",value:"$42.67",detail:"7-day total: $24.81",trend:"up 14.2% vs prior 7 days",tone:"green"},{label:"Cache Hit Rate",value:"38.7%",detail:"7-day average: 42.3%",trend:"down 3.6pp vs prior 7 days",tone:"purple"},{label:"Total Calls",value:"1,342",detail:"678 calls in last 7 days",trend:"up 11.3% vs prior 7 days",tone:"blue"},{label:"Usage Remaining",value:"32.4%",detail:"~15.9K credits estimated",trend:"resets in 4d 12h",tone:"green"}],tokenSeries:[Q("input","Input","#2563eb",[5.2,6.4,7.5,9.2,6.7,7.5,6.6,9],1e6),Q("output","Output","#059669",[2.5,3,3.6,5.1,3.7,5,4,5.4],1e6),Q("cached","Cached","#7c3aed",[1.1,1.4,1.7,2.4,1.8,2.3,1.8,2.6],1e6,!0)],costSeries:[Q("cost","Estimated Cost","#2563eb",[8.4,10.1,14.3,9.9,11.4,7.8,12.7,16.5])],cacheSeries:[Q("cache","Cache Hit Rate","#059669",[58,61,39,45,50,44,48,41])],weeklyCreditSeries:[{id:"pro",label:"Pro observed",color:"#2563eb",points:Mt.map((e,t)=>({label:e,value:[59800,44900,45e3,40500,42800,38900,31400,35900][t]??0,low:[52100,38800,38900,34700,36200,32200,26100,29900][t]??0,high:[67400,51200,51100,46800,49200,45100,37300,41900][t]??0}))},Q("pro-trend","Pro trend","#1d4ed8",[54.2,51,47.8,44.6,41.4,38.2,35,31.8],1e3,!0),Q("prolite","Prolite observed","#0f766e",[15.9,15.8,15.9,16.1,15.7,15.6,15.9,15.8],1e3)],usageRemainingSeries:[Q("remaining","Usage remaining","#059669",[87,71,63,56,56,48,50,54]),Q("allowance","Allowance guide","#0f766e",[86,85,84,83,82,81,80,79],1,!0)],actualVsPredictedSeries:[Q("observed","Observed drain","#2563eb",[18.7,22.1,45.3,31,34.8],1e3),Q("predicted","Predicted baseline","#1d4ed8",[17.9,21.4,41.2,29.6,33.9],1e3,!0)],findings:[{rank:1,title:"Long Thread: data-engine-refactor",severity:"High",credits:12847,share:25.6,summary:"Very long duration with high model effort."},{rank:2,title:"Cache Misses (Large Inputs)",severity:"High",credits:9612,share:19.1,summary:"Large uncached inputs across 214 calls."},{rank:3,title:"High Model Effort",severity:"Medium",credits:7404,share:14.7,summary:"Reasoning and output token volume are concentrated."},{rank:4,title:"Tool Output Volume",severity:"Medium",credits:5231,share:10.4,summary:"Large tool outputs returned to the model."}],calls:[["2026-06-01T10:24:00Z","Jun 1, 10:24 AM","thread-9f3a1c","codex-1","high",128542,45231,62,.42,"18.4s",!1,["review"]],["2026-06-01T10:18:00Z","Jun 1, 10:18 AM","thread-7b2e91","o4-mini","medium",98731,32104,41,.31,"12.7s",!0,["analysis"]],["2026-06-01T10:12:00Z","Jun 1, 10:12 AM","thread-3c8d4e","o3","high",64221,18903,28,.12,"9.3s",!0,["uncached"]],["2026-06-01T10:06:00Z","Jun 1, 10:06 AM","thread-1a2b3c","codex-1","high",245123,98112,71,.87,"27.6s",!1,["large"]],["2026-06-01T10:01:00Z","Jun 1, 10:01 AM","thread-8d7c6b","gpt-4.1","low",12543,4231,12,.03,"3.6s",!0,["quick"]],["2026-06-01T09:55:00Z","Jun 1, 09:55 AM","thread-2f9e7d","o4-mini","medium",76881,28442,39,.24,"11.2s",!1,["subagent"]],["2026-06-01T09:50:00Z","Jun 1, 09:50 AM","thread-6a5b4c","codex-1","high",312654,112991,67,1.12,"31.8s",!1,["file-heavy"]],["2026-06-01T09:47:00Z","Jun 1, 09:47 AM","thread-0f1e2d","o3","low",8221,2903,15,.02,"2.8s",!0,["fast"]]].map(([e,t,a,n,r,s,i,o,h,f,d,b],u)=>{const p=Number(s),g=Number(i),v=Number(o),w=Math.round(p*Math.max(100-v,0)/100);return{id:`fixture-call-${u}`,rawTime:String(e),eventTimestamp:String(e),callStartedAt:String(e),time:String(t),thread:String(a),model:String(n),effort:String(r),input:p,output:g,reasoningOutput:Math.round(g*.2),totalTokens:p+g,cachedInput:Math.round(p*v/100),uncachedInput:w,cachedPct:v,cost:u===4?0:Number(h),credits:(u===4?0:Number(h))*25,duration:String(f),durationSeconds:Number.parseFloat(String(f))||0,previousCallGap:u===0?"-":`${u*7}m 0s`,previousCallEventTimestamp:u===0?"":`2026-06-01T09:${String(40+u).padStart(2,"0")}:00Z`,previousCallGapSeconds:u*420,initiator:u%3===0?"user":u%3===1?"assistant":"tool",initiatorReason:u%3===0?"direct user request":u%3===1?"assistant follow-up":"tool-driven continuation",initiatorConfidence:u%2===0?"exact":"estimated",serviceTier:"",fast:null,serviceTierSource:"",serviceTierConfidence:"",fastProxyCandidate:!!d,standardUsageCredits:(u===4?0:Number(h))*25,usageCreditMultiplier:1,usageCreditMultiplierSource:"tier_unknown",usageCreditConfidence:u===7?"user_override":u%4===0?"exact":u%4===1?"estimated":u%4===2?"missing":"fixture",usageCreditModel:u===4?"":`${n}-credits`,usageCreditSource:u===4?"":"fixture-rate-card",usageCreditFetchedAt:u===4?"":"2026-06-01T10:00:00Z",usageCreditTier:u%2===0?"standard":"estimated",usageCreditNote:u===2?"fixture inherited rate card":"",pricingModel:u===4?"":`${n}-pricing`,pricingEstimated:u===1||u===5,signal:w>5e4?"cache-risk":"aggregate",recommendation:w>5e4?"Review uncached aggregate input before continuing this thread.":"",tags:b,sessionId:`fixture-session-${u}`,turnId:`fixture-turn-${u}`,parentSessionId:u%3===0?"fixture-parent-session":"",parentSessionUpdatedAt:u%3===0?"2026-06-01T09:30:00Z":"",parentThread:u%3===0?"parent-thread-analysis":"",threadAttachmentLabel:u%3===0?"spawned child thread":"direct active thread",threadSource:u%3===0?"subagent":"user",subagentType:u%3===0?"analysis":"",agentRole:u%3===0?"reviewer":"",agentNickname:u%3===0?"usage-reviewer":"",project:u%2===0?"codex-usage-tracker":"local-ops",projectRelativeCwd:u%2===0?"frontend/dashboard":".",projectTags:u%2===0?["dashboard","rewrite"]:["local"],cwd:`/fixtures/${u%2===0?"codex-usage-tracker":"local-ops"}`,sourceFile:`fixture-thread-${u}.jsonl`,lineNumber:120+u,gitBranch:"experiment/frontend-rewrite",gitRemoteLabel:"origin",gitRemoteHash:`fixture-${u}`,contextWindowPct:Math.min(18+v,96),modelContextWindow:128e3,cumulativeTotalTokens:p+g+u*1e4,estimatedCacheSavings:Math.round((p-w)*1e-5*100)/100,efficiencyFlags:w>5e4?["cache-risk"]:[]}}),threads:[["thread-9f3a",142,58400,8.76,12,1.38,"High",42],["thread-7c2b",87,31200,4.21,22,1.12,"Medium",55],["thread-1a8c",64,22700,3.02,18,.98,"High",48],["thread-d3e1",53,18100,2.11,41,.81,"Low",72],["thread-b7f0",41,13600,1.65,47,.73,"Low",75],["thread-3c5d",36,9900,1.18,35,.66,"Medium",63],["thread-0e16",28,6400,.72,56,.58,"Low",82]].map(([e,t,a,n,r,s,i,o],h)=>{const f=Number(t),d=Number(a),b=Number(r),u=f*48,p=(h+1)*420;return{name:String(e),latestCallId:`fixture-call-${h}`,latestActivity:`Jun ${h+1}, 10:${String(24-h).padStart(2,"0")} AM`,latestActivityRaw:`2026-06-${String(h+1).padStart(2,"0")}T10:${String(24-h).padStart(2,"0")}:00Z`,turns:f,totalDurationSeconds:u,totalDuration:`${Math.floor(u/60)}m ${u%60}s`,averageGapSeconds:p,averageGap:`${Math.floor(p/60)}m ${p%60}s`,initiatorSummary:h%2===0?"user x4, assistant x2":"assistant x3, tool x1",modelSummary:h%2===0?"codex-1 x5, o4-mini x2":"o4-mini x3, o3 x1",effortSummary:h%2===0?"high x5, medium x2":"medium x3, low x1",totalTokens:d,cachedInput:Math.round(d*b/100),uncachedInput:Math.round(d*Math.max(100-b,0)/100),outputTokens:Math.round(d*.28),reasoningOutput:Math.round(d*.08),cost:Number(n),credits:Number(n)*25,cachePct:b,contextPct:Math.min(96,28+h*7),costPerCall:Number(s),coldResumeRisk:i,productivity:Number(o)}}),weeklyWindows:Mt.map((e,t)=>({week:e,plan:t===0?"Prolite":"Pro",observedPct:[61.4,49.2,47.7,48.3,44.5,37.4,40.1,35.8][t]??0,credits:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,projected:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,ciLow:[42156,34892,33424,34021,31241,26164,28234,29450][t]??0,ciHigh:[57467,47657,46349,47105,43326,36676,39450,41900][t]??0,confidence:t===0?"Medium":"High",note:["Prolite baseline","Drop in credits","Stable","Slight uptick","Down again","Lowest window","Recovery","Latest"][t]??""})),modelCosts:[{label:"codex-1",value:16.21,color:"#2563eb"},{label:"o3",value:12.43,color:"#1d4ed8"},{label:"o4-mini",value:7.62,color:"#059669"},{label:"gpt-4.1",value:4.91,color:"#f59e0b"},{label:"other",value:1.5,color:"#94a3b8"}],commandActions:[{title:"Show highest uncached calls",status:"Ready",owner:"Calls",description:"214 calls above the uncached threshold."},{title:"Compare Pro weeks",status:"Ready",owner:"Usage Drain",description:"Allowance windows with confidence intervals."},{title:"Find cold resumes",status:"Ready",owner:"Cache",description:"14 threads with long idle gaps."},{title:"Export support bundle",status:"Planned",owner:"Reports",description:"Local aggregate artifacts only."}],cacheSegments:[{label:"Cache read",value:38.7,color:"#2563eb"},{label:"Cache write",value:29.6,color:"#059669"},{label:"Uncached",value:31.7,color:"#7c3aed"}],cacheHeatmap:[{thread:"thread-8c1e",labels:it,values:[62,71,89,82,74,31]},{thread:"thread-2b9d",labels:it,values:[42,58,77,61,51,24]},{thread:"thread-713a",labels:it,values:[78,81,83,66,59,37]},{thread:"thread-4af2",labels:it,values:[24,36,63,54,71,44]},{thread:"thread-f9c3",labels:it,values:[18,25,41,38,52,22]}],diagnostics:[{title:"Usage Drain",status:"Ready",finding:"Projected weekly credits declined from the baseline and partially recovered in the latest window.",confidence:"High",metric:"33,842 credits / week",series:[Q("usage-drain","Projected credits","#2563eb",[41.8,46.7,45.9,32.1,33.8],1e3)]},{title:"Cache Behavior",status:"Ready",finding:"Cache hit rate is healthy overall, with spikes aligned to large cache misses and cold resumes.",confidence:"Medium",metric:"41.1% hit rate",series:[Q("cache","Cache hit %","#059669",[44,48,38,33,40])]},{title:"Thread Efficiency",status:"Ready",finding:"Long threads account for most estimated cost and are the clearest optimization target.",confidence:"High",metric:"65% cost share",series:[Q("threads","Cost share","#1d4ed8",[65,23,8,4])]},{title:"Tool And Command Activity",status:"Stale",finding:"Command volume is stable with a slight upward trend; read and shell commands dominate.",confidence:"Medium",metric:"912 commands",series:[Q("commands","Commands","#7c3aed",[542,488,611,883,912])]}],reports:[{title:"Weekly Credits",status:"Ready",owner:"Usage Drain",description:"Plan-specific weekly credits, trend lines, and confidence intervals."},{title:"Usage Remaining",status:"Ready",owner:"Usage Drain",description:"Observed remaining usage over time with reset handling."},{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Cumulative estimated cost by thread and concentration metrics."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Actual-vs-predicted drain and feature group comparisons."},{title:"Fast Mode Proxy",status:"Planned",owner:"Calls",description:"Candidate detection, speedup histogram, and confidence breakdowns."},{title:"Allowance Change",status:"Planned",owner:"Reports",description:"Week-to-week allowance estimate changes with careful language."}]};function Q(e,t,a,n,r=1,s=!1){return{id:e,label:t,color:a,dashed:s,points:n.map((i,o)=>({label:Mt[o]??`Point ${o+1}`,value:i*r}))}}function rr(e){if(window.location.protocol==="file:")throw new Error("Live refresh requires the localhost dashboard server.");if(!(e!=null&&e.api_token))throw new Error("Live refresh requires localhost dashboard API token.")}function ma(e){return{Accept:"application/json","X-Codex-Usage-Token":e.api_token||""}}function oo(e,t){return new Promise((a,n)=>{if(t!=null&&t.aborted){n(en(t));return}const r=window.setTimeout(()=>{t==null||t.removeEventListener("abort",s),a()},e);function s(){window.clearTimeout(r),n(en(t))}t==null||t.addEventListener("abort",s,{once:!0})})}function sr(e){return(e instanceof DOMException||e instanceof Error)&&e.name==="AbortError"}function en(e){return(e==null?void 0:e.reason)instanceof Error?e.reason:new DOMException("The request was cancelled.","AbortError")}const co=["#2563eb","#1d4ed8","#059669","#f59e0b","#94a3b8"];function ir(e){const t=new Map;e.forEach(r=>{const s=r.model||"unknown";t.set(s,(t.get(s)??0)+r.cost)});const a=[...t.entries()].sort((r,s)=>s[1]-r[1]||r[0].localeCompare(s[0]));return(a.length>5?[...a.slice(0,4),["other",a.slice(4).reduce((r,s)=>r+s[1],0)]]:a).map(([r,s],i)=>({label:r,value:s,color:co[i]??"#94a3b8"}))}function or(e){if(!e.length)return[];const t=Math.max(e.reduce((a,n)=>a+pt(n),0),1);return[lo(e,t),uo(e,t),ho(e,t),fo(e,t)].filter(a=>!!a).sort((a,n)=>n.credits-a.credits).map((a,n)=>({...a,rank:n+1}))}function cr(e){if(!e.length)return[];const t=[{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Estimated cost concentration by loaded aggregate thread."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Highest estimated credit-impact calls from loaded aggregate rows."}];return e.some(a=>a.fastProxyCandidate||a.effort.toLowerCase()==="low")&&t.push({title:"Fast Mode Proxy",status:"Ready",owner:"Calls",description:"Low-effort and fast-call candidates inferred from aggregate rows."}),t}function lo(e,t){const a=new Map;e.forEach(i=>a.set(i.thread,[...a.get(i.thread)??[],i]));const[n,r]=[...a.entries()].sort((i,o)=>Ae(o[1],f=>f.totalTokens)-Ae(i[1],f=>f.totalTokens)||o[1].length-i[1].length)[0]??[];if(!n||!(r!=null&&r.length)||r.length<2)return null;const s=Ae(r,pt);return{rank:0,title:`Long Thread: ${n}`,severity:s/t>=.25||r.length>=8?"High":"Medium",credits:Math.round(s),share:s/t*100,summary:`${r.length.toLocaleString()} loaded calls and ${Ae(r,i=>i.totalTokens).toLocaleString()} tokens in this thread.`}}function uo(e,t){const a=e.filter(r=>r.signal==="cache-risk"||r.cachedPct<35||r.uncachedInput>5e4);if(!a.length)return null;const n=Ae(a,pt);return{rank:0,title:"Cache Misses (Large Inputs)",severity:a.some(r=>r.cachedPct<20||r.uncachedInput>5e4)?"High":"Medium",credits:Math.round(n),share:n/t*100,summary:`${a.length.toLocaleString()} loaded calls show low cache reuse or large uncached input.`}}function ho(e,t){const a=e.filter(r=>r.effort.toLowerCase()==="high"||r.reasoningOutput>0);if(!a.length)return null;const n=Ae(a,pt);return{rank:0,title:"High Model Effort",severity:n/t>=.25?"High":"Medium",credits:Math.round(n),share:n/t*100,summary:`${a.length.toLocaleString()} loaded calls use high effort or report reasoning output.`}}function fo(e,t){const a=Math.max(25e3,mo(e.map(s=>s.output),.75)),n=e.filter(s=>s.output>=a||s.tags.some(i=>["file-heavy","subagent","large"].includes(i)));if(!n.length)return null;const r=Ae(n,pt);return{rank:0,title:"Tool Output Volume",severity:n.some(s=>s.output>5e4)?"High":"Medium",credits:Math.round(r),share:r/t*100,summary:`${n.length.toLocaleString()} loaded calls have high output volume or file-heavy/subagent tags.`}}function pt(e){return e.credits>0?e.credits:e.cost*25}function Ae(e,t){return e.reduce((a,n)=>a+t(n),0)}function mo(e,t){const a=e.filter(n=>Number.isFinite(n)).sort((n,r)=>n-r);return a.length?a[Math.min(a.length-1,Math.max(0,Math.floor((a.length-1)*t)))]??0:0}function lr(e){const t=new Map;for(const n of e){if(!Number.isFinite(n.timestamp))continue;const r=ur(n.timestamp),s=t.get(r)??{label:dr(n.timestamp),timestamp:po(n.timestamp),cached:0,cost:0,input:0,output:0};s.cached+=n.cached,s.cost+=n.cost,s.input+=n.input,s.output+=n.output,t.set(r,s)}const a=go(t);return a.length?{tokenSeries:[{id:"input",label:"Input",color:"#2563eb",points:a.map(n=>({label:n.label,value:n.input}))},{id:"output",label:"Output",color:"#059669",points:a.map(n=>({label:n.label,value:n.output}))},{id:"cached",label:"Cached",color:"#7c3aed",dashed:!0,points:a.map(n=>({label:n.label,value:n.cached}))}],costSeries:[{id:"cost",label:"Estimated Cost",color:"#f59e0b",points:a.map(n=>({label:n.label,value:n.cost}))}],cacheSeries:[{id:"cache",label:"Cache hit %",color:"#2563eb",points:a.map(n=>({label:n.label,value:n.input>0?n.cached/n.input*100:0}))}]}:{tokenSeries:[],costSeries:[],cacheSeries:[]}}function go(e){const t=[...e.values()].sort((s,i)=>s.timestamp-i.timestamp),a=t.at(0),n=t.at(-1);if(!a||!n)return[];const r=[];for(const s=new Date(a.timestamp);s.getTime()<=n.timestamp;s.setDate(s.getDate()+1)){const i=s.getTime(),o=ur(i);r.push(e.get(o)??{label:dr(i),timestamp:i,cached:0,cost:0,input:0,output:0})}return r}function ur(e){const t=new Date(e),a=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${a}-${n}`}function po(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}function dr(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function W(e,t){var n;const a=Number(((n=e.summary)==null?void 0:n[t])??0);return Number.isFinite(a)?a:0}function vo(e){if(!(!e.summary||e.load_window==="rows"))return{visibleCalls:W(e,"visible_calls"),inputTokens:W(e,"input_tokens"),cachedInputTokens:W(e,"cached_input_tokens"),uncachedInputTokens:W(e,"uncached_input_tokens"),outputTokens:W(e,"output_tokens"),reasoningOutputTokens:W(e,"reasoning_output_tokens"),totalTokens:W(e,"total_tokens"),estimatedCostUsd:W(e,"estimated_cost_usd"),usageCredits:W(e,"usage_credits")}}const bo=1e4,wo=500;async function tn(e,t,a){var s,i;const n=t.limit&&t.limit>0?t.limit:wo,r=await a(e,{...t,limit:n});return(i=t.onProgress)==null||i.call(t,{status:"completed",phase:"loading_rows",message:`Loaded ${t.loadWindow==="all"?"all-history":t.loadWindow} evidence window`,completed:Number(r.loaded_row_count??((s=r.rows)==null?void 0:s.length)??0),total:Number(r.total_available_rows??r.loaded_row_count??0),percent:100}),r}async function an(e,t,a){var o,h;const n=[];let r=0,s=null,i=Number((e==null?void 0:e.total_available_rows)??0);for(let f=0;f<1e3;f+=1){(o=t.signal)==null||o.throwIfAborted();const d=await a(e,{...t,refresh:f===0?t.refresh:!1,limit:bo,offset:r}),b=d.rows??[];s=d,n.push(...b),i=Number(d.total_available_rows??i??n.length);const u=n.length>=i||!d.has_more;if((h=t.onProgress)==null||h.call(t,{status:u?"completed":"running",phase:"loading_rows",message:"Loading all rows",completed:n.length,total:i,percent:u?100:i>0?Math.min(99,Math.floor(n.length/i*100)):0}),r+=b.length,!d.has_more||b.length===0||n.length>=i)break}return{...s??e??{},rows:n,loaded_row_count:n.length,limit:null,limit_label:"All",has_more:!1,total_available_rows:i||n.length}}function yo(){if(window.__CODEX_USAGE_BOOT__)return window.__CODEX_USAGE_BOOT__;const e=document.getElementById("usage-data");if(!(e!=null&&e.textContent))return null;try{return JSON.parse(e.textContent)}catch{return null}}async function _o(e,t={}){if(t.refresh&&(e!=null&&e.refresh_jobs_available)){const a=await So(e,t),n={...t,refresh:!a};return n.loadWindow&&n.loadWindow!=="rows"?tn(e,n,He):n.limit===0?an(e,n,He):He(e,n)}return t.loadWindow&&t.loadWindow!=="rows"?tn(e,t,He):t.limit===0?an(e,t,He):He(e,t)}async function So(e,t){try{return await Co(e,t),!0}catch(a){if(sr(a)||a instanceof hr)throw a;return!1}}async function He(e,t={}){rr(e);const a=new URLSearchParams({refresh:t.refresh?"1":"0",limit:String(t.limit??(e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??500),_:String(Date.now())});t.loadWindow&&a.set("load_window",t.loadWindow),t.since&&a.set("since",t.since),t.offset&&t.offset>0&&a.set("offset",String(t.offset)),(t.includeArchived??wr(e))&&a.set("include_archived","1");const r=await fetch(`/api/usage?${a.toString()}`,{headers:ma(e),cache:"no-store",signal:t.signal});return await ga(r,"Usage refresh")}async function Co(e,t){var o;rr(e);const a=new URLSearchParams({_:String(Date.now())});(t.includeArchived??wr(e))&&a.set("include_archived","1");const r=await fetch(`/api/refresh/start?${a.toString()}`,{headers:ma(e),cache:"no-store",signal:t.signal}),s=await ga(r,"Usage refresh start");(o=t.onProgress)==null||o.call(t,s);const i=typeof s.job_id=="string"?s.job_id:"";if(!i)throw new Error("Usage refresh start did not return a job id.");return xo(e,i,t.onProgress,t.signal)}async function xo(e,t,a,n){for(let r=0;r<600;r+=1){n==null||n.throwIfAborted();const s=new URLSearchParams({job_id:t,_:String(Date.now())}),i=await fetch(`/api/refresh/status?${s.toString()}`,{headers:ma(e),cache:"no-store",signal:n}),o=await ga(i,"Usage refresh status");if(a==null||a(o),o.status==="completed")return o;if(o.status==="failed")throw new hr(o.error||o.message||"Usage refresh failed.");await oo(Math.min(1e3,150+r*50),n)}throw new Error("Usage refresh did not complete before the polling timeout.")}class hr extends Error{}function nn(e){if(!e)return{...nr,contextRuntime:ra(e)};const t=e.rows??[],a=t.map(mr),n=t.length?ke(t,v=>Number(v.total_tokens??0)):W(e,"total_tokens"),r=t.length?ke(t,v=>Number(v.estimated_cost_usd??0)):W(e,"estimated_cost_usd"),s=t.length?ke(t,v=>Number(v.cached_input_tokens??0)):W(e,"cached_input_tokens"),i=t.length?ke(t,v=>Number(v.input_tokens??0)):W(e,"input_tokens"),o=t.length?ke(t,v=>{const w=Number(v.input_tokens??0),T=Number(v.cached_input_tokens??0);return Number(v.uncached_input_tokens??Math.max(w-T,0))}):Math.max(i-s,0),h=t.length?ke(t,v=>Number(v.output_tokens??0)):W(e,"output_tokens"),f=t.length?ke(t,v=>Number(v.reasoning_output_tokens??0)):W(e,"reasoning_output_tokens"),d=i>0?s/i*100:0,b=a.length||Math.max(0,Number(e.loaded_row_count??0)),u=To(t),p=Lo(t),g=jo({cachePct:d,cachedTokens:s,estimatedCost:r,historyScope:e.history_scope??"active",totalCalls:b,totalTokens:n,tokenBreakdown:{cachedInput:s,uncachedInput:o,output:h,reasoningOutput:f},usageRemainingCard:Ao(e)});return{...ko(e),contextRuntime:ra(e),scopeSummary:vo(e),cards:g,...u,...p,calls:a,threads:yr(a),findings:or(a),modelCosts:ir(a),reports:cr(a),cacheSegments:[{label:"Cache read",value:d,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-d,0),color:"#7c3aed"}]}}function ko(e){return{...nr,contextRuntime:ra(e),tokenSeries:[],costSeries:[],cacheSeries:[],weeklyCreditSeries:[],usageRemainingSeries:[],actualVsPredictedSeries:[],calls:[],threads:[],findings:[],weeklyWindows:[],modelCosts:[],commandActions:[],cacheSegments:[],cacheHeatmap:[],diagnostics:[],reports:[]}}function To(e){return lr(e.map(t=>({timestamp:va(t),cached:Number(t.cached_input_tokens??0),cost:Number(t.estimated_cost_usd??0),input:Number(t.input_tokens??0),output:Number(t.output_tokens??0)})))}function Lo(e){const t=[...e].map(f=>({row:f,timestamp:va(f)})).filter(f=>Number.isFinite(f.timestamp)).sort((f,d)=>f.timestamp-d.timestamp),a=new Map;for(const{row:f,timestamp:d}of t){const b=na(d),u=a.get(b)??{timestamp:d,credits:0,weeklyUsedPercent:null};u.credits+=Math.max(0,Number(f.usage_credits??0));const p=Oe(f.rate_limit_secondary_used_percent);p!==null&&(u.weeklyUsedPercent=p),a.set(b,u)}const n=[...a.entries()].map(([f,d])=>({label:f,...d}));let r=0;const s=n.map(f=>(r+=f.credits,{label:f.label,value:r})),i=s.map((f,d)=>{var b;return{label:f.label,value:s.length>1?(((b=s.at(-1))==null?void 0:b.value)??0)*((d+1)/s.length):f.value}}),o=n.filter(f=>f.weeklyUsedPercent!==null).map(f=>({label:f.label,value:Pt(100-(f.weeklyUsedPercent??0))})),h=Ro(e);return{weeklyCreditSeries:Mo(h),usageRemainingSeries:o.length?[{id:"weekly-remaining",label:"Weekly remaining",color:"#059669",points:o}]:[],actualVsPredictedSeries:s.length?[{id:"observed-drain",label:"Observed drain",color:"#2563eb",points:s},{id:"loaded-baseline",label:"Loaded-row baseline",color:"#1d4ed8",dashed:!0,points:i}]:[],weeklyWindows:h}}function Ro(e){const t=new Map;for(const a of e){const n=va(a);if(!Number.isFinite(n))continue;const r=Po(a,n),s=t.get(r)??{rows:[],latestTimestamp:0,latestUsedPercent:null};s.rows.push(a),n>=s.latestTimestamp&&(s.latestTimestamp=n,s.latestUsedPercent=Oe(a.rate_limit_secondary_used_percent)),t.set(r,s)}return[...t.entries()].map(([a,n])=>{var i;const r=n.rows.reduce((o,h)=>o+Math.max(0,Number(h.usage_credits??0)),0),s=n.latestUsedPercent??0;return{week:a,plan:String(((i=n.rows[0])==null?void 0:i.rate_limit_plan_type)??"unknown"),observedPct:s,credits:r,projected:s>0?r/(s/100):r,ciLow:s>0?r/(s/100)*.85:r,ciHigh:s>0?r/(s/100)*1.15:r,confidence:n.rows.length>=20?"Medium":"Low",note:`Loaded ${pa(n.rows.length)} rows`}}).sort((a,n)=>a.week.localeCompare(n.week))}function Mo(e){return e.length?[{id:"weekly-projected",label:"Projected weekly credits",color:"#2563eb",points:e.map(t=>({label:t.week,value:t.projected,low:t.ciLow,high:t.ciHigh}))},{id:"loaded-credits",label:"Loaded-row credits",color:"#0f766e",dashed:!0,points:e.map(t=>({label:t.week,value:t.credits}))}]:[]}function Po(e,t){const a=We(e.rate_limit_secondary_resets_at);return a!==null&&a>0?na(a*1e3):na(t)}function na(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function ra(e){return{apiToken:String((e==null?void 0:e.api_token)??""),contextApiEnabled:!!(e!=null&&e.context_api_enabled),fileMode:window.location.protocol==="file:"}}function jo(e){return[{label:"Total Tokens",value:Me(e.totalTokens),detail:`${e.historyScope} history scope`,trend:"loaded aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Me(e.tokenBreakdown.cachedInput)},{label:"Uncached",value:Me(e.tokenBreakdown.uncachedInput)},{label:"Output",value:Me(e.tokenBreakdown.output)},{label:"Reasoning",value:Me(e.tokenBreakdown.reasoningOutput)}]},{label:"Estimated Cost",value:Oo(e.estimatedCost),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.cachePct.toFixed(1)}%`,detail:`${Me(e.cachedTokens)} cached input`,trend:e.cachePct>=40?"healthy cache reuse":"cache risk",tone:e.cachePct>=40?"purple":"orange"},{label:"Total Calls",value:pa(e.totalCalls),detail:"loaded calls in this dashboard",trend:"privacy-safe",tone:"blue"},e.usageRemainingCard]}function Ao(e){const t=No(e.observed_usage);if(t)return t;const a=Eo(e.allowance_windows);return a||{label:"Usage Remaining",value:"Unknown",detail:e.allowance_configured?"allowance configured; no current window":"no observed usage or allowance window",trend:e.allowance_error?`config issue: ${e.allowance_error}`:"not available in payload",tone:e.allowance_error?"red":"orange"}}function No(e){const t=Array.isArray(e==null?void 0:e.windows)?e.windows:[];if(!(e!=null&&e.available)||!t.length)return null;const a=fr(t,s=>Oe(s.used_percent)!==null);if(!a)return null;const n=Oe(a.used_percent)??0,r=Pt(100-n);return{label:"Usage Remaining",value:gr(r),detail:`${vr(a.label||a.key,"Observed usage")} observed usage`,trend:pr(a.resets_at)||e.source||"observed locally",tone:br(r)}}function Eo(e){if(!Array.isArray(e)||!e.length)return null;const t=fr(e,o=>{const h=Oe(o.remaining_percent),f=We(o.remaining_credits),d=We(o.total_credits);return h!==null||f!==null||d!==null&&d>0});if(!t)return null;const a=We(t.remaining_credits),n=We(t.total_credits),r=a!==null&&n!==null&&n>0?a/n*100:null,s=Oe(t.remaining_percent)??r;return{label:"Usage Remaining",value:s!==null?gr(Pt(s)):`${rn(a??0)} left`,detail:`${vr(t.label||t.key,"Allowance")} allowance window`,trend:[a===null?"":`${rn(a)} left`,pr(t.reset_at)].filter(Boolean).join(" · ")||"configured allowance",tone:s===null?"green":br(Pt(s))}}function fr(e,t){const a=e.filter(t);return a.find(Do)??a[0]??null}function Do(e){const t=We(e.window_minutes),a=`${e.key??""} ${e.label??""}`.toLowerCase();return t===10080||/\b(weekly|week|7d|7-day|7 day)\b/.test(a)}function mr(e,t=0){const a=String(e.event_timestamp??e.time??e.turn_timestamp??e.started_at??e.call_started_at??""),n=a,r=String(e.call_started_at??e.started_at??a),s=Number(e.input_tokens??0),i=Number(e.output_tokens??0),o=Number(e.reasoning_output_tokens??0),h=Number(e.cached_input_tokens??0),f=Number(e.cache_hit_ratio??e.cache_ratio??0),d=s>0?h/s*100:f*100,b=Number(e.total_tokens??s+i),u=Number(e.duration_seconds??e.call_duration_seconds??0),p=String(e.previous_call_event_timestamp??""),g=Number(e.previous_call_delta_seconds??0),v=Number(e.uncached_input_tokens??Math.max(s-h,0)),w=String(e.record_id??e.id??`${n||"row"}-${t}`),T=String(e.primary_signal??"").trim(),N=Number(e.line_number),R=Oe(e.context_window_percent),_=Number(e.model_context_window),L=Number(e.cumulative_total_tokens),y=e.fast,x=y===!0||y===1?!0:y===!1||y===0?!1:null;return{id:w,threadKey:String(e.thread_key??""),rawTime:n,eventTimestamp:a,callStartedAt:r,time:_r(n),thread:Io(e),model:String(e.model??"unknown"),effort:String(e.effort??"blank"),input:s,output:i,reasoningOutput:o,totalTokens:b,cachedInput:h,uncachedInput:v,cachedPct:d,cost:Number(e.estimated_cost_usd??0),credits:Number(e.usage_credits??0),duration:jt(u),durationSeconds:u,previousCallGap:jt(g),previousCallEventTimestamp:p,previousCallGapSeconds:Number.isFinite(g)?g:0,initiator:String(e.call_initiator??"unknown"),initiatorReason:String(e.call_initiator_reason??""),initiatorConfidence:String(e.call_initiator_confidence??""),serviceTier:String(e.service_tier??""),fast:x,serviceTierSource:String(e.service_tier_source??""),serviceTierConfidence:String(e.service_tier_confidence??""),fastProxyCandidate:u>0&&b/Math.max(u,1)>4e3,standardUsageCredits:Number(e.standard_usage_credits??e.usage_credits??0),usageCreditMultiplier:Number(e.usage_credit_multiplier??1),usageCreditMultiplierSource:String(e.usage_credit_multiplier_source??""),usageCreditConfidence:String(e.usage_credit_confidence??"unknown"),usageCreditModel:String(e.usage_credit_model??""),usageCreditSource:String(e.usage_credit_source??""),usageCreditFetchedAt:String(e.usage_credit_fetched_at??""),usageCreditTier:String(e.usage_credit_tier??""),usageCreditNote:String(e.usage_credit_note??""),pricingModel:String(e.pricing_model??""),pricingEstimated:!!e.pricing_estimated,signal:T||(d<25?"cache-risk":"aggregate"),recommendation:String(e.recommended_action??""),tags:d<25?["uncached"]:d>60?["healthy-cache"]:[],sessionId:String(e.session_id??""),turnId:String(e.turn_id??""),parentSessionId:String(e.parent_session_id??""),parentSessionUpdatedAt:String(e.resolved_parent_session_updated_at??e.parent_session_updated_at??""),parentThread:String(e.resolved_parent_thread_name??e.parent_thread_name??""),threadAttachmentLabel:String(e.thread_attachment_label??""),threadSource:String(e.thread_source??""),subagentType:String(e.subagent_type??""),agentRole:String(e.agent_role??""),agentNickname:String(e.agent_nickname??""),project:String(e.project_name??""),projectRelativeCwd:String(e.project_relative_cwd??""),projectTags:Array.isArray(e.project_tags)?e.project_tags.map(M=>String(M)):[],cwd:String(e.cwd??""),sourceFile:String(e.source_file??""),lineNumber:Number.isFinite(N)&&N>0?N:null,gitBranch:String(e.git_branch??""),gitRemoteLabel:String(e.git_remote_label??""),gitRemoteHash:String(e.git_remote_hash??""),contextWindowPct:R,modelContextWindow:Number.isFinite(_)&&_>0?_:null,cumulativeTotalTokens:Number.isFinite(L)&&L>0?L:null,estimatedCacheSavings:Number(e.estimated_cache_savings_usd??0),efficiencyFlags:Array.isArray(e.efficiency_flags)?e.efficiency_flags.map(M=>String(M)):[]}}function Oe(e){const t=Number(e);return Number.isFinite(t)?t<=1?t*100:t:null}function We(e){const t=Number(e);return Number.isFinite(t)?t:null}function Pt(e){return Math.max(0,Math.min(100,e))}function gr(e){const t=Math.abs(e)>=10?0:1;return`${e.toFixed(t)}%`}function rn(e){return`${Me(e)} cr`}function pr(e){if(e==null||e==="")return"";const t=typeof e=="number"?e*1e3:Date.parse(e);return Number.isFinite(t)?`resets ${Fo(t)}`:""}function Fo(e){const t=new Date(e);return Number.isNaN(t.getTime())?String(e):`${t.toISOString().slice(0,16).replace("T"," ")} UTC`}function vr(e,t){return(e==null?void 0:e.trim())||t}function br(e){return e<20?"red":e<40?"orange":"green"}function wr(e){return typeof e.include_archived=="boolean"?e.include_archived:e.history_scope==="all-history"||e.history_scope==="all"}function Io(e){const t=e.thread_name??e.thread??e.resolved_parent_thread_name??e.parent_thread_name;if(t&&String(t).trim())return String(t);const a=e.project_name??e.project_relative_cwd,n=e.session_id?e.session_id.slice(-6):"";return a&&n?`${a} ${n}`:e.thread_attachment_label?String(e.thread_attachment_label):"Untitled thread"}function yr(e){const t=new Map;for(const a of e)t.set(a.thread,[...t.get(a.thread)??[],a]);return[...t.entries()].map(([a,n])=>{const r=n.length,i=[...n].sort((y,x)=>sn(x)-sn(y))[0]??null,o=(i==null?void 0:i.rawTime)||(i==null?void 0:i.time)||"",h=n.reduce((y,x)=>y+x.totalTokens,0),f=n.reduce((y,x)=>y+x.cachedInput,0),d=n.reduce((y,x)=>y+x.uncachedInput,0),b=n.reduce((y,x)=>y+x.output,0),u=n.reduce((y,x)=>y+x.reasoningOutput,0),p=n.reduce((y,x)=>y+x.cost,0),g=n.reduce((y,x)=>y+x.credits,0),v=n.reduce((y,x)=>y+x.durationSeconds,0),w=n.filter(y=>y.previousCallGapSeconds>0),T=w.reduce((y,x)=>y+x.previousCallGapSeconds,0)/Math.max(w.length,1),N=f+d,R=N>0?f/N*100:n.reduce((y,x)=>y+x.cachedPct,0)/Math.max(r,1),_=n.map(y=>y.contextWindowPct).filter(y=>typeof y=="number"&&Number.isFinite(y)),L=R<25?"High":R<45?"Medium":"Low";return{name:a,latestCallId:(i==null?void 0:i.id)??"",latestActivity:_r(o),latestActivityRaw:o,turns:r,totalDurationSeconds:v,totalDuration:jt(v),averageGapSeconds:T,averageGap:jt(T),initiatorSummary:zt(n.map(y=>y.initiator)),modelSummary:zt(n.map(y=>y.model)),effortSummary:zt(n.map(y=>y.effort)),totalTokens:h,cachedInput:f,uncachedInput:d,outputTokens:b,reasoningOutput:u,cost:p,credits:g,cachePct:R,contextPct:_.length?Math.max(..._):null,costPerCall:p/Math.max(r,1),coldResumeRisk:L,productivity:Math.max(20,Math.round(R-p/Math.max(r,1)*4))}}).sort((a,n)=>n.cost-a.cost).slice(0,20)}function sn(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function zt(e,t=3){const a=new Map;for(const n of e){const r=n.trim()||"unknown";a.set(r,(a.get(r)??0)+1)}return[...a.entries()].sort((n,r)=>r[1]-n[1]||n[0].localeCompare(r[0])).slice(0,t).map(([n,r])=>`${n} x${pa(r)}`).join(", ")||"unknown"}function ke(e,t){return e.reduce((a,n)=>a+t(n),0)}async function ga(e,t){let a;try{a=await e.json()}catch(n){if(e.ok)throw new Error(`${t} response could not be read as JSON: ${$o(n)}`);a={}}if(!e.ok){const n=typeof a.error=="string"?a.error:`${t} request failed (${e.status})`;throw new Error(n)}return a}function $o(e){return e instanceof Error?e.message:String(e)}function pa(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Me(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Oo(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function jt(e){if(!Number.isFinite(e)||e<=0)return"-";if(e<60)return`${e.toFixed(0)}s`;const t=Math.floor(e/60),a=Math.round(e%60);return`${t}m ${a}s`}function _r(e){const t=new Date(e);return Number.isNaN(t.getTime())?e||"-":new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).format(t)}function va(e){return Date.parse(String(e.started_at??e.call_started_at??e.time??e.event_timestamp??e.turn_timestamp??""))}const Pe=1440*60*1e3;function Uo(e,t,a=window.location.search){const n=Sr(a);if(!n.active)return e;const r=e.calls.filter(s=>Vo(s,n));return r.length===e.calls.length?e:zo(e,r,`${t} filtered`)}function Sr(e){var h,f,d,b,u,p;const t=new URLSearchParams(e),a=((h=t.get("model"))==null?void 0:h.trim())??"",n=((f=t.get("effort"))==null?void 0:f.trim())??"",r=((d=t.get("confidence")||t.get("pricing"))==null?void 0:d.trim())??"",s=((b=t.get("date")||t.get("time"))==null?void 0:b.trim())??"",i=((u=t.get("from"))==null?void 0:u.trim())??"",o=((p=t.get("to"))==null?void 0:p.trim())??"";return{model:a,effort:n,confidence:r,datePreset:s,dateStart:i,dateEnd:o,active:!!(a||n||r||s||i||o)}}function Vo(e,t){return!(t.model&&e.model!==t.model||t.effort&&e.effort!==t.effort||t.confidence&&!Ko(e,t.confidence)||!qo(e,t))}function Ko(e,t){return t==="official"||t==="cost-exact"?!!(e.pricingModel&&!e.pricingEstimated):t==="estimated"||t==="cost-estimated"?e.pricingEstimated:t==="unpriced"||t==="cost-unpriced"?!e.pricingModel:t==="credit-exact"?e.usageCreditConfidence==="exact":t==="credit-estimated"?e.usageCreditConfidence==="estimated":t==="credit-override"?e.usageCreditConfidence==="user_override":t==="credit-missing"?e.usageCreditConfidence==="missing"||e.usageCreditConfidence==="unknown":!0}function qo(e,t){const a=Ho(t);if(!a.active)return!0;if(a.invalid)return!1;const n=Date.parse(e.rawTime||e.time);return!(!Number.isFinite(n)||a.start!==null&&n=a.endExclusive)}function Ho(e){if(e.datePreset&&e.datePreset!=="all"&&e.datePreset!=="custom"){const n=Qo(e.datePreset);return n?{active:!0,invalid:!1,...n}:{active:!1,invalid:!1,start:null,endExclusive:null}}const t=on(e.dateStart),a=on(e.dateEnd);return t!==null&&a!==null&&t>a?{active:!0,invalid:!0,start:t,endExclusive:a+Pe}:{active:t!==null||a!==null,invalid:!1,start:t,endExclusive:a===null?null:a+Pe}}function Qo(e){const t=Wo(new Date);if(e==="today")return{start:t,endExclusive:t+Pe};if(e==="last-7-days")return{start:t-6*Pe,endExclusive:t+Pe};if(e==="this-week"){const n=new Date(t).getDay(),r=n===0?-6:1-n,s=t+r*Pe;return{start:s,endExclusive:s+7*Pe}}if(e==="this-month"){const a=new Date(t),n=new Date(a.getFullYear(),a.getMonth(),1).getTime(),r=new Date(a.getFullYear(),a.getMonth()+1,1).getTime();return{start:n,endExclusive:r}}return null}function on(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,a,n]=e.split("-").map(Number),r=new Date(t,a-1,n);return r.getFullYear()!==t||r.getMonth()!==a-1||r.getDate()!==n?null:r.getTime()}function Wo(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function zo(e,t,a="filtered"){const n=t.reduce((u,p)=>u+p.totalTokens,0),r=t.reduce((u,p)=>u+p.cost,0),s=t.reduce((u,p)=>u+p.cachedInput,0),i=t.reduce((u,p)=>u+p.uncachedInput,0),o=t.reduce((u,p)=>u+p.output,0),h=t.reduce((u,p)=>u+p.reasoningOutput,0),f=t.reduce((u,p)=>u+p.input,0),d=f>0?s/f*100:0,b=e.cards.find(u=>u.label==="Usage Remaining")??{label:"Usage Remaining",value:"Unknown",detail:"not available in filtered view",trend:"not available in payload",tone:"orange"};return{...e,cards:Bo({cachePct:d,cachedTokens:s,estimatedCost:r,historyScope:a,totalCalls:t.length,totalTokens:n,tokenBreakdown:{cachedInput:s,uncachedInput:i,output:o,reasoningOutput:h},usageRemainingCard:b}),...Go(t),calls:t,threads:yr(t),findings:or(t),modelCosts:ir(t),reports:cr(t),cacheSegments:[{label:"Cache read",value:d,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-d,0),color:"#7c3aed"}]}}function Bo({cachePct:e,cachedTokens:t,estimatedCost:a,historyScope:n,totalCalls:r,totalTokens:s,tokenBreakdown:i,usageRemainingCard:o}){return[{label:"Total Tokens",value:Qe(s),detail:`${n} history scope`,trend:"filtered aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Qe(i.cachedInput)},{label:"Uncached",value:Qe(i.uncachedInput)},{label:"Output",value:Qe(i.output)},{label:"Reasoning",value:Qe(i.reasoningOutput)}]},{label:"Estimated Cost",value:Zo(a),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.toFixed(1)}%`,detail:`${Qe(t)} cached input`,trend:e>=40?"healthy cache reuse":"cache risk",tone:e>=40?"purple":"orange"},{label:"Total Calls",value:Jo(r),detail:"loaded calls matching filters",trend:"legacy shell filters",tone:"blue"},o]}function Go(e){return lr(e.map(t=>({timestamp:Date.parse(t.rawTime||t.time),cached:t.cachedInput,cost:t.cost,input:t.input,output:t.output})))}function Qe(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Jo(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Zo(e){return new Intl.NumberFormat("en-US",{currency:"USD",maximumFractionDigits:2,minimumFractionDigits:2,style:"currency"}).format(e)}const Cr=[{id:"overview",label:"Overview",description:"High-level telemetry",icon:Ds},{id:"investigator",label:"Investigate",description:"Root-cause evidence",icon:Es},{id:"compression-lab",label:"Compression Lab",description:"Context savings",icon:Ls},{id:"calls",label:"Calls",description:"Model-call table",icon:Os},{id:"threads",label:"Threads",description:"Thread efficiency",icon:Ks},{id:"usage-drain",label:"Limits",description:"Allowance intelligence",icon:Vs},{id:"cache-context",label:"Cache And Context",description:"Cache and cold resumes",icon:Ps},{id:"diagnostics",label:"Diagnostics Notebook",description:"Technical report",icon:ks},{id:"reports",label:"Reports",description:"Generated analyses",icon:Rs},{id:"settings",label:"Settings",description:"Local configuration",icon:Is}],xr=[{label:"Files",icon:As,target:"settings"},{label:"Commands",icon:Cs,target:"investigator"},{label:"Models",icon:Ts,target:"calls"}];function kr(e){return ws(e)}const Xo=[{value:"day",label:"24 hours",ariaLabel:"Last 24h"},{value:"week",label:"7 days",ariaLabel:"Last 7 days"},{value:"rows",label:"Recent",ariaLabel:"Recent rows"},{value:"all",label:"All time",ariaLabel:"All time"}];function Yo(e){const t=e.refreshing||!e.canUseLiveApi,a=e.loadWindow==="rows",n=`${e.loadedRowCount.toLocaleString()} detail row${e.loadedRowCount===1?"":"s"} cached`,r=a?`${e.loadedRowCount.toLocaleString()} loaded / ${e.totalAvailableRows.toLocaleString()} total`:`${e.totalAvailableRows.toLocaleString()} calls analyzed · ${n}`,s=a?`${e.loadedRowCount.toLocaleString()} of ${e.totalAvailableRows.toLocaleString()} evidence rows loaded`:`Focused pages analyze all ${e.totalAvailableRows.toLocaleString()} calls in scope; ${e.loadedRowCount.toLocaleString()} call rows are cached for immediate detail views.`,i=a?e.rowLoadStatus:`${e.rowLoadModeLabel} analysis uses ${e.totalAvailableRows.toLocaleString()} calls; ${n}`;return c.jsxs("section",{className:"data-window-control","aria-label":"Analysis scope",children:[c.jsxs("div",{className:"data-window-summary",children:[c.jsx("span",{children:"Analysis scope"}),c.jsx("strong",{children:e.rowLoadModeLabel}),c.jsx("small",{title:s,children:r})]}),c.jsx("div",{className:"data-window-options",role:"group","aria-label":"Choose loaded call window",children:Xo.map(o=>c.jsx("button",{type:"button","aria-label":o.ariaLabel,"aria-pressed":e.loadWindow===o.value,disabled:t,onClick:()=>e.onWindowChange(o.value),children:o.label},o.value))}),e.loadWindow==="rows"?c.jsxs("div",{className:"row-window-editor",children:[c.jsx("input",{"aria-label":"Rows to load slider","aria-valuetext":`${e.finitePendingLoadLimit.toLocaleString()} recent rows`,type:"range",min:1,max:e.rowLimitSliderMax,step:100,value:e.rowLimitSliderValue,onChange:o=>e.onSliderChange(o.target.value),disabled:t}),c.jsx("input",{"aria-label":"Rows to load",type:"number",min:1,step:100,value:e.pendingLoadLimit,onChange:o=>e.onDraftChange(o.target.value),disabled:t}),c.jsx("button",{type:"button","data-primary":"true",onClick:e.onApply,disabled:t||!e.rowLimitChanged,children:e.loadLabel}),c.jsx("button",{type:"button",onClick:e.onLoadMore,disabled:t||!e.hasMoreRows,children:e.loadMoreLabel})]}):null,e.refreshing?c.jsxs("div",{className:"row-load-progress","aria-label":"Row loading progress",children:[c.jsx("div",{className:"row-load-progress-track",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":e.refreshProgressPercent??void 0,children:c.jsx("span",{style:{width:`${e.refreshProgressPercent??8}%`}})}),c.jsxs("span",{children:[e.refreshProgressPercent===null?e.refreshProgressText:`${Math.round(e.refreshProgressPercent)}% loaded`,c.jsx("button",{className:"icon-button",type:"button",onClick:()=>void e.onCancel(),"aria-label":"Cancel refresh",title:"Cancel refresh",children:c.jsx(la,{size:13})})]})]}):null,c.jsx("span",{className:"sr-only",role:"status","aria-live":"polite",children:i})]})}const ba=[{value:"all",label:"All time"},{value:"today",label:"Today"},{value:"this-week",label:"This week"},{value:"last-7-days",label:"Last 7 days"},{value:"this-month",label:"This month"},{value:"custom",label:"Custom"}],Tr=[{value:"all",label:"All confidence"},{value:"cost-exact",label:"Exact cost"},{value:"cost-estimated",label:"Estimated cost"},{value:"cost-unpriced",label:"Unpriced cost"},{value:"credit-exact",label:"Exact credit"},{value:"credit-estimated",label:"Estimated credit"},{value:"credit-override",label:"Credit override"},{value:"credit-missing",label:"Missing credit"}];function ec({activeView:e,locationSearch:t,model:a,onUrlChange:n}){const r=Sr(t),s=C.useMemo(()=>cn(a.calls.map(g=>g.model)),[a.calls]),i=C.useMemo(()=>cn(a.calls.map(g=>g.effort)),[a.calls]),o=r.dateStart||r.dateEnd?"custom":tc(r.datePreset),h=nc(r,o);if(e==="calls"||e==="call"||!a.calls.length)return null;function f(g){const v=new URL(window.location.href);g(v),n(v)}function d(g,v){f(w=>{g==="confidence"&&w.searchParams.delete("pricing"),!v||v==="all"?w.searchParams.delete(g):w.searchParams.set(g,v)})}function b(g){f(v=>{if(!g||g==="all"){v.searchParams.delete("date"),v.searchParams.delete("time"),v.searchParams.delete("from"),v.searchParams.delete("to");return}v.searchParams.set("date",g),v.searchParams.set("time",g),g!=="custom"&&(v.searchParams.delete("from"),v.searchParams.delete("to"))})}function u(g,v){f(w=>{v?(w.searchParams.set(g,v),w.searchParams.set("date","custom"),w.searchParams.set("time","custom")):(w.searchParams.delete(g),!w.searchParams.get("from")&&!w.searchParams.get("to")&&(w.searchParams.delete("date"),w.searchParams.delete("time")))})}function p(){f(g=>{for(const v of["model","effort","confidence","pricing","date","time","from","to"])g.searchParams.delete(v)})}return c.jsxs("section",{className:"global-filter-strip span-all","aria-label":"Dashboard filters",children:[c.jsxs("strong",{children:[c.jsx(Ns,{size:15}),"Filters"]}),c.jsxs("label",{children:[c.jsx("span",{children:"Model"}),c.jsxs("select",{"aria-label":"Global model filter",value:r.model||"all",onChange:g=>d("model",g.target.value),children:[c.jsx("option",{value:"all",children:"All models"}),s.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Effort"}),c.jsxs("select",{"aria-label":"Global effort filter",value:r.effort||"all",onChange:g=>d("effort",g.target.value),children:[c.jsx("option",{value:"all",children:"All effort"}),i.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Confidence"}),c.jsx("select",{"aria-label":"Global confidence filter",value:ac(r.confidence),onChange:g=>d("confidence",g.target.value),children:Tr.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Time"}),c.jsx("select",{"aria-label":"Global time filter",value:o,onChange:g=>b(g.target.value),children:ba.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))}),h?c.jsx("span",{className:"filter-status","data-state":h.state,"aria-live":"polite",children:h.label}):null]}),c.jsxs("label",{children:[c.jsx("span",{children:"Start"}),c.jsx("input",{"aria-label":"Global start date",type:"date",value:r.dateStart,onChange:g=>u("from",g.target.value)})]}),c.jsxs("label",{children:[c.jsx("span",{children:"End"}),c.jsx("input",{"aria-label":"Global end date",type:"date",value:r.dateEnd,onChange:g=>u("to",g.target.value)})]}),c.jsxs("button",{className:"toolbar-button",type:"button",disabled:!r.active,onClick:p,children:[c.jsx(la,{size:15}),"Clear filters"]})]})}function cn(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean))).sort((t,a)=>t.localeCompare(a))}function tc(e){return ba.some(t=>t.value===e)?e:"all"}function ac(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":Tr.some(t=>t.value===e)?e:"all"}function nc(e,t){var r;const a=un(e.dateStart),n=un(e.dateEnd);if(a!==null&&n!==null&&a>n)return{label:"Invalid date range",state:"error"};if(t==="custom"&&(e.dateStart||e.dateEnd))return{label:rc(e.dateStart,e.dateEnd),state:"active"};if(t!=="all"){const s=((r=ba.find(o=>o.value===t))==null?void 0:r.label)??t,i=sc(t);return{label:i?`${s}: ${ln(i.start)} to ${ln(ze(i.endExclusive,-1))}`:s,state:"active"}}return null}function rc(e,t){return e&&t?`Custom: ${e} to ${t}`:e?`Custom: from ${e}`:t?`Custom: through ${t}`:"Custom range"}function sc(e){const t=ic();if(e==="today")return{start:t,endExclusive:ze(t,1)};if(e==="this-week"){const a=oc(t);return{start:a,endExclusive:ze(a,7)}}return e==="last-7-days"?{start:ze(t,-6),endExclusive:ze(t,1)}:e==="this-month"?{start:new Date(t.getFullYear(),t.getMonth(),1),endExclusive:new Date(t.getFullYear(),t.getMonth()+1,1)}:null}function ic(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function oc(e){const t=e.getDay();return ze(e,t===0?-6:1-t)}function ze(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function ln(e){const t=String(e.getMonth()+1).padStart(2,"0"),a=String(e.getDate()).padStart(2,"0");return`${e.getFullYear()}-${t}-${a}`}function un(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,a,n]=e.split("-").map(Number),r=new Date(t,a-1,n);return r.getFullYear()!==t||r.getMonth()!==a-1||r.getDate()!==n?null:r.getTime()}function cc(e){return kr(e)&&e!=="call"}function sa(e,t="overview"){return e==="insights"?"overview":kr(e)?e:t}function dn(e=window.location.search,t="calls"){const a=new URLSearchParams(e).get("return"),n=sa(a,t);return cc(n)?n:t}function hn(e=window.location.search){return new URLSearchParams(e).has("return")}function lc(e){var t,a;return((t=Cr.find(n=>n.id===e))==null?void 0:t.label)??((a=xr.find(n=>n.target===e))==null?void 0:a.label)??"Calls"}function fn(e,t=window.location.search){return new URLSearchParams(t).get("history")==="all"?"all":e}function mn(e,t=window.location.href){const a=new URL(t);return e==="all"?a.searchParams.set("history","all"):a.searchParams.delete("history"),a}const uc={investigator:["finding"],threads:["thread","expand","threads","thread_q","risk","thread_call_sort","thread_call_page"],"cache-context":["cache_thread"],reports:["report"],"usage-drain":["usage_plan","usage_effort","usage_subagents","usage_sample","usage_confidence","limit_window","limit_hypothesis"],diagnostics:["diagnostic_source","diagnostic_fact"],calls:["explore","detail","call_q","source","sort","direction","density","page"],call:["record","return","mode","max_entries","max_chars","include_tool_output","include_compaction_history"]};function xt(e,t,a=[]){const n=new Set([t,...Array.isArray(a)?a:[a]]);for(const[r,s]of Object.entries(uc))if(!n.has(r))for(const i of s)e.searchParams.delete(i)}function gn(e){let t=!1;return e.searchParams.get("view")==="insights"&&(e.searchParams.set("view","overview"),t=!0),e.searchParams.get("return")==="insights"&&(e.searchParams.set("return","overview"),t=!0),t}const Lr=[{key:"overview",title:"Overview",path:"/api/diagnostics/overview",refreshPath:"/api/diagnostics/overview/refresh"},{key:"toolOutput",title:"Tool Output",path:"/api/diagnostics/tool-output",refreshPath:"/api/diagnostics/tool-output/refresh"},{key:"commands",title:"Commands",path:"/api/diagnostics/commands",refreshPath:"/api/diagnostics/commands/refresh"},{key:"gitInteractions",title:"Git Interactions",path:"/api/diagnostics/git-interactions",refreshPath:"/api/diagnostics/git-interactions/refresh"},{key:"fileReads",title:"File Reads",path:"/api/diagnostics/file-reads",refreshPath:"/api/diagnostics/file-reads/refresh"},{key:"fileModifications",title:"File Modifications",path:"/api/diagnostics/file-modifications",refreshPath:"/api/diagnostics/file-modifications/refresh"},{key:"readProductivity",title:"Read Productivity",path:"/api/diagnostics/read-productivity",refreshPath:"/api/diagnostics/read-productivity/refresh"},{key:"concentration",title:"Concentration",path:"/api/diagnostics/concentration",refreshPath:"/api/diagnostics/concentration/refresh"},{key:"guidedSummary",title:"What Is Driving Usage?",path:"/api/diagnostics/guided-summary",refreshPath:"/api/diagnostics/guided-summary/refresh"},{key:"usageDrain",title:"Usage Drain",path:"/api/diagnostics/usage-drain",refreshPath:"/api/diagnostics/usage-drain/refresh"}],At=new Map,Dt=new Map;function dc(){At.clear(),Dt.clear()}async function ql(e,t,a={}){_a(t);const n=pc(e);return a.signal?Nt(n,t,a.signal):gc(Dt,ya(e,t,a.cacheKey),()=>Nt(n,t))}async function Hl(e,t={}){_a(e);const a=await fetch(`/api/diagnostics/refresh?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:t.signal}),n=await Ft(a,"Diagnostic snapshot refresh"),r=n.sections??(Mr(n)?await hc(e,await Rr(n,e,t),t.signal):{});At.set(wa(e),r);for(const[s,i]of Object.entries(r))Dt.set(ya(s,e),i);return r}async function Ql(e,t,a={}){_a(t);const n=await fetch(`${e.refreshPath}?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal}),r=await Ft(n,e.title),s=Mr(r)?await fc(t,e,await Rr(r,t,a),a.signal):r,i=wa(t),o=At.get(i),h=o?await Promise.resolve(o):{};return At.set(i,{...h,[e.key]:s}),Dt.set(ya(e.key,t),s),s}async function Rr(e,t,a){var r,s,i,o;let n=e;for((r=a.onProgress)==null||r.call(a,n);n.status==="pending"||n.status==="running";){const h=a.pollIntervalMs??((s=n.next)==null?void 0:s.poll_after_ms)??250;await mc(h,a.signal);const f=new URLSearchParams({job_id:n.job_id,_:String(Date.now())}),d=await fetch(`/api/diagnostics/refresh/status?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal});n=await Ft(d,"Diagnostic refresh status"),(i=a.onProgress)==null||i.call(a,n)}if(n.status!=="completed")throw new Error(`Diagnostic refresh failed: ${((o=n.error)==null?void 0:o.code)??n.status}`);return n}async function hc(e,t,a){const n=await Promise.all(Lr.map(async r=>[r.key,await Nt(r,e,a)]));return Object.fromEntries(n)}async function fc(e,t,a,n){return Nt(t,e,n)}function Mr(e){if(!e||typeof e!="object")return!1;const t=e;return t.schema==="codex-usage-tracker-analysis-job-v1"&&t.job_kind==="diagnostic-refresh"&&typeof t.job_id=="string"}function mc(e,t){return t!=null&&t.aborted?Promise.reject(t.reason??new DOMException("Aborted","AbortError")):e<=0?Promise.resolve():new Promise((a,n)=>{const r=()=>{window.clearTimeout(s),t==null||t.removeEventListener("abort",r),n((t==null?void 0:t.reason)??new DOMException("Aborted","AbortError"))},s=window.setTimeout(()=>{t==null||t.removeEventListener("abort",r),a()},e);t==null||t.addEventListener("abort",r,{once:!0})})}function gc(e,t,a){const n=e.get(t);if(n!==void 0)return Promise.resolve(n);const r=a().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function wa(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function ya(e,t,a=""){return`snapshot:${wa(t)}:${a}:${e}`}function pc(e){const t=Lr.find(a=>a.key===e);if(!t)throw new Error(`Unknown diagnostic snapshot: ${e}`);return t}async function Nt(e,t,a){const n=await fetch(`${e.path}?_=${Date.now()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a});return await Ft(n,e.title)}function _a(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Ft(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const a=await e.json();if(typeof a.error=="string"&&a.error)throw new Error(a.error);return a}const pn=[{key:"facts",label:"Top Facts",title:"Top Diagnostic Facts",path:"/api/diagnostics/facts",limit:50},{key:"tools",label:"Tools",title:"Tool and Function Activity",path:"/api/diagnostics/tools",limit:25},{key:"compactions",label:"Compactions",title:"Compaction Activity",path:"/api/diagnostics/compactions",limit:25}],Pr=new Map,jr=new Map;function vc(){dc(),Pr.clear(),jr.clear()}async function Wl(e,t,a={}){Dr(t);const n=pn.find(f=>f.key===e)??pn[0],r=wc(a.sort??"uncached"),s=a.direction??"desc",i=Math.max(1,Math.round(a.limit??n.limit)),o=Math.max(0,Math.round(a.offset??0)),h=async()=>{const f=new URLSearchParams({limit:String(i),offset:String(o),sort:r,direction:s});Er(f,"include_archived",a.includeArchived);const d=await fetch(`${n.path}?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal});return await Fr(d,n.title)};return a.signal?h():Ar(Pr,bc(n.key,t,i,o,r,s,a.cacheKey,a.includeArchived),h)}async function zl(e,t,a={}){Dr(t);const n=Math.max(1,Math.round(a.limit??8)),r=Math.max(0,Math.round(a.offset??0)),s=a.sort??"tokens",i=a.direction??"desc",o=async()=>{const h=String(e.fact_type??""),f=String(e.fact_name??"");if(!h||!f)throw new Error("Diagnostic fact type and name are required.");const d=new URLSearchParams({fact_type:h,fact_name:f,limit:String(n),offset:String(r),sort:s,direction:i});Er(d,"include_archived",a.includeArchived);const b=await fetch(`/api/diagnostics/fact-calls?${d.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:a.signal}),u=await Fr(b,"Diagnostic fact calls");return{calls:(u.rows??[]).map((p,g)=>mr(p,g)),rawPayload:u}};return a.signal?o():Ar(jr,yc(e,t,n,r,s,i,a.cacheKey,a.includeArchived),o)}function Ar(e,t,a){const n=e.get(t);if(n!==void 0)return Promise.resolve(n);const r=a().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function Nr(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function bc(e,t,a,n,r,s,i="",o){return["facts",e,Nr(t),i,o??"default",a,n,r,s].join(":")}function wc(e){return e==="total"?"tokens":e==="latest"?"time":e}function yc(e,t,a,n,r,s,i="",o){return["fact-calls",Nr(t),i,o??"default",String(e.fact_type??""),String(e.fact_name??""),a,n,r,s].join(":")}function Er(e,t,a){a!==void 0&&e.set(t,String(a))}function Dr(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Fr(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const a=await e.json();if(a.error)throw new Error(a.error);return a}const _c=[{id:"usage-snapshot",endpoint:"/api/usage",dataClass:"snapshot",schema:"codex-usage-tracker-dashboard-v1"},{id:"overview-summary",endpoint:"/api/summary",dataClass:"aggregate",schema:"codex-usage-tracker-summary-v1"},{id:"overview-recommendations",endpoint:"/api/recommendations",dataClass:"aggregate",schema:"codex-usage-tracker-recommendations-v1"},{id:"calls",endpoint:"/api/calls",dataClass:"aggregate",schema:"codex-usage-tracker-calls-v1"},{id:"threads",endpoint:"/api/threads",dataClass:"aggregate",schema:"codex-usage-tracker-threads-v1"},{id:"thread-calls",endpoint:"/api/thread-calls",dataClass:"detail",schema:"codex-usage-tracker-thread-calls-v1"},{id:"investigator-agentic",endpoint:"/api/investigations/agentic",dataClass:"aggregate",schema:"codex-usage-tracker-agentic-investigation-v1"},{id:"investigator-walk",endpoint:"/api/investigations/walk",dataClass:"userAction",schema:"codex-usage-tracker-investigation-walk-v1"},{id:"diagnostics-facts",endpoint:"/api/diagnostics/facts",dataClass:"aggregate",schema:null},{id:"diagnostics-fact-calls",endpoint:"/api/diagnostics/fact-calls",dataClass:"detail",schema:null},{id:"diagnostics-dedupe",endpoint:"/api/diagnostics/dedupe",dataClass:"aggregate",schema:"codex-usage-tracker-dedupe-diagnostics-v1"},{id:"diagnostics-snapshot",endpoint:"/api/diagnostics/{snapshot}",dataClass:"aggregate",schema:null},{id:"compression-profile",endpoint:"/api/compression/profile",dataClass:"aggregate",schema:"codex-usage-tracker-compression-api-v1"},{id:"reports",endpoint:"/api/reports/pack",dataClass:"aggregate",schema:"codex-usage-tracker-reports-pack-v1"}],Sc=_c,Cc=new Map(Sc.map(e=>[e.id,e])),xc=15*6e4,kc=3e4,Ir={snapshot:ot({persistedCache:"aggregate-only"}),aggregate:ot({persistedCache:"aggregate-only"}),detail:ot(),heavyJob:ot({cancellation:"shared-job",staleTime:1e3}),userAction:ot({retry:0,staleTime:0})};function Tc({sourceKey:e,sourceRevision:t}){return{sourceKey:vn(e,"local-api"),sourceRevision:vn(t,"unversioned")}}function Lc(e,t,a={},...n){return["dashboard",e.id,t.sourceKey,t.sourceRevision,Pc(a),...n]}function Rc(e){return["dashboard",e.id]}function Mc(e){const t=Cc.get(e);if(!t)throw new Error(`Unknown dashboard query definition: ${e}`);return t}function $r(e){const t=Ir[e];return{gcTime:t.gcTime,refetchOnReconnect:t.refetchOnReconnect,refetchOnWindowFocus:t.refetchOnWindowFocus,retry:t.retry,staleTime:t.staleTime}}function Bl({enabled:e,hasData:t,isError:a,isFetching:n,isPending:r}){return e?t?n?"updating":"ready":a?"error":n||r?"loading":"waiting":"waiting"}function Gl(e){const t=e.filter(n=>n==="ready"||n==="updating").length,a=e.length;return{ready:t,total:a,percent:a===0?100:Math.round(t/a*100),loading:e.filter(n=>n==="loading").length,errors:e.filter(n=>n==="error").length}}function Pc(e){return{historyScope:e.historyScope??"active",loadWindow:e.loadWindow??"all",limit:e.limit??null,since:e.since??""}}function vn(e,t){return(e==null?void 0:e.trim())||t}function ot(e={}){return{staleTime:kc,gcTime:xc,retry:1,refetchOnReconnect:!1,refetchOnWindowFocus:!1,cancellation:"observer",persistedCache:"none",...e}}const jc=new Set(["command_text","content_fragment","content_fragments","excerpt","indexed_content","indexed_fragment","indexed_fragments","prompt","raw_context","raw_output","snippet","tool_output"]),Ac=new Set(["includes_indexed_content","includes_raw_fragment","includes_raw_fragments","indexed_content_included","raw_content_included","raw_context_included"]),Nc=new Set(["codex-usage-tracker-context-v1"]);function bn(e){return ia(e,new WeakSet)}function ia(e,t){if(!e||typeof e!="object")return!0;if(t.has(e))return!1;t.add(e);const a=Array.isArray(e)?e.every(n=>ia(n,t)):Object.entries(e).every(([n,r])=>{const s=n.toLowerCase();return jc.has(s)||Ac.has(s)&&r===!0||s==="schema"&&typeof r=="string"&&Nc.has(r)?!1:ia(r,t)});return t.delete(e),a}const Ec="codexUsageDashboard",Dc=1,Y="usageSnapshots",Fc=6,Ic=10080*60*1e3,$c={async read(e){if(!e.sourceRevision)return null;try{const t=await yn();if(!t)return null;const a=await Or(t.transaction(Y,"readonly").objectStore(Y).get(wn(e)));return!a||a.sourceRevision!==e.sourceRevision||Date.now()-a.storedAt>Ic?null:bn(a.payload)?a.payload:(await Oc(t,a.cacheKey),null)}catch{return null}},async write(e,t){if(!(!e.sourceRevision||!bn(t)))try{const a=await yn();if(!a)return;const n=a.transaction(Y,"readwrite");n.objectStore(Y).put({...e,cacheKey:wn(e),payload:t,storedAt:Date.now()}),await Sa(n),await Uc(a)}catch{}}};async function Oc(e,t){const a=e.transaction(Y,"readwrite");a.objectStore(Y).delete(t),await Sa(a)}function wn(e){const{historyScope:t,loadWindow:a,limit:n,since:r}=e.scope;return JSON.stringify([e.sourceKey,t,a,n,r])}function yn(){return typeof indexedDB>"u"?Promise.resolve(null):new Promise(e=>{const t=indexedDB.open(Ec,Dc);t.onupgradeneeded=()=>{t.result.objectStoreNames.contains(Y)||t.result.createObjectStore(Y,{keyPath:"cacheKey"})},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)})}function Or(e){return new Promise((t,a)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>a(e.error??new Error("IndexedDB request failed"))})}function Sa(e){return new Promise((t,a)=>{e.oncomplete=()=>t(),e.onerror=()=>a(e.error??new Error("IndexedDB transaction failed")),e.onabort=()=>a(e.error??new Error("IndexedDB transaction aborted"))})}async function Uc(e){const t=e.transaction(Y,"readonly"),n=(await Or(t.objectStore(Y).getAll())).sort((i,o)=>o.storedAt-i.storedAt).slice(Fc);if(!n.length)return;const r=e.transaction(Y,"readwrite"),s=r.objectStore(Y);n.forEach(i=>s.delete(i.cacheKey)),await Sa(r)}const Vc={kind:"production",load:_o},Kc="codexUsageDashboardRuntimeMetadata",qc=2048,oa=Mc("usage-snapshot"),Ur={all:Rc(oa),snapshot:(e,t,a)=>Lc(oa,Tc({sourceKey:e,sourceRevision:t}),a)};function Hc(){return new Ti({defaultOptions:{queries:{...$r("aggregate")}}})}const Ca=Hc();async function Qc({currentPayload:e,historyScope:t,loadWindow:a,loadLimit:n,since:r=null,onProgress:s,queryClient:i=Ca,refresh:o=!1,snapshotStore:h=$c,transport:f=Vc}){const d=Vi(n,t,r,a),b=xa(e),u=Ur.snapshot(b.sourceKey,b.sourceRevision,d);!i.getQueryData(u)&&Jc(e,d)&&i.setQueryData(u,e),o&&await i.invalidateQueries({queryKey:u,exact:!0});const p=_n(e,d),g=await i.fetchQuery({queryKey:u,...$r(oa.dataClass),queryFn:async({signal:v})=>{var R;const w=!o&&p?await h.read(p):null;if(w)return s==null||s({status:"completed",phase:"loading_rows",message:"Loaded cached dashboard snapshot",completed:Number(w.loaded_row_count??((R=w.rows)==null?void 0:R.length)??0),total:Number(w.total_available_rows??w.loaded_row_count??0),percent:100}),w;const T=await f.load(e,{refresh:o,limit:Ki(d),includeArchived:d.historyScope==="all",loadWindow:a,since:d.since,onProgress:s,signal:v}),N=p?{...p,sourceRevision:String(T.latest_refresh_at??p.sourceRevision)}:_n(T,d);return N&&await h.write(N,T),T},staleTime:o?0:Ir.snapshot.staleTime});return Gc(Bc(g,d)),g}function _n(e,t){if(!(e!=null&&e.api_token))return null;const a=String(e.latest_refresh_at??"");return a?{sourceKey:Vr(e),sourceRevision:a,scope:t}:null}async function Wc(e=Ca){await e.cancelQueries({queryKey:Ur.all})}function zc(e){return bi(e)||sr(e)}function Bc(e,t){return{schema:"codex-usage-dashboard-runtime-v1",...xa(e),scope:t,updatedAt:Date.now()}}function xa(e){return{sourceKey:Vr(e),sourceRevision:Zc(e)}}function Gc(e,t=Xc()){if(t)try{const a=JSON.stringify(e);a.length<=qc&&t.setItem(Kc,a)}catch{}}function Jc(e,t){var o;if(!e||!(((o=e.rows)==null?void 0:o.length)??0))return!1;const a=ct(e),n=t.limit===null?a===0:a===t.limit,r=(e.since??null)===t.since,s=ha(e)===t.loadWindow,i=e.include_archived||e.history_scope==="all-history"?"all":"active";return n&&r&&s&&i===t.historyScope}function Vr(e){const t=e,a=Number((t==null?void 0:t.payload_cache_version)??0),n=String((t==null?void 0:t.payload_cache_key)??(e!=null&&e.api_token?"live":"static"));return`${a}:${n}`}function Zc(e){return String((e==null?void 0:e.latest_refresh_at)??"unversioned")}function Xc(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}const Yc=new Set(["duplicate_cumulative_total"]);function el({canUseLiveApi:e,payload:t,shellI18n:a}){const n=tl(t,e,a);return c.jsxs("section",{className:"environment-status","aria-label":a.t("aria.dashboard_status","Dashboard status"),children:[c.jsx("span",{className:"environment-status-title",children:a.t("aria.dashboard_status","Dashboard status")}),c.jsx("div",{className:"environment-status-grid",children:n.map(r=>c.jsx("span",{className:"environment-chip","data-state":r.state,title:r.title,children:r.label},r.label))})]})}function tl(e,t,a){const n=il(e==null?void 0:e.parser_diagnostics,a);return[{label:a.t("badge.unofficial_project","Unofficial project"),state:"neutral",title:a.t("badge.unofficial_project_title","Codex Usage Tracker is independent and is not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI. OpenAI and Codex are trademarks of OpenAI.")},{label:t?`${a.t("badge.live","Live")} API`:a.t("badge.static","Static"),state:t?"ready":"warn",title:t?"Local API token present for refresh actions.":"Static embedded snapshot; live refresh is unavailable."},nl(e,a),rl(e,a),sl(e,a),al(e),...n?[n]:[]]}function al(e){const t=e==null?void 0:e.dedupe,a=Number((t==null?void 0:t.excluded_copied_rows)||0),n=Number((t==null?void 0:t.canonical_rows)||0),r=Number((t==null?void 0:t.physical_rows)||0);return{label:`Deduped · ${a.toLocaleString()} copied excluded`,state:"ready",title:`Billable totals use ${n.toLocaleString()} canonical rows while preserving ${r.toLocaleString()} physical source rows.`}}function nl(e,t){var s;const a=!!(e!=null&&e.pricing_configured),n=((s=e==null?void 0:e.pricing_snapshot_warning)==null?void 0:s.trim())??"",r=Kr(e==null?void 0:e.pricing_source);return{label:a?t.t("badge.costs","Costs"):t.t("badge.no_costs","No costs"),state:a?n?"warn":"ready":"missing",title:a?[r||"Pricing configured",n].filter(Boolean).join(" - "):t.t("pricing.configure_hint","Run codex-usage-tracker update-pricing to configure estimated costs.")}}function rl(e,t){var s,i;const a=((s=e==null?void 0:e.allowance_error)==null?void 0:s.trim())??"",n=((i=e==null?void 0:e.rate_card_error)==null?void 0:i.trim())??"",r=Kr(e==null?void 0:e.allowance_source)||"Codex credit rates";return a?{label:t.t("state.allowance_config_error","Allowance config error"),state:"missing",title:`Config error: ${a}`}:n?{label:"Rate-card error",state:"missing",title:`Rate-card error: ${n}`}:e!=null&&e.allowance_configured?{label:t.t("state.allowance_configured","Allowance configured"),state:"ready",title:r}:e!=null&&e.rate_card_configured?{label:"Credit rates loaded",state:"ready",title:r}:{label:t.t("action.set_limits","Set limits"),state:"warn",title:"No local allowance windows are configured."}}function sl(e,t){const a=e==null?void 0:e.project_metadata_privacy,n=(a==null?void 0:a.mode)||(e==null?void 0:e.privacy_mode)||"normal",r=n==="normal",s=[a!=null&&a.cwd_redacted?"cwd redacted":"",a!=null&&a.project_names_redacted?"project names redacted":"",a!=null&&a.git_remote_label_hidden?"git remote hidden":"",a!=null&&a.relative_cwd_hidden?"relative cwd hidden":"",a!=null&&a.git_branch_hidden?"git branch hidden":"",a!=null&&a.tags_hidden?"tags hidden":""].filter(Boolean);return{label:r?t.t("badge.metadata_normal","Metadata normal"):qr(t.t("badge.metadata_mode","Metadata {mode}"),{mode:n}),state:r?"ready":"warn",title:r?"Project metadata is shown normally.":[`Metadata mode: ${n}`,...s].join(" - ")}}function il(e,t){const a=Object.entries(e??{}).filter(([s,i])=>Number(i||0)>0&&!Yc.has(s));if(!a.length)return null;const n=a.reduce((s,[,i])=>s+Number(i||0),0),r=a.map(([s,i])=>`${s}=${Number(i||0)}`).join(", ");return{label:t.t("badge.parser_warnings","Parser warnings"),state:"missing",title:qr(t.t("parser.warnings_title","Latest refresh reported {count} parser diagnostics: {entries}. Run codex-usage-tracker inspect-log to investigate schema drift."),{count:n.toLocaleString(),entries:r})}}function Kr(e){if(!e)return"";if(typeof e=="string")return e;const t=e.label??e.name??e.type??e.path??"";return typeof t=="string"?t:""}function qr(e,t){return e.replace(/\{([a-zA-Z0-9_]+)\}/g,(a,n)=>t[n]??a)}async function Sn(e){var a;if((a=navigator.clipboard)!=null&&a.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly","readonly"),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}const ol={"highest-cost":"Highest Cost Threads","context-bloat":"Context Bloat","cache-misses":"Cache Misses","pricing-gaps":"Pricing Gaps","codex-credits":"Codex Credits","reasoning-spike":"Reasoning Spike"};function Jl(e,t){return t==="context-bloat"?Number(e.contextWindowPct??0)>=60||e.totalTokens>=2e5:t==="cache-misses"?e.signal==="cache-risk"||e.cachedPct<30||e.uncachedInput>=5e4:t==="pricing-gaps"?e.pricingEstimated||!Number.isFinite(e.cost):t==="codex-credits"?e.credits>0:t==="reasoning-spike"?e.reasoningOutput>0:!0}function cl(e){return ol[e]??e}const ll=se(()=>O(()=>import("./OverviewPage.js"),__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50])),"OverviewPage"),ul=se(()=>O(()=>import("./InvestigatorPage.js"),__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52])),"InvestigatorPage"),dl=se(()=>O(()=>import("./CompressionLabPage.js"),__vite__mapDeps([53,1,2,34,4,6,9,10,17,25,26,12,54])),"CompressionLabPage"),hl=se(()=>O(()=>import("./ExploreRoutePage.js"),__vite__mapDeps([55,1,2,44,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48,8,9,10,56])),"ExploreRoutePage"),fl=se(()=>O(()=>import("./CallInvestigatorPage.js"),__vite__mapDeps([57,1,2,46,33,19,37,38,47,25,26,12])),"CallInvestigatorPage"),ml=se(()=>O(()=>import("./ThreadsPage.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27])),"ThreadsPage"),gl=se(()=>O(()=>import("./UsageDrainPage.js"),__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39])),"UsageDrainPage"),pl=se(()=>O(()=>import("./CacheContextPage.js"),__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12])),"CacheContextPage"),vl=se(()=>O(()=>import("./DiagnosticsPage.js"),__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12])),"DiagnosticsPage"),bl=se(()=>O(()=>import("./ReportsPage.js"),__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43])),"ReportsPage"),wl=se(()=>O(()=>import("./SettingsPage.js"),__vite__mapDeps([58,1,2,33,19,32,38,47,17,25,26,12,59])),"SettingsPage");function yl(e){return c.jsx(C.Suspense,{fallback:c.jsx(Sl,{activeView:e.activeView}),children:_l(e)})}function _l(e){const{activePreset:t,activeRecordId:a,activeView:n,autoRefreshEnabled:r,applicationI18n:s,backFromCallInvestigator:i,callBackLabel:o,canLoadAllRows:h,canUseLiveApi:f,contextRuntime:d,copyCallInvestigatorLink:b,dashboardPayload:u,globalFilters:p,globalQuery:g,hasMoreRows:v,historyScope:w,loadWindow:T,loadAllRows:N,loadedRowCount:R,loadLimit:_,loadMoreRows:L,scopeSince:y,model:x,navigateView:M,onRefresh:E,openCallInvestigator:D,refreshing:me,refreshState:vt,setContextApiEnabled:bt,sourceIdentity:$,totalAvailableRows:nt}=e;switch(n){case"overview":return c.jsx(ll,{model:x,contextRuntime:d,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onRefresh:E,globalQuery:g,runtime:{historyScope:w,loadLimit:_,loadWindow:T,loadedRowCount:R,scopeSince:y,totalAvailableRows:nt},refreshing:me,canLoadMoreRows:f&&v,onLoadMoreRows:L,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:M,globalFilters:p});case"investigator":return c.jsx(ul,{model:x,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:M});case"compression-lab":return c.jsx(dl,{contextRuntime:d,includeArchived:w==="all",since:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision});case"calls":return c.jsx(hl,{model:x,globalQuery:g,activePreset:t,onRefresh:E,contextRuntime:d,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onContextApiEnabledChange:bt,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:M});case"call":return c.jsx(fl,{model:x,recordId:a,contextRuntime:d,onContextApiEnabledChange:bt,onNavigateRecord:D,onCopyCallLink:b,onBackToCalls:i,backLabel:o});case"threads":return c.jsx(ml,{model:x,globalQuery:g,onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onNavigateView:M});case"usage-drain":return c.jsx(gl,{model:x,contextRuntime:d,includeArchived:w==="all",sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"cache-context":return c.jsx(pl,{model:x,contextRuntime:d,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"diagnostics":return c.jsx(vl,{model:x,contextRuntime:d,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,rowLoadControls:{loadedRowCount:R,totalAvailableRows:nt,canLoadMoreRows:f&&v,canLoadAllRows:h,refreshing:me,onLoadMoreRows:L,onLoadAllRows:N},onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p});case"reports":return c.jsx(bl,{model:x,refreshState:vt,includeArchived:w==="all",loadWindow:T,loadLimit:_,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"settings":return c.jsx(wl,{model:x,payload:u,historyScope:w,loadWindow:T,loadLimit:_,scopeSince:y,loadedRowCount:R,totalAvailableRows:nt,canUseLiveApi:f,autoRefreshEnabled:r,refreshState:vt,applicationI18n:s})}}function Sl({activeView:e}){return c.jsxs("section",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:["Loading ",e.replace("-"," "),"..."]})}const Cn=1e4,Cl={1:"overview",2:"calls",3:"threads",4:"diagnostics"},xl=new Set(["call","compression-lab","diagnostics","investigator"]);function Hr(e){return!xl.has(e)}function kl(e){return e instanceof Element?!!e.closest('input, select, textarea, button, [contenteditable="true"]'):!1}function Qr(){var Oa;const e=C.useRef(null),t=C.useMemo(()=>yo(),[]),[a,n]=C.useState(t),[r,s]=C.useState(()=>nn(t)),[i,o]=C.useState(()=>{const m=new URLSearchParams(window.location.search);return sa(m.get("view"))}),[h,f]=C.useState(()=>new URLSearchParams(window.location.search).get("record")??""),[d,b]=C.useState(()=>dn()),[u,p]=C.useState(()=>hn()),[g,v]=C.useState(()=>new URLSearchParams(window.location.search).get("q")??""),[w,T]=C.useState(()=>new URLSearchParams(window.location.search).get("preset")??""),[N,R]=C.useState(()=>window.location.search),[_,L]=C.useState("Stored snapshot loaded just now"),[y,x]=C.useState(null),[M,E]=C.useState(!1),[D,me]=C.useState(!1),[vt,bt]=C.useState(!1),[$,nt]=C.useState(()=>zs(t)),It=C.useRef(!1),[G,ka]=C.useState(()=>je(ct(t),500)),[Ue,wt]=C.useState(()=>je(ct(t),500)),[q,Ta]=C.useState(()=>qi(t)),[J,yt]=C.useState(()=>fn(Qt(t))),[La,Ra]=C.useState(r.contextRuntime.contextApiEnabled),H=!!(a!=null&&a.api_token),Wr=C.useMemo(()=>xa(a),[a]),A=C.useMemo(()=>Dn(a,$),[a,$]),Ma=C.useMemo(()=>({...r.contextRuntime,contextApiEnabled:La}),[La,r.contextRuntime]),zr=C.useMemo(()=>Uo(r,J,N),[J,N,r]),Pa=i==="calls"||i==="call"?r:zr,rt=Hr(i),$t=je(Ue,G,500),ge=Math.max(0,Number((a==null?void 0:a.loaded_row_count)??((Oa=a==null?void 0:a.rows)==null?void 0:Oa.length)??r.calls.length??0)),Ve=Math.max(0,Number((a==null?void 0:a.total_available_rows)??ge)),Br=Ue!==G,ja=Wi({currentLimit:G,loadedRows:ge,pendingLimit:Ue}),Gr=Math.min($t,ja),Aa=!!(a!=null&&a.has_more)||Ve>0&&ge{const m=new URL(window.location.href);gn(m)&&Ke(m)},[]),C.useEffect(()=>{function m(){const S=window.location.search,P=new URLSearchParams(S);o(sa(P.get("view"))),f(P.get("record")??""),b(dn(S)),p(hn(S)),v(P.get("q")??""),T(P.get("preset")??""),yt(fn(Qt(a),S)),R(S)}return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[a]),C.useEffect(()=>{function m(S){var oe;if(kl(S.target))return;if(S.key==="/"){S.preventDefault(),(oe=e.current)==null||oe.focus();return}const P=Cl[S.key];P&&(S.preventDefault(),st(P))}return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[]),C.useEffect(()=>{function m(){bt(window.scrollY>320)}return m(),window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]);function as(m){const S=i==="call"?d:i;b(S),p(i==="call"?u:!0),o("call"),f(m);const P=new URL(window.location.href);xt(P,i,i==="call"?d:[]),P.searchParams.set("view","call"),P.searchParams.set("record",m),P.searchParams.set("return",S),Da(P)}function ns(){st(d)}function rs(m){v(m),T("");const S=new URL(window.location.href);S.searchParams.delete("preset"),m?S.searchParams.set("q",m):S.searchParams.delete("q"),Ke(S)}async function ie(m={}){var _t;if(M)return;It.current=!0;const S=m.loadLimit??G,P=m.loadWindow??q,oe=Ht(P),pe=m.historyScope??J,ee=m.refresh??!0,Ot=!!(a!=null&&a.refresh_jobs_available);E(!0),x(Ot?{status:"running",phase:ee?"refreshing_index":"loading_rows",message:`${ee?"Refreshing":"Loading"} ${Re(P,S)}`}:null),L(`${ee?"Refreshing index for":"Loading"} ${Re(P,S)}...`);let qe=!1;try{const B=await Qc({currentPayload:a,refresh:ee,loadLimit:S,loadWindow:P,since:oe,historyScope:pe,onProgress:Vt=>{qe||(qe=Vt.message==="Loaded cached dashboard snapshot"),x(Vt),L(Za(Vt,pe))}});vc(),n(B),s(nn(B)),Ra(!!B.context_api_enabled);const xe=P==="rows"?je(ct(B,S),S):S;ka(xe),wt(xe),Ta(P);const Ua=Qt(B,pe);yt(Ua),Qi(xe,Ua,P);const Ut=B.loaded_row_count??((_t=B.rows)==null?void 0:_t.length)??0,Va=B.total_available_rows??Ut;L(P==="rows"?`${qe?"Cache hit; l":ee?"Refreshed index; l":"L"}oaded ${Ut.toLocaleString()} of ${Va.toLocaleString()} calls from ${Re(P,xe)}`:`${qe?"Cache hit; ":ee?"Refreshed index; ":""}${Re(P,xe)} analysis ready across ${Va.toLocaleString()} calls; ${Ut.toLocaleString()} detail rows cached`)}catch(B){if(x(null),zc(B)){L("Refresh cancelled; stored snapshot remains visible");return}const xe=new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});L(`${Xi(B)} Stored snapshot kept at ${xe}`)}finally{x(null),E(!1)}}async function ss(){await Wc(),x(null),E(!1),L("Refresh cancelled; stored snapshot remains visible")}C.useEffect(()=>{document.documentElement.lang=A.language,document.documentElement.dir=A.direction},[A.direction,A.language]),C.useEffect(()=>{var B;const m=Number((a==null?void 0:a.total_available_rows)??0),S=Number((a==null?void 0:a.loaded_row_count)??((B=a==null?void 0:a.rows)==null?void 0:B.length)??0),P=Hi(),oe=(P==null?void 0:P.historyScope)??J,pe=(P==null?void 0:P.loadLimit)??G,ee=(P==null?void 0:P.loadWindow)??q,Ot=ha(a),qe=oe!==J||ee!==Ot||ee==="rows"&&pe!==ct(a),_t=S>0;!H||!qe&&_t||m<=0||M||It.current||(It.current=!0,qe&&(yt(oe),ka(pe),wt(pe),Ta(ee),Ke(mn(oe))),ie({refresh:!1,historyScope:oe,loadLimit:pe,loadWindow:ee}))},[H,a,J,G,q,M]),C.useEffect(()=>{!H&&D&&me(!1)},[D,H]),C.useEffect(()=>{if(!D||!H||!rt)return;const m=window.setInterval(()=>{ie()},Cn);return()=>window.clearInterval(m)},[D,rt,H,a,J,G,q,M]),C.useEffect(()=>{if(!D||!H||!rt)return;function m(){document.visibilityState==="visible"&&ie()}return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[D,rt,H,a,J,G,q,M]);function Fa(m){const S=m.trim();wt(Math.max(1,gt(S===""?Number.NaN:Number(S))))}function is(m){Fa(m)}function os(){ie({refresh:!1,loadLimit:Ue,loadWindow:"rows"})}function cs(){ie({refresh:!1,loadWindow:"all"})}function Ia(){wt(Na),ie({refresh:!1,loadLimit:Na,loadWindow:q})}function ls(m){m!==q&&ie({refresh:!1,loadWindow:m})}function us(m){const S=m==="all"?"all":"active";yt(S),Ke(mn(S)),ie({refresh:!1,historyScope:S})}function ds(m){if(me(m),m){if(!rt){L("Auto refresh pauses on this evidence-heavy view");return}L(`Auto refresh every ${Cn/1e3}s`),ie()}else L("Auto refresh paused")}function hs(m){nt(m),Bs(m)}async function fs(){try{const m=new URL(window.location.href);if(gn(m),xt(m,i,i==="call"?d:[]),!await Sn(m.toString()))throw new Error("Clipboard unavailable");L("Copied current view link")}catch{L("Copy unavailable in browser")}}async function ms(m){try{const S=new URL(window.location.href);xt(S,i,i==="call"?d:[]);const P=i==="call"?d:i;if(S.searchParams.set("view","call"),S.searchParams.set("record",m),S.searchParams.set("return",P),!await Sn(S.toString()))throw new Error("Clipboard unavailable");L("Copied call investigator link")}catch{L("Copy unavailable in browser")}}async function gs(){const m=await Gi(i,Pa,{contextRuntime:Ma,historyScope:J,loadWindow:q,loadLimit:G,scopeSince:(a==null?void 0:a.since)??Ht(q),loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,refreshState:_},g,w);if(!m.rowCount){L(`No ${m.label} to export`);return}Ni(m.filename,m.csv),L(`Exported ${m.rowCount} ${m.label}`)}function ps(){T("");const m=new URL(window.location.href);m.searchParams.delete("preset"),Ke(m),L("Investigation preset cleared")}function vs(){window.scrollTo({top:0,behavior:"smooth"})}return c.jsx(no,{value:A,children:c.jsxs("div",{className:"app-shell","data-dashboard-localization-root":!0,children:[c.jsxs("aside",{className:"sidebar",children:[c.jsxs("div",{className:"brand",children:[c.jsx("div",{className:"brand-mark",children:c.jsx(Us,{size:22})}),c.jsxs("div",{children:[c.jsx("strong",{children:"Codex Usage Tracker"}),c.jsx("span",{children:A.t("dashboard.eyebrow","Local telemetry console")})]})]}),c.jsxs("div",{className:"local-pill",children:[c.jsx("span",{"aria-hidden":"true"}),"Local data only"]}),c.jsx(el,{payload:a,canUseLiveApi:H,shellI18n:A}),c.jsx("nav",{className:"primary-nav","aria-label":"Primary",children:Cr.map(m=>{const S=m.icon,P=i===m.id||i==="call"&&m.id==="calls";return c.jsxs("button",{type:"button","aria-pressed":P,className:P?"active":"",onClick:()=>st(m.id),children:[c.jsx(S,{size:18}),c.jsx("span",{children:A.navLabel(m.id,m.label)})]},m.id)})}),c.jsxs("div",{className:"secondary-block",role:"group","aria-label":"Quick Links",children:[c.jsx("span",{children:"Quick Links"}),xr.map(m=>{const S=m.icon;return c.jsxs("button",{type:"button",onClick:()=>st(m.target),children:[c.jsx(S,{size:16}),m.label]},m.label)})]})]}),c.jsxs("main",{className:"workspace",children:[c.jsxs("div",{className:"unofficial-banner",role:"note","aria-label":"Unofficial project notice",children:[c.jsx($s,{size:16}),c.jsxs("span",{children:[c.jsx("strong",{children:"Unofficial project."})," Not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI."]})]}),c.jsxs("header",{className:"topbar","aria-label":"Dashboard toolbar",children:[c.jsxs("label",{className:"global-search",children:[c.jsx("span",{className:"sr-only",children:A.t("filter.search","Search dashboard")}),c.jsx("input",{ref:e,"aria-label":A.t("filter.search","Search dashboard"),value:g,onChange:m=>rs(m.target.value),placeholder:A.t("filter.search_placeholder","Search calls, threads, models, diagnostics...")})]}),c.jsxs("div",{className:"topbar-actions",children:[c.jsxs("div",{className:"topbar-scope-controls",children:[A.languages.length>1?c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("language.label","Language")}),c.jsx("select",{"data-localization-skip":"true","aria-label":A.t("language.label","Language"),value:A.language,onChange:m=>hs(m.target.value),children:A.languages.map(m=>c.jsx("option",{value:m.code,children:m.native_name||m.english_name||m.code},m.code))})]}):null,c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("nav.history","History")}),c.jsxs("select",{"aria-label":"History scope",title:Ea,value:J,onChange:m=>us(m.target.value),disabled:M||!H,children:[c.jsx("option",{value:"active",children:A.t("option.active_sessions_only","Active")}),c.jsx("option",{value:"all",children:A.t("option.all_history","All history")})]}),c.jsx("small",{className:"sr-only",children:Ea})]})]}),c.jsx(Yo,{canUseLiveApi:H,finitePendingLoadLimit:$t,hasMoreRows:Aa,loadLabel:A.t("nav.load","Load"),loadMoreLabel:A.t("button.load_more","Load more"),loadWindow:q,loadedRowCount:ge,pendingLoadLimit:Ue,refreshProgressPercent:Yr,refreshProgressText:es,refreshing:M,rowLimitChanged:Br,rowLimitSliderMax:ja,rowLimitSliderValue:Gr,rowLoadModeLabel:Zr,rowLoadStatus:Jr,totalAvailableRows:Ve,onApply:os,onCancel:ss,onDraftChange:Fa,onLoadMore:Ia,onSliderChange:is,onWindowChange:ls}),c.jsxs("div",{className:"topbar-meta",children:[c.jsxs("div",{className:"topbar-statuses",children:[w?c.jsxs("button",{className:"toolbar-button",type:"button",onClick:ps,children:[c.jsx(la,{size:15}),A.t("button.clear","Clear")," ",cl(w)]}):null,c.jsxs("label",{className:"topbar-toggle",children:[c.jsx("input",{"aria-label":"Auto refresh",type:"checkbox",checked:D,onChange:m=>ds(m.target.checked),disabled:M||!H}),c.jsx("span",{children:"Auto"})]})]}),c.jsxs("div",{className:"topbar-icon-actions",children:[c.jsx("button",{className:"icon-button",type:"button",onClick:fs,"aria-label":A.t("button.copy_link","Copy link"),title:A.t("button.copy_link","Copy link"),children:c.jsx(Ms,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:gs,"aria-label":A.t("button.export_csv","Export CSV"),title:A.t("button.export_csv","Export CSV"),children:c.jsx(js,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:$a,"aria-label":A.t("button.refresh","Refresh"),title:A.t("button.refresh","Refresh"),disabled:M,children:c.jsx(Fs,{size:17})})]})]})]})]}),c.jsx("p",{className:"sr-only",role:"status","aria-live":"polite",children:_}),c.jsx(yl,{activeView:i,model:Pa,navigateView:st,onRefresh:$a,refreshState:_,globalQuery:g,activePreset:w,activeRecordId:h,contextRuntime:Ma,setContextApiEnabled:Ra,openCallInvestigator:as,copyCallInvestigatorLink:ms,callBackLabel:u?`Back to ${lc(d)}`:A.t("button.back_to_dashboard","Back to dashboard"),backFromCallInvestigator:ns,dashboardPayload:a,sourceIdentity:Wr,historyScope:J,loadWindow:q,scopeSince:(a==null?void 0:a.since)??Ht(q),loadLimit:G,loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,applicationI18n:A,refreshing:M,hasMoreRows:Aa,canLoadAllRows:ts,loadMoreRows:Ia,loadAllRows:cs,globalFilters:c.jsx(ec,{activeView:i,locationSearch:N,model:r,onUrlChange:Ke})})]}),vt?c.jsxs("button",{className:"to-top-button",type:"button",onClick:vs,"aria-label":"Back to top",children:[c.jsx(xs,{size:18}),A.t("button.top","Top")]}):null]})});function $a(){ie()}}function Tl(){return c.jsx(Li,{client:Ca,children:c.jsx(Qr,{})})}const Zl=Object.freeze(Object.defineProperty({__proto__:null,App:Qr,RoutedApp:Tl,shouldAutoRefreshUsageView:Hr},Symbol.toStringTag,{value:"Module"}));export{cl as $,xs as A,Al as B,Fi as C,js as D,Ul as E,Es as F,Cs as G,Ps as H,bn as I,Et as J,z as K,Nl as L,Vn as M,ae as N,Wl as O,wc as P,ql as Q,Fs as R,Is as S,zl as T,Rs as U,Os as V,Jl as W,Sn as X,Ol as Y,Ns as Z,la as _,Ms as a,Fl as a0,Dl as a1,fi as a2,ii as a3,Gt as a4,qn as a5,ri as a6,si as a7,Bt as a8,Un as a9,_i as aa,li as ab,El as ac,$l as ad,xt as ae,dn as af,Re as ag,Zl as ah,Vl as b,I as c,Ni as d,ce as e,Le as f,Ei as g,Gl as h,Bl as i,Te as j,lr as k,Il as l,Xt as m,Lr as n,Ql as o,Lt as p,Hl as q,Ai as r,pn as s,Kl as t,On as u,mr as v,$r as w,Lc as x,Tc as y,Mc as z}; + */const un=I("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),Ea="codex-usage-dashboard-language",qs={"button.back_to_dashboard":"Back to dashboard","button.clear":"Clear","button.copy_link":"Copy link","button.enable_context_loading":"Enable context loading","button.export_csv":"Export CSV","button.full_serialized_analysis":"Run full serialized analysis","button.hide_details":"Hide details","button.include_tool_output":"Include tool output","button.load_more":"Load more","button.load_older_context":"Load older entries","button.next_call":"Next call","button.no_char_limit":"No char limit","button.open_investigator":"Open investigator","button.previous_call":"Previous call","button.refresh":"Refresh","button.show_compaction_history":"Show compacted replacement","button.show_tool_output":"Show tool output","button.top":"Top","button.show_turn_evidence":"Show turn log evidence","badge.live":"Live","dashboard.eyebrow":"Local Codex analytics","dashboard.call_details":"Call Details","dashboard.title":"Usage Dashboard","dashboard.view.call":"Call Investigator","dashboard.view.calls":"Calls","dashboard.view.insights":"Overview","dashboard.view.overview":"Overview","dashboard.view.threads":"Threads","detail.next_action":"Next action","filter.search":"Search dashboard","filter.search_placeholder":"Search calls, threads, models, diagnostics...","language.label":"Language","nav.history":"History","nav.load":"Load","nav.live":"Live","option.active_sessions_only":"Active","option.all_history":"All history","status.paused":"Paused","status.static":"Static"},Hs={overview:"dashboard.view.overview",calls:"dashboard.view.calls",call:"dashboard.view.call",threads:"dashboard.view.threads"};function Nl(e,t){return typeof t=="string"?e.translateText(t):e.formatText(t.template,t.values)}function Da(e,t){const n=Fa(e),a=Ia(t,n),r=(e==null?void 0:e.translation_catalog)??{},s=r[a]??((e==null?void 0:e.language)===a?e==null?void 0:e.translations:void 0)??{},i=r.en??((e==null?void 0:e.language)==="en"?e.translations:void 0)??{},o={...qs,...i,...s},d=Qs(i,s),f=Ws(i,s),h=n.find(p=>p.code===a),b=(h==null?void 0:h.dir)==="rtl"||!h&&(e==null?void 0:e.language_direction)==="rtl"?"rtl":"ltr",u=p=>a==="zh-Hans"?bs(p,d,f):d.get(p)??p;return{language:a,direction:b,languages:n,t:(p,g)=>o[p]??g??p,translateText:u,formatText:(p,g)=>u(p).replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu,(v,w)=>String(g[String(w)]??v)),navLabel:(p,g)=>{const v=Hs[p];return v?o[v]??g:g}}}function Ws(e,t){const n=[];for(const[a,r]of Object.entries(e)){const s=t[a];if(!s||s===r||!r.includes("{"))continue;const i=[],o=[];let d=0;for(const f of r.matchAll(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu)){const h=f.index??d;o.push(Hn(r.slice(d,h))),o.push("(.+?)"),i.push(f[1]),d=h+f[0].length}o.push(Hn(r.slice(d))),n.push({pattern:new RegExp(`^${o.join("")}$`,"u"),placeholders:i,translatedTemplate:s})}return n.sort((a,r)=>r.translatedTemplate.length-a.translatedTemplate.length)}function Hn(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function Qs(e,t){const n=new Map;for(const[a,r]of Object.entries(e)){const s=t[a];s&&s!==r&&n.set(r,s)}return n}function Fa(e){var n;const t=((n=e==null?void 0:e.available_languages)==null?void 0:n.filter(a=>a.code))??[];return t.length?t:[{code:"en",english_name:"English",native_name:"English",dir:"ltr"}]}function zs(e){return Ia(Gs()||(e==null?void 0:e.language)||"en",Fa(e))}function Bs(e){var t;try{(t=window.localStorage)==null||t.setItem(Ea,e)}catch{}}function Gs(){var e;try{return((e=window.localStorage)==null?void 0:e.getItem(Ea))??""}catch{return""}}function Ia(e,t){if(new Set(t.map(s=>s.code)).has(e))return e;const a=e.toLowerCase(),r=t.find(s=>s.code.toLowerCase()===a);return(r==null?void 0:r.code)??"en"}const Js=Da(null,"en"),$a=C.createContext(Js);function Zs({value:e,children:t}){return c.jsx($a.Provider,{value:e,children:t})}function Oa(){return C.useContext($a)}var Et=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Ne,we,Be,xa,Xs=(xa=class extends Et{constructor(){super();P(this,Ne);P(this,we);P(this,Be);x(this,Be,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t();return window.addEventListener("visibilitychange",n,!1),()=>{window.removeEventListener("visibilitychange",n)}}})}onSubscribe(){l(this,we)||this.setEventListener(l(this,Be))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,we))==null||t.call(this),x(this,we,void 0))}setEventListener(t){var n;x(this,Be,t),(n=l(this,we))==null||n.call(this),x(this,we,t(a=>{typeof a=="boolean"?this.setFocused(a):this.onFocus()}))}setFocused(t){l(this,Ne)!==t&&(x(this,Ne,t),this.onFocus())}onFocus(){const t=this.isFocused();this.listeners.forEach(n=>{n(t)})}isFocused(){var t;return typeof l(this,Ne)=="boolean"?l(this,Ne):((t=globalThis.document)==null?void 0:t.visibilityState)!=="hidden"}},Ne=new WeakMap,we=new WeakMap,Be=new WeakMap,xa),Ua=new Xs,Ys={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},ye,ln,ka,ei=(ka=class{constructor(){P(this,ye,Ys);P(this,ln,!1)}setTimeoutProvider(e){x(this,ye,e)}setTimeout(e,t){return l(this,ye).setTimeout(e,t)}clearTimeout(e){l(this,ye).clearTimeout(e)}setInterval(e,t){return l(this,ye).setInterval(e,t)}clearInterval(e){l(this,ye).clearInterval(e)}},ye=new WeakMap,ln=new WeakMap,ka),Bt=new ei;function ti(e){setTimeout(e,0)}var ni=typeof window>"u"||"Deno"in globalThis;function ne(){}function ai(e,t){return typeof e=="function"?e(t):e}function ri(e){return typeof e=="number"&&e>=0&&e!==1/0}function si(e,t){return Math.max(e+(t||0)-Date.now(),0)}function Gt(e,t){return typeof e=="function"?e(t):e}function ii(e,t){return typeof e=="function"?e(t):e}function Wn(e,t){const{type:n="all",exact:a,fetchStatus:r,predicate:s,queryKey:i,stale:o}=e;if(i){if(a){if(t.queryHash!==dn(i,t.options))return!1}else if(!ut(t.queryKey,i))return!1}if(n!=="all"){const d=t.isActive();if(n==="active"&&!d||n==="inactive"&&d)return!1}return!(typeof o=="boolean"&&t.isStale()!==o||r&&r!==t.state.fetchStatus||s&&!s(t))}function Qn(e,t){const{exact:n,status:a,predicate:r,mutationKey:s}=e;if(s){if(!t.options.mutationKey)return!1;if(n){if(lt(t.options.mutationKey)!==lt(s))return!1}else if(!ut(t.options.mutationKey,s))return!1}return!(a&&t.state.status!==a||r&&!r(t))}function dn(e,t){return((t==null?void 0:t.queryKeyHashFn)||lt)(e)}function lt(e){return JSON.stringify(e,(t,n)=>Jt(n)?Object.keys(n).sort().reduce((a,r)=>(a[r]=n[r],a),{}):n)}function ut(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="object"&&typeof t=="object"?Object.keys(t).every(n=>ut(e[n],t[n])):!1}var oi=Object.prototype.hasOwnProperty;function Va(e,t,n=0){if(e===t)return e;if(n>500)return t;const a=zn(e)&&zn(t);if(!a&&!(Jt(e)&&Jt(t)))return t;const s=(a?e:Object.keys(e)).length,i=a?t:Object.keys(t),o=i.length,d=a?new Array(o):{};let f=0;for(let h=0;h{Bt.setTimeout(t,e)})}function li(e,t,n){return typeof n.structuralSharing=="function"?n.structuralSharing(e,t):n.structuralSharing!==!1?Va(e,t):t}function ui(e,t,n=0){const a=[...e,t];return n&&a.length>n?a.slice(1):a}function di(e,t,n=0){const a=[t,...e];return n&&a.length>n?a.slice(0,-1):a}var hn=Symbol();function Ka(e,t){return!e.queryFn&&(t!=null&&t.initialPromise)?()=>t.initialPromise:!e.queryFn||e.queryFn===hn?()=>Promise.reject(new Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function Dl(e,t){return typeof e=="function"?e(...t):!!e}function hi(e,t,n){let a=!1,r;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(r??(r=t()),a||(a=!0,r.aborted?n():r.addEventListener("abort",n,{once:!0})),r)}),e}var qa=(()=>{let e=()=>ni;return{isServer(){return e()},setIsServer(t){e=t}}})();function fi(){let e,t;const n=new Promise((r,s)=>{e=r,t=s});n.status="pending",n.catch(()=>{});function a(r){Object.assign(n,r),delete n.resolve,delete n.reject}return n.resolve=r=>{a({status:"fulfilled",value:r}),e(r)},n.reject=r=>{a({status:"rejected",reason:r}),t(r)},n}var mi=ti;function gi(){let e=[],t=0,n=o=>{o()},a=o=>{o()},r=mi;const s=o=>{t?e.push(o):r(()=>{n(o)})},i=()=>{const o=e;e=[],o.length&&r(()=>{a(()=>{o.forEach(d=>{n(d)})})})};return{batch:o=>{let d;t++;try{d=o()}finally{t--,t||i()}return d},batchCalls:o=>(...d)=>{s(()=>{o(...d)})},schedule:s,setNotifyFunction:o=>{n=o},setBatchNotifyFunction:o=>{a=o},setScheduler:o=>{r=o}}}var z=gi(),Ge,_e,Je,Ta,pi=(Ta=class extends Et{constructor(){super();P(this,Ge,!0);P(this,_e);P(this,Je);x(this,Je,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t(!0),a=()=>t(!1);return window.addEventListener("online",n,!1),window.addEventListener("offline",a,!1),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",a)}}})}onSubscribe(){l(this,_e)||this.setEventListener(l(this,Je))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,_e))==null||t.call(this),x(this,_e,void 0))}setEventListener(t){var n;x(this,Je,t),(n=l(this,_e))==null||n.call(this),x(this,_e,t(this.setOnline.bind(this)))}setOnline(t){l(this,Ge)!==t&&(x(this,Ge,t),this.listeners.forEach(a=>{a(t)}))}isOnline(){return l(this,Ge)}},Ge=new WeakMap,_e=new WeakMap,Je=new WeakMap,Ta),Tt=new pi;function vi(e){return Math.min(1e3*2**e,3e4)}function Ha(e){return(e??"online")==="online"?Tt.isOnline():!0}var Lt=class extends Error{constructor(e){super("CancelledError"),this.revert=e==null?void 0:e.revert,this.silent=e==null?void 0:e.silent}};function bi(e){return e instanceof Lt}function Wa(e){let t=!1,n=0,a;const r=fi(),s=()=>r.status!=="pending",i=v=>{var w;if(!s()){const T=new Lt(v);u(T),(w=e.onCancel)==null||w.call(e,T)}},o=()=>{t=!0},d=()=>{t=!1},f=()=>Ua.isFocused()&&(e.networkMode==="always"||Tt.isOnline())&&e.canRun(),h=()=>Ha(e.networkMode)&&e.canRun(),b=v=>{s()||(a==null||a(),r.resolve(v))},u=v=>{s()||(a==null||a(),r.reject(v))},p=()=>new Promise(v=>{var w;a=T=>{(s()||f())&&v(T)},(w=e.onPause)==null||w.call(e)}).then(()=>{var v;a=void 0,s()||(v=e.onContinue)==null||v.call(e)}),g=()=>{if(s())return;let v;const w=n===0?e.initialPromise:void 0;try{v=w??e.fn()}catch(T){v=Promise.reject(T)}Promise.resolve(v).then(b).catch(T=>{var y;if(s())return;const N=e.retry??(qa.isServer()?0:3),R=e.retryDelay??vi,_=typeof R=="function"?R(n,T):R,L=N===!0||typeof N=="number"&&nf()?void 0:p()).then(()=>{t?u(T):g()})})};return{promise:r,status:()=>r.status,cancel:i,continue:()=>(a==null||a(),r),cancelRetry:o,continueRetry:d,canStart:h,start:()=>(h()?g():p().then(g),r)}}var Ee,La,Qa=(La=class{constructor(){P(this,Ee)}destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),ri(this.gcTime)&&x(this,Ee,Bt.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(qa.isServer()?1/0:300*1e3))}clearGcTimeout(){l(this,Ee)!==void 0&&(Bt.clearTimeout(l(this,Ee)),x(this,Ee,void 0))}},Ee=new WeakMap,La);function wi(e){return{onFetch:(t,n)=>{var h,b,u,p,g;const a=t.options,r=(u=(b=(h=t.fetchOptions)==null?void 0:h.meta)==null?void 0:b.fetchMore)==null?void 0:u.direction,s=((p=t.state.data)==null?void 0:p.pages)||[],i=((g=t.state.data)==null?void 0:g.pageParams)||[];let o={pages:[],pageParams:[]},d=0;const f=async()=>{let v=!1;const w=R=>{hi(R,()=>t.signal,()=>v=!0)},T=Ka(t.options,t.fetchOptions),N=async(R,_,L)=>{if(v)return Promise.reject(t.signal.reason);if(_==null&&R.pages.length)return Promise.resolve(R);const k=(()=>{const me={client:t.client,queryKey:t.queryKey,pageParam:_,direction:L?"backward":"forward",meta:t.options.meta};return w(me),me})(),j=await T(k),{maxPages:E}=t.options,D=L?di:ui;return{pages:D(R.pages,j,E),pageParams:D(R.pageParams,_,E)}};if(r&&s.length){const R=r==="backward",_=R?za:Zt,L={pages:s,pageParams:i},y=_(a,L);o=await N(L,y,R)}else{const R=e??s.length;do{const _=d===0?i[0]??a.initialPageParam:Zt(a,o);if(d>0&&_==null)break;o=await N(o,_),d++}while(d{var v,w;return(w=(v=t.options).persister)==null?void 0:w.call(v,f,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},n)}:t.fetchFn=f}}}function Zt(e,{pages:t,pageParams:n}){const a=t.length-1;return t.length>0?e.getNextPageParam(t[a],t,n[a],n):void 0}function za(e,{pages:t,pageParams:n}){var a;return t.length>0?(a=e.getPreviousPageParam)==null?void 0:a.call(e,t[0],t,n[0],n):void 0}function Fl(e,t){return t?Zt(e,t)!=null:!1}function Il(e,t){return!t||!e.getPreviousPageParam?!1:za(e,t)!=null}var Ze,De,Xe,X,Fe,U,ft,Ie,Z,Ba,he,Ra,yi=(Ra=class extends Qa{constructor(t){super();P(this,Z);P(this,Ze);P(this,De);P(this,Xe);P(this,X);P(this,Fe);P(this,U);P(this,ft);P(this,Ie);x(this,Ie,!1),x(this,ft,t.defaultOptions),this.setOptions(t.options),this.observers=[],x(this,Fe,t.client),x(this,X,l(this,Fe).getQueryCache()),this.queryKey=t.queryKey,this.queryHash=t.queryHash,x(this,De,Jn(this.options)),this.state=t.state??l(this,De),this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return l(this,Ze)}get promise(){var t;return(t=l(this,U))==null?void 0:t.promise}setOptions(t){if(this.options={...l(this,ft),...t},t!=null&&t._type&&x(this,Ze,t._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){const n=Jn(this.options);n.data!==void 0&&(this.setState(Gn(n.data,n.dataUpdatedAt)),x(this,De,n))}}optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"&&l(this,X).remove(this)}setData(t,n){const a=li(this.state.data,t,this.options);return V(this,Z,he).call(this,{data:a,type:"success",dataUpdatedAt:n==null?void 0:n.updatedAt,manual:n==null?void 0:n.manual}),a}setState(t){V(this,Z,he).call(this,{type:"setState",state:t})}cancel(t){var a,r;const n=(a=l(this,U))==null?void 0:a.promise;return(r=l(this,U))==null||r.cancel(t),n?n.then(ne).catch(ne):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return l(this,De)}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(t=>ii(t.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===hn||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0?this.observers.some(t=>Gt(t.options.staleTime,this)==="static"):!1}isStale(){return this.getObserversCount()>0?this.observers.some(t=>t.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(t=0){return this.state.data===void 0?!0:t==="static"?!1:this.state.isInvalidated?!0:!si(this.state.dataUpdatedAt,t)}onFocus(){var n;const t=this.observers.find(a=>a.shouldFetchOnWindowFocus());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}onOnline(){var n;const t=this.observers.find(a=>a.shouldFetchOnReconnect());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}addObserver(t){this.observers.includes(t)||(this.observers.push(t),this.clearGcTimeout(),l(this,X).notify({type:"observerAdded",query:this,observer:t}))}removeObserver(t){this.observers.includes(t)&&(this.observers=this.observers.filter(n=>n!==t),this.observers.length||(l(this,U)&&(l(this,Ie)||V(this,Z,Ba).call(this)?l(this,U).cancel({revert:!0}):l(this,U).cancelRetry()),this.scheduleGc()),l(this,X).notify({type:"observerRemoved",query:this,observer:t}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||V(this,Z,he).call(this,{type:"invalidate"})}async fetch(t,n){var f,h,b,u,p,g,v,w,T,N,R;if(this.state.fetchStatus!=="idle"&&((f=l(this,U))==null?void 0:f.status())!=="rejected"){if(this.state.data!==void 0&&(n!=null&&n.cancelRefetch))this.cancel({silent:!0});else if(l(this,U))return l(this,U).continueRetry(),l(this,U).promise}if(t&&this.setOptions(t),!this.options.queryFn){const _=this.observers.find(L=>L.options.queryFn);_&&this.setOptions(_.options)}const a=new AbortController,r=_=>{Object.defineProperty(_,"signal",{enumerable:!0,get:()=>(x(this,Ie,!0),a.signal)})},s=()=>{const _=Ka(this.options,n),y=(()=>{const k={client:l(this,Fe),queryKey:this.queryKey,meta:this.meta};return r(k),k})();return x(this,Ie,!1),this.options.persister?this.options.persister(_,y,this):_(y)},o=(()=>{const _={fetchOptions:n,options:this.options,queryKey:this.queryKey,client:l(this,Fe),state:this.state,fetchFn:s};return r(_),_})(),d=l(this,Ze)==="infinite"?wi(this.options.pages):this.options.behavior;d==null||d.onFetch(o,this),x(this,Xe,this.state),(this.state.fetchStatus==="idle"||this.state.fetchMeta!==((h=o.fetchOptions)==null?void 0:h.meta))&&V(this,Z,he).call(this,{type:"fetch",meta:(b=o.fetchOptions)==null?void 0:b.meta}),x(this,U,Wa({initialPromise:n==null?void 0:n.initialPromise,fn:o.fetchFn,onCancel:_=>{_ instanceof Lt&&_.revert&&this.setState({...l(this,Xe),fetchStatus:"idle"}),a.abort()},onFail:(_,L)=>{V(this,Z,he).call(this,{type:"failed",failureCount:_,error:L})},onPause:()=>{V(this,Z,he).call(this,{type:"pause"})},onContinue:()=>{V(this,Z,he).call(this,{type:"continue"})},retry:o.options.retry,retryDelay:o.options.retryDelay,networkMode:o.options.networkMode,canRun:()=>!0}));try{const _=await l(this,U).start();if(_===void 0)throw new Error(`${this.queryHash} data is undefined`);return this.setData(_),(p=(u=l(this,X).config).onSuccess)==null||p.call(u,_,this),(v=(g=l(this,X).config).onSettled)==null||v.call(g,_,this.state.error,this),_}catch(_){if(_ instanceof Lt){if(_.silent)return l(this,U).promise;if(_.revert){if(this.state.data===void 0)throw _;return this.state.data}}throw V(this,Z,he).call(this,{type:"error",error:_}),(T=(w=l(this,X).config).onError)==null||T.call(w,_,this),(R=(N=l(this,X).config).onSettled)==null||R.call(N,this.state.data,_,this),_}finally{this.scheduleGc()}}},Ze=new WeakMap,De=new WeakMap,Xe=new WeakMap,X=new WeakMap,Fe=new WeakMap,U=new WeakMap,ft=new WeakMap,Ie=new WeakMap,Z=new WeakSet,Ba=function(){return this.state.fetchStatus==="paused"&&this.state.status==="pending"},he=function(t){const n=a=>{switch(t.type){case"failed":return{...a,fetchFailureCount:t.failureCount,fetchFailureReason:t.error};case"pause":return{...a,fetchStatus:"paused"};case"continue":return{...a,fetchStatus:"fetching"};case"fetch":return{...a,..._i(a.data,this.options),fetchMeta:t.meta??null};case"success":const r={...a,...Gn(t.data,t.dataUpdatedAt),dataUpdateCount:a.dataUpdateCount+1,...!t.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return x(this,Xe,t.manual?r:void 0),r;case"error":const s=t.error;return{...a,error:s,errorUpdateCount:a.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:a.fetchFailureCount+1,fetchFailureReason:s,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...a,isInvalidated:!0};case"setState":return{...a,...t.state}}};this.state=n(this.state),z.batch(()=>{this.observers.forEach(a=>{a.onQueryUpdate()}),l(this,X).notify({query:this,type:"updated",action:t})})},Ra);function _i(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Ha(t.networkMode)?"fetching":"paused",...e===void 0&&{error:null,status:"pending"}}}function Gn(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:"success"}}function Jn(e){const t=typeof e.initialData=="function"?e.initialData():e.initialData,n=t!==void 0,a=n?typeof e.initialDataUpdatedAt=="function"?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:n?a??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:n?"success":"pending",fetchStatus:"idle"}}var mt,le,K,$e,ue,ve,Ma,Si=(Ma=class extends Qa{constructor(t){super();P(this,ue);P(this,mt);P(this,le);P(this,K);P(this,$e);x(this,mt,t.client),this.mutationId=t.mutationId,x(this,K,t.mutationCache),x(this,le,[]),this.state=t.state||Ci(),this.setOptions(t.options),this.scheduleGc()}setOptions(t){this.options=t,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(t){l(this,le).includes(t)||(l(this,le).push(t),this.clearGcTimeout(),l(this,K).notify({type:"observerAdded",mutation:this,observer:t}))}removeObserver(t){x(this,le,l(this,le).filter(n=>n!==t)),this.scheduleGc(),l(this,K).notify({type:"observerRemoved",mutation:this,observer:t})}optionalRemove(){l(this,le).length||(this.state.status==="pending"?this.scheduleGc():l(this,K).remove(this))}continue(){var t;return((t=l(this,$e))==null?void 0:t.continue())??this.execute(this.state.variables)}async execute(t){var i,o,d,f,h,b,u,p,g,v,w,T,N,R,_,L,y,k;const n=()=>{V(this,ue,ve).call(this,{type:"continue"})},a={client:l(this,mt),meta:this.options.meta,mutationKey:this.options.mutationKey};x(this,$e,Wa({fn:()=>this.options.mutationFn?this.options.mutationFn(t,a):Promise.reject(new Error("No mutationFn found")),onFail:(j,E)=>{V(this,ue,ve).call(this,{type:"failed",failureCount:j,error:E})},onPause:()=>{V(this,ue,ve).call(this,{type:"pause"})},onContinue:n,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>l(this,K).canRun(this)}));const r=this.state.status==="pending",s=!l(this,$e).canStart();try{if(r)n();else{V(this,ue,ve).call(this,{type:"pending",variables:t,isPaused:s}),l(this,K).config.onMutate&&await l(this,K).config.onMutate(t,this,a);const E=await((o=(i=this.options).onMutate)==null?void 0:o.call(i,t,a));E!==this.state.context&&V(this,ue,ve).call(this,{type:"pending",context:E,variables:t,isPaused:s})}const j=await l(this,$e).start();return await((f=(d=l(this,K).config).onSuccess)==null?void 0:f.call(d,j,t,this.state.context,this,a)),await((b=(h=this.options).onSuccess)==null?void 0:b.call(h,j,t,this.state.context,a)),await((p=(u=l(this,K).config).onSettled)==null?void 0:p.call(u,j,null,this.state.variables,this.state.context,this,a)),await((v=(g=this.options).onSettled)==null?void 0:v.call(g,j,null,t,this.state.context,a)),V(this,ue,ve).call(this,{type:"success",data:j}),j}catch(j){try{await((T=(w=l(this,K).config).onError)==null?void 0:T.call(w,j,t,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((R=(N=this.options).onError)==null?void 0:R.call(N,j,t,this.state.context,a))}catch(E){Promise.reject(E)}try{await((L=(_=l(this,K).config).onSettled)==null?void 0:L.call(_,void 0,j,this.state.variables,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((k=(y=this.options).onSettled)==null?void 0:k.call(y,void 0,j,t,this.state.context,a))}catch(E){Promise.reject(E)}throw V(this,ue,ve).call(this,{type:"error",error:j}),j}finally{l(this,K).runNext(this)}}},mt=new WeakMap,le=new WeakMap,K=new WeakMap,$e=new WeakMap,ue=new WeakSet,ve=function(t){const n=a=>{switch(t.type){case"failed":return{...a,failureCount:t.failureCount,failureReason:t.error};case"pause":return{...a,isPaused:!0};case"continue":return{...a,isPaused:!1};case"pending":return{...a,context:t.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:t.isPaused,status:"pending",variables:t.variables,submittedAt:Date.now()};case"success":return{...a,data:t.data,failureCount:0,failureReason:null,error:null,status:"success",isPaused:!1};case"error":return{...a,data:void 0,error:t.error,failureCount:a.failureCount+1,failureReason:t.error,isPaused:!1,status:"error"}}};this.state=n(this.state),z.batch(()=>{l(this,le).forEach(a=>{a.onMutationUpdate(t)}),l(this,K).notify({mutation:this,type:"updated",action:t})})},Ma);function Ci(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:"idle",variables:void 0,submittedAt:0}}var fe,ae,gt,Pa,xi=(Pa=class extends Et{constructor(t={}){super();P(this,fe);P(this,ae);P(this,gt);this.config=t,x(this,fe,new Set),x(this,ae,new Map),x(this,gt,0)}build(t,n,a){const r=new Si({client:t,mutationCache:this,mutationId:++Ct(this,gt)._,options:t.defaultMutationOptions(n),state:a});return this.add(r),r}add(t){l(this,fe).add(t);const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n);a?a.push(t):l(this,ae).set(n,[t])}this.notify({type:"added",mutation:t})}remove(t){if(l(this,fe).delete(t)){const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n);if(a)if(a.length>1){const r=a.indexOf(t);r!==-1&&a.splice(r,1)}else a[0]===t&&l(this,ae).delete(n)}}this.notify({type:"removed",mutation:t})}canRun(t){const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n),r=a==null?void 0:a.find(s=>s.state.status==="pending");return!r||r===t}else return!0}runNext(t){var a;const n=xt(t);if(typeof n=="string"){const r=(a=l(this,ae).get(n))==null?void 0:a.find(s=>s!==t&&s.state.isPaused);return(r==null?void 0:r.continue())??Promise.resolve()}else return Promise.resolve()}clear(){z.batch(()=>{l(this,fe).forEach(t=>{this.notify({type:"removed",mutation:t})}),l(this,fe).clear(),l(this,ae).clear()})}getAll(){return Array.from(l(this,fe))}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Qn(n,a))}findAll(t={}){return this.getAll().filter(n=>Qn(t,n))}notify(t){z.batch(()=>{this.listeners.forEach(n=>{n(t)})})}resumePausedMutations(){const t=this.getAll().filter(n=>n.state.isPaused);return z.batch(()=>Promise.all(t.map(n=>n.continue().catch(ne))))}},fe=new WeakMap,ae=new WeakMap,gt=new WeakMap,Pa);function xt(e){var t;return(t=e.options.scope)==null?void 0:t.id}var de,ja,ki=(ja=class extends Et{constructor(t={}){super();P(this,de);this.config=t,x(this,de,new Map)}build(t,n,a){const r=n.queryKey,s=n.queryHash??dn(r,n);let i=this.get(s);return i||(i=new yi({client:t,queryKey:r,queryHash:s,options:t.defaultQueryOptions(n),state:a,defaultOptions:t.getQueryDefaults(r)}),this.add(i)),i}add(t){l(this,de).has(t.queryHash)||(l(this,de).set(t.queryHash,t),this.notify({type:"added",query:t}))}remove(t){const n=l(this,de).get(t.queryHash);n&&(t.destroy(),n===t&&l(this,de).delete(t.queryHash),this.notify({type:"removed",query:t}))}clear(){z.batch(()=>{this.getAll().forEach(t=>{this.remove(t)})})}get(t){return l(this,de).get(t)}getAll(){return[...l(this,de).values()]}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Wn(n,a))}findAll(t={}){const n=this.getAll();return Object.keys(t).length>0?n.filter(a=>Wn(t,a)):n}notify(t){z.batch(()=>{this.listeners.forEach(n=>{n(t)})})}onFocus(){z.batch(()=>{this.getAll().forEach(t=>{t.onFocus()})})}onOnline(){z.batch(()=>{this.getAll().forEach(t=>{t.onOnline()})})}},de=new WeakMap,ja),F,Se,Ce,Ye,et,xe,tt,nt,Aa,Ti=(Aa=class{constructor(e={}){P(this,F);P(this,Se);P(this,Ce);P(this,Ye);P(this,et);P(this,xe);P(this,tt);P(this,nt);x(this,F,e.queryCache||new ki),x(this,Se,e.mutationCache||new xi),x(this,Ce,e.defaultOptions||{}),x(this,Ye,new Map),x(this,et,new Map),x(this,xe,0)}mount(){Ct(this,xe)._++,l(this,xe)===1&&(x(this,tt,Ua.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onFocus())})),x(this,nt,Tt.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onOnline())})))}unmount(){var e,t;Ct(this,xe)._--,l(this,xe)===0&&((e=l(this,tt))==null||e.call(this),x(this,tt,void 0),(t=l(this,nt))==null||t.call(this),x(this,nt,void 0))}isFetching(e){return l(this,F).findAll({...e,fetchStatus:"fetching"}).length}isMutating(e){return l(this,Se).findAll({...e,status:"pending"}).length}getQueryData(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,F).get(t.queryHash))==null?void 0:n.state.data}ensureQueryData(e){const t=this.defaultQueryOptions(e),n=l(this,F).build(this,t),a=n.state.data;return a===void 0?this.fetchQuery(e):(e.revalidateIfStale&&n.isStaleByTime(Gt(t.staleTime,n))&&this.prefetchQuery(t),Promise.resolve(a))}getQueriesData(e){return l(this,F).findAll(e).map(({queryKey:t,state:n})=>{const a=n.data;return[t,a]})}setQueryData(e,t,n){const a=this.defaultQueryOptions({queryKey:e}),r=l(this,F).get(a.queryHash),s=r==null?void 0:r.state.data,i=ai(t,s);if(i!==void 0)return l(this,F).build(this,a).setData(i,{...n,manual:!0})}setQueriesData(e,t,n){return z.batch(()=>l(this,F).findAll(e).map(({queryKey:a})=>[a,this.setQueryData(a,t,n)]))}getQueryState(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,F).get(t.queryHash))==null?void 0:n.state}removeQueries(e){const t=l(this,F);z.batch(()=>{t.findAll(e).forEach(n=>{t.remove(n)})})}resetQueries(e,t){const n=l(this,F);return z.batch(()=>(n.findAll(e).forEach(a=>{a.reset()}),this.refetchQueries({type:"active",...e},t)))}cancelQueries(e,t={}){const n={revert:!0,...t},a=z.batch(()=>l(this,F).findAll(e).map(r=>r.cancel(n)));return Promise.all(a).then(ne).catch(ne)}invalidateQueries(e,t={}){return z.batch(()=>(l(this,F).findAll(e).forEach(n=>{n.invalidate()}),(e==null?void 0:e.refetchType)==="none"?Promise.resolve():this.refetchQueries({...e,type:(e==null?void 0:e.refetchType)??(e==null?void 0:e.type)??"active"},t)))}refetchQueries(e,t={}){const n={...t,cancelRefetch:t.cancelRefetch??!0},a=z.batch(()=>l(this,F).findAll(e).filter(r=>!r.isDisabled()&&!r.isStatic()).map(r=>{let s=r.fetch(void 0,n);return n.throwOnError||(s=s.catch(ne)),r.state.fetchStatus==="paused"?Promise.resolve():s}));return Promise.all(a).then(ne)}fetchQuery(e){const t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);const n=l(this,F).build(this,t);return n.isStaleByTime(Gt(t.staleTime,n))?n.fetch(t):Promise.resolve(n.state.data)}prefetchQuery(e){return this.fetchQuery(e).then(ne).catch(ne)}fetchInfiniteQuery(e){return e._type="infinite",this.fetchQuery(e)}prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(ne).catch(ne)}ensureInfiniteQueryData(e){return e._type="infinite",this.ensureQueryData(e)}resumePausedMutations(){return Tt.isOnline()?l(this,Se).resumePausedMutations():Promise.resolve()}getQueryCache(){return l(this,F)}getMutationCache(){return l(this,Se)}getDefaultOptions(){return l(this,Ce)}setDefaultOptions(e){x(this,Ce,e)}setQueryDefaults(e,t){l(this,Ye).set(lt(e),{queryKey:e,defaultOptions:t})}getQueryDefaults(e){const t=[...l(this,Ye).values()],n={};return t.forEach(a=>{ut(e,a.queryKey)&&Object.assign(n,a.defaultOptions)}),n}setMutationDefaults(e,t){l(this,et).set(lt(e),{mutationKey:e,defaultOptions:t})}getMutationDefaults(e){const t=[...l(this,et).values()],n={};return t.forEach(a=>{ut(e,a.mutationKey)&&Object.assign(n,a.defaultOptions)}),n}defaultQueryOptions(e){if(e._defaulted)return e;const t={...l(this,Ce).queries,...this.getQueryDefaults(e.queryKey),...e,_defaulted:!0};return t.queryHash||(t.queryHash=dn(t.queryKey,t)),t.refetchOnReconnect===void 0&&(t.refetchOnReconnect=t.networkMode!=="always"),t.throwOnError===void 0&&(t.throwOnError=!!t.suspense),!t.networkMode&&t.persister&&(t.networkMode="offlineFirst"),t.queryFn===hn&&(t.enabled=!1),t}defaultMutationOptions(e){return e!=null&&e._defaulted?e:{...l(this,Ce).mutations,...(e==null?void 0:e.mutationKey)&&this.getMutationDefaults(e.mutationKey),...e,_defaulted:!0}}clear(){l(this,F).clear(),l(this,Se).clear()}},F=new WeakMap,Se=new WeakMap,Ce=new WeakMap,Ye=new WeakMap,et=new WeakMap,xe=new WeakMap,tt=new WeakMap,nt=new WeakMap,Aa),Ga=C.createContext(void 0),$l=e=>{const t=C.useContext(Ga);if(!t)throw new Error("No QueryClient set, use QueryClientProvider to set one");return t},Li=({client:e,children:t})=>(C.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),c.jsx(Ga.Provider,{value:e,children:t}));function Ri(e,t=window.location.href){var a;const n=(a=new URL(t).searchParams.get("record"))==null?void 0:a.trim();if(n){const r=e.calls.find(s=>s.id===n);return r?[r]:[]}return e.calls[0]?[e.calls[0]]:[]}function Ol({calls:e,recordId:t,detail:n}){const a=e.findIndex(b=>b.id===t),r=a>=0?a:!t&&e.length?0:-1,s=(n==null?void 0:n.record.id)===t?n:null,i=(s==null?void 0:s.record)??(r>=0?e[r]:null),o=(s==null?void 0:s.previousRecord)??(r>0?e[r-1]:null),d=(s==null?void 0:s.nextRecord)??(r>=0&&r=0?`${r+1} of ${e.length} loaded calls`:"Record outside loaded snapshot";return{modelIndex:a,activeIndex:r,hydratedDetail:s,call:i,previous:o,next:d,threadCalls:f,positionLabel:h}}function Mi(e,t,n){const a=e.filter(i=>i.thread===t.thread),r=[n==null?void 0:n.previousRecord,n==null?void 0:n.record,n==null?void 0:n.nextRecord].filter(Pi),s=new Map;for(const i of[...a,...r,t])s.set(i.id,i);return[...s.values()].sort(ji)}function Pi(e){return!!(e!=null&&e.id)}function ji(e,t){return Date.parse(t.rawTime||t.time)-Date.parse(e.rawTime||e.time)}function Ai(e,t){const n=t.map(r=>Zn(r.header)).join(","),a=e.map(r=>t.map(s=>Zn(s.value(r))).join(","));return[n,...a].join(` +`)}function Ni(e,t){const n=new Blob([t],{type:"text/csv;charset=utf-8"}),a=typeof URL.createObjectURL=="function"?URL.createObjectURL(n):`data:text/csv;charset=utf-8,${encodeURIComponent(t)}`,r=document.createElement("a");r.href=a,r.download=e,r.rel="noopener",document.body.append(r),r.click(),r.remove(),a.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(a)}function Ei(e=new Date){return e.toISOString().slice(0,10)}function Zn(e){const t=String(e??"");return/[",\n\r]/.test(t)?`"${t.replaceAll('"','""')}"`:t}function Le(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function be(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Xt(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function dt(e){return`${e.toFixed(1)}%`}function Ja(e){return e.fast===!0?"Fast":e.fast===!1?"Standard":"Unknown"}function Ul(e){return e.fast!==null?`confirmed ${Ja(e)} · ${e.serviceTierConfidence||"exact"}`:e.fastProxyCandidate?"tier unknown · Fast proxy candidate":"tier unknown · normal throughput proxy"}function Vl(e){return e.cachedPct<25?"cold or weak cache":e.cachedPct<50?"partial cache reuse":"healthy cache reuse"}function Kl(e){return e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available"}function ql(e){if(e.contextWindowPct===null||e.contextWindowPct===void 0)return"Not reported";const t=e.modelContextWindow?` of ${be(e.modelContextWindow)}`:"";return`${dt(e.contextWindowPct)}${t}`}function Hl(e,{limit:t=2,emptyLabel:n="No related calls",unknownLabel:a="Unknown",style:r="parenthetical"}={}){const s=new Map;for(const o of e){const d=o||a;s.set(d,(s.get(d)??0)+1)}const i=[...s.entries()].sort((o,d)=>d[1]-o[1]||o[0].localeCompare(d[0])).slice(0,t).map(([o,d])=>r==="x"?`${o} x${d}`:`${o} (${d})`);return i.length?i.join(", "):n}const Wl=[{id:"time",accessorFn:e=>Number(Date.parse(e.eventTimestamp||e.callStartedAt||e.rawTime||e.time))||0,header:"Time",cell:e=>e.row.original.time},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:e=>c.jsx("span",{className:`pill effort-${String(e.getValue())}`,children:String(e.getValue())})},{accessorKey:"input",header:"Input Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"output",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:e=>c.jsx("span",{className:"cache-pill",children:dt(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"contextWindowPct",header:"Context %",cell:e=>{const t=e.getValue(),n=typeof t=="number"?t:Number.NaN;return c.jsx("span",{className:"num",children:Number.isFinite(n)?dt(n):"-"})}},{accessorKey:"duration",header:"Duration"},{id:"serviceTier",accessorFn:e=>Ja(e),header:"Service Tier",cell:e=>{const t=String(e.getValue()),n=t==="Fast"?"green":t==="Standard"?"blue":"";return c.jsx("span",{className:`status-badge ${n}`.trim(),children:t})}},{accessorKey:"previousCallGap",header:"Prev Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiator",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"signal",header:"Signals",cell:e=>c.jsx(Fi,{call:e.row.original})}],ce=[{header:"timestamp",value:e=>e.eventTimestamp||e.rawTime||e.time},{header:"thread",value:e=>e.thread},{header:"call_started_at",value:e=>e.callStartedAt||e.rawTime||e.time},{header:"call_duration_seconds",value:e=>e.durationSeconds},{header:"previous_call_event_timestamp",value:e=>e.previousCallEventTimestamp},{header:"previous_call_delta_seconds",value:e=>e.previousCallGapSeconds},{header:"initiated",value:e=>e.initiator},{header:"initiated_reason",value:e=>e.initiatorReason},{header:"project",value:e=>e.project},{header:"model",value:e=>e.model},{header:"effort",value:e=>e.effort},{header:"total_tokens",value:e=>e.totalTokens},{header:"input_tokens",value:e=>e.input},{header:"cached_input_tokens",value:e=>e.cachedInput},{header:"uncached_input_tokens",value:e=>e.uncachedInput},{header:"output_tokens",value:e=>e.output},{header:"reasoning_output_tokens",value:e=>e.reasoningOutput},{header:"estimated_cost_usd",value:e=>e.cost.toFixed(6)},{header:"usage_credits",value:e=>e.credits.toFixed(6)},{header:"standard_usage_credits",value:e=>e.standardUsageCredits.toFixed(6)},{header:"service_tier",value:e=>e.serviceTier},{header:"fast",value:e=>e.fast===null?"":e.fast?1:0},{header:"service_tier_source",value:e=>e.serviceTierSource},{header:"service_tier_confidence",value:e=>e.serviceTierConfidence},{header:"fast_proxy_candidate",value:e=>String(e.fastProxyCandidate)},{header:"usage_credit_multiplier",value:e=>e.usageCreditMultiplier},{header:"usage_credit_multiplier_source",value:e=>e.usageCreditMultiplierSource},{header:"cache_ratio",value:e=>e.cachedPct.toFixed(2)},{header:"context_window_percent",value:e=>{var t;return((t=e.contextWindowPct)==null?void 0:t.toFixed(2))??""}},{header:"pricing_model",value:e=>e.pricingModel},{header:"usage_credit_confidence",value:e=>e.usageCreditConfidence},{header:"recommendation",value:e=>e.recommendation},{header:"record_id",value:e=>e.id},{header:"thread_attachment",value:e=>e.threadAttachmentLabel},{header:"thread_source",value:e=>e.threadSource},{header:"parent_thread",value:e=>e.parentThread},{header:"session_id",value:e=>e.sessionId},{header:"turn_id",value:e=>e.turnId},{header:"parent_session_id",value:e=>e.parentSessionId},{header:"parent_session_updated_at",value:e=>e.parentSessionUpdatedAt},{header:"project_relative_cwd",value:e=>e.projectRelativeCwd},{header:"cwd",value:e=>e.cwd},{header:"source_file",value:e=>e.sourceFile},{header:"source_line",value:e=>e.lineNumber??""},{header:"git_branch",value:e=>e.gitBranch},{header:"git_remote_label",value:e=>e.gitRemoteLabel},{header:"git_remote_hash",value:e=>e.gitRemoteHash},{header:"pricing_estimated",value:e=>String(e.pricingEstimated)},{header:"usage_credit_model",value:e=>e.usageCreditModel},{header:"usage_credit_source",value:e=>e.usageCreditSource},{header:"usage_credit_tier",value:e=>e.usageCreditTier},{header:"usage_credit_fetched_at",value:e=>e.usageCreditFetchedAt},{header:"usage_credit_note",value:e=>e.usageCreditNote},{header:"model_context_window",value:e=>e.modelContextWindow??""},{header:"cumulative_total_tokens",value:e=>e.cumulativeTotalTokens??""},{header:"estimated_cache_savings_usd",value:e=>e.estimatedCacheSavings.toFixed(6)},{header:"initiated_confidence",value:e=>e.initiatorConfidence},{header:"signal",value:e=>e.signal},{header:"tags",value:e=>e.tags.join("|")},{header:"efficiency_flags",value:e=>e.efficiencyFlags.join("|")}];function Di(e,t=3){const a=Ii([e.signal,...e.efficiencyFlags]).map((r,s)=>({key:`${r}-${s}`,label:Za(r),shortLabel:$i(r)}));return{visible:a.slice(0,t),hidden:a.slice(t)}}function Fi({call:e}){const t=Oa(),{visible:n,hidden:a}=Di(e);if(!n.length)return c.jsx("span",{className:"muted",children:"None"});const r=n.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),s=a.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),i=s.map(o=>o.label).join("、");return c.jsxs("span",{className:"flags compact-flags","aria-label":t.language==="zh-Hans"?`信号:${[...r,...s].map(o=>o.label).join("、")}`:`Signals: ${[...n,...a].map(o=>o.label).join(", ")}`,children:[r.map(o=>c.jsx("span",{className:"flag signal-puck",title:o.label,children:o.shortLabel},o.key)),s.length?c.jsxs("span",{className:"flag signal-puck more",title:i,children:["+",s.length]}):null]})}function Ii(e){const t=new Set;return e.map(n=>n.trim()).filter(n=>n&&n!=="aggregate").filter(n=>{const a=n.toLowerCase();return t.has(a)?!1:(t.add(a),!0)})}function Za(e){return e.replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function $i(e){const t=e.toLowerCase().replace(/[_\s]+/g,"-"),n={"cache-drop":"CACHE","cache-risk":"CACHE","context-bloat":"CTX","context-heavy":"CTX","elevated-context":"CTX","elevated-context-use":"CTX","estimated-pricing":"EST","expensive-low-output-call":"LO","high-context-use":"CTX","high-cost":"$","high-estimated-cost":"$","high-reasoning-share":"RSN","large-thread":"BIG","low-cache":"CACHE","low-cache-reuse":"CACHE","low-output":"LO","pricing-gap":"PRICE","reasoning-spike":"RSN","subagent-attribution":"SUB"};if(n[t])return n[t];const a=Za(e).split(/\s+/).filter(Boolean);return a.length?a.length===1?a[0].slice(0,4).toUpperCase():a.slice(0,3).map(r=>r[0]).join("").toUpperCase():"?"}const Ql=[{accessorKey:"name",header:"Thread"},{accessorKey:"latestActivity",header:"Latest"},{accessorKey:"turns",header:"Turns",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalDuration",header:"Duration"},{accessorKey:"averageGap",header:"Avg Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiatorSummary",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"modelSummary",header:"Models",cell:e=>c.jsx("span",{className:"pill model-pill",children:String(e.getValue())})},{accessorKey:"effortSummary",header:"Effort Mix"},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"outputTokens",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"cachePct",header:"Cache %",cell:e=>c.jsx("span",{className:"cache-pill",children:dt(Number(e.getValue()))})},{accessorKey:"contextPct",header:"Context %",cell:e=>{const t=e.getValue();return c.jsx("span",{className:"num",children:typeof t=="number"?dt(t):"-"})}},{accessorKey:"costPerCall",header:"Cost / Call",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"coldResumeRisk",header:"Cold Resume Risk",cell:e=>c.jsx("span",{className:`status-badge ${Oi(String(e.getValue()))}`,children:String(e.getValue())})},{accessorKey:"productivity",header:"Productivity",cell:e=>c.jsx("span",{className:"score",children:Number(e.getValue())})}],zl=[{id:"name",label:"Thread",locked:!0},{id:"latestActivity",label:"Latest"},{id:"turns",label:"Turns"},{id:"totalDuration",label:"Duration"},{id:"averageGap",label:"Avg Gap"},{id:"initiatorSummary",label:"Initiated"},{id:"modelSummary",label:"Models"},{id:"effortSummary",label:"Effort Mix"},{id:"totalTokens",label:"Total Tokens"},{id:"cachedInput",label:"Cached Input"},{id:"uncachedInput",label:"Uncached Input"},{id:"outputTokens",label:"Output Tokens"},{id:"reasoningOutput",label:"Reasoning Output"},{id:"cost",label:"Est. Cost"},{id:"credits",label:"Codex Credits"},{id:"cachePct",label:"Cache %"},{id:"contextPct",label:"Context %"},{id:"costPerCall",label:"Cost / Call"},{id:"coldResumeRisk",label:"Cold Resume Risk"},{id:"productivity",label:"Productivity"},{id:"investigate",label:"Investigate",locked:!0}];function Oi(e){return e==="High"?"red":e==="Medium"?"orange":e==="Low"?"green":"neutral"}const ht=1,re=0,qt=100,Xa=1e3,Ya=500,er="codexUsageDashboardLoadSettings",Ui={day:1440*60*1e3,week:10080*60*1e3};function ct(e,t=Ya){if((e==null?void 0:e.limit_label)==="All"||t===re&&(e==null?void 0:e.limit)==null)return re;const n=Number((e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??t);return Number.isFinite(n)&&n>=0?n:t}function pt(e){return Number.isFinite(e)?e<=re?re:Math.max(ht,Math.round(e)):ht}function je(...e){const t=e.find(n=>typeof n=="number"&&Number.isFinite(n)&&n>0);return t?Math.max(ht,Math.round(t)):ht}function Vi(e,t,n=null,a="rows"){const r=pt(e);return{historyScope:t,loadWindow:a,limit:r===re?null:r,since:n}}function Ki(e){return e.limit??re}function fn(e){return mn(e==null?void 0:e.load_window)?e.load_window:e!=null&&e.since?"week":(e==null?void 0:e.limit_label)==="All"||(e==null?void 0:e.limit)==null?"all":"rows"}function qi(e){return mn(e==null?void 0:e.default_load_window)?e.default_load_window:fn(e)}function Ht(e,t=new Date){const n=Ui[e];if(!n)return null;const a=Math.floor(t.getTime()/6e4)*6e4;return new Date(a-n).toISOString()}function Re(e,t=Ya){return e==="day"?"Last 24 hours":e==="week"?"Last 7 days":e==="all"?"All time":`Most recent ${pt(t).toLocaleString()}`}function Hi(e=tr()){if(!e)return null;try{const t=e.getItem(er);if(!t)return null;const n=JSON.parse(t),a=typeof n.loadLimit=="number"&&Number.isFinite(n.loadLimit)?pt(n.loadLimit):void 0,r=n.historyScope==="active"||n.historyScope==="all"?n.historyScope:void 0,s=mn(n.loadWindow)?n.loadWindow:void 0;return a===void 0&&r===void 0&&s===void 0?null:{loadLimit:a,historyScope:r,loadWindow:s}}catch{return null}}function Wi(e,t,n="rows",a=tr()){if(a)try{a.setItem(er,JSON.stringify({loadLimit:pt(e),historyScope:t,loadWindow:n}))}catch{}}function mn(e){return e==="day"||e==="week"||e==="rows"||e==="all"}function Qi({currentLimit:e,loadedRows:t,pendingLimit:n}){const a=n===re?0:n+qt,s=Math.max(ht,e===re?0:e,a,t);return Math.ceil((s+Xa)/qt)*qt}function zi({currentLimit:e,loadedRows:t,pendingLimit:n}){return Math.max(je(e),je(n),je(t))+Xa}function Bi({loadedRows:e,limit:t,totalRows:n}){return t===re&&e>0?`Loaded all ${e.toLocaleString()}`:n>e?`Loaded ${e.toLocaleString()} of ${n.toLocaleString()}`:`Loaded ${e.toLocaleString()} rows`}function tr(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}async function Gi(e,t,n,a="",r=""){const s=Ei();switch(e){case"threads":{const{threadCallsForCurrentUrl:i}=await O(async()=>{const{threadCallsForCurrentUrl:o}=await import("./ThreadsPage.js");return{threadCallsForCurrentUrl:o}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]));return te(`codex-thread-filtered-calls-${s}.csv`,i(t,a),ce,"call rows")}case"cache-context":{const{cacheContextCallsForCurrentUrl:i}=await O(async()=>{const{cacheContextCallsForCurrentUrl:o}=await import("./CacheContextPage.js");return{cacheContextCallsForCurrentUrl:o}},__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12]));return te(`codex-${e}-calls-${s}.csv`,i(t),ce,"call rows")}case"usage-drain":{const{usageDrainCallsForCurrentUrl:i}=await O(async()=>{const{usageDrainCallsForCurrentUrl:o}=await import("./UsageDrainPage.js");return{usageDrainCallsForCurrentUrl:o}},__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39]));return te(`codex-usage-drain-calls-${s}.csv`,i(t),ce,"call rows")}case"diagnostics":{const{diagnosticsCallsForCurrentUrl:i}=await O(async()=>{const{diagnosticsCallsForCurrentUrl:o}=await import("./DiagnosticsPage.js");return{diagnosticsCallsForCurrentUrl:o}},__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12]));return te(`codex-diagnostics-calls-${s}.csv`,i(t),ce,"call rows")}case"reports":{const{reportCallsForCurrentUrl:i}=await O(async()=>{const{reportCallsForCurrentUrl:o}=await import("./ReportsPage.js");return{reportCallsForCurrentUrl:o}},__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43]));return te(`codex-reports-evidence-${s}.csv`,i(t),ce,"call rows")}case"settings":return te(`codex-dashboard-settings-${s}.csv`,Zi(t,n),Ji,"settings rows");case"calls":{const{callsForCurrentUrl:i}=await O(async()=>{const{callsForCurrentUrl:o}=await import("./CallsPage.js");return{callsForCurrentUrl:o}},__vite__mapDeps([44,1,2,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48]));return te(`codex-calls-${s}.csv`,i(t.calls,a,r),ce,"call rows")}case"overview":{const{overviewCallsForQuery:i}=await O(async()=>{const{overviewCallsForQuery:o}=await import("./OverviewPage.js");return{overviewCallsForQuery:o}},__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50]));return te(`codex-overview-calls-${s}.csv`,i(t.calls,a),ce,"call rows")}case"investigator":{const{investigatorCallsForCurrentUrl:i}=await O(async()=>{const{investigatorCallsForCurrentUrl:o}=await import("./InvestigatorPage.js");return{investigatorCallsForCurrentUrl:o}},__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52]));return te(`codex-investigator-calls-${s}.csv`,i(t),ce,"call rows")}case"compression-lab":return te(`codex-compression-lab-scope-${s}.csv`,t.calls,ce,"call rows");case"call":return te(`codex-call-calls-${s}.csv`,Ri(t),ce,"call rows")}}function te(e,t,n,a){return{filename:e,csv:Ai(t,n),rowCount:t.length,label:a}}const Ji=[{header:"Field",value:e=>e.field},{header:"Value",value:e=>e.value}];function Zi(e,t){return[{field:"live_api",value:t.canUseLiveApi?"available":"static snapshot"},{field:"context_api",value:t.contextRuntime.contextApiEnabled?"enabled":"gated"},{field:"history_scope",value:t.historyScope},{field:"data_window",value:Re(t.loadWindow,t.loadLimit)},{field:"scope_since",value:t.scopeSince??"none"},{field:"row_request",value:t.loadLimit===re?"no cap":String(t.loadLimit)},{field:"loaded_rows",value:String(t.loadedRowCount)},{field:"total_available_rows",value:String(t.totalAvailableRows)},{field:"auto_refresh",value:t.autoRefreshEnabled?"enabled":"paused"},{field:"refresh_state",value:t.refreshState},{field:"visible_calls",value:String(e.calls.length)},{field:"visible_threads",value:String(e.threads.length)}]}function Xi(e){return e instanceof Error?e.message:String(e)}function Xn(e,t){const n=t==="all"?"all history":"active history",a=e.message||"Refreshing usage index",r=typeof e.percent=="number"?` ${Math.round(e.percent)}%`:"";return`${a}${r} (${n})`}function Wt(e,t="active"){return e?typeof e.include_archived=="boolean"?e.include_archived?"all":"active":e.history_scope==="all-history"||e.history_scope==="all"?"all":e.history_scope==="active"?"active":t:t}function Yi({historyScope:e,activeRows:t,allRows:n,archivedRows:a}){const r=eo({activeRows:t,allRows:n,archivedRows:a});return e==="all"?r===null?"All history selected":r>0?`All history includes ${r.toLocaleString()} archived calls`:"All history selected; no archived calls are indexed yet":r===null||r<=0?"Active sessions only":`Active sessions only; ${r.toLocaleString()} archived calls hidden`}function eo({activeRows:e,allRows:t,archivedRows:n}){const a=Qt(n);if(a!==null)return a;const r=Qt(e),s=Qt(t);return r!==null&&s!==null?Math.max(s-r,0):null}function Qt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.round(e):null}const nr=["aria-description","aria-label","aria-valuetext","title","placeholder","alt"],to="data-localization-attributes",no=new Set(["CODE","KBD","PRE","SAMP","SCRIPT","STYLE","TEXTAREA"]),Yt=new WeakMap,en=new WeakMap;function ao({value:e,children:t}){return c.jsxs(Zs,{value:e,children:[c.jsx(ro,{}),t]})}function ro(){const e=Oa();return C.useLayoutEffect(()=>{const t=document.querySelector("[data-dashboard-localization-root]");if(!t)return;if(e.language!=="zh-Hans"){io(t),document.title="Codex Usage Tracker React Dashboard";return}document.title="Codex Usage Tracker · 用量仪表盘",Yn(t,e.translateText);const n=new MutationObserver(a=>{for(const r of a){if(r.type==="characterData"&&r.target instanceof Text){tn(r.target,e.translateText);continue}if(r.type==="attributes"&&r.target instanceof Element){nn(r.target,e.translateText);continue}for(const s of r.addedNodes)s instanceof Text?tn(s,e.translateText):s instanceof Element&&Yn(s,e.translateText)}});return n.observe(t,{attributes:!0,attributeFilter:[...nr],characterData:!0,childList:!0,subtree:!0}),()=>n.disconnect()},[e]),null}function Yn(e,t){if(Rt(e))return;nn(e,t);const n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);let a=n.nextNode();for(;a;){if(a instanceof Element){if(Rt(a)){a=so(n,a,e);continue}nn(a,t)}else a instanceof Text&&tn(a,t);a=n.nextNode()}}function so(e,t,n){let a=t;for(;a&&a!==n;){const r=e.nextSibling();if(r)return r;a=a.parentNode,a&&(e.currentNode=a)}return null}function tn(e,t){const n=e.parentElement;if(!n||Rt(n))return;const a=e.nodeValue??"",r=Yt.get(e),s=r&&(a===r.source||a===r.translated)?r.source:a,i=s.match(/^(\s*)([\s\S]*?)(\s*)$/u);if(!i||!i[2])return;const o=t(i[2]),d=`${i[1]}${o}${i[3]}`;Yt.set(e,{source:s,translated:d}),d!==a&&(e.nodeValue=d)}function nn(e,t){if(Rt(e))return;const n=new Set((e.getAttribute(to)??"").split(/[\s,]+/u).filter(Boolean));if(!n.size)return;const a=en.get(e)??new Map;for(const r of nr){if(!n.has(r))continue;const s=e.getAttribute(r);if(!s)continue;const i=a.get(r),o=i&&(s===i.source||s===i.translated)?i.source:s,d=t(o);a.set(r,{source:o,translated:d}),d!==s&&e.setAttribute(r,d)}a.size&&en.set(e,a)}function io(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);ea(e);let n=t.nextNode();for(;n;){if(n instanceof Text){const a=Yt.get(n);a&&n.nodeValue===a.translated&&(n.nodeValue=a.source)}else n instanceof Element&&ea(n);n=t.nextNode()}}function ea(e){const t=en.get(e);if(t)for(const[n,a]of t)e.getAttribute(n)===a.translated&&e.setAttribute(n,a.source)}function Rt(e){return no.has(e.tagName)||!!e.closest('[data-localization-skip="true"]')}const Mt=["May 12","May 19","May 26","Jun 02","Jun 09","Jun 16","Jun 23","Jun 30"],it=Mt.slice(2),ar={contextRuntime:{apiToken:"",contextApiEnabled:!1,fileMode:!1},cards:[{label:"Total Tokens",value:"24.83M",detail:"7-day total: 12.56M",trend:"up 18.7% vs prior 7 days",tone:"blue"},{label:"Estimated Cost",value:"$42.67",detail:"7-day total: $24.81",trend:"up 14.2% vs prior 7 days",tone:"green"},{label:"Cache Hit Rate",value:"38.7%",detail:"7-day average: 42.3%",trend:"down 3.6pp vs prior 7 days",tone:"purple"},{label:"Total Calls",value:"1,342",detail:"678 calls in last 7 days",trend:"up 11.3% vs prior 7 days",tone:"blue"},{label:"Usage Remaining",value:"32.4%",detail:"~15.9K credits estimated",trend:"resets in 4d 12h",tone:"green"}],tokenSeries:[W("input","Input","#2563eb",[5.2,6.4,7.5,9.2,6.7,7.5,6.6,9],1e6),W("output","Output","#059669",[2.5,3,3.6,5.1,3.7,5,4,5.4],1e6),W("cached","Cached","#7c3aed",[1.1,1.4,1.7,2.4,1.8,2.3,1.8,2.6],1e6,!0)],costSeries:[W("cost","Estimated Cost","#2563eb",[8.4,10.1,14.3,9.9,11.4,7.8,12.7,16.5])],cacheSeries:[W("cache","Cache Hit Rate","#059669",[58,61,39,45,50,44,48,41])],weeklyCreditSeries:[{id:"pro",label:"Pro observed",color:"#2563eb",points:Mt.map((e,t)=>({label:e,value:[59800,44900,45e3,40500,42800,38900,31400,35900][t]??0,low:[52100,38800,38900,34700,36200,32200,26100,29900][t]??0,high:[67400,51200,51100,46800,49200,45100,37300,41900][t]??0}))},W("pro-trend","Pro trend","#1d4ed8",[54.2,51,47.8,44.6,41.4,38.2,35,31.8],1e3,!0),W("prolite","Prolite observed","#0f766e",[15.9,15.8,15.9,16.1,15.7,15.6,15.9,15.8],1e3)],usageRemainingSeries:[W("remaining","Usage remaining","#059669",[87,71,63,56,56,48,50,54]),W("allowance","Allowance guide","#0f766e",[86,85,84,83,82,81,80,79],1,!0)],actualVsPredictedSeries:[W("observed","Observed drain","#2563eb",[18.7,22.1,45.3,31,34.8],1e3),W("predicted","Predicted baseline","#1d4ed8",[17.9,21.4,41.2,29.6,33.9],1e3,!0)],findings:[{rank:1,title:"Long Thread: data-engine-refactor",severity:"High",credits:12847,share:25.6,summary:"Very long duration with high model effort."},{rank:2,title:"Cache Misses (Large Inputs)",severity:"High",credits:9612,share:19.1,summary:"Large uncached inputs across 214 calls."},{rank:3,title:"High Model Effort",severity:"Medium",credits:7404,share:14.7,summary:"Reasoning and output token volume are concentrated."},{rank:4,title:"Tool Output Volume",severity:"Medium",credits:5231,share:10.4,summary:"Large tool outputs returned to the model."}],calls:[["2026-06-01T10:24:00Z","Jun 1, 10:24 AM","thread-9f3a1c","codex-1","high",128542,45231,62,.42,"18.4s",!1,["review"]],["2026-06-01T10:18:00Z","Jun 1, 10:18 AM","thread-7b2e91","o4-mini","medium",98731,32104,41,.31,"12.7s",!0,["analysis"]],["2026-06-01T10:12:00Z","Jun 1, 10:12 AM","thread-3c8d4e","o3","high",64221,18903,28,.12,"9.3s",!0,["uncached"]],["2026-06-01T10:06:00Z","Jun 1, 10:06 AM","thread-1a2b3c","codex-1","high",245123,98112,71,.87,"27.6s",!1,["large"]],["2026-06-01T10:01:00Z","Jun 1, 10:01 AM","thread-8d7c6b","gpt-4.1","low",12543,4231,12,.03,"3.6s",!0,["quick"]],["2026-06-01T09:55:00Z","Jun 1, 09:55 AM","thread-2f9e7d","o4-mini","medium",76881,28442,39,.24,"11.2s",!1,["subagent"]],["2026-06-01T09:50:00Z","Jun 1, 09:50 AM","thread-6a5b4c","codex-1","high",312654,112991,67,1.12,"31.8s",!1,["file-heavy"]],["2026-06-01T09:47:00Z","Jun 1, 09:47 AM","thread-0f1e2d","o3","low",8221,2903,15,.02,"2.8s",!0,["fast"]]].map(([e,t,n,a,r,s,i,o,d,f,h,b],u)=>{const p=Number(s),g=Number(i),v=Number(o),w=Math.round(p*Math.max(100-v,0)/100);return{id:`fixture-call-${u}`,rawTime:String(e),eventTimestamp:String(e),callStartedAt:String(e),time:String(t),thread:String(n),model:String(a),effort:String(r),input:p,output:g,reasoningOutput:Math.round(g*.2),totalTokens:p+g,cachedInput:Math.round(p*v/100),uncachedInput:w,cachedPct:v,cost:u===4?0:Number(d),credits:(u===4?0:Number(d))*25,duration:String(f),durationSeconds:Number.parseFloat(String(f))||0,previousCallGap:u===0?"-":`${u*7}m 0s`,previousCallEventTimestamp:u===0?"":`2026-06-01T09:${String(40+u).padStart(2,"0")}:00Z`,previousCallGapSeconds:u*420,initiator:u%3===0?"user":u%3===1?"assistant":"tool",initiatorReason:u%3===0?"direct user request":u%3===1?"assistant follow-up":"tool-driven continuation",initiatorConfidence:u%2===0?"exact":"estimated",serviceTier:"",fast:null,serviceTierSource:"",serviceTierConfidence:"",fastProxyCandidate:!!h,standardUsageCredits:(u===4?0:Number(d))*25,usageCreditMultiplier:1,usageCreditMultiplierSource:"tier_unknown",usageCreditConfidence:u===7?"user_override":u%4===0?"exact":u%4===1?"estimated":u%4===2?"missing":"fixture",usageCreditModel:u===4?"":`${a}-credits`,usageCreditSource:u===4?"":"fixture-rate-card",usageCreditFetchedAt:u===4?"":"2026-06-01T10:00:00Z",usageCreditTier:u%2===0?"standard":"estimated",usageCreditNote:u===2?"fixture inherited rate card":"",pricingModel:u===4?"":`${a}-pricing`,pricingEstimated:u===1||u===5,signal:w>5e4?"cache-risk":"aggregate",recommendation:w>5e4?"Review uncached aggregate input before continuing this thread.":"",tags:b,sessionId:`fixture-session-${u}`,turnId:`fixture-turn-${u}`,parentSessionId:u%3===0?"fixture-parent-session":"",parentSessionUpdatedAt:u%3===0?"2026-06-01T09:30:00Z":"",parentThread:u%3===0?"parent-thread-analysis":"",threadAttachmentLabel:u%3===0?"spawned child thread":"direct active thread",threadSource:u%3===0?"subagent":"user",subagentType:u%3===0?"analysis":"",agentRole:u%3===0?"reviewer":"",agentNickname:u%3===0?"usage-reviewer":"",project:u%2===0?"codex-usage-tracker":"local-ops",projectRelativeCwd:u%2===0?"frontend/dashboard":".",projectTags:u%2===0?["dashboard","rewrite"]:["local"],cwd:`/fixtures/${u%2===0?"codex-usage-tracker":"local-ops"}`,sourceFile:`fixture-thread-${u}.jsonl`,lineNumber:120+u,gitBranch:"experiment/frontend-rewrite",gitRemoteLabel:"origin",gitRemoteHash:`fixture-${u}`,contextWindowPct:Math.min(18+v,96),modelContextWindow:128e3,cumulativeTotalTokens:p+g+u*1e4,estimatedCacheSavings:Math.round((p-w)*1e-5*100)/100,efficiencyFlags:w>5e4?["cache-risk"]:[]}}),threads:[["thread-9f3a",142,58400,8.76,12,1.38,"High",42],["thread-7c2b",87,31200,4.21,22,1.12,"Medium",55],["thread-1a8c",64,22700,3.02,18,.98,"High",48],["thread-d3e1",53,18100,2.11,41,.81,"Low",72],["thread-b7f0",41,13600,1.65,47,.73,"Low",75],["thread-3c5d",36,9900,1.18,35,.66,"Medium",63],["thread-0e16",28,6400,.72,56,.58,"Low",82]].map(([e,t,n,a,r,s,i,o],d)=>{const f=Number(t),h=Number(n),b=Number(r),u=f*48,p=(d+1)*420;return{name:String(e),latestCallId:`fixture-call-${d}`,latestActivity:`Jun ${d+1}, 10:${String(24-d).padStart(2,"0")} AM`,latestActivityRaw:`2026-06-${String(d+1).padStart(2,"0")}T10:${String(24-d).padStart(2,"0")}:00Z`,turns:f,totalDurationSeconds:u,totalDuration:`${Math.floor(u/60)}m ${u%60}s`,averageGapSeconds:p,averageGap:`${Math.floor(p/60)}m ${p%60}s`,initiatorSummary:d%2===0?"user x4, assistant x2":"assistant x3, tool x1",modelSummary:d%2===0?"codex-1 x5, o4-mini x2":"o4-mini x3, o3 x1",effortSummary:d%2===0?"high x5, medium x2":"medium x3, low x1",totalTokens:h,cachedInput:Math.round(h*b/100),uncachedInput:Math.round(h*Math.max(100-b,0)/100),outputTokens:Math.round(h*.28),reasoningOutput:Math.round(h*.08),cost:Number(a),credits:Number(a)*25,cachePct:b,contextPct:Math.min(96,28+d*7),costPerCall:Number(s),coldResumeRisk:i,productivity:Number(o)}}),weeklyWindows:Mt.map((e,t)=>({week:e,plan:t===0?"Prolite":"Pro",observedPct:[61.4,49.2,47.7,48.3,44.5,37.4,40.1,35.8][t]??0,credits:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,projected:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,ciLow:[42156,34892,33424,34021,31241,26164,28234,29450][t]??0,ciHigh:[57467,47657,46349,47105,43326,36676,39450,41900][t]??0,confidence:t===0?"Medium":"High",note:["Prolite baseline","Drop in credits","Stable","Slight uptick","Down again","Lowest window","Recovery","Latest"][t]??""})),modelCosts:[{label:"codex-1",value:16.21,color:"#2563eb"},{label:"o3",value:12.43,color:"#1d4ed8"},{label:"o4-mini",value:7.62,color:"#059669"},{label:"gpt-4.1",value:4.91,color:"#f59e0b"},{label:"other",value:1.5,color:"#94a3b8"}],commandActions:[{title:"Show highest uncached calls",status:"Ready",owner:"Calls",description:"214 calls above the uncached threshold."},{title:"Compare Pro weeks",status:"Ready",owner:"Usage Drain",description:"Allowance windows with confidence intervals."},{title:"Find cold resumes",status:"Ready",owner:"Cache",description:"14 threads with long idle gaps."},{title:"Export support bundle",status:"Planned",owner:"Reports",description:"Local aggregate artifacts only."}],cacheSegments:[{label:"Cache read",value:38.7,color:"#2563eb"},{label:"Cache write",value:29.6,color:"#059669"},{label:"Uncached",value:31.7,color:"#7c3aed"}],cacheHeatmap:[{thread:"thread-8c1e",labels:it,values:[62,71,89,82,74,31]},{thread:"thread-2b9d",labels:it,values:[42,58,77,61,51,24]},{thread:"thread-713a",labels:it,values:[78,81,83,66,59,37]},{thread:"thread-4af2",labels:it,values:[24,36,63,54,71,44]},{thread:"thread-f9c3",labels:it,values:[18,25,41,38,52,22]}],diagnostics:[{title:"Usage Drain",status:"Ready",finding:"Projected weekly credits declined from the baseline and partially recovered in the latest window.",confidence:"High",metric:"33,842 credits / week",series:[W("usage-drain","Projected credits","#2563eb",[41.8,46.7,45.9,32.1,33.8],1e3)]},{title:"Cache Behavior",status:"Ready",finding:"Cache hit rate is healthy overall, with spikes aligned to large cache misses and cold resumes.",confidence:"Medium",metric:"41.1% hit rate",series:[W("cache","Cache hit %","#059669",[44,48,38,33,40])]},{title:"Thread Efficiency",status:"Ready",finding:"Long threads account for most estimated cost and are the clearest optimization target.",confidence:"High",metric:"65% cost share",series:[W("threads","Cost share","#1d4ed8",[65,23,8,4])]},{title:"Tool And Command Activity",status:"Stale",finding:"Command volume is stable with a slight upward trend; read and shell commands dominate.",confidence:"Medium",metric:"912 commands",series:[W("commands","Commands","#7c3aed",[542,488,611,883,912])]}],reports:[{title:"Weekly Credits",status:"Ready",owner:"Usage Drain",description:"Plan-specific weekly credits, trend lines, and confidence intervals."},{title:"Usage Remaining",status:"Ready",owner:"Usage Drain",description:"Observed remaining usage over time with reset handling."},{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Cumulative estimated cost by thread and concentration metrics."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Actual-vs-predicted drain and feature group comparisons."},{title:"Fast Mode Proxy",status:"Planned",owner:"Calls",description:"Candidate detection, speedup histogram, and confidence breakdowns."},{title:"Allowance Change",status:"Planned",owner:"Reports",description:"Week-to-week allowance estimate changes with careful language."}]};function W(e,t,n,a,r=1,s=!1){return{id:e,label:t,color:n,dashed:s,points:a.map((i,o)=>({label:Mt[o]??`Point ${o+1}`,value:i*r}))}}function rr(e){if(window.location.protocol==="file:")throw new Error("Live refresh requires the localhost dashboard server.");if(!(e!=null&&e.api_token))throw new Error("Live refresh requires localhost dashboard API token.")}function gn(e){return{Accept:"application/json","X-Codex-Usage-Token":e.api_token||""}}function oo(e,t){return new Promise((n,a)=>{if(t!=null&&t.aborted){a(ta(t));return}const r=window.setTimeout(()=>{t==null||t.removeEventListener("abort",s),n()},e);function s(){window.clearTimeout(r),a(ta(t))}t==null||t.addEventListener("abort",s,{once:!0})})}function sr(e){return(e instanceof DOMException||e instanceof Error)&&e.name==="AbortError"}function ta(e){return(e==null?void 0:e.reason)instanceof Error?e.reason:new DOMException("The request was cancelled.","AbortError")}const co=["#2563eb","#1d4ed8","#059669","#f59e0b","#94a3b8"];function ir(e){const t=new Map;e.forEach(r=>{const s=r.model||"unknown";t.set(s,(t.get(s)??0)+r.cost)});const n=[...t.entries()].sort((r,s)=>s[1]-r[1]||r[0].localeCompare(s[0]));return(n.length>5?[...n.slice(0,4),["other",n.slice(4).reduce((r,s)=>r+s[1],0)]]:n).map(([r,s],i)=>({label:r,value:s,color:co[i]??"#94a3b8"}))}function or(e){if(!e.length)return[];const t=Math.max(e.reduce((n,a)=>n+vt(a),0),1);return[lo(e,t),uo(e,t),ho(e,t),fo(e,t)].filter(n=>!!n).sort((n,a)=>a.credits-n.credits).map((n,a)=>({...n,rank:a+1}))}function cr(e){if(!e.length)return[];const t=[{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Estimated cost concentration by loaded aggregate thread."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Highest estimated credit-impact calls from loaded aggregate rows."}];return e.some(n=>n.fastProxyCandidate||n.effort.toLowerCase()==="low")&&t.push({title:"Fast Mode Proxy",status:"Ready",owner:"Calls",description:"Low-effort and fast-call candidates inferred from aggregate rows."}),t}function lo(e,t){const n=new Map;e.forEach(i=>n.set(i.thread,[...n.get(i.thread)??[],i]));const[a,r]=[...n.entries()].sort((i,o)=>Ae(o[1],f=>f.totalTokens)-Ae(i[1],f=>f.totalTokens)||o[1].length-i[1].length)[0]??[];if(!a||!(r!=null&&r.length)||r.length<2)return null;const s=Ae(r,vt);return{rank:0,title:`Long Thread: ${a}`,severity:s/t>=.25||r.length>=8?"High":"Medium",credits:Math.round(s),share:s/t*100,summary:`${r.length.toLocaleString()} loaded calls and ${Ae(r,i=>i.totalTokens).toLocaleString()} tokens in this thread.`}}function uo(e,t){const n=e.filter(r=>r.signal==="cache-risk"||r.cachedPct<35||r.uncachedInput>5e4);if(!n.length)return null;const a=Ae(n,vt);return{rank:0,title:"Cache Misses (Large Inputs)",severity:n.some(r=>r.cachedPct<20||r.uncachedInput>5e4)?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls show low cache reuse or large uncached input.`}}function ho(e,t){const n=e.filter(r=>r.effort.toLowerCase()==="high"||r.reasoningOutput>0);if(!n.length)return null;const a=Ae(n,vt);return{rank:0,title:"High Model Effort",severity:a/t>=.25?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls use high effort or report reasoning output.`}}function fo(e,t){const n=Math.max(25e3,mo(e.map(s=>s.output),.75)),a=e.filter(s=>s.output>=n||s.tags.some(i=>["file-heavy","subagent","large"].includes(i)));if(!a.length)return null;const r=Ae(a,vt);return{rank:0,title:"Tool Output Volume",severity:a.some(s=>s.output>5e4)?"High":"Medium",credits:Math.round(r),share:r/t*100,summary:`${a.length.toLocaleString()} loaded calls have high output volume or file-heavy/subagent tags.`}}function vt(e){return e.credits>0?e.credits:e.cost*25}function Ae(e,t){return e.reduce((n,a)=>n+t(a),0)}function mo(e,t){const n=e.filter(a=>Number.isFinite(a)).sort((a,r)=>a-r);return n.length?n[Math.min(n.length-1,Math.max(0,Math.floor((n.length-1)*t)))]??0:0}function lr(e){const t=new Map;for(const a of e){if(!Number.isFinite(a.timestamp))continue;const r=ur(a.timestamp),s=t.get(r)??{label:dr(a.timestamp),timestamp:po(a.timestamp),cached:0,cost:0,input:0,output:0};s.cached+=a.cached,s.cost+=a.cost,s.input+=a.input,s.output+=a.output,t.set(r,s)}const n=go(t);return n.length?{tokenSeries:[{id:"input",label:"Input",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input}))},{id:"output",label:"Output",color:"#059669",points:n.map(a=>({label:a.label,value:a.output}))},{id:"cached",label:"Cached",color:"#7c3aed",dashed:!0,points:n.map(a=>({label:a.label,value:a.cached}))}],costSeries:[{id:"cost",label:"Estimated Cost",color:"#f59e0b",points:n.map(a=>({label:a.label,value:a.cost}))}],cacheSeries:[{id:"cache",label:"Cache hit %",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input>0?a.cached/a.input*100:0}))}]}:{tokenSeries:[],costSeries:[],cacheSeries:[]}}function go(e){const t=[...e.values()].sort((s,i)=>s.timestamp-i.timestamp),n=t.at(0),a=t.at(-1);if(!n||!a)return[];const r=[];for(const s=new Date(n.timestamp);s.getTime()<=a.timestamp;s.setDate(s.getDate()+1)){const i=s.getTime(),o=ur(i);r.push(e.get(o)??{label:dr(i),timestamp:i,cached:0,cost:0,input:0,output:0})}return r}function ur(e){const t=new Date(e),n=String(t.getMonth()+1).padStart(2,"0"),a=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${n}-${a}`}function po(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}function dr(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function Q(e,t){var a;const n=Number(((a=e.summary)==null?void 0:a[t])??0);return Number.isFinite(n)?n:0}function vo(e){if(!(!e.summary||e.load_window==="rows"))return{visibleCalls:Q(e,"visible_calls"),inputTokens:Q(e,"input_tokens"),cachedInputTokens:Q(e,"cached_input_tokens"),uncachedInputTokens:Q(e,"uncached_input_tokens"),outputTokens:Q(e,"output_tokens"),reasoningOutputTokens:Q(e,"reasoning_output_tokens"),totalTokens:Q(e,"total_tokens"),estimatedCostUsd:Q(e,"estimated_cost_usd"),usageCredits:Q(e,"usage_credits")}}function bo(e,t,n){const a=e.fast,r=a===!0||a===1?!0:a===!1||a===0?!1:null;return{credits:Number(e.usage_credits??0),serviceTier:String(e.service_tier??""),fast:r,serviceTierSource:String(e.service_tier_source??""),serviceTierConfidence:String(e.service_tier_confidence??""),fastProxyCandidate:t>0&&n/Math.max(t,1)>4e3,standardUsageCredits:Number(e.standard_usage_credits??e.usage_credits??0),usageCreditMultiplier:Number(e.usage_credit_multiplier??1),usageCreditMultiplierSource:String(e.usage_credit_multiplier_source??"")}}const wo=1e4,yo=500;async function na(e,t,n){var s,i;const a=t.limit&&t.limit>0?t.limit:yo,r=await n(e,{...t,limit:a});return(i=t.onProgress)==null||i.call(t,{status:"completed",phase:"loading_rows",message:`Loaded ${t.loadWindow==="all"?"all-history":t.loadWindow} evidence window`,completed:Number(r.loaded_row_count??((s=r.rows)==null?void 0:s.length)??0),total:Number(r.total_available_rows??r.loaded_row_count??0),percent:100}),r}async function aa(e,t,n){var o,d;const a=[];let r=0,s=null,i=Number((e==null?void 0:e.total_available_rows)??0);for(let f=0;f<1e3;f+=1){(o=t.signal)==null||o.throwIfAborted();const h=await n(e,{...t,refresh:f===0?t.refresh:!1,limit:wo,offset:r}),b=h.rows??[];s=h,a.push(...b),i=Number(h.total_available_rows??i??a.length);const u=a.length>=i||!h.has_more;if((d=t.onProgress)==null||d.call(t,{status:u?"completed":"running",phase:"loading_rows",message:"Loading all rows",completed:a.length,total:i,percent:u?100:i>0?Math.min(99,Math.floor(a.length/i*100)):0}),r+=b.length,!h.has_more||b.length===0||a.length>=i)break}return{...s??e??{},rows:a,loaded_row_count:a.length,limit:null,limit_label:"All",has_more:!1,total_available_rows:i||a.length}}function _o(){if(window.__CODEX_USAGE_BOOT__)return window.__CODEX_USAGE_BOOT__;const e=document.getElementById("usage-data");if(!(e!=null&&e.textContent))return null;try{return JSON.parse(e.textContent)}catch{return null}}async function So(e,t={}){if(t.refresh&&(e!=null&&e.refresh_jobs_available)){const n=await Co(e,t),a={...t,refresh:!n};return a.loadWindow&&a.loadWindow!=="rows"?na(e,a,He):a.limit===0?aa(e,a,He):He(e,a)}return t.loadWindow&&t.loadWindow!=="rows"?na(e,t,He):t.limit===0?aa(e,t,He):He(e,t)}async function Co(e,t){try{return await xo(e,t),!0}catch(n){if(sr(n)||n instanceof hr)throw n;return!1}}async function He(e,t={}){rr(e);const n=new URLSearchParams({refresh:t.refresh?"1":"0",limit:String(t.limit??(e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??500),_:String(Date.now())});t.loadWindow&&n.set("load_window",t.loadWindow),t.since&&n.set("since",t.since),t.offset&&t.offset>0&&n.set("offset",String(t.offset)),(t.includeArchived??wr(e))&&n.set("include_archived","1");const r=await fetch(`/api/usage?${n.toString()}`,{headers:gn(e),cache:"no-store",signal:t.signal});return await pn(r,"Usage refresh")}async function xo(e,t){var o;rr(e);const n=new URLSearchParams({_:String(Date.now())});(t.includeArchived??wr(e))&&n.set("include_archived","1");const r=await fetch(`/api/refresh/start?${n.toString()}`,{headers:gn(e),cache:"no-store",signal:t.signal}),s=await pn(r,"Usage refresh start");(o=t.onProgress)==null||o.call(t,s);const i=typeof s.job_id=="string"?s.job_id:"";if(!i)throw new Error("Usage refresh start did not return a job id.");return ko(e,i,t.onProgress,t.signal)}async function ko(e,t,n,a){for(let r=0;r<600;r+=1){a==null||a.throwIfAborted();const s=new URLSearchParams({job_id:t,_:String(Date.now())}),i=await fetch(`/api/refresh/status?${s.toString()}`,{headers:gn(e),cache:"no-store",signal:a}),o=await pn(i,"Usage refresh status");if(n==null||n(o),o.status==="completed")return o;if(o.status==="failed")throw new hr(o.error||o.message||"Usage refresh failed.");await oo(Math.min(1e3,150+r*50),a)}throw new Error("Usage refresh did not complete before the polling timeout.")}class hr extends Error{}function ra(e){if(!e)return{...ar,contextRuntime:rn(e)};const t=e.rows??[],n=t.map(mr),a=t.length?Te(t,v=>Number(v.total_tokens??0)):Q(e,"total_tokens"),r=t.length?Te(t,v=>Number(v.estimated_cost_usd??0)):Q(e,"estimated_cost_usd"),s=t.length?Te(t,v=>Number(v.cached_input_tokens??0)):Q(e,"cached_input_tokens"),i=t.length?Te(t,v=>Number(v.input_tokens??0)):Q(e,"input_tokens"),o=t.length?Te(t,v=>{const w=Number(v.input_tokens??0),T=Number(v.cached_input_tokens??0);return Number(v.uncached_input_tokens??Math.max(w-T,0))}):Math.max(i-s,0),d=t.length?Te(t,v=>Number(v.output_tokens??0)):Q(e,"output_tokens"),f=t.length?Te(t,v=>Number(v.reasoning_output_tokens??0)):Q(e,"reasoning_output_tokens"),h=i>0?s/i*100:0,b=n.length||Math.max(0,Number(e.loaded_row_count??0)),u=Lo(t),p=Ro(t),g=Ao({cachePct:h,cachedTokens:s,estimatedCost:r,historyScope:e.history_scope??"active",totalCalls:b,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:o,output:d,reasoningOutput:f},usageRemainingCard:No(e)});return{...To(e),contextRuntime:rn(e),scopeSummary:vo(e),cards:g,...u,...p,calls:n,threads:yr(n),findings:or(n),modelCosts:ir(n),reports:cr(n),cacheSegments:[{label:"Cache read",value:h,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-h,0),color:"#7c3aed"}]}}function To(e){return{...ar,contextRuntime:rn(e),tokenSeries:[],costSeries:[],cacheSeries:[],weeklyCreditSeries:[],usageRemainingSeries:[],actualVsPredictedSeries:[],calls:[],threads:[],findings:[],weeklyWindows:[],modelCosts:[],commandActions:[],cacheSegments:[],cacheHeatmap:[],diagnostics:[],reports:[]}}function Lo(e){return lr(e.map(t=>({timestamp:bn(t),cached:Number(t.cached_input_tokens??0),cost:Number(t.estimated_cost_usd??0),input:Number(t.input_tokens??0),output:Number(t.output_tokens??0)})))}function Ro(e){const t=[...e].map(f=>({row:f,timestamp:bn(f)})).filter(f=>Number.isFinite(f.timestamp)).sort((f,h)=>f.timestamp-h.timestamp),n=new Map;for(const{row:f,timestamp:h}of t){const b=an(h),u=n.get(b)??{timestamp:h,credits:0,weeklyUsedPercent:null};u.credits+=Math.max(0,Number(f.usage_credits??0));const p=Oe(f.rate_limit_secondary_used_percent);p!==null&&(u.weeklyUsedPercent=p),n.set(b,u)}const a=[...n.entries()].map(([f,h])=>({label:f,...h}));let r=0;const s=a.map(f=>(r+=f.credits,{label:f.label,value:r})),i=s.map((f,h)=>{var b;return{label:f.label,value:s.length>1?(((b=s.at(-1))==null?void 0:b.value)??0)*((h+1)/s.length):f.value}}),o=a.filter(f=>f.weeklyUsedPercent!==null).map(f=>({label:f.label,value:Pt(100-(f.weeklyUsedPercent??0))})),d=Mo(e);return{weeklyCreditSeries:Po(d),usageRemainingSeries:o.length?[{id:"weekly-remaining",label:"Weekly remaining",color:"#059669",points:o}]:[],actualVsPredictedSeries:s.length?[{id:"observed-drain",label:"Observed drain",color:"#2563eb",points:s},{id:"loaded-baseline",label:"Loaded-row baseline",color:"#1d4ed8",dashed:!0,points:i}]:[],weeklyWindows:d}}function Mo(e){const t=new Map;for(const n of e){const a=bn(n);if(!Number.isFinite(a))continue;const r=jo(n,a),s=t.get(r)??{rows:[],latestTimestamp:0,latestUsedPercent:null};s.rows.push(n),a>=s.latestTimestamp&&(s.latestTimestamp=a,s.latestUsedPercent=Oe(n.rate_limit_secondary_used_percent)),t.set(r,s)}return[...t.entries()].map(([n,a])=>{var i;const r=a.rows.reduce((o,d)=>o+Math.max(0,Number(d.usage_credits??0)),0),s=a.latestUsedPercent??0;return{week:n,plan:String(((i=a.rows[0])==null?void 0:i.rate_limit_plan_type)??"unknown"),observedPct:s,credits:r,projected:s>0?r/(s/100):r,ciLow:s>0?r/(s/100)*.85:r,ciHigh:s>0?r/(s/100)*1.15:r,confidence:a.rows.length>=20?"Medium":"Low",note:`Loaded ${vn(a.rows.length)} rows`}}).sort((n,a)=>n.week.localeCompare(a.week))}function Po(e){return e.length?[{id:"weekly-projected",label:"Projected weekly credits",color:"#2563eb",points:e.map(t=>({label:t.week,value:t.projected,low:t.ciLow,high:t.ciHigh}))},{id:"loaded-credits",label:"Loaded-row credits",color:"#0f766e",dashed:!0,points:e.map(t=>({label:t.week,value:t.credits}))}]:[]}function jo(e,t){const n=Qe(e.rate_limit_secondary_resets_at);return n!==null&&n>0?an(n*1e3):an(t)}function an(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function rn(e){return{apiToken:String((e==null?void 0:e.api_token)??""),contextApiEnabled:!!(e!=null&&e.context_api_enabled),fileMode:window.location.protocol==="file:"}}function Ao(e){return[{label:"Total Tokens",value:Me(e.totalTokens),detail:`${e.historyScope} history scope`,trend:"loaded aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Me(e.tokenBreakdown.cachedInput)},{label:"Uncached",value:Me(e.tokenBreakdown.uncachedInput)},{label:"Output",value:Me(e.tokenBreakdown.output)},{label:"Reasoning",value:Me(e.tokenBreakdown.reasoningOutput)}]},{label:"Estimated Cost",value:Uo(e.estimatedCost),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.cachePct.toFixed(1)}%`,detail:`${Me(e.cachedTokens)} cached input`,trend:e.cachePct>=40?"healthy cache reuse":"cache risk",tone:e.cachePct>=40?"purple":"orange"},{label:"Total Calls",value:vn(e.totalCalls),detail:"loaded calls in this dashboard",trend:"privacy-safe",tone:"blue"},e.usageRemainingCard]}function No(e){const t=Eo(e.observed_usage);if(t)return t;const n=Do(e.allowance_windows);return n||{label:"Usage Remaining",value:"Unknown",detail:e.allowance_configured?"allowance configured; no current window":"no observed usage or allowance window",trend:e.allowance_error?`config issue: ${e.allowance_error}`:"not available in payload",tone:e.allowance_error?"red":"orange"}}function Eo(e){const t=Array.isArray(e==null?void 0:e.windows)?e.windows:[];if(!(e!=null&&e.available)||!t.length)return null;const n=fr(t,s=>Oe(s.used_percent)!==null);if(!n)return null;const a=Oe(n.used_percent)??0,r=Pt(100-a);return{label:"Usage Remaining",value:gr(r),detail:`${vr(n.label||n.key,"Observed usage")} observed usage`,trend:pr(n.resets_at)||e.source||"observed locally",tone:br(r)}}function Do(e){if(!Array.isArray(e)||!e.length)return null;const t=fr(e,o=>{const d=Oe(o.remaining_percent),f=Qe(o.remaining_credits),h=Qe(o.total_credits);return d!==null||f!==null||h!==null&&h>0});if(!t)return null;const n=Qe(t.remaining_credits),a=Qe(t.total_credits),r=n!==null&&a!==null&&a>0?n/a*100:null,s=Oe(t.remaining_percent)??r;return{label:"Usage Remaining",value:s!==null?gr(Pt(s)):`${sa(n??0)} left`,detail:`${vr(t.label||t.key,"Allowance")} allowance window`,trend:[n===null?"":`${sa(n)} left`,pr(t.reset_at)].filter(Boolean).join(" · ")||"configured allowance",tone:s===null?"green":br(Pt(s))}}function fr(e,t){const n=e.filter(t);return n.find(Fo)??n[0]??null}function Fo(e){const t=Qe(e.window_minutes),n=`${e.key??""} ${e.label??""}`.toLowerCase();return t===10080||/\b(weekly|week|7d|7-day|7 day)\b/.test(n)}function mr(e,t=0){const n=String(e.event_timestamp??e.time??e.turn_timestamp??e.started_at??e.call_started_at??""),a=n,r=String(e.call_started_at??e.started_at??n),s=Number(e.input_tokens??0),i=Number(e.output_tokens??0),o=Number(e.reasoning_output_tokens??0),d=Number(e.cached_input_tokens??0),f=Number(e.cache_hit_ratio??e.cache_ratio??0),h=s>0?d/s*100:f*100,b=Number(e.total_tokens??s+i),u=Number(e.duration_seconds??e.call_duration_seconds??0),p=String(e.previous_call_event_timestamp??""),g=Number(e.previous_call_delta_seconds??0),v=Number(e.uncached_input_tokens??Math.max(s-d,0)),w=String(e.record_id??e.id??`${a||"row"}-${t}`),T=String(e.primary_signal??"").trim(),N=Number(e.line_number),R=Oe(e.context_window_percent),_=Number(e.model_context_window),L=Number(e.cumulative_total_tokens);return{id:w,threadKey:String(e.thread_key??""),rawTime:a,eventTimestamp:n,callStartedAt:r,time:_r(a),thread:$o(e),model:String(e.model??"unknown"),effort:String(e.effort??"blank"),input:s,output:i,reasoningOutput:o,totalTokens:b,cachedInput:d,uncachedInput:v,cachedPct:h,cost:Number(e.estimated_cost_usd??0),duration:jt(u),durationSeconds:u,previousCallGap:jt(g),previousCallEventTimestamp:p,previousCallGapSeconds:Number.isFinite(g)?g:0,initiator:String(e.call_initiator??"unknown"),initiatorReason:String(e.call_initiator_reason??""),initiatorConfidence:String(e.call_initiator_confidence??""),...bo(e,u,b),usageCreditConfidence:String(e.usage_credit_confidence??"unknown"),usageCreditModel:String(e.usage_credit_model??""),usageCreditSource:String(e.usage_credit_source??""),usageCreditFetchedAt:String(e.usage_credit_fetched_at??""),usageCreditTier:String(e.usage_credit_tier??""),usageCreditNote:String(e.usage_credit_note??""),pricingModel:String(e.pricing_model??""),pricingEstimated:!!e.pricing_estimated,signal:T||(h<25?"cache-risk":"aggregate"),recommendation:String(e.recommended_action??""),tags:h<25?["uncached"]:h>60?["healthy-cache"]:[],sessionId:String(e.session_id??""),turnId:String(e.turn_id??""),parentSessionId:String(e.parent_session_id??""),parentSessionUpdatedAt:String(e.resolved_parent_session_updated_at??e.parent_session_updated_at??""),parentThread:String(e.resolved_parent_thread_name??e.parent_thread_name??""),threadAttachmentLabel:String(e.thread_attachment_label??""),threadSource:String(e.thread_source??""),subagentType:String(e.subagent_type??""),agentRole:String(e.agent_role??""),agentNickname:String(e.agent_nickname??""),project:String(e.project_name??""),projectRelativeCwd:String(e.project_relative_cwd??""),projectTags:Array.isArray(e.project_tags)?e.project_tags.map(y=>String(y)):[],cwd:String(e.cwd??""),sourceFile:String(e.source_file??""),lineNumber:Number.isFinite(N)&&N>0?N:null,gitBranch:String(e.git_branch??""),gitRemoteLabel:String(e.git_remote_label??""),gitRemoteHash:String(e.git_remote_hash??""),contextWindowPct:R,modelContextWindow:Number.isFinite(_)&&_>0?_:null,cumulativeTotalTokens:Number.isFinite(L)&&L>0?L:null,estimatedCacheSavings:Number(e.estimated_cache_savings_usd??0),efficiencyFlags:Array.isArray(e.efficiency_flags)?e.efficiency_flags.map(y=>String(y)):[]}}function Oe(e){const t=Number(e);return Number.isFinite(t)?t<=1?t*100:t:null}function Qe(e){const t=Number(e);return Number.isFinite(t)?t:null}function Pt(e){return Math.max(0,Math.min(100,e))}function gr(e){const t=Math.abs(e)>=10?0:1;return`${e.toFixed(t)}%`}function sa(e){return`${Me(e)} cr`}function pr(e){if(e==null||e==="")return"";const t=typeof e=="number"?e*1e3:Date.parse(e);return Number.isFinite(t)?`resets ${Io(t)}`:""}function Io(e){const t=new Date(e);return Number.isNaN(t.getTime())?String(e):`${t.toISOString().slice(0,16).replace("T"," ")} UTC`}function vr(e,t){return(e==null?void 0:e.trim())||t}function br(e){return e<20?"red":e<40?"orange":"green"}function wr(e){return typeof e.include_archived=="boolean"?e.include_archived:e.history_scope==="all-history"||e.history_scope==="all"}function $o(e){const t=e.thread_name??e.thread??e.resolved_parent_thread_name??e.parent_thread_name;if(t&&String(t).trim())return String(t);const n=e.project_name??e.project_relative_cwd,a=e.session_id?e.session_id.slice(-6):"";return n&&a?`${n} ${a}`:e.thread_attachment_label?String(e.thread_attachment_label):"Untitled thread"}function yr(e){const t=new Map;for(const n of e)t.set(n.thread,[...t.get(n.thread)??[],n]);return[...t.entries()].map(([n,a])=>{const r=a.length,i=[...a].sort((y,k)=>ia(k)-ia(y))[0]??null,o=(i==null?void 0:i.rawTime)||(i==null?void 0:i.time)||"",d=a.reduce((y,k)=>y+k.totalTokens,0),f=a.reduce((y,k)=>y+k.cachedInput,0),h=a.reduce((y,k)=>y+k.uncachedInput,0),b=a.reduce((y,k)=>y+k.output,0),u=a.reduce((y,k)=>y+k.reasoningOutput,0),p=a.reduce((y,k)=>y+k.cost,0),g=a.reduce((y,k)=>y+k.credits,0),v=a.reduce((y,k)=>y+k.durationSeconds,0),w=a.filter(y=>y.previousCallGapSeconds>0),T=w.reduce((y,k)=>y+k.previousCallGapSeconds,0)/Math.max(w.length,1),N=f+h,R=N>0?f/N*100:a.reduce((y,k)=>y+k.cachedPct,0)/Math.max(r,1),_=a.map(y=>y.contextWindowPct).filter(y=>typeof y=="number"&&Number.isFinite(y)),L=R<25?"High":R<45?"Medium":"Low";return{name:n,latestCallId:(i==null?void 0:i.id)??"",latestActivity:_r(o),latestActivityRaw:o,turns:r,totalDurationSeconds:v,totalDuration:jt(v),averageGapSeconds:T,averageGap:jt(T),initiatorSummary:zt(a.map(y=>y.initiator)),modelSummary:zt(a.map(y=>y.model)),effortSummary:zt(a.map(y=>y.effort)),totalTokens:d,cachedInput:f,uncachedInput:h,outputTokens:b,reasoningOutput:u,cost:p,credits:g,cachePct:R,contextPct:_.length?Math.max(..._):null,costPerCall:p/Math.max(r,1),coldResumeRisk:L,productivity:Math.max(20,Math.round(R-p/Math.max(r,1)*4))}}).sort((n,a)=>a.cost-n.cost).slice(0,20)}function ia(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function zt(e,t=3){const n=new Map;for(const a of e){const r=a.trim()||"unknown";n.set(r,(n.get(r)??0)+1)}return[...n.entries()].sort((a,r)=>r[1]-a[1]||a[0].localeCompare(r[0])).slice(0,t).map(([a,r])=>`${a} x${vn(r)}`).join(", ")||"unknown"}function Te(e,t){return e.reduce((n,a)=>n+t(a),0)}async function pn(e,t){let n;try{n=await e.json()}catch(a){if(e.ok)throw new Error(`${t} response could not be read as JSON: ${Oo(a)}`);n={}}if(!e.ok){const a=typeof n.error=="string"?n.error:`${t} request failed (${e.status})`;throw new Error(a)}return n}function Oo(e){return e instanceof Error?e.message:String(e)}function vn(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Me(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Uo(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function jt(e){if(!Number.isFinite(e)||e<=0)return"-";if(e<60)return`${e.toFixed(0)}s`;const t=Math.floor(e/60),n=Math.round(e%60);return`${t}m ${n}s`}function _r(e){const t=new Date(e);return Number.isNaN(t.getTime())?e||"-":new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).format(t)}function bn(e){return Date.parse(String(e.started_at??e.call_started_at??e.time??e.event_timestamp??e.turn_timestamp??""))}const Pe=1440*60*1e3;function Vo(e,t,n=window.location.search){const a=Sr(n);if(!a.active)return e;const r=e.calls.filter(s=>Ko(s,a));return r.length===e.calls.length?e:Bo(e,r,`${t} filtered`)}function Sr(e){var d,f,h,b,u,p;const t=new URLSearchParams(e),n=((d=t.get("model"))==null?void 0:d.trim())??"",a=((f=t.get("effort"))==null?void 0:f.trim())??"",r=((h=t.get("confidence")||t.get("pricing"))==null?void 0:h.trim())??"",s=((b=t.get("date")||t.get("time"))==null?void 0:b.trim())??"",i=((u=t.get("from"))==null?void 0:u.trim())??"",o=((p=t.get("to"))==null?void 0:p.trim())??"";return{model:n,effort:a,confidence:r,datePreset:s,dateStart:i,dateEnd:o,active:!!(n||a||r||s||i||o)}}function Ko(e,t){return!(t.model&&e.model!==t.model||t.effort&&e.effort!==t.effort||t.confidence&&!qo(e,t.confidence)||!Ho(e,t))}function qo(e,t){return t==="official"||t==="cost-exact"?!!(e.pricingModel&&!e.pricingEstimated):t==="estimated"||t==="cost-estimated"?e.pricingEstimated:t==="unpriced"||t==="cost-unpriced"?!e.pricingModel:t==="credit-exact"?e.usageCreditConfidence==="exact":t==="credit-estimated"?e.usageCreditConfidence==="estimated":t==="credit-override"?e.usageCreditConfidence==="user_override":t==="credit-missing"?e.usageCreditConfidence==="missing"||e.usageCreditConfidence==="unknown":!0}function Ho(e,t){const n=Wo(t);if(!n.active)return!0;if(n.invalid)return!1;const a=Date.parse(e.rawTime||e.time);return!(!Number.isFinite(a)||n.start!==null&&a=n.endExclusive)}function Wo(e){if(e.datePreset&&e.datePreset!=="all"&&e.datePreset!=="custom"){const a=Qo(e.datePreset);return a?{active:!0,invalid:!1,...a}:{active:!1,invalid:!1,start:null,endExclusive:null}}const t=oa(e.dateStart),n=oa(e.dateEnd);return t!==null&&n!==null&&t>n?{active:!0,invalid:!0,start:t,endExclusive:n+Pe}:{active:t!==null||n!==null,invalid:!1,start:t,endExclusive:n===null?null:n+Pe}}function Qo(e){const t=zo(new Date);if(e==="today")return{start:t,endExclusive:t+Pe};if(e==="last-7-days")return{start:t-6*Pe,endExclusive:t+Pe};if(e==="this-week"){const a=new Date(t).getDay(),r=a===0?-6:1-a,s=t+r*Pe;return{start:s,endExclusive:s+7*Pe}}if(e==="this-month"){const n=new Date(t),a=new Date(n.getFullYear(),n.getMonth(),1).getTime(),r=new Date(n.getFullYear(),n.getMonth()+1,1).getTime();return{start:a,endExclusive:r}}return null}function oa(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function zo(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function Bo(e,t,n="filtered"){const a=t.reduce((u,p)=>u+p.totalTokens,0),r=t.reduce((u,p)=>u+p.cost,0),s=t.reduce((u,p)=>u+p.cachedInput,0),i=t.reduce((u,p)=>u+p.uncachedInput,0),o=t.reduce((u,p)=>u+p.output,0),d=t.reduce((u,p)=>u+p.reasoningOutput,0),f=t.reduce((u,p)=>u+p.input,0),h=f>0?s/f*100:0,b=e.cards.find(u=>u.label==="Usage Remaining")??{label:"Usage Remaining",value:"Unknown",detail:"not available in filtered view",trend:"not available in payload",tone:"orange"};return{...e,cards:Go({cachePct:h,cachedTokens:s,estimatedCost:r,historyScope:n,totalCalls:t.length,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:i,output:o,reasoningOutput:d},usageRemainingCard:b}),...Jo(t),calls:t,threads:yr(t),findings:or(t),modelCosts:ir(t),reports:cr(t),cacheSegments:[{label:"Cache read",value:h,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-h,0),color:"#7c3aed"}]}}function Go({cachePct:e,cachedTokens:t,estimatedCost:n,historyScope:a,totalCalls:r,totalTokens:s,tokenBreakdown:i,usageRemainingCard:o}){return[{label:"Total Tokens",value:We(s),detail:`${a} history scope`,trend:"filtered aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:We(i.cachedInput)},{label:"Uncached",value:We(i.uncachedInput)},{label:"Output",value:We(i.output)},{label:"Reasoning",value:We(i.reasoningOutput)}]},{label:"Estimated Cost",value:Xo(n),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.toFixed(1)}%`,detail:`${We(t)} cached input`,trend:e>=40?"healthy cache reuse":"cache risk",tone:e>=40?"purple":"orange"},{label:"Total Calls",value:Zo(r),detail:"loaded calls matching filters",trend:"legacy shell filters",tone:"blue"},o]}function Jo(e){return lr(e.map(t=>({timestamp:Date.parse(t.rawTime||t.time),cached:t.cachedInput,cost:t.cost,input:t.input,output:t.output})))}function We(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Zo(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Xo(e){return new Intl.NumberFormat("en-US",{currency:"USD",maximumFractionDigits:2,minimumFractionDigits:2,style:"currency"}).format(e)}const Cr=[{id:"overview",label:"Overview",description:"High-level telemetry",icon:Ds},{id:"investigator",label:"Investigate",description:"Root-cause evidence",icon:Es},{id:"compression-lab",label:"Compression Lab",description:"Context savings",icon:Ls},{id:"calls",label:"Calls",description:"Model-call table",icon:Os},{id:"threads",label:"Threads",description:"Thread efficiency",icon:Ks},{id:"usage-drain",label:"Limits",description:"Allowance intelligence",icon:Vs},{id:"cache-context",label:"Cache And Context",description:"Cache and cold resumes",icon:Ps},{id:"diagnostics",label:"Diagnostics Notebook",description:"Technical report",icon:ks},{id:"reports",label:"Reports",description:"Generated analyses",icon:Rs},{id:"settings",label:"Settings",description:"Local configuration",icon:Is}],xr=[{label:"Files",icon:As,target:"settings"},{label:"Commands",icon:Cs,target:"investigator"},{label:"Models",icon:Ts,target:"calls"}];function kr(e){return ws(e)}const Yo=[{value:"day",label:"24 hours",ariaLabel:"Last 24h"},{value:"week",label:"7 days",ariaLabel:"Last 7 days"},{value:"rows",label:"Recent",ariaLabel:"Recent rows"},{value:"all",label:"All time",ariaLabel:"All time"}];function ec(e){const t=e.refreshing||!e.canUseLiveApi,n=e.loadWindow==="rows",a=`${e.loadedRowCount.toLocaleString()} detail row${e.loadedRowCount===1?"":"s"} cached`,r=n?`${e.loadedRowCount.toLocaleString()} loaded / ${e.totalAvailableRows.toLocaleString()} total`:`${e.totalAvailableRows.toLocaleString()} calls analyzed · ${a}`,s=n?`${e.loadedRowCount.toLocaleString()} of ${e.totalAvailableRows.toLocaleString()} evidence rows loaded`:`Focused pages analyze all ${e.totalAvailableRows.toLocaleString()} calls in scope; ${e.loadedRowCount.toLocaleString()} call rows are cached for immediate detail views.`,i=n?e.rowLoadStatus:`${e.rowLoadModeLabel} analysis uses ${e.totalAvailableRows.toLocaleString()} calls; ${a}`;return c.jsxs("section",{className:"data-window-control","aria-label":"Analysis scope",children:[c.jsxs("div",{className:"data-window-summary",children:[c.jsx("span",{children:"Analysis scope"}),c.jsx("strong",{children:e.rowLoadModeLabel}),c.jsx("small",{title:s,children:r})]}),c.jsx("div",{className:"data-window-options",role:"group","aria-label":"Choose loaded call window",children:Yo.map(o=>c.jsx("button",{type:"button","aria-label":o.ariaLabel,"aria-pressed":e.loadWindow===o.value,disabled:t,onClick:()=>e.onWindowChange(o.value),children:o.label},o.value))}),e.loadWindow==="rows"?c.jsxs("div",{className:"row-window-editor",children:[c.jsx("input",{"aria-label":"Rows to load slider","aria-valuetext":`${e.finitePendingLoadLimit.toLocaleString()} recent rows`,type:"range",min:1,max:e.rowLimitSliderMax,step:100,value:e.rowLimitSliderValue,onChange:o=>e.onSliderChange(o.target.value),disabled:t}),c.jsx("input",{"aria-label":"Rows to load",type:"number",min:1,step:100,value:e.pendingLoadLimit,onChange:o=>e.onDraftChange(o.target.value),disabled:t}),c.jsx("button",{type:"button","data-primary":"true",onClick:e.onApply,disabled:t||!e.rowLimitChanged,children:e.loadLabel}),c.jsx("button",{type:"button",onClick:e.onLoadMore,disabled:t||!e.hasMoreRows,children:e.loadMoreLabel})]}):null,e.refreshing?c.jsxs("div",{className:"row-load-progress","aria-label":"Row loading progress",children:[c.jsx("div",{className:"row-load-progress-track",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":e.refreshProgressPercent??void 0,children:c.jsx("span",{style:{width:`${e.refreshProgressPercent??8}%`}})}),c.jsxs("span",{children:[e.refreshProgressPercent===null?e.refreshProgressText:`${Math.round(e.refreshProgressPercent)}% loaded`,c.jsx("button",{className:"icon-button",type:"button",onClick:()=>void e.onCancel(),"aria-label":"Cancel refresh",title:"Cancel refresh",children:c.jsx(un,{size:13})})]})]}):null,c.jsx("span",{className:"sr-only",role:"status","aria-live":"polite",children:i})]})}const wn=[{value:"all",label:"All time"},{value:"today",label:"Today"},{value:"this-week",label:"This week"},{value:"last-7-days",label:"Last 7 days"},{value:"this-month",label:"This month"},{value:"custom",label:"Custom"}],Tr=[{value:"all",label:"All confidence"},{value:"cost-exact",label:"Exact cost"},{value:"cost-estimated",label:"Estimated cost"},{value:"cost-unpriced",label:"Unpriced cost"},{value:"credit-exact",label:"Exact credit"},{value:"credit-estimated",label:"Estimated credit"},{value:"credit-override",label:"Credit override"},{value:"credit-missing",label:"Missing credit"}];function tc({activeView:e,locationSearch:t,model:n,onUrlChange:a}){const r=Sr(t),s=C.useMemo(()=>ca(n.calls.map(g=>g.model)),[n.calls]),i=C.useMemo(()=>ca(n.calls.map(g=>g.effort)),[n.calls]),o=r.dateStart||r.dateEnd?"custom":nc(r.datePreset),d=rc(r,o);if(e==="calls"||e==="call"||!n.calls.length)return null;function f(g){const v=new URL(window.location.href);g(v),a(v)}function h(g,v){f(w=>{g==="confidence"&&w.searchParams.delete("pricing"),!v||v==="all"?w.searchParams.delete(g):w.searchParams.set(g,v)})}function b(g){f(v=>{if(!g||g==="all"){v.searchParams.delete("date"),v.searchParams.delete("time"),v.searchParams.delete("from"),v.searchParams.delete("to");return}v.searchParams.set("date",g),v.searchParams.set("time",g),g!=="custom"&&(v.searchParams.delete("from"),v.searchParams.delete("to"))})}function u(g,v){f(w=>{v?(w.searchParams.set(g,v),w.searchParams.set("date","custom"),w.searchParams.set("time","custom")):(w.searchParams.delete(g),!w.searchParams.get("from")&&!w.searchParams.get("to")&&(w.searchParams.delete("date"),w.searchParams.delete("time")))})}function p(){f(g=>{for(const v of["model","effort","confidence","pricing","date","time","from","to"])g.searchParams.delete(v)})}return c.jsxs("section",{className:"global-filter-strip span-all","aria-label":"Dashboard filters",children:[c.jsxs("strong",{children:[c.jsx(Ns,{size:15}),"Filters"]}),c.jsxs("label",{children:[c.jsx("span",{children:"Model"}),c.jsxs("select",{"aria-label":"Global model filter",value:r.model||"all",onChange:g=>h("model",g.target.value),children:[c.jsx("option",{value:"all",children:"All models"}),s.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Effort"}),c.jsxs("select",{"aria-label":"Global effort filter",value:r.effort||"all",onChange:g=>h("effort",g.target.value),children:[c.jsx("option",{value:"all",children:"All effort"}),i.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Confidence"}),c.jsx("select",{"aria-label":"Global confidence filter",value:ac(r.confidence),onChange:g=>h("confidence",g.target.value),children:Tr.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Time"}),c.jsx("select",{"aria-label":"Global time filter",value:o,onChange:g=>b(g.target.value),children:wn.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))}),d?c.jsx("span",{className:"filter-status","data-state":d.state,"aria-live":"polite",children:d.label}):null]}),c.jsxs("label",{children:[c.jsx("span",{children:"Start"}),c.jsx("input",{"aria-label":"Global start date",type:"date",value:r.dateStart,onChange:g=>u("from",g.target.value)})]}),c.jsxs("label",{children:[c.jsx("span",{children:"End"}),c.jsx("input",{"aria-label":"Global end date",type:"date",value:r.dateEnd,onChange:g=>u("to",g.target.value)})]}),c.jsxs("button",{className:"toolbar-button",type:"button",disabled:!r.active,onClick:p,children:[c.jsx(un,{size:15}),"Clear filters"]})]})}function ca(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean))).sort((t,n)=>t.localeCompare(n))}function nc(e){return wn.some(t=>t.value===e)?e:"all"}function ac(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":Tr.some(t=>t.value===e)?e:"all"}function rc(e,t){var r;const n=ua(e.dateStart),a=ua(e.dateEnd);if(n!==null&&a!==null&&n>a)return{label:"Invalid date range",state:"error"};if(t==="custom"&&(e.dateStart||e.dateEnd))return{label:sc(e.dateStart,e.dateEnd),state:"active"};if(t!=="all"){const s=((r=wn.find(o=>o.value===t))==null?void 0:r.label)??t,i=ic(t);return{label:i?`${s}: ${la(i.start)} to ${la(ze(i.endExclusive,-1))}`:s,state:"active"}}return null}function sc(e,t){return e&&t?`Custom: ${e} to ${t}`:e?`Custom: from ${e}`:t?`Custom: through ${t}`:"Custom range"}function ic(e){const t=oc();if(e==="today")return{start:t,endExclusive:ze(t,1)};if(e==="this-week"){const n=cc(t);return{start:n,endExclusive:ze(n,7)}}return e==="last-7-days"?{start:ze(t,-6),endExclusive:ze(t,1)}:e==="this-month"?{start:new Date(t.getFullYear(),t.getMonth(),1),endExclusive:new Date(t.getFullYear(),t.getMonth()+1,1)}:null}function oc(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function cc(e){const t=e.getDay();return ze(e,t===0?-6:1-t)}function ze(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function la(e){const t=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${e.getFullYear()}-${t}-${n}`}function ua(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function lc(e){return kr(e)&&e!=="call"}function sn(e,t="overview"){return e==="insights"?"overview":kr(e)?e:t}function da(e=window.location.search,t="calls"){const n=new URLSearchParams(e).get("return"),a=sn(n,t);return lc(a)?a:t}function ha(e=window.location.search){return new URLSearchParams(e).has("return")}function uc(e){var t,n;return((t=Cr.find(a=>a.id===e))==null?void 0:t.label)??((n=xr.find(a=>a.target===e))==null?void 0:n.label)??"Calls"}function fa(e,t=window.location.search){return new URLSearchParams(t).get("history")==="all"?"all":e}function ma(e,t=window.location.href){const n=new URL(t);return e==="all"?n.searchParams.set("history","all"):n.searchParams.delete("history"),n}const dc={investigator:["finding"],threads:["thread","expand","threads","thread_q","risk","thread_call_sort","thread_call_page"],"cache-context":["cache_thread"],reports:["report"],"usage-drain":["usage_plan","usage_effort","usage_subagents","usage_sample","usage_confidence","limit_window","limit_hypothesis"],diagnostics:["diagnostic_source","diagnostic_fact"],calls:["explore","detail","call_q","source","sort","direction","density","page"],call:["record","return","mode","max_entries","max_chars","include_tool_output","include_compaction_history"]};function kt(e,t,n=[]){const a=new Set([t,...Array.isArray(n)?n:[n]]);for(const[r,s]of Object.entries(dc))if(!a.has(r))for(const i of s)e.searchParams.delete(i)}function ga(e){let t=!1;return e.searchParams.get("view")==="insights"&&(e.searchParams.set("view","overview"),t=!0),e.searchParams.get("return")==="insights"&&(e.searchParams.set("return","overview"),t=!0),t}const Lr=[{key:"overview",title:"Overview",path:"/api/diagnostics/overview",refreshPath:"/api/diagnostics/overview/refresh"},{key:"toolOutput",title:"Tool Output",path:"/api/diagnostics/tool-output",refreshPath:"/api/diagnostics/tool-output/refresh"},{key:"commands",title:"Commands",path:"/api/diagnostics/commands",refreshPath:"/api/diagnostics/commands/refresh"},{key:"gitInteractions",title:"Git Interactions",path:"/api/diagnostics/git-interactions",refreshPath:"/api/diagnostics/git-interactions/refresh"},{key:"fileReads",title:"File Reads",path:"/api/diagnostics/file-reads",refreshPath:"/api/diagnostics/file-reads/refresh"},{key:"fileModifications",title:"File Modifications",path:"/api/diagnostics/file-modifications",refreshPath:"/api/diagnostics/file-modifications/refresh"},{key:"readProductivity",title:"Read Productivity",path:"/api/diagnostics/read-productivity",refreshPath:"/api/diagnostics/read-productivity/refresh"},{key:"concentration",title:"Concentration",path:"/api/diagnostics/concentration",refreshPath:"/api/diagnostics/concentration/refresh"},{key:"guidedSummary",title:"What Is Driving Usage?",path:"/api/diagnostics/guided-summary",refreshPath:"/api/diagnostics/guided-summary/refresh"},{key:"usageDrain",title:"Usage Drain",path:"/api/diagnostics/usage-drain",refreshPath:"/api/diagnostics/usage-drain/refresh"}],At=new Map,Dt=new Map;function hc(){At.clear(),Dt.clear()}async function Bl(e,t,n={}){Sn(t);const a=vc(e);return n.signal?Nt(a,t,n.signal):pc(Dt,_n(e,t,n.cacheKey),()=>Nt(a,t))}async function Gl(e,t={}){Sn(e);const n=await fetch(`/api/diagnostics/refresh?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:t.signal}),a=await Ft(n,"Diagnostic snapshot refresh"),r=a.sections??(Mr(a)?await fc(e,await Rr(a,e,t),t.signal):{});At.set(yn(e),r);for(const[s,i]of Object.entries(r))Dt.set(_n(s,e),i);return r}async function Jl(e,t,n={}){Sn(t);const a=await fetch(`${e.refreshPath}?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),r=await Ft(a,e.title),s=Mr(r)?await mc(t,e,await Rr(r,t,n),n.signal):r,i=yn(t),o=At.get(i),d=o?await Promise.resolve(o):{};return At.set(i,{...d,[e.key]:s}),Dt.set(_n(e.key,t),s),s}async function Rr(e,t,n){var r,s,i,o;let a=e;for((r=n.onProgress)==null||r.call(n,a);a.status==="pending"||a.status==="running";){const d=n.pollIntervalMs??((s=a.next)==null?void 0:s.poll_after_ms)??250;await gc(d,n.signal);const f=new URLSearchParams({job_id:a.job_id,_:String(Date.now())}),h=await fetch(`/api/diagnostics/refresh/status?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});a=await Ft(h,"Diagnostic refresh status"),(i=n.onProgress)==null||i.call(n,a)}if(a.status!=="completed")throw new Error(`Diagnostic refresh failed: ${((o=a.error)==null?void 0:o.code)??a.status}`);return a}async function fc(e,t,n){const a=await Promise.all(Lr.map(async r=>[r.key,await Nt(r,e,n)]));return Object.fromEntries(a)}async function mc(e,t,n,a){return Nt(t,e,a)}function Mr(e){if(!e||typeof e!="object")return!1;const t=e;return t.schema==="codex-usage-tracker-analysis-job-v1"&&t.job_kind==="diagnostic-refresh"&&typeof t.job_id=="string"}function gc(e,t){return t!=null&&t.aborted?Promise.reject(t.reason??new DOMException("Aborted","AbortError")):e<=0?Promise.resolve():new Promise((n,a)=>{const r=()=>{window.clearTimeout(s),t==null||t.removeEventListener("abort",r),a((t==null?void 0:t.reason)??new DOMException("Aborted","AbortError"))},s=window.setTimeout(()=>{t==null||t.removeEventListener("abort",r),n()},e);t==null||t.addEventListener("abort",r,{once:!0})})}function pc(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function yn(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function _n(e,t,n=""){return`snapshot:${yn(t)}:${n}:${e}`}function vc(e){const t=Lr.find(n=>n.key===e);if(!t)throw new Error(`Unknown diagnostic snapshot: ${e}`);return t}async function Nt(e,t,n){const a=await fetch(`${e.path}?_=${Date.now()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n});return await Ft(a,e.title)}function Sn(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Ft(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(typeof n.error=="string"&&n.error)throw new Error(n.error);return n}const pa=[{key:"facts",label:"Top Facts",title:"Top Diagnostic Facts",path:"/api/diagnostics/facts",limit:50},{key:"tools",label:"Tools",title:"Tool and Function Activity",path:"/api/diagnostics/tools",limit:25},{key:"compactions",label:"Compactions",title:"Compaction Activity",path:"/api/diagnostics/compactions",limit:25}],Pr=new Map,jr=new Map;function bc(){hc(),Pr.clear(),jr.clear()}async function Zl(e,t,n={}){Dr(t);const a=pa.find(f=>f.key===e)??pa[0],r=yc(n.sort??"uncached"),s=n.direction??"desc",i=Math.max(1,Math.round(n.limit??a.limit)),o=Math.max(0,Math.round(n.offset??0)),d=async()=>{const f=new URLSearchParams({limit:String(i),offset:String(o),sort:r,direction:s});Er(f,"include_archived",n.includeArchived);const h=await fetch(`${a.path}?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});return await Fr(h,a.title)};return n.signal?d():Ar(Pr,wc(a.key,t,i,o,r,s,n.cacheKey,n.includeArchived),d)}async function Xl(e,t,n={}){Dr(t);const a=Math.max(1,Math.round(n.limit??8)),r=Math.max(0,Math.round(n.offset??0)),s=n.sort??"tokens",i=n.direction??"desc",o=async()=>{const d=String(e.fact_type??""),f=String(e.fact_name??"");if(!d||!f)throw new Error("Diagnostic fact type and name are required.");const h=new URLSearchParams({fact_type:d,fact_name:f,limit:String(a),offset:String(r),sort:s,direction:i});Er(h,"include_archived",n.includeArchived);const b=await fetch(`/api/diagnostics/fact-calls?${h.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),u=await Fr(b,"Diagnostic fact calls");return{calls:(u.rows??[]).map((p,g)=>mr(p,g)),rawPayload:u}};return n.signal?o():Ar(jr,_c(e,t,a,r,s,i,n.cacheKey,n.includeArchived),o)}function Ar(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function Nr(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function wc(e,t,n,a,r,s,i="",o){return["facts",e,Nr(t),i,o??"default",n,a,r,s].join(":")}function yc(e){return e==="total"?"tokens":e==="latest"?"time":e}function _c(e,t,n,a,r,s,i="",o){return["fact-calls",Nr(t),i,o??"default",String(e.fact_type??""),String(e.fact_name??""),n,a,r,s].join(":")}function Er(e,t,n){n!==void 0&&e.set(t,String(n))}function Dr(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Fr(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(n.error)throw new Error(n.error);return n}const Sc=[{id:"usage-snapshot",endpoint:"/api/usage",dataClass:"snapshot",schema:"codex-usage-tracker-dashboard-v1"},{id:"overview-summary",endpoint:"/api/summary",dataClass:"aggregate",schema:"codex-usage-tracker-summary-v1"},{id:"overview-recommendations",endpoint:"/api/recommendations",dataClass:"aggregate",schema:"codex-usage-tracker-recommendations-v1"},{id:"calls",endpoint:"/api/calls",dataClass:"aggregate",schema:"codex-usage-tracker-calls-v1"},{id:"threads",endpoint:"/api/threads",dataClass:"aggregate",schema:"codex-usage-tracker-threads-v1"},{id:"thread-calls",endpoint:"/api/thread-calls",dataClass:"detail",schema:"codex-usage-tracker-thread-calls-v1"},{id:"investigator-agentic",endpoint:"/api/investigations/agentic",dataClass:"aggregate",schema:"codex-usage-tracker-agentic-investigation-v1"},{id:"investigator-walk",endpoint:"/api/investigations/walk",dataClass:"userAction",schema:"codex-usage-tracker-investigation-walk-v1"},{id:"diagnostics-facts",endpoint:"/api/diagnostics/facts",dataClass:"aggregate",schema:null},{id:"diagnostics-fact-calls",endpoint:"/api/diagnostics/fact-calls",dataClass:"detail",schema:null},{id:"diagnostics-dedupe",endpoint:"/api/diagnostics/dedupe",dataClass:"aggregate",schema:"codex-usage-tracker-dedupe-diagnostics-v1"},{id:"diagnostics-snapshot",endpoint:"/api/diagnostics/{snapshot}",dataClass:"aggregate",schema:null},{id:"compression-profile",endpoint:"/api/compression/profile",dataClass:"aggregate",schema:"codex-usage-tracker-compression-api-v1"},{id:"reports",endpoint:"/api/reports/pack",dataClass:"aggregate",schema:"codex-usage-tracker-reports-pack-v1"}],Cc=Sc,xc=new Map(Cc.map(e=>[e.id,e])),kc=15*6e4,Tc=3e4,Ir={snapshot:ot({persistedCache:"aggregate-only"}),aggregate:ot({persistedCache:"aggregate-only"}),detail:ot(),heavyJob:ot({cancellation:"shared-job",staleTime:1e3}),userAction:ot({retry:0,staleTime:0})};function Lc({sourceKey:e,sourceRevision:t}){return{sourceKey:va(e,"local-api"),sourceRevision:va(t,"unversioned")}}function Rc(e,t,n={},...a){return["dashboard",e.id,t.sourceKey,t.sourceRevision,jc(n),...a]}function Mc(e){return["dashboard",e.id]}function Pc(e){const t=xc.get(e);if(!t)throw new Error(`Unknown dashboard query definition: ${e}`);return t}function $r(e){const t=Ir[e];return{gcTime:t.gcTime,refetchOnReconnect:t.refetchOnReconnect,refetchOnWindowFocus:t.refetchOnWindowFocus,retry:t.retry,staleTime:t.staleTime}}function Yl({enabled:e,hasData:t,isError:n,isFetching:a,isPending:r}){return e?t?a?"updating":"ready":n?"error":a||r?"loading":"waiting":"waiting"}function eu(e){const t=e.filter(a=>a==="ready"||a==="updating").length,n=e.length;return{ready:t,total:n,percent:n===0?100:Math.round(t/n*100),loading:e.filter(a=>a==="loading").length,errors:e.filter(a=>a==="error").length}}function jc(e){return{historyScope:e.historyScope??"active",loadWindow:e.loadWindow??"all",limit:e.limit??null,since:e.since??""}}function va(e,t){return(e==null?void 0:e.trim())||t}function ot(e={}){return{staleTime:Tc,gcTime:kc,retry:1,refetchOnReconnect:!1,refetchOnWindowFocus:!1,cancellation:"observer",persistedCache:"none",...e}}const Ac=new Set(["command_text","content_fragment","content_fragments","excerpt","indexed_content","indexed_fragment","indexed_fragments","prompt","raw_context","raw_output","snippet","tool_output"]),Nc=new Set(["includes_indexed_content","includes_raw_fragment","includes_raw_fragments","indexed_content_included","raw_content_included","raw_context_included"]),Ec=new Set(["codex-usage-tracker-context-v1"]);function ba(e){return on(e,new WeakSet)}function on(e,t){if(!e||typeof e!="object")return!0;if(t.has(e))return!1;t.add(e);const n=Array.isArray(e)?e.every(a=>on(a,t)):Object.entries(e).every(([a,r])=>{const s=a.toLowerCase();return Ac.has(s)||Nc.has(s)&&r===!0||s==="schema"&&typeof r=="string"&&Ec.has(r)?!1:on(r,t)});return t.delete(e),n}const Dc="codexUsageDashboard",Fc=1,Y="usageSnapshots",Ic=6,$c=10080*60*1e3,Oc={async read(e){if(!e.sourceRevision)return null;try{const t=await ya();if(!t)return null;const n=await Or(t.transaction(Y,"readonly").objectStore(Y).get(wa(e)));return!n||n.sourceRevision!==e.sourceRevision||Date.now()-n.storedAt>$c?null:ba(n.payload)?n.payload:(await Uc(t,n.cacheKey),null)}catch{return null}},async write(e,t){if(!(!e.sourceRevision||!ba(t)))try{const n=await ya();if(!n)return;const a=n.transaction(Y,"readwrite");a.objectStore(Y).put({...e,cacheKey:wa(e),payload:t,storedAt:Date.now()}),await Cn(a),await Vc(n)}catch{}}};async function Uc(e,t){const n=e.transaction(Y,"readwrite");n.objectStore(Y).delete(t),await Cn(n)}function wa(e){const{historyScope:t,loadWindow:n,limit:a,since:r}=e.scope;return JSON.stringify([e.sourceKey,t,n,a,r])}function ya(){return typeof indexedDB>"u"?Promise.resolve(null):new Promise(e=>{const t=indexedDB.open(Dc,Fc);t.onupgradeneeded=()=>{t.result.objectStoreNames.contains(Y)||t.result.createObjectStore(Y,{keyPath:"cacheKey"})},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)})}function Or(e){return new Promise((t,n)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>n(e.error??new Error("IndexedDB request failed"))})}function Cn(e){return new Promise((t,n)=>{e.oncomplete=()=>t(),e.onerror=()=>n(e.error??new Error("IndexedDB transaction failed")),e.onabort=()=>n(e.error??new Error("IndexedDB transaction aborted"))})}async function Vc(e){const t=e.transaction(Y,"readonly"),a=(await Or(t.objectStore(Y).getAll())).sort((i,o)=>o.storedAt-i.storedAt).slice(Ic);if(!a.length)return;const r=e.transaction(Y,"readwrite"),s=r.objectStore(Y);a.forEach(i=>s.delete(i.cacheKey)),await Cn(r)}const Kc={kind:"production",load:So},qc="codexUsageDashboardRuntimeMetadata",Hc=2048,cn=Pc("usage-snapshot"),Ur={all:Mc(cn),snapshot:(e,t,n)=>Rc(cn,Lc({sourceKey:e,sourceRevision:t}),n)};function Wc(){return new Ti({defaultOptions:{queries:{...$r("aggregate")}}})}const xn=Wc();async function Qc({currentPayload:e,historyScope:t,loadWindow:n,loadLimit:a,since:r=null,onProgress:s,queryClient:i=xn,refresh:o=!1,snapshotStore:d=Oc,transport:f=Kc}){const h=Vi(a,t,r,n),b=kn(e),u=Ur.snapshot(b.sourceKey,b.sourceRevision,h);!i.getQueryData(u)&&Zc(e,h)&&i.setQueryData(u,e),o&&await i.invalidateQueries({queryKey:u,exact:!0});const p=_a(e,h),g=await i.fetchQuery({queryKey:u,...$r(cn.dataClass),queryFn:async({signal:v})=>{var R;const w=!o&&p?await d.read(p):null;if(w)return s==null||s({status:"completed",phase:"loading_rows",message:"Loaded cached dashboard snapshot",completed:Number(w.loaded_row_count??((R=w.rows)==null?void 0:R.length)??0),total:Number(w.total_available_rows??w.loaded_row_count??0),percent:100}),w;const T=await f.load(e,{refresh:o,limit:Ki(h),includeArchived:h.historyScope==="all",loadWindow:n,since:h.since,onProgress:s,signal:v}),N=p?{...p,sourceRevision:String(T.latest_refresh_at??p.sourceRevision)}:_a(T,h);return N&&await d.write(N,T),T},staleTime:o?0:Ir.snapshot.staleTime});return Jc(Gc(g,h)),g}function _a(e,t){if(!(e!=null&&e.api_token))return null;const n=String(e.latest_refresh_at??"");return n?{sourceKey:Vr(e),sourceRevision:n,scope:t}:null}async function zc(e=xn){await e.cancelQueries({queryKey:Ur.all})}function Bc(e){return bi(e)||sr(e)}function Gc(e,t){return{schema:"codex-usage-dashboard-runtime-v1",...kn(e),scope:t,updatedAt:Date.now()}}function kn(e){return{sourceKey:Vr(e),sourceRevision:Xc(e)}}function Jc(e,t=Yc()){if(t)try{const n=JSON.stringify(e);n.length<=Hc&&t.setItem(qc,n)}catch{}}function Zc(e,t){var o;if(!e||!(((o=e.rows)==null?void 0:o.length)??0))return!1;const n=ct(e),a=t.limit===null?n===0:n===t.limit,r=(e.since??null)===t.since,s=fn(e)===t.loadWindow,i=e.include_archived||e.history_scope==="all-history"?"all":"active";return a&&r&&s&&i===t.historyScope}function Vr(e){const t=e,n=Number((t==null?void 0:t.payload_cache_version)??0),a=String((t==null?void 0:t.payload_cache_key)??(e!=null&&e.api_token?"live":"static"));return`${n}:${a}`}function Xc(e){return String((e==null?void 0:e.latest_refresh_at)??"unversioned")}function Yc(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}const el=new Set(["duplicate_cumulative_total"]);function tl({canUseLiveApi:e,payload:t,shellI18n:n}){const a=nl(t,e,n);return c.jsxs("section",{className:"environment-status","aria-label":n.t("aria.dashboard_status","Dashboard status"),children:[c.jsx("span",{className:"environment-status-title",children:n.t("aria.dashboard_status","Dashboard status")}),c.jsx("div",{className:"environment-status-grid",children:a.map(r=>c.jsx("span",{className:"environment-chip","data-state":r.state,title:r.title,children:r.label},r.label))})]})}function nl(e,t,n){const a=ol(e==null?void 0:e.parser_diagnostics,n);return[{label:n.t("badge.unofficial_project","Unofficial project"),state:"neutral",title:n.t("badge.unofficial_project_title","Codex Usage Tracker is independent and is not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI. OpenAI and Codex are trademarks of OpenAI.")},{label:t?`${n.t("badge.live","Live")} API`:n.t("badge.static","Static"),state:t?"ready":"warn",title:t?"Local API token present for refresh actions.":"Static embedded snapshot; live refresh is unavailable."},rl(e,n),sl(e,n),il(e,n),al(e),...a?[a]:[]]}function al(e){const t=e==null?void 0:e.dedupe,n=Number((t==null?void 0:t.excluded_copied_rows)||0),a=Number((t==null?void 0:t.canonical_rows)||0),r=Number((t==null?void 0:t.physical_rows)||0);return{label:`Deduped · ${n.toLocaleString()} copied excluded`,state:"ready",title:`Billable totals use ${a.toLocaleString()} canonical rows while preserving ${r.toLocaleString()} physical source rows.`}}function rl(e,t){var s;const n=!!(e!=null&&e.pricing_configured),a=((s=e==null?void 0:e.pricing_snapshot_warning)==null?void 0:s.trim())??"",r=Kr(e==null?void 0:e.pricing_source);return{label:n?t.t("badge.costs","Costs"):t.t("badge.no_costs","No costs"),state:n?a?"warn":"ready":"missing",title:n?[r||"Pricing configured",a].filter(Boolean).join(" - "):t.t("pricing.configure_hint","Run codex-usage-tracker update-pricing to configure estimated costs.")}}function sl(e,t){var s,i;const n=((s=e==null?void 0:e.allowance_error)==null?void 0:s.trim())??"",a=((i=e==null?void 0:e.rate_card_error)==null?void 0:i.trim())??"",r=Kr(e==null?void 0:e.allowance_source)||"Codex credit rates";return n?{label:t.t("state.allowance_config_error","Allowance config error"),state:"missing",title:`Config error: ${n}`}:a?{label:"Rate-card error",state:"missing",title:`Rate-card error: ${a}`}:e!=null&&e.allowance_configured?{label:t.t("state.allowance_configured","Allowance configured"),state:"ready",title:r}:e!=null&&e.rate_card_configured?{label:"Credit rates loaded",state:"ready",title:r}:{label:t.t("action.set_limits","Set limits"),state:"warn",title:"No local allowance windows are configured."}}function il(e,t){const n=e==null?void 0:e.project_metadata_privacy,a=(n==null?void 0:n.mode)||(e==null?void 0:e.privacy_mode)||"normal",r=a==="normal",s=[n!=null&&n.cwd_redacted?"cwd redacted":"",n!=null&&n.project_names_redacted?"project names redacted":"",n!=null&&n.git_remote_label_hidden?"git remote hidden":"",n!=null&&n.relative_cwd_hidden?"relative cwd hidden":"",n!=null&&n.git_branch_hidden?"git branch hidden":"",n!=null&&n.tags_hidden?"tags hidden":""].filter(Boolean);return{label:r?t.t("badge.metadata_normal","Metadata normal"):qr(t.t("badge.metadata_mode","Metadata {mode}"),{mode:a}),state:r?"ready":"warn",title:r?"Project metadata is shown normally.":[`Metadata mode: ${a}`,...s].join(" - ")}}function ol(e,t){const n=Object.entries(e??{}).filter(([s,i])=>Number(i||0)>0&&!el.has(s));if(!n.length)return null;const a=n.reduce((s,[,i])=>s+Number(i||0),0),r=n.map(([s,i])=>`${s}=${Number(i||0)}`).join(", ");return{label:t.t("badge.parser_warnings","Parser warnings"),state:"missing",title:qr(t.t("parser.warnings_title","Latest refresh reported {count} parser diagnostics: {entries}. Run codex-usage-tracker inspect-log to investigate schema drift."),{count:a.toLocaleString(),entries:r})}}function Kr(e){if(!e)return"";if(typeof e=="string")return e;const t=e.label??e.name??e.type??e.path??"";return typeof t=="string"?t:""}function qr(e,t){return e.replace(/\{([a-zA-Z0-9_]+)\}/g,(n,a)=>t[a]??n)}async function Sa(e){var n;if((n=navigator.clipboard)!=null&&n.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly","readonly"),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}const cl={"highest-cost":"Highest Cost Threads","context-bloat":"Context Bloat","cache-misses":"Cache Misses","pricing-gaps":"Pricing Gaps","codex-credits":"Codex Credits","reasoning-spike":"Reasoning Spike"};function tu(e,t){return t==="context-bloat"?Number(e.contextWindowPct??0)>=60||e.totalTokens>=2e5:t==="cache-misses"?e.signal==="cache-risk"||e.cachedPct<30||e.uncachedInput>=5e4:t==="pricing-gaps"?e.pricingEstimated||!Number.isFinite(e.cost):t==="codex-credits"?e.credits>0:t==="reasoning-spike"?e.reasoningOutput>0:!0}function ll(e){return cl[e]??e}const ul=se(()=>O(()=>import("./OverviewPage.js"),__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50])),"OverviewPage"),dl=se(()=>O(()=>import("./InvestigatorPage.js"),__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52])),"InvestigatorPage"),hl=se(()=>O(()=>import("./CompressionLabPage.js"),__vite__mapDeps([53,1,2,34,4,6,9,10,17,25,26,12,54])),"CompressionLabPage"),fl=se(()=>O(()=>import("./ExploreRoutePage.js"),__vite__mapDeps([55,1,2,44,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48,8,9,10,56])),"ExploreRoutePage"),ml=se(()=>O(()=>import("./CallInvestigatorPage.js"),__vite__mapDeps([57,1,2,46,33,19,37,38,47,25,26,12])),"CallInvestigatorPage"),gl=se(()=>O(()=>import("./ThreadsPage.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27])),"ThreadsPage"),pl=se(()=>O(()=>import("./UsageDrainPage.js"),__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39])),"UsageDrainPage"),vl=se(()=>O(()=>import("./CacheContextPage.js"),__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12])),"CacheContextPage"),bl=se(()=>O(()=>import("./DiagnosticsPage.js"),__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12])),"DiagnosticsPage"),wl=se(()=>O(()=>import("./ReportsPage.js"),__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43])),"ReportsPage"),yl=se(()=>O(()=>import("./SettingsPage.js"),__vite__mapDeps([58,1,2,33,19,32,38,47,17,25,26,12,59])),"SettingsPage");function _l(e){return c.jsx(C.Suspense,{fallback:c.jsx(Cl,{activeView:e.activeView}),children:Sl(e)})}function Sl(e){const{activePreset:t,activeRecordId:n,activeView:a,autoRefreshEnabled:r,applicationI18n:s,backFromCallInvestigator:i,callBackLabel:o,canLoadAllRows:d,canUseLiveApi:f,contextRuntime:h,copyCallInvestigatorLink:b,dashboardPayload:u,globalFilters:p,globalQuery:g,hasMoreRows:v,historyScope:w,loadWindow:T,loadAllRows:N,loadedRowCount:R,loadLimit:_,loadMoreRows:L,scopeSince:y,model:k,navigateView:j,onRefresh:E,openCallInvestigator:D,refreshing:me,refreshState:bt,setContextApiEnabled:wt,sourceIdentity:$,totalAvailableRows:at}=e;switch(a){case"overview":return c.jsx(ul,{model:k,contextRuntime:h,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onRefresh:E,globalQuery:g,runtime:{historyScope:w,loadLimit:_,loadWindow:T,loadedRowCount:R,scopeSince:y,totalAvailableRows:at},refreshing:me,canLoadMoreRows:f&&v,onLoadMoreRows:L,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:j,globalFilters:p});case"investigator":return c.jsx(dl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:j});case"compression-lab":return c.jsx(hl,{contextRuntime:h,includeArchived:w==="all",since:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision});case"calls":return c.jsx(fl,{model:k,globalQuery:g,activePreset:t,onRefresh:E,contextRuntime:h,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onContextApiEnabledChange:wt,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:j});case"call":return c.jsx(ml,{model:k,recordId:n,contextRuntime:h,onContextApiEnabledChange:wt,onNavigateRecord:D,onCopyCallLink:b,onBackToCalls:i,backLabel:o});case"threads":return c.jsx(gl,{model:k,globalQuery:g,onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p,contextRuntime:h,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onNavigateView:j});case"usage-drain":return c.jsx(pl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"cache-context":return c.jsx(vl,{model:k,contextRuntime:h,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"diagnostics":return c.jsx(bl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,rowLoadControls:{loadedRowCount:R,totalAvailableRows:at,canLoadMoreRows:f&&v,canLoadAllRows:d,refreshing:me,onLoadMoreRows:L,onLoadAllRows:N},onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p});case"reports":return c.jsx(wl,{model:k,refreshState:bt,includeArchived:w==="all",loadWindow:T,loadLimit:_,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"settings":return c.jsx(yl,{model:k,payload:u,historyScope:w,loadWindow:T,loadLimit:_,scopeSince:y,loadedRowCount:R,totalAvailableRows:at,canUseLiveApi:f,autoRefreshEnabled:r,refreshState:bt,applicationI18n:s})}}function Cl({activeView:e}){return c.jsxs("section",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:["Loading ",e.replace("-"," "),"..."]})}const Ca=1e4,xl={1:"overview",2:"calls",3:"threads",4:"diagnostics"},kl=new Set(["call","compression-lab","diagnostics","investigator"]);function Hr(e){return!kl.has(e)}function Tl(e){return e instanceof Element?!!e.closest('input, select, textarea, button, [contenteditable="true"]'):!1}function Wr(){var Un;const e=C.useRef(null),t=C.useMemo(()=>_o(),[]),[n,a]=C.useState(t),[r,s]=C.useState(()=>ra(t)),[i,o]=C.useState(()=>{const m=new URLSearchParams(window.location.search);return sn(m.get("view"))}),[d,f]=C.useState(()=>new URLSearchParams(window.location.search).get("record")??""),[h,b]=C.useState(()=>da()),[u,p]=C.useState(()=>ha()),[g,v]=C.useState(()=>new URLSearchParams(window.location.search).get("q")??""),[w,T]=C.useState(()=>new URLSearchParams(window.location.search).get("preset")??""),[N,R]=C.useState(()=>window.location.search),[_,L]=C.useState("Stored snapshot loaded just now"),[y,k]=C.useState(null),[j,E]=C.useState(!1),[D,me]=C.useState(!1),[bt,wt]=C.useState(!1),[$,at]=C.useState(()=>zs(t)),It=C.useRef(!1),[G,Tn]=C.useState(()=>je(ct(t),500)),[Ue,yt]=C.useState(()=>je(ct(t),500)),[q,Ln]=C.useState(()=>qi(t)),[J,_t]=C.useState(()=>fa(Wt(t))),[Rn,Mn]=C.useState(r.contextRuntime.contextApiEnabled),H=!!(n!=null&&n.api_token),Qr=C.useMemo(()=>kn(n),[n]),A=C.useMemo(()=>Da(n,$),[n,$]),Pn=C.useMemo(()=>({...r.contextRuntime,contextApiEnabled:Rn}),[Rn,r.contextRuntime]),zr=C.useMemo(()=>Vo(r,J,N),[J,N,r]),jn=i==="calls"||i==="call"?r:zr,rt=Hr(i),$t=je(Ue,G,500),ge=Math.max(0,Number((n==null?void 0:n.loaded_row_count)??((Un=n==null?void 0:n.rows)==null?void 0:Un.length)??r.calls.length??0)),Ve=Math.max(0,Number((n==null?void 0:n.total_available_rows)??ge)),Br=Ue!==G,An=Qi({currentLimit:G,loadedRows:ge,pendingLimit:Ue}),Gr=Math.min($t,An),Nn=!!(n!=null&&n.has_more)||Ve>0&&ge{const m=new URL(window.location.href);ga(m)&&Ke(m)},[]),C.useEffect(()=>{function m(){const S=window.location.search,M=new URLSearchParams(S);o(sn(M.get("view"))),f(M.get("record")??""),b(da(S)),p(ha(S)),v(M.get("q")??""),T(M.get("preset")??""),_t(fa(Wt(n),S)),R(S)}return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[n]),C.useEffect(()=>{function m(S){var oe;if(Tl(S.target))return;if(S.key==="/"){S.preventDefault(),(oe=e.current)==null||oe.focus();return}const M=xl[S.key];M&&(S.preventDefault(),st(M))}return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[]),C.useEffect(()=>{function m(){wt(window.scrollY>320)}return m(),window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]);function ns(m){const S=i==="call"?h:i;b(S),p(i==="call"?u:!0),o("call"),f(m);const M=new URL(window.location.href);kt(M,i,i==="call"?h:[]),M.searchParams.set("view","call"),M.searchParams.set("record",m),M.searchParams.set("return",S),Fn(M)}function as(){st(h)}function rs(m){v(m),T("");const S=new URL(window.location.href);S.searchParams.delete("preset"),m?S.searchParams.set("q",m):S.searchParams.delete("q"),Ke(S)}async function ie(m={}){var St;if(j)return;It.current=!0;const S=m.loadLimit??G,M=m.loadWindow??q,oe=Ht(M),pe=m.historyScope??J,ee=m.refresh??!0,Ot=!!(n!=null&&n.refresh_jobs_available);E(!0),k(Ot?{status:"running",phase:ee?"refreshing_index":"loading_rows",message:`${ee?"Refreshing":"Loading"} ${Re(M,S)}`}:null),L(`${ee?"Refreshing index for":"Loading"} ${Re(M,S)}...`);let qe=!1;try{const B=await Qc({currentPayload:n,refresh:ee,loadLimit:S,loadWindow:M,since:oe,historyScope:pe,onProgress:Vt=>{qe||(qe=Vt.message==="Loaded cached dashboard snapshot"),k(Vt),L(Xn(Vt,pe))}});bc(),a(B),s(ra(B)),Mn(!!B.context_api_enabled);const ke=M==="rows"?je(ct(B,S),S):S;Tn(ke),yt(ke),Ln(M);const Vn=Wt(B,pe);_t(Vn),Wi(ke,Vn,M);const Ut=B.loaded_row_count??((St=B.rows)==null?void 0:St.length)??0,Kn=B.total_available_rows??Ut;L(M==="rows"?`${qe?"Cache hit; l":ee?"Refreshed index; l":"L"}oaded ${Ut.toLocaleString()} of ${Kn.toLocaleString()} calls from ${Re(M,ke)}`:`${qe?"Cache hit; ":ee?"Refreshed index; ":""}${Re(M,ke)} analysis ready across ${Kn.toLocaleString()} calls; ${Ut.toLocaleString()} detail rows cached`)}catch(B){if(k(null),Bc(B)){L("Refresh cancelled; stored snapshot remains visible");return}const ke=new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});L(`${Xi(B)} Stored snapshot kept at ${ke}`)}finally{k(null),E(!1)}}async function ss(){await zc(),k(null),E(!1),L("Refresh cancelled; stored snapshot remains visible")}C.useEffect(()=>{document.documentElement.lang=A.language,document.documentElement.dir=A.direction},[A.direction,A.language]),C.useEffect(()=>{var B;const m=Number((n==null?void 0:n.total_available_rows)??0),S=Number((n==null?void 0:n.loaded_row_count)??((B=n==null?void 0:n.rows)==null?void 0:B.length)??0),M=Hi(),oe=(M==null?void 0:M.historyScope)??J,pe=(M==null?void 0:M.loadLimit)??G,ee=(M==null?void 0:M.loadWindow)??q,Ot=fn(n),qe=oe!==J||ee!==Ot||ee==="rows"&&pe!==ct(n),St=S>0;!H||!qe&&St||m<=0||j||It.current||(It.current=!0,qe&&(_t(oe),Tn(pe),yt(pe),Ln(ee),Ke(ma(oe))),ie({refresh:!1,historyScope:oe,loadLimit:pe,loadWindow:ee}))},[H,n,J,G,q,j]),C.useEffect(()=>{!H&&D&&me(!1)},[D,H]),C.useEffect(()=>{if(!D||!H||!rt)return;const m=window.setInterval(()=>{ie()},Ca);return()=>window.clearInterval(m)},[D,rt,H,n,J,G,q,j]),C.useEffect(()=>{if(!D||!H||!rt)return;function m(){document.visibilityState==="visible"&&ie()}return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[D,rt,H,n,J,G,q,j]);function In(m){const S=m.trim();yt(Math.max(1,pt(S===""?Number.NaN:Number(S))))}function is(m){In(m)}function os(){ie({refresh:!1,loadLimit:Ue,loadWindow:"rows"})}function cs(){ie({refresh:!1,loadWindow:"all"})}function $n(){yt(En),ie({refresh:!1,loadLimit:En,loadWindow:q})}function ls(m){m!==q&&ie({refresh:!1,loadWindow:m})}function us(m){const S=m==="all"?"all":"active";_t(S),Ke(ma(S)),ie({refresh:!1,historyScope:S})}function ds(m){if(me(m),m){if(!rt){L("Auto refresh pauses on this evidence-heavy view");return}L(`Auto refresh every ${Ca/1e3}s`),ie()}else L("Auto refresh paused")}function hs(m){at(m),Bs(m)}async function fs(){try{const m=new URL(window.location.href);if(ga(m),kt(m,i,i==="call"?h:[]),!await Sa(m.toString()))throw new Error("Clipboard unavailable");L("Copied current view link")}catch{L("Copy unavailable in browser")}}async function ms(m){try{const S=new URL(window.location.href);kt(S,i,i==="call"?h:[]);const M=i==="call"?h:i;if(S.searchParams.set("view","call"),S.searchParams.set("record",m),S.searchParams.set("return",M),!await Sa(S.toString()))throw new Error("Clipboard unavailable");L("Copied call investigator link")}catch{L("Copy unavailable in browser")}}async function gs(){const m=await Gi(i,jn,{contextRuntime:Pn,historyScope:J,loadWindow:q,loadLimit:G,scopeSince:(n==null?void 0:n.since)??Ht(q),loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,refreshState:_},g,w);if(!m.rowCount){L(`No ${m.label} to export`);return}Ni(m.filename,m.csv),L(`Exported ${m.rowCount} ${m.label}`)}function ps(){T("");const m=new URL(window.location.href);m.searchParams.delete("preset"),Ke(m),L("Investigation preset cleared")}function vs(){window.scrollTo({top:0,behavior:"smooth"})}return c.jsx(ao,{value:A,children:c.jsxs("div",{className:"app-shell","data-dashboard-localization-root":!0,children:[c.jsxs("aside",{className:"sidebar",children:[c.jsxs("div",{className:"brand",children:[c.jsx("div",{className:"brand-mark",children:c.jsx(Us,{size:22})}),c.jsxs("div",{children:[c.jsx("strong",{children:"Codex Usage Tracker"}),c.jsx("span",{children:A.t("dashboard.eyebrow","Local telemetry console")})]})]}),c.jsxs("div",{className:"local-pill",children:[c.jsx("span",{"aria-hidden":"true"}),"Local data only"]}),c.jsx(tl,{payload:n,canUseLiveApi:H,shellI18n:A}),c.jsx("nav",{className:"primary-nav","aria-label":"Primary",children:Cr.map(m=>{const S=m.icon,M=i===m.id||i==="call"&&m.id==="calls";return c.jsxs("button",{type:"button","aria-pressed":M,className:M?"active":"",onClick:()=>st(m.id),children:[c.jsx(S,{size:18}),c.jsx("span",{children:A.navLabel(m.id,m.label)})]},m.id)})}),c.jsxs("div",{className:"secondary-block",role:"group","aria-label":"Quick Links",children:[c.jsx("span",{children:"Quick Links"}),xr.map(m=>{const S=m.icon;return c.jsxs("button",{type:"button",onClick:()=>st(m.target),children:[c.jsx(S,{size:16}),m.label]},m.label)})]})]}),c.jsxs("main",{className:"workspace",children:[c.jsxs("div",{className:"unofficial-banner",role:"note","aria-label":"Unofficial project notice",children:[c.jsx($s,{size:16}),c.jsxs("span",{children:[c.jsx("strong",{children:"Unofficial project."})," Not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI."]})]}),c.jsxs("header",{className:"topbar","aria-label":"Dashboard toolbar",children:[c.jsxs("label",{className:"global-search",children:[c.jsx("span",{className:"sr-only",children:A.t("filter.search","Search dashboard")}),c.jsx("input",{ref:e,"aria-label":A.t("filter.search","Search dashboard"),value:g,onChange:m=>rs(m.target.value),placeholder:A.t("filter.search_placeholder","Search calls, threads, models, diagnostics...")})]}),c.jsxs("div",{className:"topbar-actions",children:[c.jsxs("div",{className:"topbar-scope-controls",children:[A.languages.length>1?c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("language.label","Language")}),c.jsx("select",{"data-localization-skip":"true","aria-label":A.t("language.label","Language"),value:A.language,onChange:m=>hs(m.target.value),children:A.languages.map(m=>c.jsx("option",{value:m.code,children:m.native_name||m.english_name||m.code},m.code))})]}):null,c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("nav.history","History")}),c.jsxs("select",{"aria-label":"History scope",title:Dn,value:J,onChange:m=>us(m.target.value),disabled:j||!H,children:[c.jsx("option",{value:"active",children:A.t("option.active_sessions_only","Active")}),c.jsx("option",{value:"all",children:A.t("option.all_history","All history")})]}),c.jsx("small",{className:"sr-only",children:Dn})]})]}),c.jsx(ec,{canUseLiveApi:H,finitePendingLoadLimit:$t,hasMoreRows:Nn,loadLabel:A.t("nav.load","Load"),loadMoreLabel:A.t("button.load_more","Load more"),loadWindow:q,loadedRowCount:ge,pendingLoadLimit:Ue,refreshProgressPercent:Yr,refreshProgressText:es,refreshing:j,rowLimitChanged:Br,rowLimitSliderMax:An,rowLimitSliderValue:Gr,rowLoadModeLabel:Zr,rowLoadStatus:Jr,totalAvailableRows:Ve,onApply:os,onCancel:ss,onDraftChange:In,onLoadMore:$n,onSliderChange:is,onWindowChange:ls}),c.jsxs("div",{className:"topbar-meta",children:[c.jsxs("div",{className:"topbar-statuses",children:[w?c.jsxs("button",{className:"toolbar-button",type:"button",onClick:ps,children:[c.jsx(un,{size:15}),A.t("button.clear","Clear")," ",ll(w)]}):null,c.jsxs("label",{className:"topbar-toggle",children:[c.jsx("input",{"aria-label":"Auto refresh",type:"checkbox",checked:D,onChange:m=>ds(m.target.checked),disabled:j||!H}),c.jsx("span",{children:"Auto"})]})]}),c.jsxs("div",{className:"topbar-icon-actions",children:[c.jsx("button",{className:"icon-button",type:"button",onClick:fs,"aria-label":A.t("button.copy_link","Copy link"),title:A.t("button.copy_link","Copy link"),children:c.jsx(Ms,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:gs,"aria-label":A.t("button.export_csv","Export CSV"),title:A.t("button.export_csv","Export CSV"),children:c.jsx(js,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:On,"aria-label":A.t("button.refresh","Refresh"),title:A.t("button.refresh","Refresh"),disabled:j,children:c.jsx(Fs,{size:17})})]})]})]})]}),c.jsx("p",{className:"sr-only",role:"status","aria-live":"polite",children:_}),c.jsx(_l,{activeView:i,model:jn,navigateView:st,onRefresh:On,refreshState:_,globalQuery:g,activePreset:w,activeRecordId:d,contextRuntime:Pn,setContextApiEnabled:Mn,openCallInvestigator:ns,copyCallInvestigatorLink:ms,callBackLabel:u?`Back to ${uc(h)}`:A.t("button.back_to_dashboard","Back to dashboard"),backFromCallInvestigator:as,dashboardPayload:n,sourceIdentity:Qr,historyScope:J,loadWindow:q,scopeSince:(n==null?void 0:n.since)??Ht(q),loadLimit:G,loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,applicationI18n:A,refreshing:j,hasMoreRows:Nn,canLoadAllRows:ts,loadMoreRows:$n,loadAllRows:cs,globalFilters:c.jsx(tc,{activeView:i,locationSearch:N,model:r,onUrlChange:Ke})})]}),bt?c.jsxs("button",{className:"to-top-button",type:"button",onClick:vs,"aria-label":"Back to top",children:[c.jsx(xs,{size:18}),A.t("button.top","Top")]}):null]})});function On(){ie()}}function Ll(){return c.jsx(Li,{client:xn,children:c.jsx(Wr,{})})}const nu=Object.freeze(Object.defineProperty({__proto__:null,App:Wr,RoutedApp:Ll,shouldAutoRefreshUsageView:Hr},Symbol.toStringTag,{value:"Module"}));export{Ns as $,xs as A,Nl as B,Fi as C,js as D,Wl as E,Es as F,Cs as G,Ps as H,ba as I,Et as J,z as K,El as L,Va as M,ne as N,Zl as O,yc as P,Bl as Q,Fs as R,Is as S,Xl as T,Rs as U,Os as V,tu as W,Sa as X,Vl as Y,Ul as Z,Hl as _,Ms as a,un as a0,ll as a1,Il as a2,Fl as a3,fi as a4,ii as a5,Gt as a6,qa as a7,ri as a8,si as a9,Bt as aa,Ua as ab,_i as ac,li as ad,Dl as ae,Ol as af,ql as ag,kt as ah,da as ai,Kl as aj,Re as ak,nu as al,Ql as b,I as c,Ni as d,ce as e,be as f,Ei as g,eu as h,Yl as i,Le as j,lr as k,$l as l,Xt as m,Lr as n,Jl as o,dt as p,Gl as q,Ai as r,pa as s,zl as t,Oa as u,mr as v,$r as w,Rc as x,Lc as y,Pc as z}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js index 3de619f2..e96f8316 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js @@ -1,6 +1,6 @@ -import{r as C,j as e}from"./dashboard-react.js";import{c as Z,v as R,p as U,j as h,u as A,ad as ee,a as te,C as ae,f as F,m as Q,Y as ne,ae as se,af as le,X as oe}from"./App.js";import{f as q,t as ie,u as ce,T as re,w as de,C as ue,z as he,v as xe,x as O,y as me,A as pe,B as be,c as ge,d as K,a as B,r as $,l as je,g as ve,D as V,b as fe,e as ye,h as Ce,i as J,j as W,k as we,m as ke,n as _e,o as Ne,p as Ee,q as Se,s as Te}from"./contextEvidenceState.js";import{P as T}from"./Panel.js";import{S as z}from"./StatusBadge.js";import{C as Ie,a as Ae}from"./chevron-right.js";import{S as Le}from"./shield-check.js";import{L as Pe}from"./lock-keyhole.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** +import{r as C,j as e}from"./dashboard-react.js";import{c as G,v as R,p as U,j as h,u as A,af as ee,a as te,C as ae,f as F,Y as ne,m as Q,Z as se,ag as le,ah as oe,ai as ie,X as ce,_ as O,aj as re}from"./App.js";import{f as q,t as de,T as ue,v as he,C as xe,u as me,w as pe,x as be,c as ge,d as K,a as B,r as $,l as je,g as ve,y as V,b as fe,e as ye,h as Ce,i as J,j as W,k as we,m as ke,n as _e,o as Ne,p as Ee,q as Se,s as Te}from"./contextEvidenceState.js";import{P as T}from"./Panel.js";import{S as z}from"./StatusBadge.js";import{C as Ie,a as Ae}from"./chevron-right.js";import{S as Le}from"./shield-check.js";import{L as Pe}from"./lock-keyhole.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const X=Z("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]),D=new Map;function Re(t,n){Me(t,n);const s=`${n.apiToken}:${t}`,i=D.get(s);if(i)return i;const l=ze(t,n).finally(()=>{D.delete(s)});return D.set(s,l),l}async function ze(t,n){var o;const s=new URLSearchParams({record_id:t,_:String(Date.now())}),i=await fetch(`/api/call?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":n.apiToken},cache:"no-store"}),l=await Oe(i,"Call detail");if(!((o=l.record)!=null&&o.record_id))throw new Error("Call detail response did not include the requested aggregate record.");const u=Array.isArray(l.adjacent_records)&&l.adjacent_records.length?l.adjacent_records:[l.previous_record,l.record,l.next_record].filter(p=>!!p);return{record:R(l.record,0),previousRecord:l.previous_record?R(l.previous_record,-1):null,nextRecord:l.next_record?R(l.next_record,1):null,adjacentRecords:u.map((p,c)=>R(p,c)),rawPayload:l}}function Me(t,n){if(!t)throw new Error("record_id is required for call detail loading.");if(n.fileMode)throw new Error("Call detail hydration requires the localhost dashboard server.");if(!n.apiToken)throw new Error("Call detail hydration requires a localhost dashboard API token.")}async function Oe(t,n){let s={};try{s=await t.json()}catch{s={}}if(!t.ok){const i=typeof s.error=="string"?s.error:`${n} request failed (${t.status})`;throw new Error(i)}return s}function $e(t,n){return H(n.t("call.readout.exact_body","{input} input tokens = {cached} cached + {uncached} uncached; {output} output tokens; {cache} cache reuse."),{input:h(t.input),cached:h(t.cachedInput),uncached:h(t.uncachedInput),output:h(t.output),cache:U(t.cachedPct)})}function De(t){return t.t("call.readout.previous_unavailable","No previous call is loaded in resolved thread, call-to-call deltas unavailable.")}function qe(t,n){const s=t.uncachedInput-n.uncachedInput,i=t.cachedInput-n.cachedInput;return s>0&&i<0?`Fresh input rose by ${h(s)} while cached input fell by ${h(Math.abs(i))}; classic cache-drop profile.`:s>0?`Fresh input increased by ${h(s)} from previous call; inspect evidence new files, tool results, or rewritten context.`:s<0&&i>=0?`Fresh input fell by ${h(Math.abs(s))} while cached input increased, so this call reused context more efficiently previous one.`:"Token accounting broadly stable compared previous call in resolved thread."}function Ue(t,n){var s;if(t.status==="loaded"){const i=((s=t.payload.entries)==null?void 0:s.length)??0,l=Number(t.payload.visible_char_count??0),u=Number(t.payload.visible_token_estimate??0),o=Fe(t.payload,n);return H(n.t("call.readout.evidence_analyzed","Evidence analyzed: {totalEntries} selected-turn entries, {visibleChars} visible redacted chars, {visibleTokens} visible tokens.{serializedDetail}"),{totalEntries:h(i),visibleChars:h(l),visibleTokens:h(u),estimator:t.payload.visible_token_estimator??"visible-token estimate",serializedDetail:o,renderedEntries:h(i)})}return t.status==="loading"?n.t("call.readout.evidence_loading",t.message):t.status==="error"?`Evidence request failed: ${t.message}`:"Evidence is not loaded yet. Aggregate token counts are exact, but visible-context attribution needs runtime evidence."}function Fe(t,n){const s=t.serialized_evidence??{};if(s.deferred||s.deferred_buckets)return n.t("call.readout.evidence_serialized_deferred","Fast serialized estimate only; full serialized grouping deferred.");const i=Be(t);return i<=0?"":H(n.t("call.readout.evidence_serialized_bound"," Serialized local upper bound: {tokens} tokens."),{tokens:h(i),chars:h(Number(s.raw_json_char_count??s.total_chars??0))})}function He(t,n){const s=t.input>0?t.cachedInput/t.input:t.cachedPct/100,i=n&&n.input>0?n.cachedInput/n.input:n?n.cachedPct/100:null,l=(n==null?void 0:n.uncachedInput)??0;return n&&i!==null&&i>=.8&&s<=.05&&t.input>=1e3?"Compare previous call, then inspect loaded evidence see fresh context was sent after cache miss.":n&&t.uncachedInput>Math.max(l*2,1e3)?"Inspect most recent evidence entries first; spike is in fresh uncached input, not cached history.":s>=.85?`Cache reuse is healthy; focus on ${h(t.uncachedInput)} uncached tokens were still billed as fresh input.`:n?"Use delta cards to locate whether change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough understand this isolated call."}function Ke(t){return t==="Hydrated from /api/call"?"Position: hydrated live record outside loaded snapshot":`Position: ${t}`}function H(t,n){return t.replace(/\{(\w+)\}/g,(s,i)=>n[i]??s)}function Be(t){const n=t.serialized_evidence??{};return Number(n.raw_json_token_estimate??n.token_estimate??0)}function rt({model:t,recordId:n,contextRuntime:s,onContextApiEnabledChange:i,onNavigateRecord:l,onCopyCallLink:u,onBackToCalls:o,backLabel:p}){const c=A(),[j,b]=C.useState(""),[x,k]=C.useState({status:"idle"}),[d,w]=C.useState({status:"idle"}),[S,L]=C.useState({recordId:"",nonce:0}),I=x.status==="loaded"&&x.recordId===n?x.detail:null,{modelIndex:N,hydratedDetail:E,call:a,previous:r,next:g,threadCalls:m,positionLabel:v}=C.useMemo(()=>ee({calls:t.calls,recordId:n,detail:I}),[I,t.calls,n]),Y=d.status==="loaded"?d.payload:null;if(C.useEffect(()=>{w({status:"idle"})},[n]),C.useEffect(()=>{if(!n||N>=0){k({status:"idle"});return}if(s.fileMode||!s.apiToken){k({status:"error",recordId:n,message:"This call is outside the loaded snapshot. Serve the dashboard with its localhost API token to hydrate it."});return}let _=!1;return k({status:"loading",recordId:n,message:"Loading call detail from localhost..."}),Re(n,s).then(P=>{_||k({status:"loaded",recordId:n,detail:P})}).catch(P=>{_||k({status:"error",recordId:n,message:q(P)})}),()=>{_=!0}},[s,N,n]),!a){const _=x.status==="loading"||x.status==="error"?x.message:n?"Selected call is not present in the loaded dashboard rows.":"No aggregate call rows are loaded.";return e.jsx("div",{className:"page-grid",children:e.jsxs("div",{className:"page-title-row",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsx("p",{children:_})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]})]})})}async function G(){try{const _=new URL(window.location.href);if(se(_,"call",le(_.search)),!await oe(_.toString()))throw new Error("Clipboard unavailable");b("Copied investigator link")}catch{b("Copy unavailable in this browser")}}return e.jsxs("div",{className:"call-investigator-layout",children:[e.jsxs("div",{className:"page-title-row span-all",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsxs("p",{children:[a.thread," / ",a.model]})]}),e.jsxs("div",{className:"toolbar",children:[e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>r&&l(r.id),disabled:!r,children:[e.jsx(Ie,{size:16})," ",c.t("button.previous_call","Previous call")]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>g&&l(g.id),disabled:!g,children:[c.t("button.next_call","Next call")," ",e.jsx(Ae,{size:16})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:G,"aria-label":c.t("button.copy_investigator_link","Copy investigator link"),children:[e.jsx(te,{size:16})," ",c.t("button.copy_link","Copy link")]})]})]}),e.jsxs(T,{title:c.t("call.readout.title","Investigation Readout"),subtitle:j||v,className:"span-all",action:e.jsx(z,{label:c.t("call.readout.badge","Aggregate + on-demand evidence"),tone:"blue"}),children:[e.jsxs("div",{className:"call-summary",children:[e.jsx(z,{label:"Aggregate only",tone:"green"}),E?e.jsx(z,{label:"Hydrated live",tone:"blue"}):null,e.jsx(ae,{call:a}),e.jsx(z,{label:"Raw context gated",tone:"blue"}),e.jsx("span",{className:"call-id",children:a.id.slice(0,16)})]}),e.jsx(Ve,{call:a,previous:r,evidenceState:d,positionLabel:v}),e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Total tokens",value:h(a.totalTokens),detail:`${F(a.input)} input`}),e.jsx(f,{label:"Uncached input",value:h(a.uncachedInput),detail:"fresh billed input"}),e.jsx(f,{label:"Cache hit rate",value:U(a.cachedPct),detail:ie(a)}),e.jsx(f,{label:"Estimated cost",value:Q(a.cost),detail:a.pricingEstimated?"estimated pricing":"configured pricing"}),e.jsx(f,{label:"Duration",value:a.duration,detail:ne(a)}),e.jsx(f,{label:"Usage credits",value:a.credits?a.credits.toFixed(3):"-",detail:a.usageCreditConfidence})]}),e.jsx(ce,{call:a})]}),e.jsxs(T,{title:"Token Accounting",subtitle:"Exact aggregate row fields",children:[e.jsx(Ye,{call:a}),e.jsx(re,{call:a})]}),e.jsx(T,{title:"Cache Accounting",subtitle:"Derived from adjacent aggregate call",children:e.jsx(de,{call:a,calls:m})}),e.jsx(T,{title:"Context Attribution",subtitle:"Estimated from visible log volume",className:"span-all",children:e.jsx(ue,{call:a,payload:Y,onRunFullAnalysis:()=>L(_=>({recordId:a.id,nonce:_.nonce+1})),showHeading:!1})}),e.jsxs(T,{title:"Aggregate Identity",subtitle:"Local metadata only",children:[e.jsxs("dl",{className:"detail-list",children:[e.jsx(y,{label:"Record id",value:a.id}),e.jsx(y,{label:"Time",value:a.time}),e.jsx(y,{label:"Thread",value:a.thread}),e.jsx(y,{label:"Model",value:a.model}),e.jsx(y,{label:"Effort",value:a.effort}),e.jsx(y,{label:"Project",value:a.project||"Unknown"}),e.jsx(y,{label:"Context window",value:he(a)}),e.jsx(y,{label:"Recommendation",value:a.recommendation||"No aggregate recommendation"})]}),e.jsx(xe,{call:a}),a.recommendation?e.jsxs("div",{className:"recommendation-box",children:[e.jsx(Le,{size:16}),e.jsx("p",{children:a.recommendation})]}):null]}),e.jsx(T,{title:"Thread Context",subtitle:`${m.length} loaded related calls`,className:"span-all",children:e.jsx(Qe,{call:a,calls:m,onNavigateRecord:l,onCopyCallLink:u})}),e.jsx(T,{title:"Raw Evidence",subtitle:"Explicit localhost request only",className:"span-all",children:e.jsx(Je,{call:a,contextRuntime:s,onContextApiEnabledChange:i,onEvidenceStateChange:w,fullAnalysisRequestNonce:S.recordId===a.id?S.nonce:0},a.id)})]})}function Ve({call:t,previous:n,evidenceState:s,positionLabel:i}){const l=A();return e.jsxs("div",{className:"investigation-readout-grid",children:[e.jsx(M,{label:l.t("call.readout.exact_label","Exact callback accounting"),body:$e(t,l)}),e.jsx(M,{label:l.t("call.readout.previous_label","Compared previous call"),body:n?qe(t,n):De(l)}),e.jsx(M,{label:l.t("call.readout.evidence_label","Evidence state"),body:Ue(s,l)}),e.jsx(M,{label:l.t("call.readout.next_label","Next diagnostic move"),body:He(t,n),detail:Ke(i)})]})}function M({label:t,body:n,detail:s}){return e.jsxs("div",{className:"investigation-readout-card",children:[e.jsx("span",{children:t}),e.jsx("p",{children:n}),s?e.jsx("small",{children:s}):null]})}function Je({call:t,contextRuntime:n,onContextApiEnabledChange:s,onEvidenceStateChange:i,fullAnalysisRequestNonce:l}){const u=A(),[o,p]=C.useState(()=>be(window.location.search,ge(t.id)??K)),[c,j]=C.useState({status:"idle"}),b=!!n.apiToken&&!n.fileMode,x=b&&n.contextApiEnabled;C.useEffect(()=>{const a=B(t.id,o);j(a?{status:"loaded",payload:a}:{status:"idle"})},[t.id,o.includeToolOutput,o.includeCompactionHistory,o.maxChars,o.maxEntries,o.mode]),C.useEffect(()=>{i(c)},[c,i]),C.useEffect(()=>{if(l<=0||!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")},[l]);async function k(){j({status:"loading",message:"Enabling localhost context API..."});try{const a=await ye(n);s(a),j({status:"idle",message:a?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(a){j({status:"error",message:q(a)})}}async function d(a=o,r="Loading selected-turn evidence..."){$(t.id,a);const g=B(t.id,a);if(g){j({status:"loaded",payload:g});return}j({status:"loading",message:r});try{const m=await je(t.id,n,a);ve(t.id,a,m),j({status:"loaded",payload:m})}catch(m){j({status:"error",message:q(m)})}}function w(){if(!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")}function S(a){const r=Ee(a,o);N(r),d(r,"Loading older context...")}function L(){const a={...o,includeToolOutput:!0};N(a),d(a,"Loading omitted tool output...")}function I(){const a={...o,includeCompactionHistory:!0};N(a),d(a,"Loading compacted replacement...")}function N(a){p(a),$(t.id,a);const r=new URL(window.location.href);V(r,a),window.history.replaceState(null,"",r)}function E(a,r){p(g=>{const m={...g,[a]:r};$(t.id,m);const v=new URL(window.location.href);return V(v,m),window.history.replaceState(null,"",v),m})}return e.jsxs("div",{className:"investigator-evidence",children:[e.jsxs("div",{className:"locked-context-card",children:[e.jsx(Pe,{size:20}),e.jsxs("div",{children:[e.jsx("strong",{children:"Raw context is gated"}),e.jsx("p",{children:fe(n)})]})]}),e.jsxs("div",{className:"context-action-grid",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:k,disabled:!b||n.contextApiEnabled||c.status==="loading",children:u.t("button.enable_context_loading","Enable context loading")}),e.jsx("button",{className:"primary-button",type:"button",onClick:()=>d(),disabled:!x||c.status==="loading",children:u.t("button.show_turn_evidence","Show turn log evidence")}),e.jsx("button",{className:"toolbar-button",type:"button",onClick:w,disabled:!x||c.status==="loading",children:u.t("button.full_serialized_analysis","Run full serialized analysis")}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Mode"}),e.jsxs("select",{"aria-label":"Context mode",value:o.mode,disabled:!x||c.status==="loading",onChange:a=>E("mode",a.target.value==="full"?"full":"quick"),children:[e.jsx("option",{value:"quick",children:"Quick"}),e.jsx("option",{value:"full",children:"Full"})]})]}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Entries"}),e.jsxs("select",{"aria-label":"Context entries",value:String(o.maxEntries),disabled:!x||c.status==="loading",onChange:a=>E("maxEntries",Number(a.target.value)),children:[e.jsx("option",{value:"20",children:"20"}),e.jsx("option",{value:"50",children:"50"}),e.jsx("option",{value:"100",children:"100"}),e.jsx("option",{value:"0",children:"All"})]})]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeToolOutput,disabled:!x||c.status==="loading",onChange:a=>E("includeToolOutput",a.target.checked)}),u.t("button.include_tool_output","Include tool output")]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeCompactionHistory,disabled:!x||c.status==="loading",onChange:a=>E("includeCompactionHistory",a.target.checked)}),"Include compaction history"]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.maxChars===0,disabled:!x||c.status==="loading",onChange:a=>E("maxChars",a.target.checked?0:K.maxChars)}),u.t("button.no_char_limit","No char limit")]})]}),c.status==="idle"&&c.message?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="loading"?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="error"?e.jsx("p",{className:"context-state-note error",children:c.message}):null,c.status==="loaded"?e.jsx(We,{payload:c.payload,onLoadOlder:S,onLoadCompactionHistory:I,onLoadToolOutput:L}):null,e.jsx("p",{className:"privacy-note",children:"Raw context is read from the local JSONL source only after this explicit action and is not embedded in static dashboard HTML."})]})}function We({payload:t,onLoadOlder:n,onLoadCompactionHistory:s,onLoadToolOutput:i}){var E,a;const l=A(),u=t.entries??[],o=t.omitted??{},p=Number(o.older_entries??0),c=Ce(t),j=10,b=String(t.record_id??""),[x,k]=C.useState(()=>J(b)),[d,w]=C.useState(()=>W(b,u));C.useEffect(()=>{k(J(b)),w(W(b,u))},[u.length,t.context_mode,t.include_compaction_history,t.include_tool_output,(E=t.omitted)==null?void 0:E.max_chars,(a=t.omitted)==null?void 0:a.max_entries,t.record_id,b]);const S=x?u:u.slice(0,j),L=Math.max(u.length-S.length,0);function I(){k(r=>{const g=!r;return Te(b,g),g})}function N(r,g){Se(b,r,g),w(m=>{const v=new Set(m);return g?v.add(r):v.delete(r),v})}return e.jsxs("div",{className:"context-evidence",children:[e.jsxs("div",{className:"context-evidence-summary",children:[e.jsx(f,{label:"Entries",value:h(u.length),detail:String(t.context_mode??"quick")}),e.jsx(f,{label:"Visible chars",value:h(Number(t.visible_char_count??0)),detail:"redacted local text"}),e.jsx(f,{label:"Visible tokens",value:h(Number(t.visible_token_estimate??0)),detail:"estimator"}),e.jsx(f,{label:"Older omitted",value:h(p),detail:"entry budget"})]}),c.length?e.jsx("p",{className:"context-note",children:c.join(" ")}):null,p>0?e.jsx("div",{className:"context-followup-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>n(t),children:l.t("button.load_older_context","Load older entries")})}):null,e.jsxs("div",{className:"context-entry-list",children:[S.map((r,g)=>{const m=we(r,g);return e.jsxs("details",{className:"context-entry",open:d.has(m),onToggle:v=>N(m,v.currentTarget.open),children:[e.jsx("summary",{className:"context-entry-summary",children:e.jsxs("div",{className:"context-entry-meta",children:[e.jsx("strong",{children:r.label||r.role||r.type||`Entry ${g+1}`}),e.jsx("span",{children:r.line_number?`line ${r.line_number}`:r.timestamp||"local evidence"})]})}),e.jsx(ke,{entry:r}),r.tool_output_omitted?e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:i,children:l.t("button.show_tool_output","Show tool output")})}):null,e.jsx(Xe,{entry:r,onLoadCompactionHistory:s}),e.jsx("pre",{ref:v=>{v&&(v.scrollTop=Ne(b,m))},onScroll:v=>_e(b,m,v.currentTarget.scrollTop),children:r.text||"[no visible text]"})]},m)}),u.length?null:e.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),u.length>j?e.jsxs("div",{className:"context-followup-actions",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:I,children:x?`Show first ${h(j)} entries`:`Show all ${h(u.length)} returned entries`}),x?null:e.jsxs("span",{className:"context-entry-count-note",children:[h(L)," entries hidden in compact view"]})]}):null]})}function Xe({entry:t,onLoadCompactionHistory:n}){const s=A(),i=t.compaction;if(!(i!=null&&i.replacement_history_available))return null;const l=i.replacement_history??[],u=Number(i.replacement_entry_count??l.length);return e.jsxs("div",{className:"context-entry-compaction",children:[e.jsx("strong",{children:"Compaction detected"}),e.jsxs("span",{children:[h(u)," replacement history entries available."]}),l.length?e.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:l.map((o,p)=>e.jsxs("div",{className:"context-replacement-entry",children:[e.jsx("strong",{children:o.label||`Replacement item ${p+1}`}),e.jsx("pre",{children:o.text||"[no visible replacement text]"})]},`${o.label??"replacement"}-${p}`))}):e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}function Qe({call:t,calls:n,onNavigateRecord:s,onCopyCallLink:i}){const u=A().t("button.copy_link","Copy link"),o=n.length?n:[t],p=Math.max(o.findIndex(d=>d.id===t.id),0),c=o.reduce((d,w)=>d+w.totalTokens,0),j=o.reduce((d,w)=>d+w.cost,0),b=o.reduce((d,w)=>d+w.cachedPct,0)/Math.max(o.length,1),x=o.filter(d=>Number(d.contextWindowPct??0)>=60).length,k=o.filter(d=>d.cachedPct<25||d.signal==="cache-risk").length;return e.jsxs("div",{className:"thread-context-module",children:[e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Thread calls",value:h(o.length),detail:`selected ${p+1} of ${o.length}`}),e.jsx(f,{label:"Thread tokens",value:F(c),detail:"loaded aggregate rows"}),e.jsx(f,{label:"Thread cost",value:Q(j),detail:"estimated aggregate"}),e.jsx(f,{label:"Avg cache",value:U(b),detail:O(o.map(d=>d.model))}),e.jsx(f,{label:"Cache risks",value:h(k),detail:"weak reuse or flagged"}),e.jsx(f,{label:"Context pressure",value:h(x),detail:">=60% context window"})]}),e.jsxs("div",{className:"thread-context-grid",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Thread timeline"}),e.jsx(me,{selectedCall:t,calls:o,onOpenInvestigator:s,onCopyCallLink:i,className:"investigator-thread-timeline",copyAriaContext:"thread context call",copyLabel:u})]}),e.jsxs("dl",{className:"detail-list compact",children:[e.jsx(y,{label:"Project",value:t.project||"Unknown"}),e.jsx(y,{label:"Project path",value:t.projectRelativeCwd||t.cwd||"."}),e.jsx(y,{label:"Source line",value:pe(t)}),e.jsx(y,{label:"Session",value:t.sessionId||"Not available"}),e.jsx(y,{label:"Parent thread",value:t.parentThread||"None"}),e.jsx(y,{label:"Models in thread",value:O(o.map(d=>d.model),{limit:3})}),e.jsx(y,{label:"Effort mix",value:O(o.map(d=>d.effort),{limit:3})})]})]})]})}function f({label:t,value:n,detail:s}){return e.jsxs("span",{className:"drilldown-metric",children:[e.jsx("small",{children:t}),e.jsx("strong",{children:n}),e.jsx("em",{children:s})]})}function y({label:t,value:n}){return e.jsxs("div",{children:[e.jsx("dt",{children:t}),e.jsx("dd",{children:n})]})}function Ye({call:t}){const s=[{label:"Cached input",value:Math.max(t.input-t.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:t.uncachedInput,color:"#f59e0b"},{label:"Output",value:t.output,color:"#059669"},{label:"Reasoning",value:t.reasoningOutput,color:"#7c3aed"}].filter(l=>l.value>0),i=Math.max(s.reduce((l,u)=>l+u.value,0),1);return e.jsxs("div",{className:"composition-card",children:[e.jsxs("div",{className:"composition-head",children:[e.jsx("strong",{children:"Token composition"}),e.jsxs("span",{children:[F(i)," visible tokens"]})]}),e.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(l=>e.jsx("i",{style:{width:`${Math.max(l.value/i*100,3)}%`,background:l.color}},l.label))}),e.jsx("div",{className:"composition-legend",children:s.map(l=>e.jsxs("span",{children:[e.jsx("i",{style:{background:l.color}}),l.label]},l.label))})]})}export{rt as CallInvestigatorPage}; + */const X=G("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]),D=new Map;function Re(t,n){Me(t,n);const s=`${n.apiToken}:${t}`,i=D.get(s);if(i)return i;const l=ze(t,n).finally(()=>{D.delete(s)});return D.set(s,l),l}async function ze(t,n){var o;const s=new URLSearchParams({record_id:t,_:String(Date.now())}),i=await fetch(`/api/call?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":n.apiToken},cache:"no-store"}),l=await Oe(i,"Call detail");if(!((o=l.record)!=null&&o.record_id))throw new Error("Call detail response did not include the requested aggregate record.");const u=Array.isArray(l.adjacent_records)&&l.adjacent_records.length?l.adjacent_records:[l.previous_record,l.record,l.next_record].filter(p=>!!p);return{record:R(l.record,0),previousRecord:l.previous_record?R(l.previous_record,-1):null,nextRecord:l.next_record?R(l.next_record,1):null,adjacentRecords:u.map((p,c)=>R(p,c)),rawPayload:l}}function Me(t,n){if(!t)throw new Error("record_id is required for call detail loading.");if(n.fileMode)throw new Error("Call detail hydration requires the localhost dashboard server.");if(!n.apiToken)throw new Error("Call detail hydration requires a localhost dashboard API token.")}async function Oe(t,n){let s={};try{s=await t.json()}catch{s={}}if(!t.ok){const i=typeof s.error=="string"?s.error:`${n} request failed (${t.status})`;throw new Error(i)}return s}function $e(t,n){return H(n.t("call.readout.exact_body","{input} input tokens = {cached} cached + {uncached} uncached; {output} output tokens; {cache} cache reuse."),{input:h(t.input),cached:h(t.cachedInput),uncached:h(t.uncachedInput),output:h(t.output),cache:U(t.cachedPct)})}function De(t){return t.t("call.readout.previous_unavailable","No previous call is loaded in resolved thread, call-to-call deltas unavailable.")}function qe(t,n){const s=t.uncachedInput-n.uncachedInput,i=t.cachedInput-n.cachedInput;return s>0&&i<0?`Fresh input rose by ${h(s)} while cached input fell by ${h(Math.abs(i))}; classic cache-drop profile.`:s>0?`Fresh input increased by ${h(s)} from previous call; inspect evidence new files, tool results, or rewritten context.`:s<0&&i>=0?`Fresh input fell by ${h(Math.abs(s))} while cached input increased, so this call reused context more efficiently previous one.`:"Token accounting broadly stable compared previous call in resolved thread."}function Ue(t,n){var s;if(t.status==="loaded"){const i=((s=t.payload.entries)==null?void 0:s.length)??0,l=Number(t.payload.visible_char_count??0),u=Number(t.payload.visible_token_estimate??0),o=Fe(t.payload,n);return H(n.t("call.readout.evidence_analyzed","Evidence analyzed: {totalEntries} selected-turn entries, {visibleChars} visible redacted chars, {visibleTokens} visible tokens.{serializedDetail}"),{totalEntries:h(i),visibleChars:h(l),visibleTokens:h(u),estimator:t.payload.visible_token_estimator??"visible-token estimate",serializedDetail:o,renderedEntries:h(i)})}return t.status==="loading"?n.t("call.readout.evidence_loading",t.message):t.status==="error"?`Evidence request failed: ${t.message}`:"Evidence is not loaded yet. Aggregate token counts are exact, but visible-context attribution needs runtime evidence."}function Fe(t,n){const s=t.serialized_evidence??{};if(s.deferred||s.deferred_buckets)return n.t("call.readout.evidence_serialized_deferred","Fast serialized estimate only; full serialized grouping deferred.");const i=Be(t);return i<=0?"":H(n.t("call.readout.evidence_serialized_bound"," Serialized local upper bound: {tokens} tokens."),{tokens:h(i),chars:h(Number(s.raw_json_char_count??s.total_chars??0))})}function He(t,n){const s=t.input>0?t.cachedInput/t.input:t.cachedPct/100,i=n&&n.input>0?n.cachedInput/n.input:n?n.cachedPct/100:null,l=(n==null?void 0:n.uncachedInput)??0;return n&&i!==null&&i>=.8&&s<=.05&&t.input>=1e3?"Compare previous call, then inspect loaded evidence see fresh context was sent after cache miss.":n&&t.uncachedInput>Math.max(l*2,1e3)?"Inspect most recent evidence entries first; spike is in fresh uncached input, not cached history.":s>=.85?`Cache reuse is healthy; focus on ${h(t.uncachedInput)} uncached tokens were still billed as fresh input.`:n?"Use delta cards to locate whether change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough understand this isolated call."}function Ke(t){return t==="Hydrated from /api/call"?"Position: hydrated live record outside loaded snapshot":`Position: ${t}`}function H(t,n){return t.replace(/\{(\w+)\}/g,(s,i)=>n[i]??s)}function Be(t){const n=t.serialized_evidence??{};return Number(n.raw_json_token_estimate??n.token_estimate??0)}function rt({model:t,recordId:n,contextRuntime:s,onContextApiEnabledChange:i,onNavigateRecord:l,onCopyCallLink:u,onBackToCalls:o,backLabel:p}){const c=A(),[j,b]=C.useState(""),[x,k]=C.useState({status:"idle"}),[d,w]=C.useState({status:"idle"}),[S,L]=C.useState({recordId:"",nonce:0}),I=x.status==="loaded"&&x.recordId===n?x.detail:null,{modelIndex:N,hydratedDetail:E,call:a,previous:r,next:g,threadCalls:m,positionLabel:v}=C.useMemo(()=>ee({calls:t.calls,recordId:n,detail:I}),[I,t.calls,n]),Y=d.status==="loaded"?d.payload:null;if(C.useEffect(()=>{w({status:"idle"})},[n]),C.useEffect(()=>{if(!n||N>=0){k({status:"idle"});return}if(s.fileMode||!s.apiToken){k({status:"error",recordId:n,message:"This call is outside the loaded snapshot. Serve the dashboard with its localhost API token to hydrate it."});return}let _=!1;return k({status:"loading",recordId:n,message:"Loading call detail from localhost..."}),Re(n,s).then(P=>{_||k({status:"loaded",recordId:n,detail:P})}).catch(P=>{_||k({status:"error",recordId:n,message:q(P)})}),()=>{_=!0}},[s,N,n]),!a){const _=x.status==="loading"||x.status==="error"?x.message:n?"Selected call is not present in the loaded dashboard rows.":"No aggregate call rows are loaded.";return e.jsx("div",{className:"page-grid",children:e.jsxs("div",{className:"page-title-row",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsx("p",{children:_})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]})]})})}async function Z(){try{const _=new URL(window.location.href);if(oe(_,"call",ie(_.search)),!await ce(_.toString()))throw new Error("Clipboard unavailable");b("Copied investigator link")}catch{b("Copy unavailable in this browser")}}return e.jsxs("div",{className:"call-investigator-layout",children:[e.jsxs("div",{className:"page-title-row span-all",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsxs("p",{children:[a.thread," / ",a.model]})]}),e.jsxs("div",{className:"toolbar",children:[e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>r&&l(r.id),disabled:!r,children:[e.jsx(Ie,{size:16})," ",c.t("button.previous_call","Previous call")]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>g&&l(g.id),disabled:!g,children:[c.t("button.next_call","Next call")," ",e.jsx(Ae,{size:16})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:Z,"aria-label":c.t("button.copy_investigator_link","Copy investigator link"),children:[e.jsx(te,{size:16})," ",c.t("button.copy_link","Copy link")]})]})]}),e.jsxs(T,{title:c.t("call.readout.title","Investigation Readout"),subtitle:j||v,className:"span-all",action:e.jsx(z,{label:c.t("call.readout.badge","Aggregate + on-demand evidence"),tone:"blue"}),children:[e.jsxs("div",{className:"call-summary",children:[e.jsx(z,{label:"Aggregate only",tone:"green"}),E?e.jsx(z,{label:"Hydrated live",tone:"blue"}):null,e.jsx(ae,{call:a}),e.jsx(z,{label:"Raw context gated",tone:"blue"}),e.jsx("span",{className:"call-id",children:a.id.slice(0,16)})]}),e.jsx(Ve,{call:a,previous:r,evidenceState:d,positionLabel:v}),e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Total tokens",value:h(a.totalTokens),detail:`${F(a.input)} input`}),e.jsx(f,{label:"Uncached input",value:h(a.uncachedInput),detail:"fresh billed input"}),e.jsx(f,{label:"Cache hit rate",value:U(a.cachedPct),detail:ne(a)}),e.jsx(f,{label:"Estimated cost",value:Q(a.cost),detail:a.pricingEstimated?"estimated pricing":"configured pricing"}),e.jsx(f,{label:"Duration",value:a.duration,detail:se(a)}),e.jsx(f,{label:"Usage credits",value:a.credits?a.credits.toFixed(3):"-",detail:a.usageCreditConfidence})]}),e.jsx(de,{call:a})]}),e.jsxs(T,{title:"Token Accounting",subtitle:"Exact aggregate row fields",children:[e.jsx(Ye,{call:a}),e.jsx(ue,{call:a})]}),e.jsx(T,{title:"Cache Accounting",subtitle:"Derived from adjacent aggregate call",children:e.jsx(he,{call:a,calls:m})}),e.jsx(T,{title:"Context Attribution",subtitle:"Estimated from visible log volume",className:"span-all",children:e.jsx(xe,{call:a,payload:Y,onRunFullAnalysis:()=>L(_=>({recordId:a.id,nonce:_.nonce+1})),showHeading:!1})}),e.jsxs(T,{title:"Aggregate Identity",subtitle:"Local metadata only",children:[e.jsxs("dl",{className:"detail-list",children:[e.jsx(y,{label:"Record id",value:a.id}),e.jsx(y,{label:"Time",value:a.time}),e.jsx(y,{label:"Thread",value:a.thread}),e.jsx(y,{label:"Model",value:a.model}),e.jsx(y,{label:"Effort",value:a.effort}),e.jsx(y,{label:"Project",value:a.project||"Unknown"}),e.jsx(y,{label:"Context window",value:le(a)}),e.jsx(y,{label:"Recommendation",value:a.recommendation||"No aggregate recommendation"})]}),e.jsx(me,{call:a}),a.recommendation?e.jsxs("div",{className:"recommendation-box",children:[e.jsx(Le,{size:16}),e.jsx("p",{children:a.recommendation})]}):null]}),e.jsx(T,{title:"Thread Context",subtitle:`${m.length} loaded related calls`,className:"span-all",children:e.jsx(Qe,{call:a,calls:m,onNavigateRecord:l,onCopyCallLink:u})}),e.jsx(T,{title:"Raw Evidence",subtitle:"Explicit localhost request only",className:"span-all",children:e.jsx(Je,{call:a,contextRuntime:s,onContextApiEnabledChange:i,onEvidenceStateChange:w,fullAnalysisRequestNonce:S.recordId===a.id?S.nonce:0},a.id)})]})}function Ve({call:t,previous:n,evidenceState:s,positionLabel:i}){const l=A();return e.jsxs("div",{className:"investigation-readout-grid",children:[e.jsx(M,{label:l.t("call.readout.exact_label","Exact callback accounting"),body:$e(t,l)}),e.jsx(M,{label:l.t("call.readout.previous_label","Compared previous call"),body:n?qe(t,n):De(l)}),e.jsx(M,{label:l.t("call.readout.evidence_label","Evidence state"),body:Ue(s,l)}),e.jsx(M,{label:l.t("call.readout.next_label","Next diagnostic move"),body:He(t,n),detail:Ke(i)})]})}function M({label:t,body:n,detail:s}){return e.jsxs("div",{className:"investigation-readout-card",children:[e.jsx("span",{children:t}),e.jsx("p",{children:n}),s?e.jsx("small",{children:s}):null]})}function Je({call:t,contextRuntime:n,onContextApiEnabledChange:s,onEvidenceStateChange:i,fullAnalysisRequestNonce:l}){const u=A(),[o,p]=C.useState(()=>be(window.location.search,ge(t.id)??K)),[c,j]=C.useState({status:"idle"}),b=!!n.apiToken&&!n.fileMode,x=b&&n.contextApiEnabled;C.useEffect(()=>{const a=B(t.id,o);j(a?{status:"loaded",payload:a}:{status:"idle"})},[t.id,o.includeToolOutput,o.includeCompactionHistory,o.maxChars,o.maxEntries,o.mode]),C.useEffect(()=>{i(c)},[c,i]),C.useEffect(()=>{if(l<=0||!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")},[l]);async function k(){j({status:"loading",message:"Enabling localhost context API..."});try{const a=await ye(n);s(a),j({status:"idle",message:a?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(a){j({status:"error",message:q(a)})}}async function d(a=o,r="Loading selected-turn evidence..."){$(t.id,a);const g=B(t.id,a);if(g){j({status:"loaded",payload:g});return}j({status:"loading",message:r});try{const m=await je(t.id,n,a);ve(t.id,a,m),j({status:"loaded",payload:m})}catch(m){j({status:"error",message:q(m)})}}function w(){if(!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")}function S(a){const r=Ee(a,o);N(r),d(r,"Loading older context...")}function L(){const a={...o,includeToolOutput:!0};N(a),d(a,"Loading omitted tool output...")}function I(){const a={...o,includeCompactionHistory:!0};N(a),d(a,"Loading compacted replacement...")}function N(a){p(a),$(t.id,a);const r=new URL(window.location.href);V(r,a),window.history.replaceState(null,"",r)}function E(a,r){p(g=>{const m={...g,[a]:r};$(t.id,m);const v=new URL(window.location.href);return V(v,m),window.history.replaceState(null,"",v),m})}return e.jsxs("div",{className:"investigator-evidence",children:[e.jsxs("div",{className:"locked-context-card",children:[e.jsx(Pe,{size:20}),e.jsxs("div",{children:[e.jsx("strong",{children:"Raw context is gated"}),e.jsx("p",{children:fe(n)})]})]}),e.jsxs("div",{className:"context-action-grid",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:k,disabled:!b||n.contextApiEnabled||c.status==="loading",children:u.t("button.enable_context_loading","Enable context loading")}),e.jsx("button",{className:"primary-button",type:"button",onClick:()=>d(),disabled:!x||c.status==="loading",children:u.t("button.show_turn_evidence","Show turn log evidence")}),e.jsx("button",{className:"toolbar-button",type:"button",onClick:w,disabled:!x||c.status==="loading",children:u.t("button.full_serialized_analysis","Run full serialized analysis")}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Mode"}),e.jsxs("select",{"aria-label":"Context mode",value:o.mode,disabled:!x||c.status==="loading",onChange:a=>E("mode",a.target.value==="full"?"full":"quick"),children:[e.jsx("option",{value:"quick",children:"Quick"}),e.jsx("option",{value:"full",children:"Full"})]})]}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Entries"}),e.jsxs("select",{"aria-label":"Context entries",value:String(o.maxEntries),disabled:!x||c.status==="loading",onChange:a=>E("maxEntries",Number(a.target.value)),children:[e.jsx("option",{value:"20",children:"20"}),e.jsx("option",{value:"50",children:"50"}),e.jsx("option",{value:"100",children:"100"}),e.jsx("option",{value:"0",children:"All"})]})]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeToolOutput,disabled:!x||c.status==="loading",onChange:a=>E("includeToolOutput",a.target.checked)}),u.t("button.include_tool_output","Include tool output")]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeCompactionHistory,disabled:!x||c.status==="loading",onChange:a=>E("includeCompactionHistory",a.target.checked)}),"Include compaction history"]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.maxChars===0,disabled:!x||c.status==="loading",onChange:a=>E("maxChars",a.target.checked?0:K.maxChars)}),u.t("button.no_char_limit","No char limit")]})]}),c.status==="idle"&&c.message?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="loading"?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="error"?e.jsx("p",{className:"context-state-note error",children:c.message}):null,c.status==="loaded"?e.jsx(We,{payload:c.payload,onLoadOlder:S,onLoadCompactionHistory:I,onLoadToolOutput:L}):null,e.jsx("p",{className:"privacy-note",children:"Raw context is read from the local JSONL source only after this explicit action and is not embedded in static dashboard HTML."})]})}function We({payload:t,onLoadOlder:n,onLoadCompactionHistory:s,onLoadToolOutput:i}){var E,a;const l=A(),u=t.entries??[],o=t.omitted??{},p=Number(o.older_entries??0),c=Ce(t),j=10,b=String(t.record_id??""),[x,k]=C.useState(()=>J(b)),[d,w]=C.useState(()=>W(b,u));C.useEffect(()=>{k(J(b)),w(W(b,u))},[u.length,t.context_mode,t.include_compaction_history,t.include_tool_output,(E=t.omitted)==null?void 0:E.max_chars,(a=t.omitted)==null?void 0:a.max_entries,t.record_id,b]);const S=x?u:u.slice(0,j),L=Math.max(u.length-S.length,0);function I(){k(r=>{const g=!r;return Te(b,g),g})}function N(r,g){Se(b,r,g),w(m=>{const v=new Set(m);return g?v.add(r):v.delete(r),v})}return e.jsxs("div",{className:"context-evidence",children:[e.jsxs("div",{className:"context-evidence-summary",children:[e.jsx(f,{label:"Entries",value:h(u.length),detail:String(t.context_mode??"quick")}),e.jsx(f,{label:"Visible chars",value:h(Number(t.visible_char_count??0)),detail:"redacted local text"}),e.jsx(f,{label:"Visible tokens",value:h(Number(t.visible_token_estimate??0)),detail:"estimator"}),e.jsx(f,{label:"Older omitted",value:h(p),detail:"entry budget"})]}),c.length?e.jsx("p",{className:"context-note",children:c.join(" ")}):null,p>0?e.jsx("div",{className:"context-followup-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>n(t),children:l.t("button.load_older_context","Load older entries")})}):null,e.jsxs("div",{className:"context-entry-list",children:[S.map((r,g)=>{const m=we(r,g);return e.jsxs("details",{className:"context-entry",open:d.has(m),onToggle:v=>N(m,v.currentTarget.open),children:[e.jsx("summary",{className:"context-entry-summary",children:e.jsxs("div",{className:"context-entry-meta",children:[e.jsx("strong",{children:r.label||r.role||r.type||`Entry ${g+1}`}),e.jsx("span",{children:r.line_number?`line ${r.line_number}`:r.timestamp||"local evidence"})]})}),e.jsx(ke,{entry:r}),r.tool_output_omitted?e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:i,children:l.t("button.show_tool_output","Show tool output")})}):null,e.jsx(Xe,{entry:r,onLoadCompactionHistory:s}),e.jsx("pre",{ref:v=>{v&&(v.scrollTop=Ne(b,m))},onScroll:v=>_e(b,m,v.currentTarget.scrollTop),children:r.text||"[no visible text]"})]},m)}),u.length?null:e.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),u.length>j?e.jsxs("div",{className:"context-followup-actions",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:I,children:x?`Show first ${h(j)} entries`:`Show all ${h(u.length)} returned entries`}),x?null:e.jsxs("span",{className:"context-entry-count-note",children:[h(L)," entries hidden in compact view"]})]}):null]})}function Xe({entry:t,onLoadCompactionHistory:n}){const s=A(),i=t.compaction;if(!(i!=null&&i.replacement_history_available))return null;const l=i.replacement_history??[],u=Number(i.replacement_entry_count??l.length);return e.jsxs("div",{className:"context-entry-compaction",children:[e.jsx("strong",{children:"Compaction detected"}),e.jsxs("span",{children:[h(u)," replacement history entries available."]}),l.length?e.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:l.map((o,p)=>e.jsxs("div",{className:"context-replacement-entry",children:[e.jsx("strong",{children:o.label||`Replacement item ${p+1}`}),e.jsx("pre",{children:o.text||"[no visible replacement text]"})]},`${o.label??"replacement"}-${p}`))}):e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}function Qe({call:t,calls:n,onNavigateRecord:s,onCopyCallLink:i}){const u=A().t("button.copy_link","Copy link"),o=n.length?n:[t],p=Math.max(o.findIndex(d=>d.id===t.id),0),c=o.reduce((d,w)=>d+w.totalTokens,0),j=o.reduce((d,w)=>d+w.cost,0),b=o.reduce((d,w)=>d+w.cachedPct,0)/Math.max(o.length,1),x=o.filter(d=>Number(d.contextWindowPct??0)>=60).length,k=o.filter(d=>d.cachedPct<25||d.signal==="cache-risk").length;return e.jsxs("div",{className:"thread-context-module",children:[e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Thread calls",value:h(o.length),detail:`selected ${p+1} of ${o.length}`}),e.jsx(f,{label:"Thread tokens",value:F(c),detail:"loaded aggregate rows"}),e.jsx(f,{label:"Thread cost",value:Q(j),detail:"estimated aggregate"}),e.jsx(f,{label:"Avg cache",value:U(b),detail:O(o.map(d=>d.model))}),e.jsx(f,{label:"Cache risks",value:h(k),detail:"weak reuse or flagged"}),e.jsx(f,{label:"Context pressure",value:h(x),detail:">=60% context window"})]}),e.jsxs("div",{className:"thread-context-grid",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Thread timeline"}),e.jsx(pe,{selectedCall:t,calls:o,onOpenInvestigator:s,onCopyCallLink:i,className:"investigator-thread-timeline",copyAriaContext:"thread context call",copyLabel:u})]}),e.jsxs("dl",{className:"detail-list compact",children:[e.jsx(y,{label:"Project",value:t.project||"Unknown"}),e.jsx(y,{label:"Project path",value:t.projectRelativeCwd||t.cwd||"."}),e.jsx(y,{label:"Source line",value:re(t)}),e.jsx(y,{label:"Session",value:t.sessionId||"Not available"}),e.jsx(y,{label:"Parent thread",value:t.parentThread||"None"}),e.jsx(y,{label:"Models in thread",value:O(o.map(d=>d.model),{limit:3})}),e.jsx(y,{label:"Effort mix",value:O(o.map(d=>d.effort),{limit:3})})]})]})]})}function f({label:t,value:n,detail:s}){return e.jsxs("span",{className:"drilldown-metric",children:[e.jsx("small",{children:t}),e.jsx("strong",{children:n}),e.jsx("em",{children:s})]})}function y({label:t,value:n}){return e.jsxs("div",{children:[e.jsx("dt",{children:t}),e.jsx("dd",{children:n})]})}function Ye({call:t}){const s=[{label:"Cached input",value:Math.max(t.input-t.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:t.uncachedInput,color:"#f59e0b"},{label:"Output",value:t.output,color:"#059669"},{label:"Reasoning",value:t.reasoningOutput,color:"#7c3aed"}].filter(l=>l.value>0),i=Math.max(s.reduce((l,u)=>l+u.value,0),1);return e.jsxs("div",{className:"composition-card",children:[e.jsxs("div",{className:"composition-head",children:[e.jsx("strong",{children:"Token composition"}),e.jsxs("span",{children:[F(i)," visible tokens"]})]}),e.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(l=>e.jsx("i",{style:{width:`${Math.max(l.value/i*100,3)}%`,background:l.color}},l.label))}),e.jsx("div",{className:"composition-legend",children:s.map(l=>e.jsxs("span",{children:[e.jsx("i",{style:{background:l.color}}),l.label]},l.label))})]})}export{rt as CallInvestigatorPage}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js index 55c655c3..1dc1bd6f 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js @@ -1,4 +1,4 @@ -import{j as t,r as c}from"./dashboard-react.js";import{u as Lt}from"./useInfiniteQuery.js";import{c as kt,d as It}from"./exploreQueries.js";import{c as Re,W as $t,u as ce,j as O,C as Rt,a as dt,G as At,U as ut,H as Ot,X as ht,f as ee,p as q,m as Ae,Y as Bt,Z as Vt,_ as Ht,D as Kt,R as zt,$ as mt,E as Ut,d as qt,r as Gt,e as Qt,g as Wt}from"./App.js";import{r as Yt,u as Ze}from"./filtering.js";import{L as et}from"./LineChart.js";import{P as Z}from"./Panel.js";import{S as re}from"./StatusBadge.js";import{E as Xt}from"./EvidenceGrid.js";import{b as Jt,c as Zt}from"./tableActions.js";import{u as en}from"./useQuery.js";import{d as tt,c as tn,a as nt,b as nn,e as sn,f as st,r as at,l as an,g as on,h as rn,i as it,j as ot,C as ln,k as cn,m as dn,n as un,o as hn,p as mn,q as xn,s as pn,t as Oe,u as fn,v as gn,T as xt,w as jn,x as vn,y as bn}from"./contextEvidenceState.js";import{L as pt}from"./lock-keyhole.js";import{S as Cn}from"./search.js";import{S as yn}from"./shield-check.js";import{a as Sn}from"./EvidenceGridControls.js";import"./useBaseQuery.js";import"./queryOptions.js";import"./infiniteQueryOptions.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./index2.js";import"./rowActionEvents.js";/** +import{j as t,r as c}from"./dashboard-react.js";import{u as Lt}from"./useInfiniteQuery.js";import{c as kt,d as It}from"./exploreQueries.js";import{c as Re,W as $t,u as ce,j as O,C as Rt,a as dt,G as At,U as ut,H as Ot,X as ht,f as ee,Y as Ae,p as q,m as Oe,Z as Bt,_ as Vt,$ as Ht,a0 as Kt,D as zt,R as Ut,a1 as mt,E as qt,d as Gt,r as Qt,e as Wt,g as Yt}from"./App.js";import{r as Xt,u as Ze}from"./filtering.js";import{L as et}from"./LineChart.js";import{P as Z}from"./Panel.js";import{S as re}from"./StatusBadge.js";import{E as Jt}from"./EvidenceGrid.js";import{b as Zt,c as en}from"./tableActions.js";import{u as tn}from"./useQuery.js";import{d as tt,c as nn,a as nt,b as sn,e as an,f as st,r as at,l as on,g as rn,h as ln,i as it,j as ot,C as cn,k as dn,m as un,n as hn,o as mn,p as xn,q as pn,s as fn,t as gn,u as jn,T as xt,v as vn,w as bn}from"./contextEvidenceState.js";import{L as pt}from"./lock-keyhole.js";import{S as Cn}from"./search.js";import{S as yn}from"./shield-check.js";import{a as Sn}from"./EvidenceGridControls.js";import"./useBaseQuery.js";import"./queryOptions.js";import"./infiniteQueryOptions.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./index2.js";import"./rowActionEvents.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. @@ -13,4 +13,4 @@ import{j as t,r as c}from"./dashboard-react.js";import{u as Lt}from"./useInfinit * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Nn=Re("PanelRightOpen",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m10 15-3-3 3-3",key:"1pgupc"}]]);function Tn(e){const n=[],s=[e.localQuery.trim(),e.globalQuery.trim()].filter(Boolean);s.length&&n.push(`Search ${s.map(i=>`"${i}"`).join(" + ")}`),e.modelFilter!=="all"&&n.push(`Model ${e.modelFilter}`),e.effortFilter!=="all"&&n.push(`Effort ${e.effortFilter}`),e.confidenceFilter!=="all"&&n.push(`Confidence ${_n(e.confidenceFilter)}`),e.sourceFilter!=="all"&&n.push(`Source ${Ln(e.sourceFilter)}`),e.dateRangeStatus.invalid?n.push("Date range invalid"):(e.dateRangeStatus.active||e.timeFilter!=="all")&&n.push(e.dateRangeStatus.label||kn(e.timeFilter)),e.activePresetLabel&&n.push(`Preset ${e.activePresetLabel}`);const a=`Showing ${e.shownCount.toLocaleString()} of ${e.totalCount.toLocaleString()} aggregate rows`;return n.length?`${a} - Filters: ${n.join("; ")}`:a}function En(e,n){return n==="project"?`${e.project.toLocaleString()} project/cwd rows`:n==="session"?`${e.session.toLocaleString()} session-linked rows`:n==="git"?`${e.git.toLocaleString()} git rows`:n==="source-file"?`${e.sourceFile.toLocaleString()} source-file rows`:n==="missing"?`${e.missing.toLocaleString()} rows missing source`:`${e.project.toLocaleString()} project, ${e.session.toLocaleString()} session, ${e.git.toLocaleString()} git`}function Mn(e,n){return n==="all"?!0:n==="project"?Be(e):n==="session"?Ve(e):n==="git"?He(e):n==="source-file"?Ke(e):!ft(e)}function Dn(e,n){if(n==="all")return!0;if(n==="cost-exact")return!e.pricingEstimated&&Number.isFinite(e.cost)&&e.cost>0;if(n==="cost-estimated")return e.pricingEstimated;if(n==="cost-unpriced")return!e.pricingEstimated&&(!Number.isFinite(e.cost)||e.cost<=0);const s=e.usageCreditConfidence.toLowerCase();return n==="credit-exact"?s.includes("exact"):n==="credit-override"?s.includes("override"):n==="credit-estimated"?s.includes("estimated"):s.includes("missing")||s.includes("unpriced")}function Pn(e){return e.reduce((n,s)=>({project:n.project+(Be(s)?1:0),session:n.session+(Ve(s)?1:0),git:n.git+(He(s)?1:0),sourceFile:n.sourceFile+(Ke(s)?1:0),missing:n.missing+(ft(s)?0:1),total:n.total+1}),{project:0,session:0,git:0,sourceFile:0,missing:0,total:0})}function Be(e){return!!(e.project||e.projectRelativeCwd||e.cwd||e.projectTags.length)}function Ve(e){return!!(e.sessionId||e.turnId||e.parentSessionId)}function He(e){return!!(e.gitBranch||e.gitRemoteLabel||e.gitRemoteHash)}function Ke(e){return!!(e.sourceFile||e.lineNumber!==null)}function ft(e){return Be(e)||Ve(e)||He(e)||Ke(e)}function _n(e){return e==="cost-exact"?"exact cost":e==="cost-estimated"?"estimated cost":e==="cost-unpriced"?"unpriced cost":e==="credit-exact"?"exact credit rate":e==="credit-estimated"?"estimated credit mapping":e==="credit-override"?"user credit override":"missing credit rate"}function Ln(e){return e==="project"?"project/cwd":e==="session"?"session-linked":e==="git"?"git metadata":e==="source-file"?"source file":"missing source"}function kn(e){return e==="today"?"Today":e==="this-week"?"This week":e==="last-7-days"?"Last 7 days":e==="this-month"?"This month":e==="custom"?"Custom date range":"All time"}const oe="__detail_first__",In=new Set(["all","cost-exact","cost-estimated","cost-unpriced","credit-exact","credit-estimated","credit-override","credit-missing"]),$n=new Set(["all","today","this-week","last-7-days","this-month","custom"]),Rn=new Set(["all","project","session","git","source-file","missing"]),An=new Set(["time","duration","gap","attention","thread","initiator","model","effort","total","cached","uncached","output","reasoning","cost","usage","cache","context"]);function T(e,n=window.location.href){var s;return((s=new URL(n).searchParams.get(e))==null?void 0:s.trim())??""}function gt(e=window.location.href){const n=T("confidence",e)||T("pricing",e),s=Kn(n);return In.has(s)?s:"all"}function jt(e=window.location.href){const n=T("source",e);return Rn.has(n)?n:"all"}function vt(e=window.location.href){const n=T("date",e)||T("time",e);return $n.has(n)?n:"all"}function le(e,n=window.location.href){return Le(T(e,n))}function On(e=window.location.href){const n=T("record",e);return n||(T("detail",e)==="first"?oe:null)}function Pe(e=window.location.href){const n=T("sort",e);return bt(n)}function bt(e){return An.has(e)?e:"time"}function Ct(e,n=window.location.href){const s=T("direction",n);return s==="asc"||s==="desc"?s:U(e)}function Bn(e=window.location.href){return T("density",e)==="roomy"?"roomy":"dense"}function Vn(e,n=window.location.href){const s=Number(T("page",n)||1);return Number.isFinite(s)&&s>1?Math.floor(s)*e:e}function _e(e,n=window.location.href){const s=new URL(n);return s.searchParams.set("view","calls"),s.searchParams.delete("detail"),s.searchParams.delete("pricing"),k(s,"record",e.selectedRecordId,""),k(s,"call_q",e.localQuery.trim(),""),k(s,"model",e.modelFilter,"all"),k(s,"effort",e.effortFilter,"all"),k(s,"confidence",e.confidenceFilter,"all"),k(s,"source",e.sourceFilter,"all"),k(s,"time",e.timeFilter,"all"),k(s,"date",e.timeFilter,"all"),k(s,"from",e.timeFilter==="custom"?e.dateStart:"",""),k(s,"to",e.timeFilter==="custom"?e.dateEnd:"",""),k(s,"sort",e.sortKey,"time"),k(s,"direction",e.sortDirection,U(e.sortKey)),k(s,"density",e.density,"dense"),k(s,"page",String(Hn(e.visibleRowCount,e.pageSize)),"1"),s}function U(e){return e==="cache"||e==="effort"||e==="initiator"||e==="model"||e==="thread"?"asc":"desc"}function Le(e){const n=zn(e);return n?Un(n):""}function Hn(e,n){return Math.max(1,Math.ceil(Math.max(e,n)/n))}function k(e,n,s,a){if(!s||s===a){e.searchParams.delete(n);return}e.searchParams.set(n,s)}function Kn(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":e}function zn(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function Un(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(e,n){return e.filter(s=>qn(s,n))}function ke(e,n,s){return[...e].sort((a,i)=>Gn(a,i,n,s))}function ze(e,n,s,a){const i=Yn(a);if(e==="custom"){const o=lt(n),r=lt(s);return o&&r&&o>r?{active:!0,invalid:!0,start:o,endExclusive:K(r,1),label:"Invalid date range"}:{active:!!(o||r),invalid:!1,start:o,endExclusive:r?K(r,1):null,label:J("Custom",o,r)}}if(e==="today")return{active:!0,invalid:!1,start:i,endExclusive:K(i,1),label:J("Today",i,i)};if(e==="this-week"){const o=Xn(i);return{active:!0,invalid:!1,start:o,endExclusive:K(o,7),label:J("This week",o,K(o,6))}}if(e==="last-7-days"){const o=K(i,-6);return{active:!0,invalid:!1,start:o,endExclusive:K(i,1),label:J("Last 7 days",o,i)}}if(e==="this-month"){const o=new Date(i.getFullYear(),i.getMonth(),1),r=new Date(i.getFullYear(),i.getMonth()+1,1);return{active:!0,invalid:!1,start:o,endExclusive:r,label:J("This month",o,K(r,-1))}}return{active:!1,invalid:!1,start:null,endExclusive:null,label:"All time"}}function qn(e,n){if(n.modelFilter!=="all"&&e.model!==n.modelFilter||n.effortFilter!=="all"&&e.effort!==n.effortFilter||!Dn(e,n.confidenceFilter)||!Mn(e,n.sourceFilter)||!Jn(e,n.timeFilter,n.dateStart,n.dateEnd)||n.activePreset&&!$t(e,n.activePreset))return!1;const s=[e.thread,e.cwd,e.project,e.projectRelativeCwd,e.gitBranch,e.gitRemoteLabel,e.sessionId,e.model,e.effort,e.initiator,e.initiatorReason,e.signal,e.recommendation,e.rawTime,e.sourceFile,e.lineNumber,e.tags.join(" ")];return[n.globalQuery,n.localQuery].every(a=>Yt(s,a))}function Gn(e,n,s,a){const i=rt(e,s),o=rt(n,s);if(i===null&&o!==null)return 1;if(o===null&&i!==null)return-1;const r=Wn(i,o);return r!==0?a==="asc"?r:-r:Ie(e,n)||e.id.localeCompare(n.id)}function rt(e,n){return n==="time"?$e(e):n==="duration"?e.durationSeconds:n==="gap"?e.previousCallGapSeconds:n==="attention"?Qn(e):n==="thread"?e.thread.toLowerCase():n==="initiator"?e.initiator.toLowerCase():n==="model"?e.model.toLowerCase():n==="effort"?e.effort.toLowerCase():n==="total"?e.totalTokens:n==="cached"?e.input*(e.cachedPct/100):n==="uncached"?e.uncachedInput:n==="output"?e.output:n==="reasoning"?e.reasoningOutput:n==="cost"?e.cost:n==="usage"?e.credits:n==="cache"?e.cachedPct:e.contextWindowPct}function Qn(e){const n=e.signal&&e.signal!=="aggregate"?1e3:0,s=e.recommendation?750:0,a=e.contextWindowPct??0,i=Math.min(e.uncachedInput/1e3,250),o=Math.min(e.cost*25,200),r=Math.min(e.credits,200),h=Math.min(e.durationSeconds/60,120);return n+s+a+i+o+r+h}function Wn(e,n){return e===null&&n===null?0:e===null?1:n===null?-1:typeof e=="string"||typeof n=="string"?String(e).localeCompare(String(n)):e-n}function Ie(e,n){return $e(n)-$e(e)}function $e(e){const n=Date.parse(e.rawTime);return Number.isFinite(n)?n:0}function lt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function ct(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function J(e,n,s){const a=n?ct(n):"",i=s?ct(s):"";return a&&i&&a===i?`${e}: ${a}`:a&&i?`${e}: ${a} to ${i}`:a?`${e}: from ${a}`:i?`${e}: through ${i}`:e}function Yn(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function K(e,n){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+n)}function Xn(e){const n=e.getDay();return K(e,n===0?-6:1-n)}function Jn(e,n,s="",a="",i=new Date){if(n==="all")return!0;const o=ze(n,s,a,i);if(o.invalid)return!1;if(!o.active)return!0;const r=Date.parse(e.rawTime);return!(!Number.isFinite(r)||o.start&&r=o.endExclusive.getTime())}const Zn={time:"time",duration:"duration",gap:"gap",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"tokens",cached:"cached",uncached:"uncached",output:"output",reasoning:"reasoning",cache:"cache"};function es(e){const n=Zn[e.sortKey],s=ze(e.timeFilter,e.dateStart,e.dateEnd,new Date),a=ts(e,n,s.invalid);return{enabled:!a,reason:a,sort:n??"time",filters:{query:[e.globalQuery.trim(),e.localQuery.trim()].filter(Boolean).join(" "),model:e.modelFilter==="all"?void 0:e.modelFilter,effort:e.effortFilter==="all"?void 0:e.effortFilter,...ns(e.confidenceFilter),...ss(s.start,s.endExclusive,e.scopeSince)}}}function ts(e,n,s){return!e.enabled||e.runtime.fileMode||!e.runtime.apiToken?"Stored snapshot":e.globalQuery.trim()&&e.localQuery.trim()?"Multiple searches use loaded snapshot":e.activePreset?"Preset uses loaded snapshot":e.sourceFilter!=="all"?"Source filter uses loaded snapshot":n?s?"Invalid date range":"":"This sort uses loaded snapshot"}function ns(e){return e==="cost-exact"?{pricingStatus:"priced"}:e==="cost-estimated"?{pricingStatus:"estimated"}:e==="cost-unpriced"?{pricingStatus:"unpriced"}:e==="credit-exact"?{creditConfidence:"exact"}:e==="credit-estimated"?{creditConfidence:"estimated"}:e==="credit-override"?{creditConfidence:"user_override"}:e==="credit-missing"?{creditConfidence:"unpriced"}:{}}function ss(e,n,s){return{since:(e==null?void 0:e.toISOString())??s??void 0,until:n?new Date(n.getTime()-1).toISOString():void 0}}function as({data:e,valueLabel:n=s=>String(s)}){const s=Math.max(...e.map(a=>a.value),1);return t.jsx("div",{className:"bar-list",children:e.map(a=>t.jsxs("div",{className:"bar-row",children:[t.jsx("span",{children:a.label}),t.jsx("div",{className:"bar-track","aria-hidden":"true",children:t.jsx("i",{style:{width:`${a.value/s*100}%`,backgroundColor:a.color??"#2563eb"}})}),t.jsx("strong",{children:n(a.value)})]},a.label))})}function P({label:e,value:n,detail:s}){return t.jsxs("span",{className:"drilldown-metric",children:[t.jsx("small",{children:e}),t.jsx("strong",{children:n}),t.jsx("em",{children:s})]})}function S({label:e,value:n}){return t.jsxs("div",{children:[t.jsx("dt",{children:e}),t.jsx("dd",{children:n})]})}function is({call:e,contextRuntime:n,onContextApiEnabledChange:s}){const a=ce(),[i,o]=c.useState(()=>tn(e.id)??tt),[r,h]=c.useState({status:"idle"}),F=!!n.apiToken&&!n.fileMode,d=F&&n.contextApiEnabled;c.useEffect(()=>{const l=nt(e.id,i);h(l?{status:"loaded",payload:l}:{status:"idle"})},[e.id,i.includeCompactionHistory,i.includeToolOutput,i.maxChars,i.maxEntries,i.mode]);async function b(){h({status:"loading",message:"Enabling localhost context API..."});try{const l=await sn(n);s(l),h({status:"idle",message:l?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(l){h({status:"error",message:st(l)})}}async function j(l=i,p="Loading selected-turn evidence..."){at(e.id,l);const w=nt(e.id,l);if(w){h({status:"loaded",payload:w});return}h({status:"loading",message:p});try{const g=await an(e.id,n,l);on(e.id,l,g),h({status:"loaded",payload:g})}catch(g){h({status:"error",message:st(g)})}}function C(){const l={...i,mode:"full"};o(l),j(l,"Loading full turn analysis...")}function D(l){const p=mn(l,i);o(p),j(p,"Loading older context...")}function N(){const l={...i,includeToolOutput:!0};o(l),j(l,"Loading omitted tool output...")}function y(){const l={...i,includeCompactionHistory:!0};o(l),j(l,"Loading compacted replacement...")}function m(l,p){o(w=>{const g={...w,[l]:p};return at(e.id,g),g})}return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"locked-context-card",children:[t.jsx(pt,{size:20}),t.jsxs("div",{children:[t.jsx("strong",{children:"Raw context is gated"}),t.jsx("p",{children:nn(n)})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Record id",value:e.id}),t.jsx(S,{label:"Time",value:e.time}),t.jsx(S,{label:"Thread",value:e.thread}),t.jsx(S,{label:"Model",value:e.model}),t.jsx(S,{label:"Effort",value:e.effort})]}),t.jsxs("div",{className:"context-action-grid",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:b,disabled:!F||n.contextApiEnabled||r.status==="loading",children:a.t("button.enable_context_loading","Enable context loading")}),t.jsx("button",{className:"primary-button",type:"button",onClick:()=>j(),disabled:!d||r.status==="loading",children:a.t("button.show_turn_evidence","Show turn log evidence")}),t.jsx("button",{className:"toolbar-button",type:"button",onClick:C,disabled:!d||r.status==="loading",children:a.t("button.full_serialized_analysis","Run full serialized analysis")}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Mode"}),t.jsxs("select",{"aria-label":"Side panel context mode",value:i.mode,disabled:!d||r.status==="loading",onChange:l=>m("mode",l.target.value==="full"?"full":"quick"),children:[t.jsx("option",{value:"quick",children:"Quick"}),t.jsx("option",{value:"full",children:"Full"})]})]}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Entries"}),t.jsxs("select",{"aria-label":"Side panel context entries",value:String(i.maxEntries),disabled:!d||r.status==="loading",onChange:l=>m("maxEntries",Number(l.target.value)),children:[t.jsx("option",{value:"20",children:"20"}),t.jsx("option",{value:"50",children:"50"}),t.jsx("option",{value:"100",children:"100"}),t.jsx("option",{value:"0",children:"All"})]})]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeToolOutput,disabled:!d||r.status==="loading",onChange:l=>m("includeToolOutput",l.target.checked)}),a.t("button.include_tool_output","Include tool output")]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeCompactionHistory,disabled:!d||r.status==="loading",onChange:l=>m("includeCompactionHistory",l.target.checked)}),"Include compaction history"]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.maxChars===0,disabled:!d||r.status==="loading",onChange:l=>m("maxChars",l.target.checked?0:tt.maxChars)}),a.t("button.no_char_limit","No char limit")]})]}),r.status==="idle"&&r.message?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="loading"?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="error"?t.jsx("p",{className:"context-state-note error",children:r.message}):null,r.status==="loaded"?t.jsx(os,{call:e,payload:r.payload,onLoadOlder:D,onRunFullAnalysis:C,onLoadCompactionHistory:y,onLoadToolOutput:N}):null,t.jsx("p",{className:"privacy-note",children:"Raw context is never embedded in the dashboard HTML. This view reads the selected local JSONL turn only after an explicit request."})]})}function os({call:e,payload:n,onLoadOlder:s,onRunFullAnalysis:a,onLoadCompactionHistory:i,onLoadToolOutput:o}){var _,E;const r=ce(),h=n.entries??[],F=n.omitted??{},d=Number(F.older_entries??0),b=rn(n),j=8,C=e.id||String(n.record_id??""),[D,N]=c.useState(()=>it(C)),[y,m]=c.useState(()=>ot(C,h));c.useEffect(()=>{N(it(C)),m(ot(C,h))},[h.length,n.context_mode,n.include_compaction_history,n.include_tool_output,(_=n.omitted)==null?void 0:_.max_chars,(E=n.omitted)==null?void 0:E.max_entries,n.record_id,C]);const l=D?h:h.slice(0,j),p=Math.max(h.length-l.length,0);function w(){N(x=>{const L=!x;return pn(C,L),L})}function g(x,L){xn(C,x,L),m(v=>{const u=new Set(v);return L?u.add(x):u.delete(x),u})}return t.jsxs("div",{className:"context-evidence",children:[t.jsxs("div",{className:"context-evidence-summary",children:[t.jsx(P,{label:"Entries",value:O(h.length),detail:String(n.context_mode??"quick")}),t.jsx(P,{label:"Visible chars",value:O(Number(n.visible_char_count??0)),detail:"redacted local text"}),t.jsx(P,{label:"Visible tokens",value:O(Number(n.visible_token_estimate??0)),detail:"estimator"}),t.jsx(P,{label:"Older omitted",value:O(d),detail:"entry budget"})]}),b.length?t.jsx("p",{className:"context-note",children:b.join(" ")}):null,t.jsx(ln,{call:e,payload:n,onRunFullAnalysis:a}),d>0?t.jsx("div",{className:"context-followup-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>s(n),children:r.t("button.load_older_context","Load older entries")})}):null,t.jsxs("div",{className:"context-entry-list",children:[l.map((x,L)=>{const v=cn(x,L);return t.jsxs("details",{className:"context-entry",open:y.has(v),onToggle:u=>g(v,u.currentTarget.open),children:[t.jsx("summary",{className:"context-entry-summary",children:t.jsxs("div",{className:"context-entry-meta",children:[t.jsx("strong",{children:x.label||x.role||x.type||`Entry ${L+1}`}),t.jsx("span",{children:x.line_number?`line ${x.line_number}`:x.timestamp||"local evidence"})]})}),t.jsx(dn,{entry:x}),x.tool_output_omitted?t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:o,children:r.t("button.show_tool_output","Show tool output")})}):null,t.jsx(rs,{entry:x,onLoadCompactionHistory:i}),t.jsx("pre",{ref:u=>{u&&(u.scrollTop=hn(C,v))},onScroll:u=>un(C,v,u.currentTarget.scrollTop),children:x.text||"[no visible text]"})]},v)}),h.length?null:t.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),h.length>j?t.jsxs("div",{className:"context-followup-actions",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:w,children:D?`Show first ${O(j)} entries`:`Show all ${O(h.length)} returned entries`}),D?null:t.jsxs("span",{className:"context-entry-count-note",children:[O(p)," entries hidden in compact view"]})]}):null]})}function rs({entry:e,onLoadCompactionHistory:n}){const s=ce(),a=e.compaction;if(!(a!=null&&a.replacement_history_available))return null;const i=a.replacement_history??[],o=Number(a.replacement_entry_count??i.length);return t.jsxs("div",{className:"context-entry-compaction",children:[t.jsx("strong",{children:"Compaction detected"}),t.jsxs("span",{children:[O(o)," replacement history entries available."]}),i.length?t.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:i.map((r,h)=>t.jsxs("div",{className:"context-replacement-entry",children:[t.jsx("strong",{children:r.label||`Replacement item ${h+1}`}),t.jsx("pre",{children:r.text||"[no visible replacement text]"})]},`${r.label??"replacement"}-${h}`))}):t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}const ls=[{id:"summary",label:"Summary",icon:At},{id:"tokens",label:"Tokens",icon:ut},{id:"cache",label:"Cache",icon:Ot},{id:"thread",label:"Thread",icon:wn},{id:"evidence",label:"Evidence",icon:pt}];function cs({call:e,calls:n,contextRuntime:s,includeArchived:a,sourceRevision:i,hydrateThreadCalls:o,onContextApiEnabledChange:r,onOpenInvestigator:h,onCopyCallLink:F}){const[d,b]=c.useState("summary"),[j,C]=c.useState(""),D=c.useMemo(()=>e?n.filter(m=>m.thread===e.thread).sort(Ie):[],[e,n]),N=en({...kt({runtime:s,includeArchived:a,sourceRevision:i,threadKey:(e==null?void 0:e.threadKey)||(e==null?void 0:e.thread)||"",selectedRecordId:(e==null?void 0:e.id)??"",selectedEventTimestamp:(e==null?void 0:e.eventTimestamp)??""}),enabled:o&&!s.fileMode&&!!s.apiToken&&!!e,placeholderData:m=>m}),y=c.useMemo(()=>{var l;const m=((l=N.data)==null?void 0:l.rows)??D;return!e||m.some(p=>p.id===e.id)?m:[...m,e].sort(Ie)},[e,D,N.data]);return e?t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsxs(Z,{title:"Call Drill-Down",subtitle:`${e.thread} / ${e.model}`,children:[t.jsxs("div",{className:"call-summary",children:[t.jsx(re,{label:"Aggregate only",tone:"green"}),t.jsx(Rt,{call:e}),t.jsx(re,{label:"Raw context gated",tone:"blue"}),t.jsx("span",{className:"call-id",children:e.id.slice(0,12)})]}),t.jsxs("div",{className:"action-row",children:[t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>h(e.id),children:[t.jsx(Cn,{size:16}),"Open investigator"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>ps(e,C),children:[t.jsx(dt,{size:16}),"Copy link"]})]}),j?t.jsx("p",{className:"context-state-note",children:j}):null,t.jsx("div",{className:"drilldown-tabs",role:"tablist","aria-label":"Call drill-down sections",children:ls.map(m=>{const l=m.icon,p=d===m.id;return t.jsxs("button",{type:"button",role:"tab","aria-selected":p,className:p?"active":"",onClick:()=>b(m.id),children:[t.jsx(l,{size:14}),m.label]},m.id)})}),t.jsxs("div",{className:"drilldown-tab-panel",role:"tabpanel",children:[d==="summary"?t.jsx(ds,{call:e}):null,d==="tokens"?t.jsx(hs,{call:e}):null,d==="cache"?t.jsx(ms,{call:e,calls:y}):null,d==="thread"?t.jsx(xs,{call:e,calls:y,onOpenInvestigator:h,onCopyCallLink:F}):null,d==="evidence"?t.jsx(is,{call:e,contextRuntime:s,onContextApiEnabledChange:r},e.id):null]})]})}):t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsx(Z,{title:"Call Drill-Down",subtitle:"No matching call",children:t.jsx("p",{className:"empty-state",children:"No aggregate row matches the active filters."})})})}function ds({call:e}){return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Total tokens",value:O(e.totalTokens),detail:`${ee(e.input)} input`}),t.jsx(P,{label:"Uncached input",value:O(e.uncachedInput),detail:"fresh billed input"}),t.jsx(P,{label:"Cache hit rate",value:q(e.cachedPct),detail:Oe(e)}),t.jsx(P,{label:"Estimated cost",value:Ae(e.cost),detail:e.pricingEstimated?"estimated pricing":"configured pricing"}),t.jsx(P,{label:"Duration",value:e.duration,detail:Bt(e)}),t.jsx(P,{label:"Usage credits",value:e.credits?e.credits.toFixed(3):"-",detail:e.usageCreditConfidence})]}),t.jsx(fn,{call:e}),t.jsx(gn,{call:e}),t.jsx(us,{call:e}),t.jsx(St,{call:e}),t.jsx(wt,{call:e}),e.recommendation?t.jsxs("div",{className:"recommendation-box",children:[t.jsx(yn,{size:16}),t.jsx("p",{children:e.recommendation})]}):null]})}function us({call:e}){return t.jsxs("div",{className:"composition-card accounting-snapshot-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Accounting Snapshot"}),t.jsx("span",{children:"pricing, credits, and cache savings"})]}),t.jsx(xt,{call:e})]})}function hs({call:e}){return t.jsxs(t.Fragment,{children:[t.jsx(St,{call:e}),t.jsx(xt,{call:e})]})}function ms({call:e,calls:n}){return t.jsxs(t.Fragment,{children:[t.jsx(wt,{call:e}),t.jsx(jn,{call:e,calls:n}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Cache state",value:Oe(e)}),t.jsx(S,{label:"Cache hit rate",value:q(e.cachedPct)}),t.jsx(S,{label:"Fresh share",value:q(Math.max(100-e.cachedPct,0))}),t.jsx(S,{label:"Signal",value:e.signal})]}),t.jsx("p",{className:"privacy-note",children:"Use this readout to decide whether the aggregate call needs deeper raw-context investigation."})]})}function xs({call:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a}){const i=n.reduce((b,j)=>b+j.totalTokens,0),o=n.reduce((b,j)=>b+j.cost,0),r=n.reduce((b,j)=>b+j.cachedPct,0)/Math.max(n.length,1),h=Math.max(n.findIndex(b=>b.id===e.id),0),F=Math.min(Math.max(n.length,1),5),d=e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available";return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Loaded thread calls",value:O(n.length),detail:`selected ${h+1} of ${n.length}`}),t.jsx(P,{label:"Thread tokens",value:ee(i),detail:"loaded aggregate rows"}),t.jsx(P,{label:"Thread cost",value:Ae(o),detail:"estimated aggregate"}),t.jsx(P,{label:"Avg cache",value:q(r),detail:vn(n.map(b=>b.model),{style:"x",emptyLabel:"no model mix"})}),t.jsx(P,{label:"Context window",value:e.contextWindowPct===null?"-":q(e.contextWindowPct),detail:e.modelContextWindow?`${ee(e.modelContextWindow)} window`:"not reported"}),t.jsx(P,{label:"Parent thread",value:e.parentThread||"-",detail:e.parentSessionId||"no parent session"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Thread timeline"}),t.jsxs("span",{children:[F," nearby loaded calls"]})]}),t.jsx(bn,{selectedCall:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a,copyAriaContext:"side-panel thread call"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Call Narrative"}),t.jsx("span",{children:e.initiatorConfidence||"aggregate inference"})]}),t.jsxs("dl",{className:"detail-list compact",children:[t.jsx(S,{label:"Initiated by",value:e.initiator||"unknown"}),t.jsx(S,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),t.jsx(S,{label:"Parent thread",value:e.parentThread||"None"}),t.jsx(S,{label:"Parent session",value:e.parentSessionId||"None"}),t.jsx(S,{label:"Timestamp",value:e.time}),t.jsx(S,{label:"Duration",value:e.duration}),t.jsx(S,{label:"Previous gap",value:e.previousCallGap})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Project",value:e.project||"Unknown"}),t.jsx(S,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),t.jsx(S,{label:"Source line",value:d}),t.jsx(S,{label:"Session",value:e.sessionId||"Not available"}),t.jsx(S,{label:"Git branch",value:e.gitBranch||"Unknown"}),t.jsx(S,{label:"Remote",value:e.gitRemoteLabel||e.gitRemoteHash||"None"})]})]})}function St({call:e}){const s=[{label:"Cached input",value:Math.max(e.input-e.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:e.uncachedInput,color:"#f59e0b"},{label:"Output",value:e.output,color:"#059669"},{label:"Reasoning",value:e.reasoningOutput,color:"#7c3aed"}].filter(i=>i.value>0),a=Math.max(s.reduce((i,o)=>i+o.value,0),1);return t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Token composition"}),t.jsxs("span",{children:[ee(a)," visible tokens"]})]}),t.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(i=>t.jsx("i",{style:{width:`${Math.max(i.value/a*100,3)}%`,background:i.color}},i.label))}),t.jsx("div",{className:"composition-legend",children:s.map(i=>t.jsxs("span",{children:[t.jsx("i",{style:{background:i.color}}),i.label]},i.label))})]})}function wt({call:e}){const n=[{label:"Cache",value:Math.min(Math.max(e.cachedPct,0),100),color:"#2563eb"},{label:"Fresh",value:Math.min(Math.max(100-e.cachedPct,0),100),color:"#f59e0b"},{label:"Output",value:Math.min(Math.max(e.output/Math.max(e.totalTokens,1)*100,0),100),color:"#059669"}];return t.jsxs("div",{className:"cache-mini-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"Cache delta readout"}),t.jsx("span",{children:Oe(e)})]}),t.jsx("div",{className:"cache-bars","aria-label":"Cache delta readout",children:n.map(s=>t.jsxs("span",{children:[t.jsx("i",{style:{height:`${Math.max(s.value,4)}%`,background:s.color}}),t.jsx("em",{children:s.label})]},s.label))})]})}async function ps(e,n){try{const s=new URL(window.location.href);if(s.searchParams.set("view","call"),s.searchParams.set("record",e.id),s.searchParams.set("return","calls"),!await ht(s.toString()))throw new Error("Clipboard unavailable");n("Copied investigator link")}catch{n("Copy unavailable in this browser")}}const fs="_page_gyxvc_1",gs="_pageHeader_gyxvc_5",js="_tableHeading_gyxvc_13",vs="_eyebrow_gyxvc_22",bs="_headerActions_gyxvc_36",Cs="_tableActions_gyxvc_37",ys="_gridFooter_gyxvc_38",Ss="_queryBar_gyxvc_46",ws="_advancedFilters_gyxvc_80",Fs="_patternsDisclosure_gyxvc_85",Ns="_advancedFilterGrid_gyxvc_107",Ts="_gridColumn_gyxvc_138",$={page:fs,pageHeader:gs,tableHeading:js,eyebrow:vs,headerActions:bs,tableActions:Cs,gridFooter:ys,queryBar:Ss,advancedFilters:ws,patternsDisclosure:Fs,advancedFilterGrid:Ns,gridColumn:Ts};function Es({searchInputRef:e,localQuery:n,modelFilter:s,effortFilter:a,confidenceFilter:i,sourceFilter:o,timeFilter:r,dateStart:h,dateEnd:F,sortKey:d,sortDirection:b,modelOptions:j,effortOptions:C,sourceCoverage:D,dateRangeStatus:N,onLocalQueryChange:y,onModelFilterChange:m,onEffortFilterChange:l,onConfidenceFilterChange:p,onSourceFilterChange:w,onTimeFilterChange:g,onDateStartChange:_,onDateEndChange:E,onSortKeyChange:x,onSortDirectionChange:L,onClear:v}){return t.jsxs("section",{className:$.queryBar,"aria-label":"Call filters",children:[t.jsxs("label",{className:"search-box",children:[t.jsx("span",{className:"sr-only",children:"Search calls"}),t.jsx("input",{ref:e,value:n,onChange:u=>y(u.target.value),placeholder:"Search calls, cwd, projects, models..."})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Model"}),t.jsxs("select",{value:s,onChange:u=>m(u.target.value),children:[t.jsx("option",{value:"all",children:"All models"}),j.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Effort"}),t.jsxs("select",{value:a,onChange:u=>l(u.target.value),children:[t.jsx("option",{value:"all",children:"All effort"}),C.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Confidence"}),t.jsxs("select",{"aria-label":"Confidence filter",value:i,onChange:u=>p(u.target.value),children:[t.jsx("option",{value:"all",children:"All confidence"}),t.jsx("option",{value:"cost-exact",children:"Exact cost"}),t.jsx("option",{value:"cost-estimated",children:"Estimated cost"}),t.jsx("option",{value:"cost-unpriced",children:"Unpriced cost"}),t.jsx("option",{value:"credit-exact",children:"Exact credit rate"}),t.jsx("option",{value:"credit-estimated",children:"Estimated credit mapping"}),t.jsx("option",{value:"credit-override",children:"User credit override"}),t.jsx("option",{value:"credit-missing",children:"Missing credit rate"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Time"}),t.jsxs("select",{"aria-label":"Time filter",value:r,onChange:u=>g(u.target.value),children:[t.jsx("option",{value:"all",children:"All time"}),t.jsx("option",{value:"today",children:"Today"}),t.jsx("option",{value:"this-week",children:"This week"}),t.jsx("option",{value:"last-7-days",children:"Last 7 days"}),t.jsx("option",{value:"this-month",children:"This month"}),t.jsx("option",{value:"custom",children:"Custom range"})]}),N.active||N.invalid?t.jsx("span",{className:"filter-status","data-state":N.invalid?"error":"active","aria-live":"polite",children:N.label}):null]}),t.jsxs("details",{className:$.advancedFilters,children:[t.jsxs("summary",{children:[t.jsx(Vt,{size:16}),"More filters"]}),t.jsxs("div",{className:$.advancedFilterGrid,children:[t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Source"}),t.jsxs("select",{"aria-label":"Source filter",value:o,onChange:u=>w(u.target.value),children:[t.jsx("option",{value:"all",children:"All sources"}),t.jsx("option",{value:"project",children:"Project / cwd"}),t.jsx("option",{value:"session",children:"Session-linked"}),t.jsx("option",{value:"git",children:"Git metadata"}),t.jsx("option",{value:"source-file",children:"Source file"}),t.jsx("option",{value:"missing",children:"Missing source"})]}),t.jsx("span",{className:"filter-status","data-state":o==="all"?"active":"filtered","aria-live":"polite",children:En(D,o)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Start"}),t.jsx("input",{"aria-label":"Start date",type:"date",value:h,onChange:u=>_(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"End"}),t.jsx("input",{"aria-label":"End date",type:"date",value:F,onChange:u=>E(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Sort"}),t.jsxs("select",{"aria-label":"Sort calls",value:d,onChange:u=>x(u.target.value),children:[t.jsx("option",{value:"time",children:"Newest calls"}),t.jsx("option",{value:"duration",children:"Longest duration"}),t.jsx("option",{value:"gap",children:"Longest gap"}),t.jsx("option",{value:"attention",children:"Needs attention"}),t.jsx("option",{value:"thread",children:"Thread name"}),t.jsx("option",{value:"initiator",children:"Initiated"}),t.jsx("option",{value:"model",children:"Model"}),t.jsx("option",{value:"effort",children:"Reasoning"}),t.jsx("option",{value:"total",children:"Most tokens"}),t.jsx("option",{value:"cached",children:"Cached"}),t.jsx("option",{value:"uncached",children:"Uncached"}),t.jsx("option",{value:"output",children:"Output"}),t.jsx("option",{value:"reasoning",children:"Reasoning output"}),t.jsx("option",{value:"cost",children:"Highest estimated cost"}),t.jsx("option",{value:"usage",children:"Highest Codex credits"}),t.jsx("option",{value:"cache",children:"Lowest cache ratio"}),t.jsx("option",{value:"context",children:"Highest context use"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Direction"}),t.jsxs("select",{"aria-label":"Sort direction",value:b,onChange:u=>L(u.target.value),children:[t.jsx("option",{value:"desc",children:"Descending"}),t.jsx("option",{value:"asc",children:"Ascending"})]})]})]})]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:v,children:[t.jsx(Ht,{size:16}),"Clear filters"]})]})}function Ms({workspaceSwitcher:e,canExport:n,onExport:s,onCopyView:a,onRefresh:i}){return t.jsxs("header",{className:$.pageHeader,children:[t.jsxs("div",{children:[t.jsx("p",{className:$.eyebrow,children:"Evidence explorer"}),t.jsx("h1",{children:"Calls"}),t.jsx("p",{children:"Find expensive, cold, or context-heavy calls and move directly into their evidence."})]}),t.jsxs("div",{className:$.headerActions,children:[e,t.jsxs("button",{className:"toolbar-button",type:"button",onClick:s,disabled:!n,children:[t.jsx(Kt,{size:16}),"Export"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:a,children:[t.jsx(dt,{size:16}),"Copy view"]}),t.jsxs("button",{className:"primary-button",type:"button",onClick:i,children:[t.jsx(zt,{size:16}),"Refresh"]})]})]})}const Ft="codexUsageDetailPanel";function Ds(e=!1){var n;try{const s=(n=window.sessionStorage)==null?void 0:n.getItem(Ft);return s?s==="expanded":e}catch{return e}}function Ps(e){var n;try{(n=window.sessionStorage)==null||n.setItem(Ft,e?"expanded":"collapsed")}catch{}}const B=250;function _s(e,n){const s=T("density"),[a,i]=c.useState(()=>T("call_q")),[o,r]=c.useState(()=>T("model")||"all"),[h,F]=c.useState(()=>T("effort")||"all"),[d,b]=c.useState(()=>gt()),[j,C]=c.useState(()=>jt()),[D,N]=c.useState(()=>vt()),[y,m]=c.useState(()=>le("from")),[l,p]=c.useState(()=>le("to")),[w,g]=c.useState(()=>Pe()),[_,E]=c.useState(()=>Ct(Pe())),x=Sn("codexUsageCallsEvidenceGrid",{density:Bn()==="dense"?"compact":"comfortable",columnVisibility:{}},s==="roomy"?"comfortable":s==="dense"?"compact":void 0),L=x.density==="compact"?"dense":"roomy",v=c.useMemo(()=>On(),[]),[u,te]=c.useState(v),[G,R]=c.useState(()=>Vn(B)),[ne,Q]=c.useState(""),[de,ue]=c.useState(""),[W,he]=c.useState(()=>Ds(!!v)),me=c.useRef(null),se=c.useRef(n),xe=c.useMemo(()=>Ze(e.calls.map(f=>f.model)),[e.calls]),pe=c.useMemo(()=>Ze(e.calls.map(f=>f.effort)),[e.calls]),fe=c.useMemo(()=>Pn(e.calls),[e.calls]),Y=c.useMemo(()=>ze(D,y,l,new Date),[l,y,D]);c.useEffect(()=>{se.current!==n&&(se.current=n,R(B))},[n]);function I(){R(B)}function ge(f){i(f),I()}function je(f){r(f),I()}function ve(f){F(f),I()}function be(f){b(f),I()}function Ce(f){C(f),I()}function ye(f){N(f),I()}function Se(f){m(Le(f)),N("custom"),I()}function we(f){p(Le(f)),N("custom"),I()}function Fe(f){const A=bt(f);g(A),E(U(A)),I()}function Ne(f){E(f==="asc"?"asc":"desc"),I()}function Te(){i(""),r("all"),F("all"),b("all"),C("all"),N("all"),m(""),p(""),g("time"),E(U("time")),x.setDensity("compact"),x.setColumnVisibility({}),te(null),R(B),window.history.replaceState(null,"",_e({localQuery:"",modelFilter:"all",effortFilter:"all",confidenceFilter:"all",sourceFilter:"all",timeFilter:"all",dateStart:"",dateEnd:"",sortKey:"time",sortDirection:U("time"),density:"dense",selectedRecordId:"",visibleRowCount:B,pageSize:B})),ue("Calls filters cleared")}function Ee(){he(f=>{const A=!f;return Ps(A),A})}return{localQuery:a,modelFilter:o,effortFilter:h,confidenceFilter:d,sourceFilter:j,timeFilter:D,dateStart:y,dateEnd:l,sortKey:w,setSortKey:g,sortDirection:_,setSortDirection:E,gridPreferences:x,density:L,initialSelectedCallId:v,selectedCallId:u,setSelectedCallId:te,visibleCallRows:G,setVisibleCallRows:R,exportStatus:ne,setExportStatus:Q,filterStatus:de,detailsExpanded:W,searchInputRef:me,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}}function Ls({model:e,header:n,filters:s,table:a,inspector:i}){var F;const o=ce(),r=o.t("dashboard.model_calls","Model Calls"),h=o.t("dashboard.model_calls","Model calls");return t.jsxs("div",{className:`${$.page} page-grid`,children:[t.jsx(Ms,{...n}),t.jsx(Es,{...s}),t.jsxs("div",{className:$.tableHeading,children:[t.jsxs("div",{children:[t.jsx("h2",{children:r}),t.jsx("p",{children:a.exportStatus||a.filterStatus||a.subtitle})]}),t.jsxs("div",{className:$.tableActions,children:[t.jsx(re,{label:ks(a.isFetching,a.focused,a.focusedReason),tone:a.focused?"green":"blue"}),t.jsx(re,{label:a.activePreset?`Preset: ${mt(a.activePreset)}`:"Raw context gated",tone:a.activePreset?"green":"blue"}),t.jsxs("button",{className:"toolbar-button",type:"button","aria-expanded":a.detailsExpanded,onClick:a.onToggleDetails,children:[a.detailsExpanded?t.jsx(Fn,{size:16}):t.jsx(Nn,{size:16}),a.detailsExpanded?o.t("button.hide_details","Hide details"):o.t("dashboard.call_details","Call Details")]})]})]}),t.jsxs("div",{className:a.detailsExpanded?"table-detail-layout":"table-detail-layout detail-collapsed",children:[t.jsxs("div",{className:$.gridColumn,children:[t.jsx(Xt,{ariaLabel:h,columns:a.columns,data:a.calls,identityColumnId:"thread",lockedColumnIds:["investigate"],getRowId:d=>d.id,mobile:{primary:d=>d.thread,secondary:d=>o.translateText(`${d.time} · ${d.model} · ${ee(d.totalTokens)} tokens · ${q(d.cachedPct)} cache`),actionLabel:d=>Jt(d)},sorting:a.sorting,onSortingChange:a.onSortingChange,manualSorting:!0,columnVisibility:a.gridPreferences.columnVisibility,onColumnVisibilityChange:a.gridPreferences.setColumnVisibility,density:a.gridPreferences.density,onDensityChange:a.gridPreferences.setDensity,onRestoreDefaults:a.gridPreferences.restoreDefaults,selectedRowId:(F=a.selectedCall)==null?void 0:F.id,onRowSelect:d=>a.onSelectCall(d.id),onRowActivate:d=>i.onOpenInvestigator(d.id),activateOnClick:!0,selectOnHover:!0,viewportHeight:560,emptyLabel:"No rows match current filters."}),t.jsxs("div",{className:$.gridFooter,"aria-live":"polite",children:[t.jsx("span",{children:o.translateText(`${a.calls.length.toLocaleString()} loaded / ${a.totalMatchedCalls.toLocaleString()} matched`)}),a.focused&&a.hasNextPage?t.jsx("button",{className:"toolbar-button",type:"button",onClick:a.onLoadMore,disabled:a.isFetchingNextPage,children:a.isFetchingNextPage?"Loading more...":`Load ${B.toLocaleString()} more`}):null]})]}),a.detailsExpanded?t.jsx(cs,{call:a.selectedCall,calls:e.calls,...i}):null]}),t.jsxs("details",{className:$.patternsDisclosure,children:[t.jsxs("summary",{children:[t.jsx(ut,{size:17}),"Usage patterns"]}),t.jsxs("div",{className:"dashboard-grid three",children:[t.jsx(Z,{title:"Usage Over Time",subtitle:"Tokens",children:t.jsx(et,{series:e.tokenSeries,yLabel:"Tokens",height:220})}),t.jsx(Z,{title:"Cost by Model",subtitle:"Estimated USD",children:t.jsx(as,{data:e.modelCosts,valueLabel:Ae})}),t.jsx(Z,{title:"Cache Hit Rate Over Time",subtitle:o.translateText("Daily"),children:t.jsx(et,{series:e.cacheSeries,yLabel:"Cache %",height:220,valueFormatter:d=>`${d}%`})})]})]})]})}function ks(e,n,s){return e&&n?"Updating focused rows":e?"Loading focused rows":n?"Focused paged API":s||"Stored snapshot"}function oa(e,n="",s=""){const a=Pe();return ke(yt(e,{globalQuery:n,localQuery:T("call_q"),modelFilter:T("model")||"all",effortFilter:T("effort")||"all",confidenceFilter:gt(),sourceFilter:jt(),timeFilter:vt(),dateStart:le("from"),dateEnd:le("to"),activePreset:s}),a,Ct(a))}const Nt={time:"time",duration:"duration",gap:"previousCallGap",attention:"signal",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"totalTokens",cached:"cachedInput",uncached:"uncachedInput",output:"output",reasoning:"reasoningOutput",cost:"cost",usage:"credits",cache:"cachedPct",context:"contextWindowPct"},Is=Object.fromEntries(Object.entries(Nt).map(([e,n])=>[n,e]));function ra({model:e,globalQuery:n,activePreset:s,onRefresh:a,contextRuntime:i,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h,includeArchived:F=!1,sourceKey:d,sourceRevision:b="",scopeSince:j=null,focusedEndpointsEnabled:C=!0,workspaceSwitcher:D}){var We,Ye;const N=_s(e,n),{localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,setSortKey:L,sortDirection:v,setSortDirection:u,gridPreferences:te,density:G,selectedCallId:R,setSelectedCallId:ne,visibleCallRows:Q,setVisibleCallRows:de,exportStatus:ue,setExportStatus:W,filterStatus:he,detailsExpanded:me,searchInputRef:se,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}=N,f=c.useMemo(()=>[...Ut,Zt({onOpenInvestigator:r,onCopyCallLink:h})],[h,r]),A=c.useMemo(()=>es({runtime:i,enabled:C,activePreset:s,sourceFilter:w,sortKey:x,scopeSince:j,timeFilter:g,dateStart:_,dateEnd:E,confidenceFilter:p,globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l}),[s,p,i,E,_,l,C,n,y,m,x,w,j,g]),V=Lt({...It({runtime:i,includeArchived:F,sourceKey:d,sourceRevision:b,filters:A.filters,sort:A.sort,direction:v,pageSize:B}),enabled:A.enabled,placeholderData:M=>M}),Ue=c.useMemo(()=>yt(e.calls,{globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,activePreset:s}),[s,p,E,_,l,n,y,e.calls,m,w,g]),qe=c.useMemo(()=>ke(Ue,x,v),[Ue,v,x]),Ge=c.useMemo(()=>{var M;return((M=V.data)==null?void 0:M.pages.flatMap(X=>X.rows))??[]},[V.data]),ae=A.enabled&&!!V.data,H=c.useMemo(()=>ae?ke(Ge,x,v):qe,[Ge,qe,v,x,ae]),Me=ae?((Ye=(We=V.data)==null?void 0:We.pages[0])==null?void 0:Ye.totalMatchedRows)??H.length:e.calls.length,Tt=c.useMemo(()=>Tn({shownCount:H.length,totalCount:Me,localQuery:y,globalQuery:n,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateRangeStatus:Y,activePresetLabel:s?mt(s):""}),[s,p,Y,l,n,y,m,H.length,w,g,Me]),Qe=c.useMemo(()=>[{id:Nt[x],desc:v==="desc"}],[v,x]),ie=R===oe?H[0]??null:H.find(M=>M.id===R)??H[0]??null,z=ie&&(ie.id===R||R===oe)?ie.id:"";c.useEffect(()=>{R===oe&&z&&ne(z)},[R,z]),c.useEffect(()=>{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});M.toString()!==window.location.href&&window.history.replaceState(null,"",M)},[p,E,_,G,l,y,m,z,v,x,w,g,Q]);function Et(){qt(`codex-calls-${Wt()}.csv`,Gt(H,Qt)),W(`Exported ${H.length} calls`)}async function Mt(){try{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});if(!await ht(M.toString()))throw new Error("Clipboard unavailable");W("Copied Calls view link")}catch{W("Copy unavailable in browser")}}function Dt(M){var Xe,Je;const X=typeof M=="function"?M(Qe):M,De=Is[((Xe=X[0])==null?void 0:Xe.id)??""]??"time",_t=De!==x;L(De),u(_t?U(De):(Je=X[0])!=null&&Je.desc?"desc":"asc"),I()}async function Pt(){!V.hasNextPage||V.isFetchingNextPage||(await V.fetchNextPage(),de(M=>M+B))}return t.jsx(Ls,{model:e,header:{workspaceSwitcher:D,canExport:!!H.length,onExport:Et,onCopyView:Mt,onRefresh:a},filters:{searchInputRef:se,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,onLocalQueryChange:ge,onModelFilterChange:je,onEffortFilterChange:ve,onConfidenceFilterChange:be,onSourceFilterChange:Ce,onTimeFilterChange:ye,onDateStartChange:Se,onDateEndChange:we,onSortKeyChange:Fe,onSortDirectionChange:Ne,onClear:Te},table:{activePreset:s,exportStatus:ue,filterStatus:he,subtitle:Tt,focused:ae,focusedReason:A.reason,isFetching:V.isFetching,isFetchingNextPage:V.isFetchingNextPage,hasNextPage:!!V.hasNextPage,detailsExpanded:me,calls:H,totalMatchedCalls:Me,columns:f,sorting:Qe,gridPreferences:te,selectedCall:ie,onSortingChange:Dt,onSelectCall:ne,onLoadMore:Pt,onToggleDetails:Ee},inspector:{contextRuntime:i,includeArchived:F,sourceRevision:b,hydrateThreadCalls:C,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h}})}export{ra as CallsPage,oa as callsForCurrentUrl}; + */const Nn=Re("PanelRightOpen",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m10 15-3-3 3-3",key:"1pgupc"}]]);function Tn(e){const n=[],s=[e.localQuery.trim(),e.globalQuery.trim()].filter(Boolean);s.length&&n.push(`Search ${s.map(i=>`"${i}"`).join(" + ")}`),e.modelFilter!=="all"&&n.push(`Model ${e.modelFilter}`),e.effortFilter!=="all"&&n.push(`Effort ${e.effortFilter}`),e.confidenceFilter!=="all"&&n.push(`Confidence ${_n(e.confidenceFilter)}`),e.sourceFilter!=="all"&&n.push(`Source ${Ln(e.sourceFilter)}`),e.dateRangeStatus.invalid?n.push("Date range invalid"):(e.dateRangeStatus.active||e.timeFilter!=="all")&&n.push(e.dateRangeStatus.label||kn(e.timeFilter)),e.activePresetLabel&&n.push(`Preset ${e.activePresetLabel}`);const a=`Showing ${e.shownCount.toLocaleString()} of ${e.totalCount.toLocaleString()} aggregate rows`;return n.length?`${a} - Filters: ${n.join("; ")}`:a}function En(e,n){return n==="project"?`${e.project.toLocaleString()} project/cwd rows`:n==="session"?`${e.session.toLocaleString()} session-linked rows`:n==="git"?`${e.git.toLocaleString()} git rows`:n==="source-file"?`${e.sourceFile.toLocaleString()} source-file rows`:n==="missing"?`${e.missing.toLocaleString()} rows missing source`:`${e.project.toLocaleString()} project, ${e.session.toLocaleString()} session, ${e.git.toLocaleString()} git`}function Mn(e,n){return n==="all"?!0:n==="project"?Be(e):n==="session"?Ve(e):n==="git"?He(e):n==="source-file"?Ke(e):!ft(e)}function Dn(e,n){if(n==="all")return!0;if(n==="cost-exact")return!e.pricingEstimated&&Number.isFinite(e.cost)&&e.cost>0;if(n==="cost-estimated")return e.pricingEstimated;if(n==="cost-unpriced")return!e.pricingEstimated&&(!Number.isFinite(e.cost)||e.cost<=0);const s=e.usageCreditConfidence.toLowerCase();return n==="credit-exact"?s.includes("exact"):n==="credit-override"?s.includes("override"):n==="credit-estimated"?s.includes("estimated"):s.includes("missing")||s.includes("unpriced")}function Pn(e){return e.reduce((n,s)=>({project:n.project+(Be(s)?1:0),session:n.session+(Ve(s)?1:0),git:n.git+(He(s)?1:0),sourceFile:n.sourceFile+(Ke(s)?1:0),missing:n.missing+(ft(s)?0:1),total:n.total+1}),{project:0,session:0,git:0,sourceFile:0,missing:0,total:0})}function Be(e){return!!(e.project||e.projectRelativeCwd||e.cwd||e.projectTags.length)}function Ve(e){return!!(e.sessionId||e.turnId||e.parentSessionId)}function He(e){return!!(e.gitBranch||e.gitRemoteLabel||e.gitRemoteHash)}function Ke(e){return!!(e.sourceFile||e.lineNumber!==null)}function ft(e){return Be(e)||Ve(e)||He(e)||Ke(e)}function _n(e){return e==="cost-exact"?"exact cost":e==="cost-estimated"?"estimated cost":e==="cost-unpriced"?"unpriced cost":e==="credit-exact"?"exact credit rate":e==="credit-estimated"?"estimated credit mapping":e==="credit-override"?"user credit override":"missing credit rate"}function Ln(e){return e==="project"?"project/cwd":e==="session"?"session-linked":e==="git"?"git metadata":e==="source-file"?"source file":"missing source"}function kn(e){return e==="today"?"Today":e==="this-week"?"This week":e==="last-7-days"?"Last 7 days":e==="this-month"?"This month":e==="custom"?"Custom date range":"All time"}const oe="__detail_first__",In=new Set(["all","cost-exact","cost-estimated","cost-unpriced","credit-exact","credit-estimated","credit-override","credit-missing"]),$n=new Set(["all","today","this-week","last-7-days","this-month","custom"]),Rn=new Set(["all","project","session","git","source-file","missing"]),An=new Set(["time","duration","gap","attention","thread","initiator","model","effort","total","cached","uncached","output","reasoning","cost","usage","cache","context"]);function T(e,n=window.location.href){var s;return((s=new URL(n).searchParams.get(e))==null?void 0:s.trim())??""}function gt(e=window.location.href){const n=T("confidence",e)||T("pricing",e),s=Kn(n);return In.has(s)?s:"all"}function jt(e=window.location.href){const n=T("source",e);return Rn.has(n)?n:"all"}function vt(e=window.location.href){const n=T("date",e)||T("time",e);return $n.has(n)?n:"all"}function le(e,n=window.location.href){return Le(T(e,n))}function On(e=window.location.href){const n=T("record",e);return n||(T("detail",e)==="first"?oe:null)}function Pe(e=window.location.href){const n=T("sort",e);return bt(n)}function bt(e){return An.has(e)?e:"time"}function Ct(e,n=window.location.href){const s=T("direction",n);return s==="asc"||s==="desc"?s:U(e)}function Bn(e=window.location.href){return T("density",e)==="roomy"?"roomy":"dense"}function Vn(e,n=window.location.href){const s=Number(T("page",n)||1);return Number.isFinite(s)&&s>1?Math.floor(s)*e:e}function _e(e,n=window.location.href){const s=new URL(n);return s.searchParams.set("view","calls"),s.searchParams.delete("detail"),s.searchParams.delete("pricing"),k(s,"record",e.selectedRecordId,""),k(s,"call_q",e.localQuery.trim(),""),k(s,"model",e.modelFilter,"all"),k(s,"effort",e.effortFilter,"all"),k(s,"confidence",e.confidenceFilter,"all"),k(s,"source",e.sourceFilter,"all"),k(s,"time",e.timeFilter,"all"),k(s,"date",e.timeFilter,"all"),k(s,"from",e.timeFilter==="custom"?e.dateStart:"",""),k(s,"to",e.timeFilter==="custom"?e.dateEnd:"",""),k(s,"sort",e.sortKey,"time"),k(s,"direction",e.sortDirection,U(e.sortKey)),k(s,"density",e.density,"dense"),k(s,"page",String(Hn(e.visibleRowCount,e.pageSize)),"1"),s}function U(e){return e==="cache"||e==="effort"||e==="initiator"||e==="model"||e==="thread"?"asc":"desc"}function Le(e){const n=zn(e);return n?Un(n):""}function Hn(e,n){return Math.max(1,Math.ceil(Math.max(e,n)/n))}function k(e,n,s,a){if(!s||s===a){e.searchParams.delete(n);return}e.searchParams.set(n,s)}function Kn(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":e}function zn(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function Un(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(e,n){return e.filter(s=>qn(s,n))}function ke(e,n,s){return[...e].sort((a,i)=>Gn(a,i,n,s))}function ze(e,n,s,a){const i=Yn(a);if(e==="custom"){const o=lt(n),r=lt(s);return o&&r&&o>r?{active:!0,invalid:!0,start:o,endExclusive:K(r,1),label:"Invalid date range"}:{active:!!(o||r),invalid:!1,start:o,endExclusive:r?K(r,1):null,label:J("Custom",o,r)}}if(e==="today")return{active:!0,invalid:!1,start:i,endExclusive:K(i,1),label:J("Today",i,i)};if(e==="this-week"){const o=Xn(i);return{active:!0,invalid:!1,start:o,endExclusive:K(o,7),label:J("This week",o,K(o,6))}}if(e==="last-7-days"){const o=K(i,-6);return{active:!0,invalid:!1,start:o,endExclusive:K(i,1),label:J("Last 7 days",o,i)}}if(e==="this-month"){const o=new Date(i.getFullYear(),i.getMonth(),1),r=new Date(i.getFullYear(),i.getMonth()+1,1);return{active:!0,invalid:!1,start:o,endExclusive:r,label:J("This month",o,K(r,-1))}}return{active:!1,invalid:!1,start:null,endExclusive:null,label:"All time"}}function qn(e,n){if(n.modelFilter!=="all"&&e.model!==n.modelFilter||n.effortFilter!=="all"&&e.effort!==n.effortFilter||!Dn(e,n.confidenceFilter)||!Mn(e,n.sourceFilter)||!Jn(e,n.timeFilter,n.dateStart,n.dateEnd)||n.activePreset&&!$t(e,n.activePreset))return!1;const s=[e.thread,e.cwd,e.project,e.projectRelativeCwd,e.gitBranch,e.gitRemoteLabel,e.sessionId,e.model,e.effort,e.initiator,e.initiatorReason,e.signal,e.recommendation,e.rawTime,e.sourceFile,e.lineNumber,e.tags.join(" ")];return[n.globalQuery,n.localQuery].every(a=>Xt(s,a))}function Gn(e,n,s,a){const i=rt(e,s),o=rt(n,s);if(i===null&&o!==null)return 1;if(o===null&&i!==null)return-1;const r=Wn(i,o);return r!==0?a==="asc"?r:-r:Ie(e,n)||e.id.localeCompare(n.id)}function rt(e,n){return n==="time"?$e(e):n==="duration"?e.durationSeconds:n==="gap"?e.previousCallGapSeconds:n==="attention"?Qn(e):n==="thread"?e.thread.toLowerCase():n==="initiator"?e.initiator.toLowerCase():n==="model"?e.model.toLowerCase():n==="effort"?e.effort.toLowerCase():n==="total"?e.totalTokens:n==="cached"?e.input*(e.cachedPct/100):n==="uncached"?e.uncachedInput:n==="output"?e.output:n==="reasoning"?e.reasoningOutput:n==="cost"?e.cost:n==="usage"?e.credits:n==="cache"?e.cachedPct:e.contextWindowPct}function Qn(e){const n=e.signal&&e.signal!=="aggregate"?1e3:0,s=e.recommendation?750:0,a=e.contextWindowPct??0,i=Math.min(e.uncachedInput/1e3,250),o=Math.min(e.cost*25,200),r=Math.min(e.credits,200),h=Math.min(e.durationSeconds/60,120);return n+s+a+i+o+r+h}function Wn(e,n){return e===null&&n===null?0:e===null?1:n===null?-1:typeof e=="string"||typeof n=="string"?String(e).localeCompare(String(n)):e-n}function Ie(e,n){return $e(n)-$e(e)}function $e(e){const n=Date.parse(e.rawTime);return Number.isFinite(n)?n:0}function lt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function ct(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function J(e,n,s){const a=n?ct(n):"",i=s?ct(s):"";return a&&i&&a===i?`${e}: ${a}`:a&&i?`${e}: ${a} to ${i}`:a?`${e}: from ${a}`:i?`${e}: through ${i}`:e}function Yn(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function K(e,n){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+n)}function Xn(e){const n=e.getDay();return K(e,n===0?-6:1-n)}function Jn(e,n,s="",a="",i=new Date){if(n==="all")return!0;const o=ze(n,s,a,i);if(o.invalid)return!1;if(!o.active)return!0;const r=Date.parse(e.rawTime);return!(!Number.isFinite(r)||o.start&&r=o.endExclusive.getTime())}const Zn={time:"time",duration:"duration",gap:"gap",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"tokens",cached:"cached",uncached:"uncached",output:"output",reasoning:"reasoning",cache:"cache"};function es(e){const n=Zn[e.sortKey],s=ze(e.timeFilter,e.dateStart,e.dateEnd,new Date),a=ts(e,n,s.invalid);return{enabled:!a,reason:a,sort:n??"time",filters:{query:[e.globalQuery.trim(),e.localQuery.trim()].filter(Boolean).join(" "),model:e.modelFilter==="all"?void 0:e.modelFilter,effort:e.effortFilter==="all"?void 0:e.effortFilter,...ns(e.confidenceFilter),...ss(s.start,s.endExclusive,e.scopeSince)}}}function ts(e,n,s){return!e.enabled||e.runtime.fileMode||!e.runtime.apiToken?"Stored snapshot":e.globalQuery.trim()&&e.localQuery.trim()?"Multiple searches use loaded snapshot":e.activePreset?"Preset uses loaded snapshot":e.sourceFilter!=="all"?"Source filter uses loaded snapshot":n?s?"Invalid date range":"":"This sort uses loaded snapshot"}function ns(e){return e==="cost-exact"?{pricingStatus:"priced"}:e==="cost-estimated"?{pricingStatus:"estimated"}:e==="cost-unpriced"?{pricingStatus:"unpriced"}:e==="credit-exact"?{creditConfidence:"exact"}:e==="credit-estimated"?{creditConfidence:"estimated"}:e==="credit-override"?{creditConfidence:"user_override"}:e==="credit-missing"?{creditConfidence:"unpriced"}:{}}function ss(e,n,s){return{since:(e==null?void 0:e.toISOString())??s??void 0,until:n?new Date(n.getTime()-1).toISOString():void 0}}function as({data:e,valueLabel:n=s=>String(s)}){const s=Math.max(...e.map(a=>a.value),1);return t.jsx("div",{className:"bar-list",children:e.map(a=>t.jsxs("div",{className:"bar-row",children:[t.jsx("span",{children:a.label}),t.jsx("div",{className:"bar-track","aria-hidden":"true",children:t.jsx("i",{style:{width:`${a.value/s*100}%`,backgroundColor:a.color??"#2563eb"}})}),t.jsx("strong",{children:n(a.value)})]},a.label))})}function P({label:e,value:n,detail:s}){return t.jsxs("span",{className:"drilldown-metric",children:[t.jsx("small",{children:e}),t.jsx("strong",{children:n}),t.jsx("em",{children:s})]})}function S({label:e,value:n}){return t.jsxs("div",{children:[t.jsx("dt",{children:e}),t.jsx("dd",{children:n})]})}function is({call:e,contextRuntime:n,onContextApiEnabledChange:s}){const a=ce(),[i,o]=c.useState(()=>nn(e.id)??tt),[r,h]=c.useState({status:"idle"}),F=!!n.apiToken&&!n.fileMode,d=F&&n.contextApiEnabled;c.useEffect(()=>{const l=nt(e.id,i);h(l?{status:"loaded",payload:l}:{status:"idle"})},[e.id,i.includeCompactionHistory,i.includeToolOutput,i.maxChars,i.maxEntries,i.mode]);async function b(){h({status:"loading",message:"Enabling localhost context API..."});try{const l=await an(n);s(l),h({status:"idle",message:l?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(l){h({status:"error",message:st(l)})}}async function j(l=i,p="Loading selected-turn evidence..."){at(e.id,l);const w=nt(e.id,l);if(w){h({status:"loaded",payload:w});return}h({status:"loading",message:p});try{const g=await on(e.id,n,l);rn(e.id,l,g),h({status:"loaded",payload:g})}catch(g){h({status:"error",message:st(g)})}}function C(){const l={...i,mode:"full"};o(l),j(l,"Loading full turn analysis...")}function D(l){const p=xn(l,i);o(p),j(p,"Loading older context...")}function N(){const l={...i,includeToolOutput:!0};o(l),j(l,"Loading omitted tool output...")}function y(){const l={...i,includeCompactionHistory:!0};o(l),j(l,"Loading compacted replacement...")}function m(l,p){o(w=>{const g={...w,[l]:p};return at(e.id,g),g})}return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"locked-context-card",children:[t.jsx(pt,{size:20}),t.jsxs("div",{children:[t.jsx("strong",{children:"Raw context is gated"}),t.jsx("p",{children:sn(n)})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Record id",value:e.id}),t.jsx(S,{label:"Time",value:e.time}),t.jsx(S,{label:"Thread",value:e.thread}),t.jsx(S,{label:"Model",value:e.model}),t.jsx(S,{label:"Effort",value:e.effort})]}),t.jsxs("div",{className:"context-action-grid",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:b,disabled:!F||n.contextApiEnabled||r.status==="loading",children:a.t("button.enable_context_loading","Enable context loading")}),t.jsx("button",{className:"primary-button",type:"button",onClick:()=>j(),disabled:!d||r.status==="loading",children:a.t("button.show_turn_evidence","Show turn log evidence")}),t.jsx("button",{className:"toolbar-button",type:"button",onClick:C,disabled:!d||r.status==="loading",children:a.t("button.full_serialized_analysis","Run full serialized analysis")}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Mode"}),t.jsxs("select",{"aria-label":"Side panel context mode",value:i.mode,disabled:!d||r.status==="loading",onChange:l=>m("mode",l.target.value==="full"?"full":"quick"),children:[t.jsx("option",{value:"quick",children:"Quick"}),t.jsx("option",{value:"full",children:"Full"})]})]}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Entries"}),t.jsxs("select",{"aria-label":"Side panel context entries",value:String(i.maxEntries),disabled:!d||r.status==="loading",onChange:l=>m("maxEntries",Number(l.target.value)),children:[t.jsx("option",{value:"20",children:"20"}),t.jsx("option",{value:"50",children:"50"}),t.jsx("option",{value:"100",children:"100"}),t.jsx("option",{value:"0",children:"All"})]})]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeToolOutput,disabled:!d||r.status==="loading",onChange:l=>m("includeToolOutput",l.target.checked)}),a.t("button.include_tool_output","Include tool output")]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeCompactionHistory,disabled:!d||r.status==="loading",onChange:l=>m("includeCompactionHistory",l.target.checked)}),"Include compaction history"]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.maxChars===0,disabled:!d||r.status==="loading",onChange:l=>m("maxChars",l.target.checked?0:tt.maxChars)}),a.t("button.no_char_limit","No char limit")]})]}),r.status==="idle"&&r.message?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="loading"?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="error"?t.jsx("p",{className:"context-state-note error",children:r.message}):null,r.status==="loaded"?t.jsx(os,{call:e,payload:r.payload,onLoadOlder:D,onRunFullAnalysis:C,onLoadCompactionHistory:y,onLoadToolOutput:N}):null,t.jsx("p",{className:"privacy-note",children:"Raw context is never embedded in the dashboard HTML. This view reads the selected local JSONL turn only after an explicit request."})]})}function os({call:e,payload:n,onLoadOlder:s,onRunFullAnalysis:a,onLoadCompactionHistory:i,onLoadToolOutput:o}){var _,E;const r=ce(),h=n.entries??[],F=n.omitted??{},d=Number(F.older_entries??0),b=ln(n),j=8,C=e.id||String(n.record_id??""),[D,N]=c.useState(()=>it(C)),[y,m]=c.useState(()=>ot(C,h));c.useEffect(()=>{N(it(C)),m(ot(C,h))},[h.length,n.context_mode,n.include_compaction_history,n.include_tool_output,(_=n.omitted)==null?void 0:_.max_chars,(E=n.omitted)==null?void 0:E.max_entries,n.record_id,C]);const l=D?h:h.slice(0,j),p=Math.max(h.length-l.length,0);function w(){N(x=>{const L=!x;return fn(C,L),L})}function g(x,L){pn(C,x,L),m(v=>{const u=new Set(v);return L?u.add(x):u.delete(x),u})}return t.jsxs("div",{className:"context-evidence",children:[t.jsxs("div",{className:"context-evidence-summary",children:[t.jsx(P,{label:"Entries",value:O(h.length),detail:String(n.context_mode??"quick")}),t.jsx(P,{label:"Visible chars",value:O(Number(n.visible_char_count??0)),detail:"redacted local text"}),t.jsx(P,{label:"Visible tokens",value:O(Number(n.visible_token_estimate??0)),detail:"estimator"}),t.jsx(P,{label:"Older omitted",value:O(d),detail:"entry budget"})]}),b.length?t.jsx("p",{className:"context-note",children:b.join(" ")}):null,t.jsx(cn,{call:e,payload:n,onRunFullAnalysis:a}),d>0?t.jsx("div",{className:"context-followup-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>s(n),children:r.t("button.load_older_context","Load older entries")})}):null,t.jsxs("div",{className:"context-entry-list",children:[l.map((x,L)=>{const v=dn(x,L);return t.jsxs("details",{className:"context-entry",open:y.has(v),onToggle:u=>g(v,u.currentTarget.open),children:[t.jsx("summary",{className:"context-entry-summary",children:t.jsxs("div",{className:"context-entry-meta",children:[t.jsx("strong",{children:x.label||x.role||x.type||`Entry ${L+1}`}),t.jsx("span",{children:x.line_number?`line ${x.line_number}`:x.timestamp||"local evidence"})]})}),t.jsx(un,{entry:x}),x.tool_output_omitted?t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:o,children:r.t("button.show_tool_output","Show tool output")})}):null,t.jsx(rs,{entry:x,onLoadCompactionHistory:i}),t.jsx("pre",{ref:u=>{u&&(u.scrollTop=mn(C,v))},onScroll:u=>hn(C,v,u.currentTarget.scrollTop),children:x.text||"[no visible text]"})]},v)}),h.length?null:t.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),h.length>j?t.jsxs("div",{className:"context-followup-actions",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:w,children:D?`Show first ${O(j)} entries`:`Show all ${O(h.length)} returned entries`}),D?null:t.jsxs("span",{className:"context-entry-count-note",children:[O(p)," entries hidden in compact view"]})]}):null]})}function rs({entry:e,onLoadCompactionHistory:n}){const s=ce(),a=e.compaction;if(!(a!=null&&a.replacement_history_available))return null;const i=a.replacement_history??[],o=Number(a.replacement_entry_count??i.length);return t.jsxs("div",{className:"context-entry-compaction",children:[t.jsx("strong",{children:"Compaction detected"}),t.jsxs("span",{children:[O(o)," replacement history entries available."]}),i.length?t.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:i.map((r,h)=>t.jsxs("div",{className:"context-replacement-entry",children:[t.jsx("strong",{children:r.label||`Replacement item ${h+1}`}),t.jsx("pre",{children:r.text||"[no visible replacement text]"})]},`${r.label??"replacement"}-${h}`))}):t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}const ls=[{id:"summary",label:"Summary",icon:At},{id:"tokens",label:"Tokens",icon:ut},{id:"cache",label:"Cache",icon:Ot},{id:"thread",label:"Thread",icon:wn},{id:"evidence",label:"Evidence",icon:pt}];function cs({call:e,calls:n,contextRuntime:s,includeArchived:a,sourceRevision:i,hydrateThreadCalls:o,onContextApiEnabledChange:r,onOpenInvestigator:h,onCopyCallLink:F}){const[d,b]=c.useState("summary"),[j,C]=c.useState(""),D=c.useMemo(()=>e?n.filter(m=>m.thread===e.thread).sort(Ie):[],[e,n]),N=tn({...kt({runtime:s,includeArchived:a,sourceRevision:i,threadKey:(e==null?void 0:e.threadKey)||(e==null?void 0:e.thread)||"",selectedRecordId:(e==null?void 0:e.id)??"",selectedEventTimestamp:(e==null?void 0:e.eventTimestamp)??""}),enabled:o&&!s.fileMode&&!!s.apiToken&&!!e,placeholderData:m=>m}),y=c.useMemo(()=>{var l;const m=((l=N.data)==null?void 0:l.rows)??D;return!e||m.some(p=>p.id===e.id)?m:[...m,e].sort(Ie)},[e,D,N.data]);return e?t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsxs(Z,{title:"Call Drill-Down",subtitle:`${e.thread} / ${e.model}`,children:[t.jsxs("div",{className:"call-summary",children:[t.jsx(re,{label:"Aggregate only",tone:"green"}),t.jsx(Rt,{call:e}),t.jsx(re,{label:"Raw context gated",tone:"blue"}),t.jsx("span",{className:"call-id",children:e.id.slice(0,12)})]}),t.jsxs("div",{className:"action-row",children:[t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>h(e.id),children:[t.jsx(Cn,{size:16}),"Open investigator"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>ps(e,C),children:[t.jsx(dt,{size:16}),"Copy link"]})]}),j?t.jsx("p",{className:"context-state-note",children:j}):null,t.jsx("div",{className:"drilldown-tabs",role:"tablist","aria-label":"Call drill-down sections",children:ls.map(m=>{const l=m.icon,p=d===m.id;return t.jsxs("button",{type:"button",role:"tab","aria-selected":p,className:p?"active":"",onClick:()=>b(m.id),children:[t.jsx(l,{size:14}),m.label]},m.id)})}),t.jsxs("div",{className:"drilldown-tab-panel",role:"tabpanel",children:[d==="summary"?t.jsx(ds,{call:e}):null,d==="tokens"?t.jsx(hs,{call:e}):null,d==="cache"?t.jsx(ms,{call:e,calls:y}):null,d==="thread"?t.jsx(xs,{call:e,calls:y,onOpenInvestigator:h,onCopyCallLink:F}):null,d==="evidence"?t.jsx(is,{call:e,contextRuntime:s,onContextApiEnabledChange:r},e.id):null]})]})}):t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsx(Z,{title:"Call Drill-Down",subtitle:"No matching call",children:t.jsx("p",{className:"empty-state",children:"No aggregate row matches the active filters."})})})}function ds({call:e}){return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Total tokens",value:O(e.totalTokens),detail:`${ee(e.input)} input`}),t.jsx(P,{label:"Uncached input",value:O(e.uncachedInput),detail:"fresh billed input"}),t.jsx(P,{label:"Cache hit rate",value:q(e.cachedPct),detail:Ae(e)}),t.jsx(P,{label:"Estimated cost",value:Oe(e.cost),detail:e.pricingEstimated?"estimated pricing":"configured pricing"}),t.jsx(P,{label:"Duration",value:e.duration,detail:Bt(e)}),t.jsx(P,{label:"Usage credits",value:e.credits?e.credits.toFixed(3):"-",detail:e.usageCreditConfidence})]}),t.jsx(gn,{call:e}),t.jsx(jn,{call:e}),t.jsx(us,{call:e}),t.jsx(St,{call:e}),t.jsx(wt,{call:e}),e.recommendation?t.jsxs("div",{className:"recommendation-box",children:[t.jsx(yn,{size:16}),t.jsx("p",{children:e.recommendation})]}):null]})}function us({call:e}){return t.jsxs("div",{className:"composition-card accounting-snapshot-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Accounting Snapshot"}),t.jsx("span",{children:"pricing, credits, and cache savings"})]}),t.jsx(xt,{call:e})]})}function hs({call:e}){return t.jsxs(t.Fragment,{children:[t.jsx(St,{call:e}),t.jsx(xt,{call:e})]})}function ms({call:e,calls:n}){return t.jsxs(t.Fragment,{children:[t.jsx(wt,{call:e}),t.jsx(vn,{call:e,calls:n}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Cache state",value:Ae(e)}),t.jsx(S,{label:"Cache hit rate",value:q(e.cachedPct)}),t.jsx(S,{label:"Fresh share",value:q(Math.max(100-e.cachedPct,0))}),t.jsx(S,{label:"Signal",value:e.signal})]}),t.jsx("p",{className:"privacy-note",children:"Use this readout to decide whether the aggregate call needs deeper raw-context investigation."})]})}function xs({call:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a}){const i=n.reduce((b,j)=>b+j.totalTokens,0),o=n.reduce((b,j)=>b+j.cost,0),r=n.reduce((b,j)=>b+j.cachedPct,0)/Math.max(n.length,1),h=Math.max(n.findIndex(b=>b.id===e.id),0),F=Math.min(Math.max(n.length,1),5),d=e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available";return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Loaded thread calls",value:O(n.length),detail:`selected ${h+1} of ${n.length}`}),t.jsx(P,{label:"Thread tokens",value:ee(i),detail:"loaded aggregate rows"}),t.jsx(P,{label:"Thread cost",value:Oe(o),detail:"estimated aggregate"}),t.jsx(P,{label:"Avg cache",value:q(r),detail:Vt(n.map(b=>b.model),{style:"x",emptyLabel:"no model mix"})}),t.jsx(P,{label:"Context window",value:e.contextWindowPct===null?"-":q(e.contextWindowPct),detail:e.modelContextWindow?`${ee(e.modelContextWindow)} window`:"not reported"}),t.jsx(P,{label:"Parent thread",value:e.parentThread||"-",detail:e.parentSessionId||"no parent session"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Thread timeline"}),t.jsxs("span",{children:[F," nearby loaded calls"]})]}),t.jsx(bn,{selectedCall:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a,copyAriaContext:"side-panel thread call"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Call Narrative"}),t.jsx("span",{children:e.initiatorConfidence||"aggregate inference"})]}),t.jsxs("dl",{className:"detail-list compact",children:[t.jsx(S,{label:"Initiated by",value:e.initiator||"unknown"}),t.jsx(S,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),t.jsx(S,{label:"Parent thread",value:e.parentThread||"None"}),t.jsx(S,{label:"Parent session",value:e.parentSessionId||"None"}),t.jsx(S,{label:"Timestamp",value:e.time}),t.jsx(S,{label:"Duration",value:e.duration}),t.jsx(S,{label:"Previous gap",value:e.previousCallGap})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Project",value:e.project||"Unknown"}),t.jsx(S,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),t.jsx(S,{label:"Source line",value:d}),t.jsx(S,{label:"Session",value:e.sessionId||"Not available"}),t.jsx(S,{label:"Git branch",value:e.gitBranch||"Unknown"}),t.jsx(S,{label:"Remote",value:e.gitRemoteLabel||e.gitRemoteHash||"None"})]})]})}function St({call:e}){const s=[{label:"Cached input",value:Math.max(e.input-e.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:e.uncachedInput,color:"#f59e0b"},{label:"Output",value:e.output,color:"#059669"},{label:"Reasoning",value:e.reasoningOutput,color:"#7c3aed"}].filter(i=>i.value>0),a=Math.max(s.reduce((i,o)=>i+o.value,0),1);return t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Token composition"}),t.jsxs("span",{children:[ee(a)," visible tokens"]})]}),t.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(i=>t.jsx("i",{style:{width:`${Math.max(i.value/a*100,3)}%`,background:i.color}},i.label))}),t.jsx("div",{className:"composition-legend",children:s.map(i=>t.jsxs("span",{children:[t.jsx("i",{style:{background:i.color}}),i.label]},i.label))})]})}function wt({call:e}){const n=[{label:"Cache",value:Math.min(Math.max(e.cachedPct,0),100),color:"#2563eb"},{label:"Fresh",value:Math.min(Math.max(100-e.cachedPct,0),100),color:"#f59e0b"},{label:"Output",value:Math.min(Math.max(e.output/Math.max(e.totalTokens,1)*100,0),100),color:"#059669"}];return t.jsxs("div",{className:"cache-mini-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"Cache delta readout"}),t.jsx("span",{children:Ae(e)})]}),t.jsx("div",{className:"cache-bars","aria-label":"Cache delta readout",children:n.map(s=>t.jsxs("span",{children:[t.jsx("i",{style:{height:`${Math.max(s.value,4)}%`,background:s.color}}),t.jsx("em",{children:s.label})]},s.label))})]})}async function ps(e,n){try{const s=new URL(window.location.href);if(s.searchParams.set("view","call"),s.searchParams.set("record",e.id),s.searchParams.set("return","calls"),!await ht(s.toString()))throw new Error("Clipboard unavailable");n("Copied investigator link")}catch{n("Copy unavailable in this browser")}}const fs="_page_gyxvc_1",gs="_pageHeader_gyxvc_5",js="_tableHeading_gyxvc_13",vs="_eyebrow_gyxvc_22",bs="_headerActions_gyxvc_36",Cs="_tableActions_gyxvc_37",ys="_gridFooter_gyxvc_38",Ss="_queryBar_gyxvc_46",ws="_advancedFilters_gyxvc_80",Fs="_patternsDisclosure_gyxvc_85",Ns="_advancedFilterGrid_gyxvc_107",Ts="_gridColumn_gyxvc_138",$={page:fs,pageHeader:gs,tableHeading:js,eyebrow:vs,headerActions:bs,tableActions:Cs,gridFooter:ys,queryBar:Ss,advancedFilters:ws,patternsDisclosure:Fs,advancedFilterGrid:Ns,gridColumn:Ts};function Es({searchInputRef:e,localQuery:n,modelFilter:s,effortFilter:a,confidenceFilter:i,sourceFilter:o,timeFilter:r,dateStart:h,dateEnd:F,sortKey:d,sortDirection:b,modelOptions:j,effortOptions:C,sourceCoverage:D,dateRangeStatus:N,onLocalQueryChange:y,onModelFilterChange:m,onEffortFilterChange:l,onConfidenceFilterChange:p,onSourceFilterChange:w,onTimeFilterChange:g,onDateStartChange:_,onDateEndChange:E,onSortKeyChange:x,onSortDirectionChange:L,onClear:v}){return t.jsxs("section",{className:$.queryBar,"aria-label":"Call filters",children:[t.jsxs("label",{className:"search-box",children:[t.jsx("span",{className:"sr-only",children:"Search calls"}),t.jsx("input",{ref:e,value:n,onChange:u=>y(u.target.value),placeholder:"Search calls, cwd, projects, models..."})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Model"}),t.jsxs("select",{value:s,onChange:u=>m(u.target.value),children:[t.jsx("option",{value:"all",children:"All models"}),j.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Effort"}),t.jsxs("select",{value:a,onChange:u=>l(u.target.value),children:[t.jsx("option",{value:"all",children:"All effort"}),C.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Confidence"}),t.jsxs("select",{"aria-label":"Confidence filter",value:i,onChange:u=>p(u.target.value),children:[t.jsx("option",{value:"all",children:"All confidence"}),t.jsx("option",{value:"cost-exact",children:"Exact cost"}),t.jsx("option",{value:"cost-estimated",children:"Estimated cost"}),t.jsx("option",{value:"cost-unpriced",children:"Unpriced cost"}),t.jsx("option",{value:"credit-exact",children:"Exact credit rate"}),t.jsx("option",{value:"credit-estimated",children:"Estimated credit mapping"}),t.jsx("option",{value:"credit-override",children:"User credit override"}),t.jsx("option",{value:"credit-missing",children:"Missing credit rate"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Time"}),t.jsxs("select",{"aria-label":"Time filter",value:r,onChange:u=>g(u.target.value),children:[t.jsx("option",{value:"all",children:"All time"}),t.jsx("option",{value:"today",children:"Today"}),t.jsx("option",{value:"this-week",children:"This week"}),t.jsx("option",{value:"last-7-days",children:"Last 7 days"}),t.jsx("option",{value:"this-month",children:"This month"}),t.jsx("option",{value:"custom",children:"Custom range"})]}),N.active||N.invalid?t.jsx("span",{className:"filter-status","data-state":N.invalid?"error":"active","aria-live":"polite",children:N.label}):null]}),t.jsxs("details",{className:$.advancedFilters,children:[t.jsxs("summary",{children:[t.jsx(Ht,{size:16}),"More filters"]}),t.jsxs("div",{className:$.advancedFilterGrid,children:[t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Source"}),t.jsxs("select",{"aria-label":"Source filter",value:o,onChange:u=>w(u.target.value),children:[t.jsx("option",{value:"all",children:"All sources"}),t.jsx("option",{value:"project",children:"Project / cwd"}),t.jsx("option",{value:"session",children:"Session-linked"}),t.jsx("option",{value:"git",children:"Git metadata"}),t.jsx("option",{value:"source-file",children:"Source file"}),t.jsx("option",{value:"missing",children:"Missing source"})]}),t.jsx("span",{className:"filter-status","data-state":o==="all"?"active":"filtered","aria-live":"polite",children:En(D,o)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Start"}),t.jsx("input",{"aria-label":"Start date",type:"date",value:h,onChange:u=>_(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"End"}),t.jsx("input",{"aria-label":"End date",type:"date",value:F,onChange:u=>E(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Sort"}),t.jsxs("select",{"aria-label":"Sort calls",value:d,onChange:u=>x(u.target.value),children:[t.jsx("option",{value:"time",children:"Newest calls"}),t.jsx("option",{value:"duration",children:"Longest duration"}),t.jsx("option",{value:"gap",children:"Longest gap"}),t.jsx("option",{value:"attention",children:"Needs attention"}),t.jsx("option",{value:"thread",children:"Thread name"}),t.jsx("option",{value:"initiator",children:"Initiated"}),t.jsx("option",{value:"model",children:"Model"}),t.jsx("option",{value:"effort",children:"Reasoning"}),t.jsx("option",{value:"total",children:"Most tokens"}),t.jsx("option",{value:"cached",children:"Cached"}),t.jsx("option",{value:"uncached",children:"Uncached"}),t.jsx("option",{value:"output",children:"Output"}),t.jsx("option",{value:"reasoning",children:"Reasoning output"}),t.jsx("option",{value:"cost",children:"Highest estimated cost"}),t.jsx("option",{value:"usage",children:"Highest Codex credits"}),t.jsx("option",{value:"cache",children:"Lowest cache ratio"}),t.jsx("option",{value:"context",children:"Highest context use"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Direction"}),t.jsxs("select",{"aria-label":"Sort direction",value:b,onChange:u=>L(u.target.value),children:[t.jsx("option",{value:"desc",children:"Descending"}),t.jsx("option",{value:"asc",children:"Ascending"})]})]})]})]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:v,children:[t.jsx(Kt,{size:16}),"Clear filters"]})]})}function Ms({workspaceSwitcher:e,canExport:n,onExport:s,onCopyView:a,onRefresh:i}){return t.jsxs("header",{className:$.pageHeader,children:[t.jsxs("div",{children:[t.jsx("p",{className:$.eyebrow,children:"Evidence explorer"}),t.jsx("h1",{children:"Calls"}),t.jsx("p",{children:"Find expensive, cold, or context-heavy calls and move directly into their evidence."})]}),t.jsxs("div",{className:$.headerActions,children:[e,t.jsxs("button",{className:"toolbar-button",type:"button",onClick:s,disabled:!n,children:[t.jsx(zt,{size:16}),"Export"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:a,children:[t.jsx(dt,{size:16}),"Copy view"]}),t.jsxs("button",{className:"primary-button",type:"button",onClick:i,children:[t.jsx(Ut,{size:16}),"Refresh"]})]})]})}const Ft="codexUsageDetailPanel";function Ds(e=!1){var n;try{const s=(n=window.sessionStorage)==null?void 0:n.getItem(Ft);return s?s==="expanded":e}catch{return e}}function Ps(e){var n;try{(n=window.sessionStorage)==null||n.setItem(Ft,e?"expanded":"collapsed")}catch{}}const B=250;function _s(e,n){const s=T("density"),[a,i]=c.useState(()=>T("call_q")),[o,r]=c.useState(()=>T("model")||"all"),[h,F]=c.useState(()=>T("effort")||"all"),[d,b]=c.useState(()=>gt()),[j,C]=c.useState(()=>jt()),[D,N]=c.useState(()=>vt()),[y,m]=c.useState(()=>le("from")),[l,p]=c.useState(()=>le("to")),[w,g]=c.useState(()=>Pe()),[_,E]=c.useState(()=>Ct(Pe())),x=Sn("codexUsageCallsEvidenceGrid",{density:Bn()==="dense"?"compact":"comfortable",columnVisibility:{}},s==="roomy"?"comfortable":s==="dense"?"compact":void 0),L=x.density==="compact"?"dense":"roomy",v=c.useMemo(()=>On(),[]),[u,te]=c.useState(v),[G,R]=c.useState(()=>Vn(B)),[ne,Q]=c.useState(""),[de,ue]=c.useState(""),[W,he]=c.useState(()=>Ds(!!v)),me=c.useRef(null),se=c.useRef(n),xe=c.useMemo(()=>Ze(e.calls.map(f=>f.model)),[e.calls]),pe=c.useMemo(()=>Ze(e.calls.map(f=>f.effort)),[e.calls]),fe=c.useMemo(()=>Pn(e.calls),[e.calls]),Y=c.useMemo(()=>ze(D,y,l,new Date),[l,y,D]);c.useEffect(()=>{se.current!==n&&(se.current=n,R(B))},[n]);function I(){R(B)}function ge(f){i(f),I()}function je(f){r(f),I()}function ve(f){F(f),I()}function be(f){b(f),I()}function Ce(f){C(f),I()}function ye(f){N(f),I()}function Se(f){m(Le(f)),N("custom"),I()}function we(f){p(Le(f)),N("custom"),I()}function Fe(f){const A=bt(f);g(A),E(U(A)),I()}function Ne(f){E(f==="asc"?"asc":"desc"),I()}function Te(){i(""),r("all"),F("all"),b("all"),C("all"),N("all"),m(""),p(""),g("time"),E(U("time")),x.setDensity("compact"),x.setColumnVisibility({}),te(null),R(B),window.history.replaceState(null,"",_e({localQuery:"",modelFilter:"all",effortFilter:"all",confidenceFilter:"all",sourceFilter:"all",timeFilter:"all",dateStart:"",dateEnd:"",sortKey:"time",sortDirection:U("time"),density:"dense",selectedRecordId:"",visibleRowCount:B,pageSize:B})),ue("Calls filters cleared")}function Ee(){he(f=>{const A=!f;return Ps(A),A})}return{localQuery:a,modelFilter:o,effortFilter:h,confidenceFilter:d,sourceFilter:j,timeFilter:D,dateStart:y,dateEnd:l,sortKey:w,setSortKey:g,sortDirection:_,setSortDirection:E,gridPreferences:x,density:L,initialSelectedCallId:v,selectedCallId:u,setSelectedCallId:te,visibleCallRows:G,setVisibleCallRows:R,exportStatus:ne,setExportStatus:Q,filterStatus:de,detailsExpanded:W,searchInputRef:me,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}}function Ls({model:e,header:n,filters:s,table:a,inspector:i}){var F;const o=ce(),r=o.t("dashboard.model_calls","Model Calls"),h=o.t("dashboard.model_calls","Model calls");return t.jsxs("div",{className:`${$.page} page-grid`,children:[t.jsx(Ms,{...n}),t.jsx(Es,{...s}),t.jsxs("div",{className:$.tableHeading,children:[t.jsxs("div",{children:[t.jsx("h2",{children:r}),t.jsx("p",{children:a.exportStatus||a.filterStatus||a.subtitle})]}),t.jsxs("div",{className:$.tableActions,children:[t.jsx(re,{label:ks(a.isFetching,a.focused,a.focusedReason),tone:a.focused?"green":"blue"}),t.jsx(re,{label:a.activePreset?`Preset: ${mt(a.activePreset)}`:"Raw context gated",tone:a.activePreset?"green":"blue"}),t.jsxs("button",{className:"toolbar-button",type:"button","aria-expanded":a.detailsExpanded,onClick:a.onToggleDetails,children:[a.detailsExpanded?t.jsx(Fn,{size:16}):t.jsx(Nn,{size:16}),a.detailsExpanded?o.t("button.hide_details","Hide details"):o.t("dashboard.call_details","Call Details")]})]})]}),t.jsxs("div",{className:a.detailsExpanded?"table-detail-layout":"table-detail-layout detail-collapsed",children:[t.jsxs("div",{className:$.gridColumn,children:[t.jsx(Jt,{ariaLabel:h,columns:a.columns,data:a.calls,identityColumnId:"thread",lockedColumnIds:["investigate"],getRowId:d=>d.id,mobile:{primary:d=>d.thread,secondary:d=>o.translateText(`${d.time} · ${d.model} · ${ee(d.totalTokens)} tokens · ${q(d.cachedPct)} cache`),actionLabel:d=>Zt(d)},sorting:a.sorting,onSortingChange:a.onSortingChange,manualSorting:!0,columnVisibility:a.gridPreferences.columnVisibility,onColumnVisibilityChange:a.gridPreferences.setColumnVisibility,density:a.gridPreferences.density,onDensityChange:a.gridPreferences.setDensity,onRestoreDefaults:a.gridPreferences.restoreDefaults,selectedRowId:(F=a.selectedCall)==null?void 0:F.id,onRowSelect:d=>a.onSelectCall(d.id),onRowActivate:d=>i.onOpenInvestigator(d.id),activateOnClick:!0,selectOnHover:!0,viewportHeight:560,emptyLabel:"No rows match current filters."}),t.jsxs("div",{className:$.gridFooter,"aria-live":"polite",children:[t.jsx("span",{children:o.translateText(`${a.calls.length.toLocaleString()} loaded / ${a.totalMatchedCalls.toLocaleString()} matched`)}),a.focused&&a.hasNextPage?t.jsx("button",{className:"toolbar-button",type:"button",onClick:a.onLoadMore,disabled:a.isFetchingNextPage,children:a.isFetchingNextPage?"Loading more...":`Load ${B.toLocaleString()} more`}):null]})]}),a.detailsExpanded?t.jsx(cs,{call:a.selectedCall,calls:e.calls,...i}):null]}),t.jsxs("details",{className:$.patternsDisclosure,children:[t.jsxs("summary",{children:[t.jsx(ut,{size:17}),"Usage patterns"]}),t.jsxs("div",{className:"dashboard-grid three",children:[t.jsx(Z,{title:"Usage Over Time",subtitle:"Tokens",children:t.jsx(et,{series:e.tokenSeries,yLabel:"Tokens",height:220})}),t.jsx(Z,{title:"Cost by Model",subtitle:"Estimated USD",children:t.jsx(as,{data:e.modelCosts,valueLabel:Oe})}),t.jsx(Z,{title:"Cache Hit Rate Over Time",subtitle:o.translateText("Daily"),children:t.jsx(et,{series:e.cacheSeries,yLabel:"Cache %",height:220,valueFormatter:d=>`${d}%`})})]})]})]})}function ks(e,n,s){return e&&n?"Updating focused rows":e?"Loading focused rows":n?"Focused paged API":s||"Stored snapshot"}function oa(e,n="",s=""){const a=Pe();return ke(yt(e,{globalQuery:n,localQuery:T("call_q"),modelFilter:T("model")||"all",effortFilter:T("effort")||"all",confidenceFilter:gt(),sourceFilter:jt(),timeFilter:vt(),dateStart:le("from"),dateEnd:le("to"),activePreset:s}),a,Ct(a))}const Nt={time:"time",duration:"duration",gap:"previousCallGap",attention:"signal",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"totalTokens",cached:"cachedInput",uncached:"uncachedInput",output:"output",reasoning:"reasoningOutput",cost:"cost",usage:"credits",cache:"cachedPct",context:"contextWindowPct"},Is=Object.fromEntries(Object.entries(Nt).map(([e,n])=>[n,e]));function ra({model:e,globalQuery:n,activePreset:s,onRefresh:a,contextRuntime:i,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h,includeArchived:F=!1,sourceKey:d,sourceRevision:b="",scopeSince:j=null,focusedEndpointsEnabled:C=!0,workspaceSwitcher:D}){var We,Ye;const N=_s(e,n),{localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,setSortKey:L,sortDirection:v,setSortDirection:u,gridPreferences:te,density:G,selectedCallId:R,setSelectedCallId:ne,visibleCallRows:Q,setVisibleCallRows:de,exportStatus:ue,setExportStatus:W,filterStatus:he,detailsExpanded:me,searchInputRef:se,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}=N,f=c.useMemo(()=>[...qt,en({onOpenInvestigator:r,onCopyCallLink:h})],[h,r]),A=c.useMemo(()=>es({runtime:i,enabled:C,activePreset:s,sourceFilter:w,sortKey:x,scopeSince:j,timeFilter:g,dateStart:_,dateEnd:E,confidenceFilter:p,globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l}),[s,p,i,E,_,l,C,n,y,m,x,w,j,g]),V=Lt({...It({runtime:i,includeArchived:F,sourceKey:d,sourceRevision:b,filters:A.filters,sort:A.sort,direction:v,pageSize:B}),enabled:A.enabled,placeholderData:M=>M}),Ue=c.useMemo(()=>yt(e.calls,{globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,activePreset:s}),[s,p,E,_,l,n,y,e.calls,m,w,g]),qe=c.useMemo(()=>ke(Ue,x,v),[Ue,v,x]),Ge=c.useMemo(()=>{var M;return((M=V.data)==null?void 0:M.pages.flatMap(X=>X.rows))??[]},[V.data]),ae=A.enabled&&!!V.data,H=c.useMemo(()=>ae?ke(Ge,x,v):qe,[Ge,qe,v,x,ae]),Me=ae?((Ye=(We=V.data)==null?void 0:We.pages[0])==null?void 0:Ye.totalMatchedRows)??H.length:e.calls.length,Tt=c.useMemo(()=>Tn({shownCount:H.length,totalCount:Me,localQuery:y,globalQuery:n,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateRangeStatus:Y,activePresetLabel:s?mt(s):""}),[s,p,Y,l,n,y,m,H.length,w,g,Me]),Qe=c.useMemo(()=>[{id:Nt[x],desc:v==="desc"}],[v,x]),ie=R===oe?H[0]??null:H.find(M=>M.id===R)??H[0]??null,z=ie&&(ie.id===R||R===oe)?ie.id:"";c.useEffect(()=>{R===oe&&z&&ne(z)},[R,z]),c.useEffect(()=>{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});M.toString()!==window.location.href&&window.history.replaceState(null,"",M)},[p,E,_,G,l,y,m,z,v,x,w,g,Q]);function Et(){Gt(`codex-calls-${Yt()}.csv`,Qt(H,Wt)),W(`Exported ${H.length} calls`)}async function Mt(){try{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});if(!await ht(M.toString()))throw new Error("Clipboard unavailable");W("Copied Calls view link")}catch{W("Copy unavailable in browser")}}function Dt(M){var Xe,Je;const X=typeof M=="function"?M(Qe):M,De=Is[((Xe=X[0])==null?void 0:Xe.id)??""]??"time",_t=De!==x;L(De),u(_t?U(De):(Je=X[0])!=null&&Je.desc?"desc":"asc"),I()}async function Pt(){!V.hasNextPage||V.isFetchingNextPage||(await V.fetchNextPage(),de(M=>M+B))}return t.jsx(Ls,{model:e,header:{workspaceSwitcher:D,canExport:!!H.length,onExport:Et,onCopyView:Mt,onRefresh:a},filters:{searchInputRef:se,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,onLocalQueryChange:ge,onModelFilterChange:je,onEffortFilterChange:ve,onConfidenceFilterChange:be,onSourceFilterChange:Ce,onTimeFilterChange:ye,onDateStartChange:Se,onDateEndChange:we,onSortKeyChange:Fe,onSortDirectionChange:Ne,onClear:Te},table:{activePreset:s,exportStatus:ue,filterStatus:he,subtitle:Tt,focused:ae,focusedReason:A.reason,isFetching:V.isFetching,isFetchingNextPage:V.isFetchingNextPage,hasNextPage:!!V.hasNextPage,detailsExpanded:me,calls:H,totalMatchedCalls:Me,columns:f,sorting:Qe,gridPreferences:te,selectedCall:ie,onSortingChange:Dt,onSelectCall:ne,onLoadMore:Pt,onToggleDetails:Ee},inspector:{contextRuntime:i,includeArchived:F,sourceRevision:b,hydrateThreadCalls:C,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h}})}export{ra as CallsPage,oa as callsForCurrentUrl}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js index 8a2f396a..0fdff1d6 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js @@ -1,4 +1,4 @@ -import{r as j,j as t}from"./dashboard-react.js";import{P as A}from"./Panel.js";import{S as v}from"./StatusBadge.js";import{c as W,H as h,G as B,ag as M,R as $}from"./App.js";import{G as f}from"./gauge.js";import{S as _}from"./shield-check.js";import{L as T}from"./lock-keyhole.js";import{T as H}from"./triangle-alert.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** +import{r as j,j as t}from"./dashboard-react.js";import{P as A}from"./Panel.js";import{S as v}from"./StatusBadge.js";import{c as W,H as h,G as B,ak as M,R as $}from"./App.js";import{G as f}from"./gauge.js";import{S as _}from"./shield-check.js";import{L as T}from"./lock-keyhole.js";import{T as H}from"./triangle-alert.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js index 40efac0b..9cd414f5 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js @@ -1 +1 @@ -import{j as n}from"./dashboard-react.js";import{j as s,p,u as G,f as N,m as q,a as J}from"./App.js";function ye({call:e,calls:t}){const i=[...t,e].filter((u,l,g)=>g.findIndex(c=>c.id===u.id)===l).sort(te),a=i.findIndex(u=>u.id===e.id),r=a>0?i[a-1]:null,o=r?Z(e,r):null,h=V(e,r);return n.jsxs("div",{className:"call-cache-delta-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Cache Accounting Delta"}),n.jsx("span",{children:r?`Call ${a+1} of ${i.length}`:"No previous call"})]}),n.jsx(K,{call:e,delta:o,diagnostic:h,previous:r,selectedIndex:a,totalCalls:i.length}),r&&o?n.jsxs(n.Fragment,{children:[n.jsx("p",{className:"diagnostic-interpretation",children:ee(o)}),n.jsxs("div",{className:"cache-delta-grid",children:[n.jsx(f,{label:"Last call input",value:x(o.input),detail:`${s(r.input)} -> ${s(e.input)}`}),n.jsx(f,{label:"Cached input",value:x(o.cached),detail:`${s(r.cachedInput)} -> ${s(e.cachedInput)}`}),n.jsx(f,{label:"Uncached input",value:x(o.uncached),detail:`${s(r.uncachedInput)} -> ${s(e.uncachedInput)}`}),n.jsx(f,{label:"Output",value:x(o.output),detail:`${s(r.output)} -> ${s(e.output)}`}),n.jsx(f,{label:"Reasoning output",value:x(o.reasoning),detail:`${s(r.reasoningOutput)} -> ${s(e.reasoningOutput)}`}),n.jsx(f,{label:"Cache ratio",value:M(o.cacheRatio),detail:`${p(r.cachedPct)} -> ${p(e.cachedPct)}`})]})]}):n.jsx("p",{className:"empty-state",children:"No previous aggregate call available for cache delta accounting."})]})}function K({call:e,delta:t,diagnostic:i,previous:a,selectedIndex:r,totalCalls:o}){return n.jsxs("div",{className:`cache-verdict-card cache-verdict-${i.key}`,children:[n.jsxs("div",{className:"cache-verdict-main",children:[n.jsx("span",{className:"cache-diagnostic-pill",children:i.label}),n.jsx("p",{children:i.body})]}),n.jsxs("div",{className:"cache-verdict-meta",children:[n.jsxs("span",{children:["Cache ratio: ",p(e.cachedPct)]}),n.jsx("span",{children:t?Q(t):"No previous call loaded for delta comparison."}),n.jsxs("span",{children:["Position: ",r+1," of ",o]}),n.jsxs("span",{children:["Next: ",Y(e,i,a)]})]})]})}function V(e,t){const i=X(e,t);return i==="spike"?{key:"spike",label:"Uncached spike",body:"Fresh input rose sharply compared with the previous call in this resolved thread."}:i==="warm"?{key:"warm",label:"Warm cache reuse",body:"Most input tokens reused prompt cache. The uncached portion is the most likely investigation target."}:i==="partial"?{key:"partial",label:"Partial cache miss",body:"Some prefix reused cache, but a meaningful share of input was fresh or reserialized."}:{key:"cold",label:"Cold resume / stale cache",body:"Conversation-specific cache likely expired or missed; remaining cache is probably stable Codex scaffolding or tool schema prefix."}}function X(e,t){const i=$(e),a=t?$(t):null,r=(t==null?void 0:t.uncachedInput)??0,o=.05,h=.85,u=.8,l=1e3;return t&&a!==null&&a>=u&&i<=o&&e.input>=l?"cold":t&&e.uncachedInput>Math.max(r*2,l)?"spike":i>=h?"warm":i>o?"partial":"cold"}function $(e){return Number.isFinite(e.cachedPct)?e.cachedPct/100:0}function Q(e){return`Uncached input: ${x(e.uncached)}. Cached input: ${x(e.cached)}. Cache ratio: ${M(e.cacheRatio)}.`}function Y(e,t,i){return t.key==="cold"?"Compare the previous call, then inspect loaded evidence to see what fresh context was sent after the cache miss.":t.key==="spike"?"Inspect the most recent evidence entries first; the spike is in fresh uncached input, not cached history.":t.key==="warm"?`Cache reuse is healthy; focus on ${s(e.uncachedInput)} uncached tokens that were still billed as fresh input.`:i?"Use delta cards to locate whether the change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough to understand this isolated call."}function Z(e,t){return{input:e.input-t.input,cached:e.cachedInput-t.cachedInput,uncached:e.uncachedInput-t.uncachedInput,output:e.output-t.output,reasoning:e.reasoningOutput-t.reasoningOutput,cacheRatio:e.cachedPct-t.cachedPct}}function ee(e){return e.uncached>0&&e.cached<0?`Uncached input rose by ${s(e.uncached)} while cached input fell by ${s(Math.abs(e.cached))}.`:e.uncached>0?`Uncached input increased by ${s(e.uncached)} versus the previous aggregate call.`:e.uncached<0&&e.cached>=0?`Uncached input decreased by ${s(Math.abs(e.uncached))} while cached input increased.`:"Cache accounting is stable versus the previous aggregate call."}function f({label:e,value:t,detail:i}){return n.jsxs("span",{className:"cache-delta-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function x(e){return e===0?"0":`${e>0?"+":"-"}${s(Math.abs(e))}`}function M(e){return e===0?"0.0pp":`${e>0?"+":"-"}${Math.abs(e).toFixed(1)}pp`}function te(e,t){return S(e)-S(t)}function S(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function we({call:e}){const t=G(),i=ne(e);return n.jsxs("div",{className:"call-decision-card",children:[n.jsxs("div",{className:"section-heading compact",children:[n.jsx("h3",{children:"Call Decision"}),n.jsx("span",{children:i.nextAction})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsxs("div",{children:[n.jsx("dt",{children:"Pricing status"}),n.jsx("dd",{children:i.pricingStatus})]}),n.jsxs("div",{children:[n.jsx("dt",{children:t.t("detail.next_action","Next action")}),n.jsx("dd",{children:i.nextAction})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Why flagged"}),n.jsx("dd",{children:i.whyFlagged})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Allowance impact"}),n.jsx("dd",{children:i.allowanceImpact})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Context use"}),n.jsx("dd",{children:i.contextUse})]})]})]})}function ne(e){return{allowanceImpact:`${oe(e.credits)} counted`,contextUse:e.contextWindowPct==null?"Not reported":p(e.contextWindowPct),nextAction:re(e),pricingStatus:ie(e),whyFlagged:ae(e)}}function ie(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function re(e){return e.recommendation?e.recommendation:e.cost<=0?"Configure pricing":e.cachedPct<30&&e.input>0?"Compare fresh input":(e.contextWindowPct??0)>=60?"Inspect thread timeline":e.reasoningOutput>e.output?"Review reasoning effort":"Use aggregate first"}function ae(e){return e.recommendation?e.recommendation:e.signal&&e.signal!=="aggregate"?`${e.signal} aggregate signal`:(e.contextWindowPct??0)>=60?"High reported context use.":e.cachedPct<30&&e.input>0?`${N(e.uncachedInput)} uncached input with weak cache reuse.`:e.reasoningOutput>e.output?"Reasoning output exceeds visible output.":e.cost>0||e.credits>0?"Review cost and credit impact before loading raw context.":"No aggregate efficiency flag on this row."}function oe(e){return`${new Intl.NumberFormat("en-US",{maximumFractionDigits:2}).format(e)} credits`}function _e(e){return e.cachedPct<25?"cold or weak cache":e.cachedPct<50?"partial cache reuse":"healthy cache reuse"}function P(e){return e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available"}function ke(e){if(e.contextWindowPct===null||e.contextWindowPct===void 0)return"Not reported";const t=e.modelContextWindow?` of ${N(e.modelContextWindow)}`:"";return`${p(e.contextWindowPct)}${t}`}function $e(e,{limit:t=2,emptyLabel:i="No related calls",unknownLabel:a="Unknown",style:r="parenthetical"}={}){const o=new Map;for(const u of e){const l=u||a;o.set(l,(o.get(l)??0)+1)}const h=[...o.entries()].sort((u,l)=>l[1]-u[1]||u[0].localeCompare(l[0])).slice(0,t).map(([u,l])=>r==="x"?`${u} x${l}`:`${u} (${l})`);return h.length?h.join(", "):i}function Se({call:e}){return n.jsxs("div",{className:"call-source-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Call Source"}),n.jsx("span",{children:P(e)})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsx(d,{label:"Project",value:e.project||"Unknown"}),n.jsx(d,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),n.jsx(d,{label:"Project tags",value:e.projectTags.length?e.projectTags.join(", "):"None"}),n.jsx(d,{label:"Thread attachment",value:e.threadAttachmentLabel||"Direct thread"}),n.jsx(d,{label:"Thread source",value:e.threadSource||"user"}),n.jsx(d,{label:"Subagent type",value:e.subagentType||"None"}),n.jsx(d,{label:"Agent role",value:e.agentRole||"None"}),n.jsx(d,{label:"Agent nickname",value:e.agentNickname||"None"}),n.jsx(d,{label:"Source line",value:P(e)}),n.jsx(d,{label:"Initiated by",value:e.initiator||"unknown"}),n.jsx(d,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),n.jsx(d,{label:"Session",value:e.sessionId||"Not available"}),n.jsx(d,{label:"Turn",value:e.turnId||"None"}),n.jsx(d,{label:"Parent thread",value:e.parentThread||"None"}),n.jsx(d,{label:"Parent session",value:e.parentSessionId||"None"}),n.jsx(d,{label:"Parent updated",value:se(e.parentSessionUpdatedAt)}),n.jsx(d,{label:"Working directory",value:e.cwd||"Not available"}),n.jsx(d,{label:"Git branch",value:e.gitBranch||"Not available"}),n.jsx(d,{label:"Git remote",value:e.gitRemoteLabel||"Not available"}),n.jsx(d,{label:"Git hash",value:e.gitRemoteHash||"Not available"}),n.jsx(d,{label:"Credit note",value:e.usageCreditNote||"None"})]})]})}function se(e){if(!e)return"None";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function d({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function Pe({call:e}){return n.jsxs("dl",{className:"detail-list",children:[n.jsx(m,{label:"Last call total",value:s(e.totalTokens)}),n.jsx(m,{label:"Last call input",value:s(e.input)}),n.jsx(m,{label:"Cached input",value:s(e.cachedInput)}),n.jsx(m,{label:"Output tokens",value:s(e.output)}),n.jsx(m,{label:"Reasoning output",value:s(e.reasoningOutput)}),n.jsx(m,{label:"Session cumulative",value:e.cumulativeTotalTokens?s(e.cumulativeTotalTokens):"Not reported"}),n.jsx(m,{label:"Pricing model",value:ce(e)}),n.jsx(m,{label:"Credit model",value:e.usageCreditModel||"No mapped rate"}),n.jsx(m,{label:"Credit confidence",value:e.usageCreditConfidence||"unknown"}),n.jsx(m,{label:"Credit source",value:e.usageCreditSource||"None"}),n.jsx(m,{label:"Credit source fetched",value:e.usageCreditFetchedAt||"Unknown"}),n.jsx(m,{label:"Credit tier",value:e.usageCreditTier||"Unknown"}),n.jsx(m,{label:"Cache savings",value:q(e.estimatedCacheSavings)}),n.jsx(m,{label:"Efficiency signals",value:de(e)})]})}function m({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function ce(e){return e.pricingModel?e.pricingModel:e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function de(e){return e.efficiencyFlags.length?e.efficiencyFlags.join(", "):e.signal&&e.signal!=="aggregate"?e.signal:e.recommendation?"recommendation":"None"}function Te({selectedCall:e,calls:t,onOpenInvestigator:i,onCopyCallLink:a,className:r,copyAriaContext:o,copyLabel:h="Copy link"}){const u=t.length?t:[e],l=ue(u,e.id),g=["thread-mini-timeline",r].filter(Boolean).join(" ");return n.jsx("ol",{className:g,children:l.map(c=>n.jsxs("li",{className:c.id===e.id?"active":"",children:[n.jsx("span",{children:c.time}),n.jsxs("strong",{children:[c.model," / ",c.effort]}),n.jsxs("em",{children:[N(c.totalTokens)," tokens - ",p(c.cachedPct)," cache"]}),n.jsxs("div",{className:"thread-call-meta",children:[n.jsx("span",{children:c.initiator||"unknown"}),n.jsx("span",{children:c.duration}),n.jsxs("span",{children:["prev ",c.previousCallGap]})]}),n.jsxs("div",{className:"thread-call-flags",children:[n.jsxs("span",{children:["Context ",le(c)]}),n.jsx("span",{children:me(c)})]}),c.recommendation?n.jsx("p",{className:"thread-call-recommendation",children:c.recommendation}):null,n.jsx("div",{className:"thread-context-bar",title:`Context window ${he(c)}`,children:n.jsx("span",{className:pe(c.contextWindowPct),style:{width:xe(c.contextWindowPct)}})}),n.jsxs("div",{className:"thread-call-actions table-action-group",children:[n.jsx("button",{className:"table-action-button",type:"button",onClick:()=>i(c.id),disabled:c.id===e.id,children:"Open"}),n.jsxs("button",{className:"table-action-button",type:"button","aria-label":`${h} for ${o} ${c.thread} ${c.model}`,onClick:()=>a(c.id),children:[n.jsx(J,{size:14})," ",h]})]})]},c.id))})}function ue(e,t){if(e.length<=5)return e;const i=e.findIndex(r=>r.id===t);if(i<0)return e.slice(0,5);const a=Math.max(0,Math.min(i-2,e.length-5));return e.slice(a,a+5)}function le(e){return e.contextWindowPct===null?"Not reported":p(e.contextWindowPct)}function he(e){if(e.contextWindowPct===null)return"Not reported";const t=e.modelContextWindow?` of ${N(e.modelContextWindow)}`:"";return`${p(e.contextWindowPct)}${t}`}function me(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function pe(e){const t=Number(e??0);return t>=75?"high":t>=50?"medium":"low"}function xe(e){const t=Number(e??0),i=Math.max(0,Math.min(100,Number.isFinite(t)?t:0));return`${Math.round(i)}%`}async function ze(e){I(e);const t=new URLSearchParams({enabled:"1",_:String(Date.now())}),i=await fetch(`/api/context-settings?${t.toString()}`,{headers:A(e),cache:"no-store"});return!!(await O(i,"Context settings")).context_api_enabled}async function Ee(e,t,i){if(I(t),!t.contextApiEnabled)throw new Error("Context API is not enabled.");const a=new URLSearchParams({record_id:e,mode:i.mode,include_tool_output:i.includeToolOutput?"1":"0",include_compaction_history:i.includeCompactionHistory?"1":"0",max_chars:String(i.maxChars),max_entries:String(i.maxEntries),_:String(Date.now())});return await fetch(`/api/context?${a.toString()}`,{headers:A(t),cache:"no-store"}).then(o=>O(o,"Context"))}function I(e){if(e.fileMode)throw new Error("Context loading requires the localhost dashboard server.");if(!e.apiToken)throw new Error("Context loading requires a localhost dashboard API token.")}function A(e){return{Accept:"application/json","X-Codex-Usage-Token":e.apiToken}}async function O(e,t){let i={};try{i=await e.json()}catch{i={}}if(!e.ok){const a=typeof i.error=="string"?i.error:`${t} API returned HTTP ${e.status}.`;throw new Error(a)}if(typeof i.error=="string")throw new Error(i.error);return i}function Me({call:e,payload:t,onRunFullAnalysis:i,showHeading:a=!0}){const r=ge(e,t);return n.jsxs("div",{className:"context-attribution-module",children:[a?n.jsxs("div",{className:"serialized-breakdown-heading context-attribution-heading",children:[n.jsx("strong",{children:"Context Attribution"}),n.jsx("span",{children:"Estimated from visible log volume"})]}):null,n.jsxs("div",{className:"drilldown-metric-grid wide context-attribution-grid",children:[n.jsx(b,{label:"Uncached input",value:s(e.uncachedInput),detail:"exact aggregate row"}),n.jsx(b,{label:"Visible new context estimate",value:r?`~${s(r.visibleTokenEstimate)}`:"Not loaded yet",detail:r?`${s(r.visibleChars)} analyzed chars`:"Runtime evidence"}),n.jsx(b,{label:"Serialized local upper bound",value:r!=null&&r.serializedTokens?`~${s(r.serializedBound)}`:"Not loaded yet",detail:r!=null&&r.serializedTokens?be(r):"Runtime evidence"}),n.jsx(b,{label:"Unexplained hidden/serialized input estimate",value:r?`~${s(r.visibleGap)}`:"Not loaded yet",detail:r?"uncached input minus visible estimate":"Runtime evidence"}),n.jsx(b,{label:"Possible serialized overhead",value:r?`~${s(r.serializedCandidate)}`:"Not loaded yet",detail:r?"serialized upper bound minus visible estimate":"Runtime evidence"}),n.jsx(b,{label:"Remaining after serialized bound",value:r?`~${s(r.remainingAfterSerialized)}`:"Not loaded yet",detail:r?"not covered by serialized upper bound":"Runtime evidence"})]}),n.jsx(fe,{stats:r,onRunFullAnalysis:(t==null?void 0:t.context_mode)==="full"?void 0:i}),n.jsx("p",{className:"privacy-note",children:"Compare exact uncached input with tokenizer-counted visible log evidence. Treat the gap as hidden scaffolding, serialization, or tokenizer estimate error."})]})}function b({label:e,value:t,detail:i}){return n.jsxs("span",{className:"drilldown-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function fe({stats:e,onRunFullAnalysis:t}){if(!(e!=null&&e.serializedTokens))return null;if(e.serializedDeferred)return n.jsxs("div",{className:"serialized-breakdown deferred",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Fast estimate loaded; full serialized grouping is deferred."})]}),t?n.jsx("div",{className:"context-followup-actions",children:n.jsx("button",{className:"toolbar-button serialized-action",type:"button",onClick:t,children:"Run full serialized analysis"})}):null]});const i=e.serializedBuckets.slice(0,6);return n.jsxs("div",{className:"serialized-breakdown",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Upper-bound local JSONL structure; not exact prompt text."})]}),n.jsx("div",{className:"serialized-bucket-grid",children:i.length?i.map(a=>n.jsxs("div",{className:"serialized-bucket",children:[n.jsx("span",{children:a.label||a.key||"Unknown"}),n.jsx("strong",{children:s(Number(a.token_estimate??0))}),n.jsxs("small",{children:[s(Number(a.count??0))," fields · ",s(Number(a.char_count??0))," chars"]}),a.note?n.jsx("small",{children:a.note}):null]},a.key??a.label??String(a.token_estimate??0))):n.jsx("p",{className:"empty-state",children:"No serialized evidence groups returned."})})]})}function be(e){const t=[`${s(e.serializedChars)} raw JSON chars`,e.serializedEstimator];return e.serializedDeferred&&t.push("fast estimate"),e.serializedLineCount&&t.push(`${s(e.serializedLineCount)} raw lines`),t.join(" · ")}function ge(e,t){if(!t)return null;const i=t.entries??[],a=Number(t.visible_char_count??i.reduce((B,H)=>B+String(H.text??"").length,0)),r=Number(t.visible_token_estimate??Math.ceil(a/4)),o=t.serialized_evidence??{},h=Number(o.raw_json_token_estimate??o.token_estimate??0),u=Number(o.raw_json_char_count??o.total_chars??0),l=Number(o.raw_line_count??0),g=o.token_estimator||t.visible_token_estimator||"chars_per_4_fallback",c=Array.isArray(o.buckets)?o.buckets:[],v=h>0?Math.min(h,e.uncachedInput):0,k=Math.max(e.uncachedInput-r,0),F=v>r?v-r:0,L=h>0?Math.max(e.uncachedInput-Math.max(r,v),0):k;return{visibleChars:a,visibleTokenEstimate:r,serializedTokens:h,serializedChars:u,serializedLineCount:l,serializedEstimator:g,serializedBound:v,visibleGap:k,serializedCandidate:F,remainingAfterSerialized:L,serializedDeferred:!!(o.deferred||o.deferred_buckets),serializedBuckets:c}}function Ie({entry:e}){const t=je(e);return t.length?n.jsx("div",{className:"context-entry-chips","aria-label":"Evidence entry metadata",children:t.map(i=>n.jsxs("span",{title:i.title,children:[i.label,": ",i.value]},`${i.label}-${i.value}`))}):null}function je(e){var o,h,u,l;const t=[],i=e.action_timing;(i==null?void 0:i.since_turn_start_ms)!==void 0&&t.push({label:"T+",value:y(i.since_turn_start_ms),title:"Elapsed since selected turn start"}),(i==null?void 0:i.since_previous_entry_ms)!==void 0&&t.push({label:"Gap",value:y(i.since_previous_entry_ms),title:"Gap since previous evidence entry"}),(i==null?void 0:i.reported_duration_ms)!==void 0&&t.push({label:"Duration",value:y(i.reported_duration_ms),title:i.duration_source||"Duration reported by this event"});const a=(o=e.token_usage)==null?void 0:o.last_token_usage;a&&t.push({label:"Entry tokens",value:T(a),title:"Token usage reported for this evidence entry"});const r=(h=e.token_usage)==null?void 0:h.total_token_usage;return r&&t.push({label:"Session tokens",value:T(r),title:"Cumulative token usage reported by this evidence entry"}),(u=e.compaction)!=null&&u.replacement_history_available&&t.push({label:"Compaction",value:`${s(((l=e.compaction.replacement_history)==null?void 0:l.length)??0)} replacement entries`,title:"Compaction replacement history is available for this entry"}),e.tool_output_omitted&&t.push({label:"Tool output",value:"omitted",title:"Tool output omitted until explicitly requested"}),t}function T(e){const t=Number((e==null?void 0:e.input_tokens)??0),i=Number((e==null?void 0:e.cached_input_tokens)??0),a=Number((e==null?void 0:e.uncached_input_tokens)??Math.max(t-i,0)),r=Number((e==null?void 0:e.output_tokens)??0),o=Number((e==null?void 0:e.total_tokens)??t+r);return`${s(o)} total · ${s(a)} uncached`}function y(e){if(!Number.isFinite(e))return"0ms";if(e<1e3)return`${Math.round(e)}ms`;const t=e/1e3;return t>=10?`${t.toFixed(0)}s`:`${t.toFixed(1)}s`}const R=new Map,U=new Map,w=new Map,_=new Map,D=new Map;function Ae(e,t){return R.get(W(e,t))??null}function Oe(e,t,i){R.set(W(e,t),i)}function Re(e){const t=U.get(e);return t?{...t}:null}function Ue(e,t){U.set(e,{...t})}function ve(e,t){return`${e.type??"entry"}-${e.line_number??e.timestamp??t}`}function De(e,t){const i=w.get(e);return i?new Set(i):t.length?new Set([ve(t[0],0)]):new Set}function We(e,t,i){const a=w.get(e)??new Set;i?a.add(t):a.delete(t),w.set(e,a)}function Fe(e,t){var i;return((i=_.get(e))==null?void 0:i.get(t))??0}function Le(e,t,i){const a=_.get(e)??new Map;i>0?a.set(t,i):a.delete(t),_.set(e,a)}function Be(e){return D.get(e)??!1}function He(e,t){D.set(e,t)}function W(e,t){return[e,t.mode,t.includeToolOutput?"tool-output":"no-tool-output",t.includeCompactionHistory?"compaction-history":"no-compaction-history",String(t.maxChars),String(t.maxEntries)].join("|")}const C={includeToolOutput:!1,includeCompactionHistory:!1,maxChars:8e3,maxEntries:20,mode:"quick"};function Ge(e=window.location.search,t=C){const i=new URLSearchParams(e);return{includeToolOutput:z(i.get("include_tool_output"),t.includeToolOutput),includeCompactionHistory:z(i.get("include_compaction_history"),t.includeCompactionHistory),maxChars:E(i.get("max_chars"),t.maxChars),maxEntries:E(i.get("max_entries"),t.maxEntries),mode:i.get("mode")==="full"?"full":t.mode}}function qe(e,t,i=C){j(e,"mode",t.mode,i.mode),j(e,"max_entries",String(t.maxEntries),String(i.maxEntries)),j(e,"max_chars",String(t.maxChars),String(i.maxChars)),j(e,"include_tool_output",t.includeToolOutput?"1":"0",i.includeToolOutput?"1":"0"),j(e,"include_compaction_history",t.includeCompactionHistory?"1":"0",i.includeCompactionHistory?"1":"0")}function Je(e){return e.fileMode?"Static file mode cannot read local JSONL context. Use serve-dashboard with the context API enabled.":e.apiToken?e.contextApiEnabled?"Context API is enabled. Load selected-turn evidence from the local JSONL source only when needed.":"Context API is available but off. Enable it here before loading selected-turn evidence.":"Context loading requires the localhost dashboard server API token."}function z(e,t){return e==="1"||e==="true"?!0:e==="0"||e==="false"?!1:t}function E(e,t){if(e===null||e.trim()==="")return t;const i=Number(e);return Number.isFinite(i)&&i>=0?Math.floor(i):t}function j(e,t,i,a){i===a?e.searchParams.delete(t):e.searchParams.set(t,i)}function Ke(e){return e instanceof Error?e.message:String(e)}function Ve(e,t){var o;const i=Number(((o=e.omitted)==null?void 0:o.max_entries)??t.maxEntries??C.maxEntries),a=C.maxEntries||20,r=i>0?Math.max(i+a,i*2):0;return{...t,maxEntries:r}}function Xe(e){const t=e.omitted??{},i=e.source??{},a=["Local JSONL context loaded on demand.",e.include_tool_output?"Tool output included with redaction and size limits.":"Tool output hidden for this view."];i.file&&a.push(`Source: ${i.file}${i.line_number?`:${i.line_number}`:""}.`);const r=Number(t.older_entries??0);r>0&&a.push(`${s(r)} older entries omitted.`);const o=Number(t.over_budget_chars??0);return o>0&&a.push(`${s(o)} chars over budget omitted.`),Number(t.max_chars??NaN)===0&&a.push("No character limit applied."),a}export{P as A,Ge as B,Me as C,qe as D,Pe as T,Ae as a,Je as b,Re as c,C as d,ze as e,Ke as f,Oe as g,Xe as h,Be as i,De as j,ve as k,Ee as l,Ie as m,Le as n,Fe as o,Ve as p,We as q,Ue as r,He as s,_e as t,we as u,Se as v,ye as w,$e as x,Te as y,ke as z}; +import{j as n}from"./dashboard-react.js";import{j as o,p as x,u as G,f as w,aj as $,m as q,a as J}from"./App.js";function ye({call:e,calls:t}){const i=[...t,e].filter((h,m,b)=>b.findIndex(c=>c.id===h.id)===m).sort(te),a=i.findIndex(h=>h.id===e.id),r=a>0?i[a-1]:null,s=r?Z(e,r):null,l=V(e,r);return n.jsxs("div",{className:"call-cache-delta-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Cache Accounting Delta"}),n.jsx("span",{children:r?`Call ${a+1} of ${i.length}`:"No previous call"})]}),n.jsx(K,{call:e,delta:s,diagnostic:l,previous:r,selectedIndex:a,totalCalls:i.length}),r&&s?n.jsxs(n.Fragment,{children:[n.jsx("p",{className:"diagnostic-interpretation",children:ee(s)}),n.jsxs("div",{className:"cache-delta-grid",children:[n.jsx(f,{label:"Last call input",value:p(s.input),detail:`${o(r.input)} -> ${o(e.input)}`}),n.jsx(f,{label:"Cached input",value:p(s.cached),detail:`${o(r.cachedInput)} -> ${o(e.cachedInput)}`}),n.jsx(f,{label:"Uncached input",value:p(s.uncached),detail:`${o(r.uncachedInput)} -> ${o(e.uncachedInput)}`}),n.jsx(f,{label:"Output",value:p(s.output),detail:`${o(r.output)} -> ${o(e.output)}`}),n.jsx(f,{label:"Reasoning output",value:p(s.reasoning),detail:`${o(r.reasoningOutput)} -> ${o(e.reasoningOutput)}`}),n.jsx(f,{label:"Cache ratio",value:M(s.cacheRatio),detail:`${x(r.cachedPct)} -> ${x(e.cachedPct)}`})]})]}):n.jsx("p",{className:"empty-state",children:"No previous aggregate call available for cache delta accounting."})]})}function K({call:e,delta:t,diagnostic:i,previous:a,selectedIndex:r,totalCalls:s}){return n.jsxs("div",{className:`cache-verdict-card cache-verdict-${i.key}`,children:[n.jsxs("div",{className:"cache-verdict-main",children:[n.jsx("span",{className:"cache-diagnostic-pill",children:i.label}),n.jsx("p",{children:i.body})]}),n.jsxs("div",{className:"cache-verdict-meta",children:[n.jsxs("span",{children:["Cache ratio: ",x(e.cachedPct)]}),n.jsx("span",{children:t?Q(t):"No previous call loaded for delta comparison."}),n.jsxs("span",{children:["Position: ",r+1," of ",s]}),n.jsxs("span",{children:["Next: ",Y(e,i,a)]})]})]})}function V(e,t){const i=X(e,t);return i==="spike"?{key:"spike",label:"Uncached spike",body:"Fresh input rose sharply compared with the previous call in this resolved thread."}:i==="warm"?{key:"warm",label:"Warm cache reuse",body:"Most input tokens reused prompt cache. The uncached portion is the most likely investigation target."}:i==="partial"?{key:"partial",label:"Partial cache miss",body:"Some prefix reused cache, but a meaningful share of input was fresh or reserialized."}:{key:"cold",label:"Cold resume / stale cache",body:"Conversation-specific cache likely expired or missed; remaining cache is probably stable Codex scaffolding or tool schema prefix."}}function X(e,t){const i=S(e),a=t?S(t):null,r=(t==null?void 0:t.uncachedInput)??0,s=.05,l=.85,h=.8,m=1e3;return t&&a!==null&&a>=h&&i<=s&&e.input>=m?"cold":t&&e.uncachedInput>Math.max(r*2,m)?"spike":i>=l?"warm":i>s?"partial":"cold"}function S(e){return Number.isFinite(e.cachedPct)?e.cachedPct/100:0}function Q(e){return`Uncached input: ${p(e.uncached)}. Cached input: ${p(e.cached)}. Cache ratio: ${M(e.cacheRatio)}.`}function Y(e,t,i){return t.key==="cold"?"Compare the previous call, then inspect loaded evidence to see what fresh context was sent after the cache miss.":t.key==="spike"?"Inspect the most recent evidence entries first; the spike is in fresh uncached input, not cached history.":t.key==="warm"?`Cache reuse is healthy; focus on ${o(e.uncachedInput)} uncached tokens that were still billed as fresh input.`:i?"Use delta cards to locate whether the change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough to understand this isolated call."}function Z(e,t){return{input:e.input-t.input,cached:e.cachedInput-t.cachedInput,uncached:e.uncachedInput-t.uncachedInput,output:e.output-t.output,reasoning:e.reasoningOutput-t.reasoningOutput,cacheRatio:e.cachedPct-t.cachedPct}}function ee(e){return e.uncached>0&&e.cached<0?`Uncached input rose by ${o(e.uncached)} while cached input fell by ${o(Math.abs(e.cached))}.`:e.uncached>0?`Uncached input increased by ${o(e.uncached)} versus the previous aggregate call.`:e.uncached<0&&e.cached>=0?`Uncached input decreased by ${o(Math.abs(e.uncached))} while cached input increased.`:"Cache accounting is stable versus the previous aggregate call."}function f({label:e,value:t,detail:i}){return n.jsxs("span",{className:"cache-delta-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function p(e){return e===0?"0":`${e>0?"+":"-"}${o(Math.abs(e))}`}function M(e){return e===0?"0.0pp":`${e>0?"+":"-"}${Math.abs(e).toFixed(1)}pp`}function te(e,t){return T(e)-T(t)}function T(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function _e({call:e}){const t=G(),i=ne(e);return n.jsxs("div",{className:"call-decision-card",children:[n.jsxs("div",{className:"section-heading compact",children:[n.jsx("h3",{children:"Call Decision"}),n.jsx("span",{children:i.nextAction})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsxs("div",{children:[n.jsx("dt",{children:"Pricing status"}),n.jsx("dd",{children:i.pricingStatus})]}),n.jsxs("div",{children:[n.jsx("dt",{children:t.t("detail.next_action","Next action")}),n.jsx("dd",{children:i.nextAction})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Why flagged"}),n.jsx("dd",{children:i.whyFlagged})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Allowance impact"}),n.jsx("dd",{children:i.allowanceImpact})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Context use"}),n.jsx("dd",{children:i.contextUse})]})]})]})}function ne(e){return{allowanceImpact:`${se(e.credits)} counted`,contextUse:e.contextWindowPct==null?"Not reported":x(e.contextWindowPct),nextAction:re(e),pricingStatus:ie(e),whyFlagged:ae(e)}}function ie(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function re(e){return e.recommendation?e.recommendation:e.cost<=0?"Configure pricing":e.cachedPct<30&&e.input>0?"Compare fresh input":(e.contextWindowPct??0)>=60?"Inspect thread timeline":e.reasoningOutput>e.output?"Review reasoning effort":"Use aggregate first"}function ae(e){return e.recommendation?e.recommendation:e.signal&&e.signal!=="aggregate"?`${e.signal} aggregate signal`:(e.contextWindowPct??0)>=60?"High reported context use.":e.cachedPct<30&&e.input>0?`${w(e.uncachedInput)} uncached input with weak cache reuse.`:e.reasoningOutput>e.output?"Reasoning output exceeds visible output.":e.cost>0||e.credits>0?"Review cost and credit impact before loading raw context.":"No aggregate efficiency flag on this row."}function se(e){return`${new Intl.NumberFormat("en-US",{maximumFractionDigits:2}).format(e)} credits`}function we({call:e}){return n.jsxs("div",{className:"call-source-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Call Source"}),n.jsx("span",{children:$(e)})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsx(d,{label:"Project",value:e.project||"Unknown"}),n.jsx(d,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),n.jsx(d,{label:"Project tags",value:e.projectTags.length?e.projectTags.join(", "):"None"}),n.jsx(d,{label:"Thread attachment",value:e.threadAttachmentLabel||"Direct thread"}),n.jsx(d,{label:"Thread source",value:e.threadSource||"user"}),n.jsx(d,{label:"Subagent type",value:e.subagentType||"None"}),n.jsx(d,{label:"Agent role",value:e.agentRole||"None"}),n.jsx(d,{label:"Agent nickname",value:e.agentNickname||"None"}),n.jsx(d,{label:"Source line",value:$(e)}),n.jsx(d,{label:"Initiated by",value:e.initiator||"unknown"}),n.jsx(d,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),n.jsx(d,{label:"Session",value:e.sessionId||"Not available"}),n.jsx(d,{label:"Turn",value:e.turnId||"None"}),n.jsx(d,{label:"Parent thread",value:e.parentThread||"None"}),n.jsx(d,{label:"Parent session",value:e.parentSessionId||"None"}),n.jsx(d,{label:"Parent updated",value:oe(e.parentSessionUpdatedAt)}),n.jsx(d,{label:"Working directory",value:e.cwd||"Not available"}),n.jsx(d,{label:"Git branch",value:e.gitBranch||"Not available"}),n.jsx(d,{label:"Git remote",value:e.gitRemoteLabel||"Not available"}),n.jsx(d,{label:"Git hash",value:e.gitRemoteHash||"Not available"}),n.jsx(d,{label:"Credit note",value:e.usageCreditNote||"None"})]})]})}function oe(e){if(!e)return"None";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function d({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function ke({call:e}){return n.jsxs("dl",{className:"detail-list",children:[n.jsx(u,{label:"Last call total",value:o(e.totalTokens)}),n.jsx(u,{label:"Last call input",value:o(e.input)}),n.jsx(u,{label:"Cached input",value:o(e.cachedInput)}),n.jsx(u,{label:"Output tokens",value:o(e.output)}),n.jsx(u,{label:"Reasoning output",value:o(e.reasoningOutput)}),n.jsx(u,{label:"Session cumulative",value:e.cumulativeTotalTokens?o(e.cumulativeTotalTokens):"Not reported"}),n.jsx(u,{label:"Pricing model",value:ce(e)}),n.jsx(u,{label:"Credit model",value:e.usageCreditModel||"No mapped rate"}),n.jsx(u,{label:"Credit confidence",value:e.usageCreditConfidence||"unknown"}),n.jsx(u,{label:"Credit source",value:e.usageCreditSource||"None"}),n.jsx(u,{label:"Credit source fetched",value:e.usageCreditFetchedAt||"Unknown"}),n.jsx(u,{label:"Credit tier",value:e.usageCreditTier||"Unknown"}),n.jsx(u,{label:"Cache savings",value:q(e.estimatedCacheSavings)}),n.jsx(u,{label:"Efficiency signals",value:de(e)})]})}function u({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function ce(e){return e.pricingModel?e.pricingModel:e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function de(e){return e.efficiencyFlags.length?e.efficiencyFlags.join(", "):e.signal&&e.signal!=="aggregate"?e.signal:e.recommendation?"recommendation":"None"}function $e({selectedCall:e,calls:t,onOpenInvestigator:i,onCopyCallLink:a,className:r,copyAriaContext:s,copyLabel:l="Copy link"}){const h=t.length?t:[e],m=le(h,e.id),b=["thread-mini-timeline",r].filter(Boolean).join(" ");return n.jsx("ol",{className:b,children:m.map(c=>n.jsxs("li",{className:c.id===e.id?"active":"",children:[n.jsx("span",{children:c.time}),n.jsxs("strong",{children:[c.model," / ",c.effort]}),n.jsxs("em",{children:[w(c.totalTokens)," tokens - ",x(c.cachedPct)," cache"]}),n.jsxs("div",{className:"thread-call-meta",children:[n.jsx("span",{children:c.initiator||"unknown"}),n.jsx("span",{children:c.duration}),n.jsxs("span",{children:["prev ",c.previousCallGap]})]}),n.jsxs("div",{className:"thread-call-flags",children:[n.jsxs("span",{children:["Context ",ue(c)]}),n.jsx("span",{children:me(c)})]}),c.recommendation?n.jsx("p",{className:"thread-call-recommendation",children:c.recommendation}):null,n.jsx("div",{className:"thread-context-bar",title:`Context window ${he(c)}`,children:n.jsx("span",{className:pe(c.contextWindowPct),style:{width:xe(c.contextWindowPct)}})}),n.jsxs("div",{className:"thread-call-actions table-action-group",children:[n.jsx("button",{className:"table-action-button",type:"button",onClick:()=>i(c.id),disabled:c.id===e.id,children:"Open"}),n.jsxs("button",{className:"table-action-button",type:"button","aria-label":`${l} for ${s} ${c.thread} ${c.model}`,onClick:()=>a(c.id),children:[n.jsx(J,{size:14})," ",l]})]})]},c.id))})}function le(e,t){if(e.length<=5)return e;const i=e.findIndex(r=>r.id===t);if(i<0)return e.slice(0,5);const a=Math.max(0,Math.min(i-2,e.length-5));return e.slice(a,a+5)}function ue(e){return e.contextWindowPct===null?"Not reported":x(e.contextWindowPct)}function he(e){if(e.contextWindowPct===null)return"Not reported";const t=e.modelContextWindow?` of ${w(e.modelContextWindow)}`:"";return`${x(e.contextWindowPct)}${t}`}function me(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function pe(e){const t=Number(e??0);return t>=75?"high":t>=50?"medium":"low"}function xe(e){const t=Number(e??0),i=Math.max(0,Math.min(100,Number.isFinite(t)?t:0));return`${Math.round(i)}%`}async function Se(e){I(e);const t=new URLSearchParams({enabled:"1",_:String(Date.now())}),i=await fetch(`/api/context-settings?${t.toString()}`,{headers:A(e),cache:"no-store"});return!!(await O(i,"Context settings")).context_api_enabled}async function Te(e,t,i){if(I(t),!t.contextApiEnabled)throw new Error("Context API is not enabled.");const a=new URLSearchParams({record_id:e,mode:i.mode,include_tool_output:i.includeToolOutput?"1":"0",include_compaction_history:i.includeCompactionHistory?"1":"0",max_chars:String(i.maxChars),max_entries:String(i.maxEntries),_:String(Date.now())});return await fetch(`/api/context?${a.toString()}`,{headers:A(t),cache:"no-store"}).then(s=>O(s,"Context"))}function I(e){if(e.fileMode)throw new Error("Context loading requires the localhost dashboard server.");if(!e.apiToken)throw new Error("Context loading requires a localhost dashboard API token.")}function A(e){return{Accept:"application/json","X-Codex-Usage-Token":e.apiToken}}async function O(e,t){let i={};try{i=await e.json()}catch{i={}}if(!e.ok){const a=typeof i.error=="string"?i.error:`${t} API returned HTTP ${e.status}.`;throw new Error(a)}if(typeof i.error=="string")throw new Error(i.error);return i}function ze({call:e,payload:t,onRunFullAnalysis:i,showHeading:a=!0}){const r=be(e,t);return n.jsxs("div",{className:"context-attribution-module",children:[a?n.jsxs("div",{className:"serialized-breakdown-heading context-attribution-heading",children:[n.jsx("strong",{children:"Context Attribution"}),n.jsx("span",{children:"Estimated from visible log volume"})]}):null,n.jsxs("div",{className:"drilldown-metric-grid wide context-attribution-grid",children:[n.jsx(g,{label:"Uncached input",value:o(e.uncachedInput),detail:"exact aggregate row"}),n.jsx(g,{label:"Visible new context estimate",value:r?`~${o(r.visibleTokenEstimate)}`:"Not loaded yet",detail:r?`${o(r.visibleChars)} analyzed chars`:"Runtime evidence"}),n.jsx(g,{label:"Serialized local upper bound",value:r!=null&&r.serializedTokens?`~${o(r.serializedBound)}`:"Not loaded yet",detail:r!=null&&r.serializedTokens?ge(r):"Runtime evidence"}),n.jsx(g,{label:"Unexplained hidden/serialized input estimate",value:r?`~${o(r.visibleGap)}`:"Not loaded yet",detail:r?"uncached input minus visible estimate":"Runtime evidence"}),n.jsx(g,{label:"Possible serialized overhead",value:r?`~${o(r.serializedCandidate)}`:"Not loaded yet",detail:r?"serialized upper bound minus visible estimate":"Runtime evidence"}),n.jsx(g,{label:"Remaining after serialized bound",value:r?`~${o(r.remainingAfterSerialized)}`:"Not loaded yet",detail:r?"not covered by serialized upper bound":"Runtime evidence"})]}),n.jsx(fe,{stats:r,onRunFullAnalysis:(t==null?void 0:t.context_mode)==="full"?void 0:i}),n.jsx("p",{className:"privacy-note",children:"Compare exact uncached input with tokenizer-counted visible log evidence. Treat the gap as hidden scaffolding, serialization, or tokenizer estimate error."})]})}function g({label:e,value:t,detail:i}){return n.jsxs("span",{className:"drilldown-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function fe({stats:e,onRunFullAnalysis:t}){if(!(e!=null&&e.serializedTokens))return null;if(e.serializedDeferred)return n.jsxs("div",{className:"serialized-breakdown deferred",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Fast estimate loaded; full serialized grouping is deferred."})]}),t?n.jsx("div",{className:"context-followup-actions",children:n.jsx("button",{className:"toolbar-button serialized-action",type:"button",onClick:t,children:"Run full serialized analysis"})}):null]});const i=e.serializedBuckets.slice(0,6);return n.jsxs("div",{className:"serialized-breakdown",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Upper-bound local JSONL structure; not exact prompt text."})]}),n.jsx("div",{className:"serialized-bucket-grid",children:i.length?i.map(a=>n.jsxs("div",{className:"serialized-bucket",children:[n.jsx("span",{children:a.label||a.key||"Unknown"}),n.jsx("strong",{children:o(Number(a.token_estimate??0))}),n.jsxs("small",{children:[o(Number(a.count??0))," fields · ",o(Number(a.char_count??0))," chars"]}),a.note?n.jsx("small",{children:a.note}):null]},a.key??a.label??String(a.token_estimate??0))):n.jsx("p",{className:"empty-state",children:"No serialized evidence groups returned."})})]})}function ge(e){const t=[`${o(e.serializedChars)} raw JSON chars`,e.serializedEstimator];return e.serializedDeferred&&t.push("fast estimate"),e.serializedLineCount&&t.push(`${o(e.serializedLineCount)} raw lines`),t.join(" · ")}function be(e,t){if(!t)return null;const i=t.entries??[],a=Number(t.visible_char_count??i.reduce((B,H)=>B+String(H.text??"").length,0)),r=Number(t.visible_token_estimate??Math.ceil(a/4)),s=t.serialized_evidence??{},l=Number(s.raw_json_token_estimate??s.token_estimate??0),h=Number(s.raw_json_char_count??s.total_chars??0),m=Number(s.raw_line_count??0),b=s.token_estimator||t.visible_token_estimator||"chars_per_4_fallback",c=Array.isArray(s.buckets)?s.buckets:[],v=l>0?Math.min(l,e.uncachedInput):0,k=Math.max(e.uncachedInput-r,0),F=v>r?v-r:0,W=l>0?Math.max(e.uncachedInput-Math.max(r,v),0):k;return{visibleChars:a,visibleTokenEstimate:r,serializedTokens:l,serializedChars:h,serializedLineCount:m,serializedEstimator:b,serializedBound:v,visibleGap:k,serializedCandidate:F,remainingAfterSerialized:W,serializedDeferred:!!(s.deferred||s.deferred_buckets),serializedBuckets:c}}function Pe({entry:e}){const t=je(e);return t.length?n.jsx("div",{className:"context-entry-chips","aria-label":"Evidence entry metadata",children:t.map(i=>n.jsxs("span",{title:i.title,children:[i.label,": ",i.value]},`${i.label}-${i.value}`))}):null}function je(e){var s,l,h,m;const t=[],i=e.action_timing;(i==null?void 0:i.since_turn_start_ms)!==void 0&&t.push({label:"T+",value:N(i.since_turn_start_ms),title:"Elapsed since selected turn start"}),(i==null?void 0:i.since_previous_entry_ms)!==void 0&&t.push({label:"Gap",value:N(i.since_previous_entry_ms),title:"Gap since previous evidence entry"}),(i==null?void 0:i.reported_duration_ms)!==void 0&&t.push({label:"Duration",value:N(i.reported_duration_ms),title:i.duration_source||"Duration reported by this event"});const a=(s=e.token_usage)==null?void 0:s.last_token_usage;a&&t.push({label:"Entry tokens",value:z(a),title:"Token usage reported for this evidence entry"});const r=(l=e.token_usage)==null?void 0:l.total_token_usage;return r&&t.push({label:"Session tokens",value:z(r),title:"Cumulative token usage reported by this evidence entry"}),(h=e.compaction)!=null&&h.replacement_history_available&&t.push({label:"Compaction",value:`${o(((m=e.compaction.replacement_history)==null?void 0:m.length)??0)} replacement entries`,title:"Compaction replacement history is available for this entry"}),e.tool_output_omitted&&t.push({label:"Tool output",value:"omitted",title:"Tool output omitted until explicitly requested"}),t}function z(e){const t=Number((e==null?void 0:e.input_tokens)??0),i=Number((e==null?void 0:e.cached_input_tokens)??0),a=Number((e==null?void 0:e.uncached_input_tokens)??Math.max(t-i,0)),r=Number((e==null?void 0:e.output_tokens)??0),s=Number((e==null?void 0:e.total_tokens)??t+r);return`${o(s)} total · ${o(a)} uncached`}function N(e){if(!Number.isFinite(e))return"0ms";if(e<1e3)return`${Math.round(e)}ms`;const t=e/1e3;return t>=10?`${t.toFixed(0)}s`:`${t.toFixed(1)}s`}const R=new Map,U=new Map,y=new Map,_=new Map,D=new Map;function Ee(e,t){return R.get(L(e,t))??null}function Me(e,t,i){R.set(L(e,t),i)}function Ie(e){const t=U.get(e);return t?{...t}:null}function Ae(e,t){U.set(e,{...t})}function ve(e,t){return`${e.type??"entry"}-${e.line_number??e.timestamp??t}`}function Oe(e,t){const i=y.get(e);return i?new Set(i):t.length?new Set([ve(t[0],0)]):new Set}function Re(e,t,i){const a=y.get(e)??new Set;i?a.add(t):a.delete(t),y.set(e,a)}function Ue(e,t){var i;return((i=_.get(e))==null?void 0:i.get(t))??0}function De(e,t,i){const a=_.get(e)??new Map;i>0?a.set(t,i):a.delete(t),_.set(e,a)}function Le(e){return D.get(e)??!1}function Fe(e,t){D.set(e,t)}function L(e,t){return[e,t.mode,t.includeToolOutput?"tool-output":"no-tool-output",t.includeCompactionHistory?"compaction-history":"no-compaction-history",String(t.maxChars),String(t.maxEntries)].join("|")}const C={includeToolOutput:!1,includeCompactionHistory:!1,maxChars:8e3,maxEntries:20,mode:"quick"};function We(e=window.location.search,t=C){const i=new URLSearchParams(e);return{includeToolOutput:P(i.get("include_tool_output"),t.includeToolOutput),includeCompactionHistory:P(i.get("include_compaction_history"),t.includeCompactionHistory),maxChars:E(i.get("max_chars"),t.maxChars),maxEntries:E(i.get("max_entries"),t.maxEntries),mode:i.get("mode")==="full"?"full":t.mode}}function Be(e,t,i=C){j(e,"mode",t.mode,i.mode),j(e,"max_entries",String(t.maxEntries),String(i.maxEntries)),j(e,"max_chars",String(t.maxChars),String(i.maxChars)),j(e,"include_tool_output",t.includeToolOutput?"1":"0",i.includeToolOutput?"1":"0"),j(e,"include_compaction_history",t.includeCompactionHistory?"1":"0",i.includeCompactionHistory?"1":"0")}function He(e){return e.fileMode?"Static file mode cannot read local JSONL context. Use serve-dashboard with the context API enabled.":e.apiToken?e.contextApiEnabled?"Context API is enabled. Load selected-turn evidence from the local JSONL source only when needed.":"Context API is available but off. Enable it here before loading selected-turn evidence.":"Context loading requires the localhost dashboard server API token."}function P(e,t){return e==="1"||e==="true"?!0:e==="0"||e==="false"?!1:t}function E(e,t){if(e===null||e.trim()==="")return t;const i=Number(e);return Number.isFinite(i)&&i>=0?Math.floor(i):t}function j(e,t,i,a){i===a?e.searchParams.delete(t):e.searchParams.set(t,i)}function Ge(e){return e instanceof Error?e.message:String(e)}function qe(e,t){var s;const i=Number(((s=e.omitted)==null?void 0:s.max_entries)??t.maxEntries??C.maxEntries),a=C.maxEntries||20,r=i>0?Math.max(i+a,i*2):0;return{...t,maxEntries:r}}function Je(e){const t=e.omitted??{},i=e.source??{},a=["Local JSONL context loaded on demand.",e.include_tool_output?"Tool output included with redaction and size limits.":"Tool output hidden for this view."];i.file&&a.push(`Source: ${i.file}${i.line_number?`:${i.line_number}`:""}.`);const r=Number(t.older_entries??0);r>0&&a.push(`${o(r)} older entries omitted.`);const s=Number(t.over_budget_chars??0);return s>0&&a.push(`${o(s)} chars over budget omitted.`),Number(t.max_chars??NaN)===0&&a.push("No character limit applied."),a}export{ze as C,ke as T,Ee as a,He as b,Ie as c,C as d,Se as e,Ge as f,Me as g,Je as h,Le as i,Oe as j,ve as k,Te as l,Pe as m,De as n,Ue as o,qe as p,Re as q,Ae as r,Fe as s,_e as t,we as u,ye as v,$e as w,We as x,Be as y}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js index 55207088..dbabdee0 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js @@ -1,2 +1,2 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/App.js","assets/dashboard-react.js","assets/index.css","assets/locale-zh-Hans.js","assets/router.js"])))=>i.map(i=>d[i]); -import{j as o,_ as u}from"./dashboard-react.js";import{Y as h,$ as f,T as g,a9 as b}from"./router.js";const p=["overview","investigator","compression-lab","calls","call","threads","usage-drain","cache-context","diagnostics","reports","settings"],m=new Set(p);function y(e){return typeof e=="string"&&m.has(e)}function d(e,r="overview"){const t=s(e);return t==="insights"?"overview":y(t)?t:r}function R(e){const r={...e,view:d(e.view)};i(r,"record",e.record),i(r,"q",e.q),i(r,"preset",e.preset);const t=d(e.return,"calls");s(e.return)&&t!=="call"?r.return=t:delete r.return;const n=s(e.history);n==="active"||n==="all"?r.history=n:delete r.history;const a=w(e.finding);return a!==null&&a>0?r.finding=a:delete r.finding,r}function i(e,r,t){const n=s(t);n?e[r]=n:delete e[r]}function s(e){return Array.isArray(e)?s(e[0]):typeof e=="string"?e.trim():""}function w(e){const r=Array.isArray(e)?e[0]:e,t=typeof r=="number"?r:Number.parseInt(s(r),10);return Number.isFinite(t)?Math.trunc(t):null}const _=b(()=>u(()=>import("./App.js").then(e=>e.ah),__vite__mapDeps([0,1,2,3,4])),"RoutedApp");function c(e={}){const r=h({validateSearch:R,component:_,pendingComponent:x,errorComponent:v});return f({routeTree:r,history:e.history??g(),basepath:e.basepath??l(),defaultPreload:"intent",defaultPendingMs:120,defaultPendingMinMs:180,scrollRestoration:!0,search:{strict:!1}})}const j=c();function l(){return"/"}function x(){return o.jsxs("main",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:[o.jsx("strong",{children:"Loading dashboard"}),o.jsx("span",{children:"Restoring the local usage workspace..."})]})}function v({error:e,reset:r}){return o.jsxs("main",{className:"route-state",role:"alert",children:[o.jsx("strong",{children:"Dashboard route could not load"}),o.jsx("span",{children:e instanceof Error?e.message:String(e)}),o.jsx("button",{type:"button",onClick:r,children:"Retry"})]})}const A=Object.freeze(Object.defineProperty({__proto__:null,createDashboardRouter:c,dashboardBasepath:l,dashboardRouter:j},Symbol.toStringTag,{value:"Module"}));export{A as d,y as i}; +import{j as o,_ as u}from"./dashboard-react.js";import{Y as h,$ as f,T as g,a9 as b}from"./router.js";const p=["overview","investigator","compression-lab","calls","call","threads","usage-drain","cache-context","diagnostics","reports","settings"],m=new Set(p);function y(e){return typeof e=="string"&&m.has(e)}function d(e,r="overview"){const t=s(e);return t==="insights"?"overview":y(t)?t:r}function R(e){const r={...e,view:d(e.view)};i(r,"record",e.record),i(r,"q",e.q),i(r,"preset",e.preset);const t=d(e.return,"calls");s(e.return)&&t!=="call"?r.return=t:delete r.return;const n=s(e.history);n==="active"||n==="all"?r.history=n:delete r.history;const a=w(e.finding);return a!==null&&a>0?r.finding=a:delete r.finding,r}function i(e,r,t){const n=s(t);n?e[r]=n:delete e[r]}function s(e){return Array.isArray(e)?s(e[0]):typeof e=="string"?e.trim():""}function w(e){const r=Array.isArray(e)?e[0]:e,t=typeof r=="number"?r:Number.parseInt(s(r),10);return Number.isFinite(t)?Math.trunc(t):null}const _=b(()=>u(()=>import("./App.js").then(e=>e.al),__vite__mapDeps([0,1,2,3,4])),"RoutedApp");function c(e={}){const r=h({validateSearch:R,component:_,pendingComponent:x,errorComponent:v});return f({routeTree:r,history:e.history??g(),basepath:e.basepath??l(),defaultPreload:"intent",defaultPendingMs:120,defaultPendingMinMs:180,scrollRestoration:!0,search:{strict:!1}})}const j=c();function l(){return"/"}function x(){return o.jsxs("main",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:[o.jsx("strong",{children:"Loading dashboard"}),o.jsx("span",{children:"Restoring the local usage workspace..."})]})}function v({error:e,reset:r}){return o.jsxs("main",{className:"route-state",role:"alert",children:[o.jsx("strong",{children:"Dashboard route could not load"}),o.jsx("span",{children:e instanceof Error?e.message:String(e)}),o.jsx("button",{type:"button",onClick:r,children:"Retry"})]})}const A=Object.freeze(Object.defineProperty({__proto__:null,createDashboardRouter:c,dashboardBasepath:l,dashboardRouter:j},Symbol.toStringTag,{value:"Module"}));export{A as d,y as i}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js index 2a603091..b482baa7 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js @@ -1 +1 @@ -var bt=s=>{throw TypeError(s)};var $=(s,t,e)=>t.has(s)||bt("Cannot "+e);var i=(s,t,e)=>($(s,t,"read from private field"),e?e.call(s):t.get(s)),p=(s,t,e)=>t.has(s)?bt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),l=(s,t,e,r)=>($(s,t,"write to private field"),r?r.call(s,e):t.set(s,e),e),d=(s,t,e)=>($(s,t,"access private method"),e);import{J as Tt,a2 as gt,a3 as R,L as q,a4 as W,N as tt,a5 as et,a6 as mt,a7 as Mt,a8 as X,a9 as Qt,aa as xt,ab as vt,K as Ct,ac as Ot,l as _t}from"./App.js";import{r as C}from"./dashboard-react.js";var m,a,z,g,x,U,E,w,V,D,P,_,F,T,L,n,H,st,it,rt,at,nt,ht,ot,It,Et,Gt=(Et=class extends Tt{constructor(t,e){super();p(this,n);p(this,m);p(this,a);p(this,z);p(this,g);p(this,x);p(this,U);p(this,E);p(this,w);p(this,V);p(this,D);p(this,P);p(this,_);p(this,F);p(this,T);p(this,L,new Set);this.options=e,l(this,m,t),l(this,w,null),l(this,E,gt()),this.bindMethods(),this.setOptions(e)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(i(this,a).addObserver(this),Rt(i(this,a),this.options)?d(this,n,H).call(this):this.updateResult(),d(this,n,at).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return ct(i(this,a),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return ct(i(this,a),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,d(this,n,nt).call(this),d(this,n,ht).call(this),i(this,a).removeObserver(this)}setOptions(t){const e=this.options,r=i(this,a);if(this.options=i(this,m).defaultQueryOptions(t),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof R(this.options.enabled,i(this,a))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");d(this,n,ot).call(this),i(this,a).setOptions(this.options),e._defaulted&&!q(this.options,e)&&i(this,m).getQueryCache().notify({type:"observerOptionsUpdated",query:i(this,a),observer:this});const h=this.hasListeners();h&&St(i(this,a),r,this.options,e)&&d(this,n,H).call(this),this.updateResult(),h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||W(this.options.staleTime,i(this,a))!==W(e.staleTime,i(this,a)))&&d(this,n,st).call(this);const o=d(this,n,it).call(this);h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||o!==i(this,T))&&d(this,n,rt).call(this,o)}getOptimisticResult(t){const e=i(this,m).getQueryCache().build(i(this,m),t),r=this.createResult(e,t);return Ut(this,r)&&(l(this,g,r),l(this,U,this.options),l(this,x,i(this,a).state)),r}getCurrentResult(){return i(this,g)}trackResult(t,e){return new Proxy(t,{get:(r,h)=>(this.trackProp(h),e==null||e(h),h==="promise"&&(this.trackProp("data"),!this.options.experimental_prefetchInRender&&i(this,E).status==="pending"&&i(this,E).reject(new Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(r,h))})}trackProp(t){i(this,L).add(t)}getCurrentQuery(){return i(this,a)}refetch({...t}={}){return this.fetch({...t})}fetchOptimistic(t){const e=i(this,m).defaultQueryOptions(t),r=i(this,m).getQueryCache().build(i(this,m),e);return r.fetch().then(()=>this.createResult(r,e))}fetch(t){return d(this,n,H).call(this,{...t,cancelRefetch:t.cancelRefetch??!0}).then(()=>(this.updateResult(),i(this,g)))}createResult(t,e){var ft;const r=i(this,a),h=this.options,o=i(this,g),c=i(this,x),S=i(this,U),N=t!==r?t.state:i(this,z),{state:b}=t;let u={...b},B=!1,f;if(e._optimisticResults){const v=this.hasListeners(),j=!v&&Rt(t,e),K=v&&St(t,r,e,h);(j||K)&&(u={...u,...xt(b.data,t.options)}),e._optimisticResults==="isRestoring"&&(u.fetchStatus="idle")}let{error:k,errorUpdatedAt:Q,status:y}=u;f=u.data;let O=!1;if(e.placeholderData!==void 0&&f===void 0&&y==="pending"){let v;o!=null&&o.isPlaceholderData&&e.placeholderData===(S==null?void 0:S.placeholderData)?(v=o.data,O=!0):v=typeof e.placeholderData=="function"?e.placeholderData((ft=i(this,P))==null?void 0:ft.state.data,i(this,P)):e.placeholderData,v!==void 0&&(y="success",f=vt(o==null?void 0:o.data,v,e),B=!0)}if(e.select&&f!==void 0&&!O)if(o&&f===(c==null?void 0:c.data)&&e.select===i(this,V))f=i(this,D);else try{l(this,V,e.select),f=e.select(f),f=vt(o==null?void 0:o.data,f,e),l(this,D,f),l(this,w,null)}catch(v){l(this,w,v)}i(this,w)&&(k=i(this,w),f=i(this,D),Q=Date.now(),y="error");const A=u.fetchStatus==="fetching",Y=y==="pending",Z=y==="error",ut=Y&&A,dt=f!==void 0,I={status:y,fetchStatus:u.fetchStatus,isPending:Y,isSuccess:y==="success",isError:Z,isInitialLoading:ut,isLoading:ut,data:f,dataUpdatedAt:u.dataUpdatedAt,error:k,errorUpdatedAt:Q,failureCount:u.fetchFailureCount,failureReason:u.fetchFailureReason,errorUpdateCount:u.errorUpdateCount,isFetched:t.isFetched(),isFetchedAfterMount:u.dataUpdateCount>N.dataUpdateCount||u.errorUpdateCount>N.errorUpdateCount,isFetching:A,isRefetching:A&&!Y,isLoadingError:Z&&!dt,isPaused:u.fetchStatus==="paused",isPlaceholderData:B,isRefetchError:Z&&dt,isStale:lt(t,e),refetch:this.refetch,promise:i(this,E),isEnabled:R(e.enabled,t)!==!1};if(this.options.experimental_prefetchInRender){const v=I.data!==void 0,j=I.status==="error"&&!v,K=G=>{j?G.reject(I.error):v&&G.resolve(I.data)},pt=()=>{const G=l(this,E,I.promise=gt());K(G)},J=i(this,E);switch(J.status){case"pending":t.queryHash===r.queryHash&&K(J);break;case"fulfilled":(j||I.data!==J.value)&&pt();break;case"rejected":(!j||I.error!==J.reason)&&pt();break}}return I}updateResult(){const t=i(this,g),e=this.createResult(i(this,a),this.options);if(l(this,x,i(this,a).state),l(this,U,this.options),i(this,x).data!==void 0&&l(this,P,i(this,a)),q(e,t))return;l(this,g,e);const r=()=>{if(!t)return!0;const{notifyOnChangeProps:h}=this.options,o=typeof h=="function"?h():h;if(o==="all"||!o&&!i(this,L).size)return!0;const c=new Set(o??i(this,L));return this.options.throwOnError&&c.add("error"),Object.keys(i(this,g)).some(S=>{const M=S;return i(this,g)[M]!==t[M]&&c.has(M)})};d(this,n,It).call(this,{listeners:r()})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&d(this,n,at).call(this)}},m=new WeakMap,a=new WeakMap,z=new WeakMap,g=new WeakMap,x=new WeakMap,U=new WeakMap,E=new WeakMap,w=new WeakMap,V=new WeakMap,D=new WeakMap,P=new WeakMap,_=new WeakMap,F=new WeakMap,T=new WeakMap,L=new WeakMap,n=new WeakSet,H=function(t){d(this,n,ot).call(this);let e=i(this,a).fetch(this.options,t);return t!=null&&t.throwOnError||(e=e.catch(tt)),e},st=function(){d(this,n,nt).call(this);const t=W(this.options.staleTime,i(this,a));if(et.isServer()||i(this,g).isStale||!mt(t))return;const r=Mt(i(this,g).dataUpdatedAt,t)+1;l(this,_,X.setTimeout(()=>{i(this,g).isStale||this.updateResult()},r))},it=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(i(this,a)):this.options.refetchInterval)??!1},rt=function(t){d(this,n,ht).call(this),l(this,T,t),!(et.isServer()||R(this.options.enabled,i(this,a))===!1||!mt(i(this,T))||i(this,T)===0)&&l(this,F,X.setInterval(()=>{(this.options.refetchIntervalInBackground||Qt.isFocused())&&d(this,n,H).call(this)},i(this,T)))},at=function(){d(this,n,st).call(this),d(this,n,rt).call(this,d(this,n,it).call(this))},nt=function(){i(this,_)!==void 0&&(X.clearTimeout(i(this,_)),l(this,_,void 0))},ht=function(){i(this,F)!==void 0&&(X.clearInterval(i(this,F)),l(this,F,void 0))},ot=function(){const t=i(this,m).getQueryCache().build(i(this,m),this.options);if(t===i(this,a))return;const e=i(this,a);l(this,a,t),l(this,z,t.state),this.hasListeners()&&(e==null||e.removeObserver(this),t.addObserver(this))},It=function(t){Ct.batch(()=>{t.listeners&&this.listeners.forEach(e=>{e(i(this,g))}),i(this,m).getQueryCache().notify({query:i(this,a),type:"observerResultsUpdated"})})},Et);function Ft(s,t){return R(t.enabled,s)!==!1&&s.state.data===void 0&&!(s.state.status==="error"&&R(t.retryOnMount,s)===!1)}function Rt(s,t){return Ft(s,t)||s.state.data!==void 0&&ct(s,t,t.refetchOnMount)}function ct(s,t,e){if(R(t.enabled,s)!==!1&&W(t.staleTime,s)!=="static"){const r=typeof e=="function"?e(s):e;return r==="always"||r!==!1&<(s,t)}return!1}function St(s,t,e,r){return(s!==t||R(r.enabled,s)===!1)&&(!e.suspense||s.state.status!=="error")&<(s,e)}function lt(s,t){return R(t.enabled,s)!==!1&&s.isStaleByTime(W(t.staleTime,s))}function Ut(s,t){return!q(s.getCurrentResult(),t)}var wt=C.createContext(!1),Dt=()=>C.useContext(wt);wt.Provider;function Pt(){let s=!1;return{clearReset:()=>{s=!1},reset:()=>{s=!0},isReset:()=>s}}var Lt=C.createContext(Pt()),Nt=()=>C.useContext(Lt),Bt=(s,t,e)=>{const r=e!=null&&e.state.error&&typeof s.throwOnError=="function"?Ot(s.throwOnError,[e.state.error,e]):s.throwOnError;(s.suspense||s.experimental_prefetchInRender||r)&&(t.isReset()||(s.retryOnMount=!1))},kt=s=>{C.useEffect(()=>{s.clearReset()},[s])},At=({result:s,errorResetBoundary:t,throwOnError:e,query:r,suspense:h})=>s.isError&&!t.isReset()&&!s.isFetching&&r&&(h&&s.data===void 0||Ot(e,[s.error,r])),jt=s=>{if(s.suspense){const e=h=>h==="static"?h:Math.max(h??1e3,1e3),r=s.staleTime;s.staleTime=typeof r=="function"?(...h)=>e(r(...h)):e(r),typeof s.gcTime=="number"&&(s.gcTime=Math.max(s.gcTime,1e3))}},Ht=(s,t)=>s.isLoading&&s.isFetching&&!t,Wt=(s,t)=>(s==null?void 0:s.suspense)&&t.isPending,yt=(s,t,e)=>t.fetchOptimistic(s).catch(()=>{e.clearReset()});function Xt(s,t,e){var f,k,Q,y;const r=Dt(),h=Nt(),o=_t(),c=o.defaultQueryOptions(s);(k=(f=o.getDefaultOptions().queries)==null?void 0:f._experimental_beforeQuery)==null||k.call(f,c);const S=o.getQueryCache().get(c.queryHash),M=s.subscribed!==!1;c._optimisticResults=r?"isRestoring":M?"optimistic":void 0,jt(c),Bt(c,h,S),kt(h);const N=!o.getQueryCache().get(c.queryHash),[b]=C.useState(()=>new t(o,c)),u=b.getOptimisticResult(c),B=!r&&M;if(C.useSyncExternalStore(C.useCallback(O=>{const A=B?b.subscribe(Ct.batchCalls(O)):tt;return b.updateResult(),A},[b,B]),()=>b.getCurrentResult(),()=>b.getCurrentResult()),C.useEffect(()=>{b.setOptions(c)},[c,b]),Wt(c,u))throw yt(c,b,h);if(At({result:u,errorResetBoundary:h,throwOnError:c.throwOnError,query:S,suspense:c.suspense}))throw u.error;if((y=(Q=o.getDefaultOptions().queries)==null?void 0:Q._experimental_afterQuery)==null||y.call(Q,c,u),c.experimental_prefetchInRender&&!et.isServer()&&Ht(u,r)){const O=N?yt(c,b,h):S==null?void 0:S.promise;O==null||O.catch(tt).finally(()=>{b.updateResult()})}return c.notifyOnChangeProps?u:b.trackResult(u)}export{Gt as Q,Nt as a,Bt as b,kt as c,Xt as d,jt as e,yt as f,At as g,Wt as s,Dt as u}; +var bt=s=>{throw TypeError(s)};var $=(s,t,e)=>t.has(s)||bt("Cannot "+e);var i=(s,t,e)=>($(s,t,"read from private field"),e?e.call(s):t.get(s)),p=(s,t,e)=>t.has(s)?bt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),l=(s,t,e,r)=>($(s,t,"write to private field"),r?r.call(s,e):t.set(s,e),e),d=(s,t,e)=>($(s,t,"access private method"),e);import{J as Tt,a4 as gt,a5 as R,L as q,a6 as W,N as tt,a7 as et,a8 as mt,a9 as Mt,aa as X,ab as Qt,ac as xt,ad as vt,K as Ct,ae as Ot,l as _t}from"./App.js";import{r as C}from"./dashboard-react.js";var m,a,z,g,x,U,E,w,V,D,P,_,F,T,L,n,H,st,it,rt,at,nt,ht,ot,It,Et,Gt=(Et=class extends Tt{constructor(t,e){super();p(this,n);p(this,m);p(this,a);p(this,z);p(this,g);p(this,x);p(this,U);p(this,E);p(this,w);p(this,V);p(this,D);p(this,P);p(this,_);p(this,F);p(this,T);p(this,L,new Set);this.options=e,l(this,m,t),l(this,w,null),l(this,E,gt()),this.bindMethods(),this.setOptions(e)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(i(this,a).addObserver(this),Rt(i(this,a),this.options)?d(this,n,H).call(this):this.updateResult(),d(this,n,at).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return ct(i(this,a),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return ct(i(this,a),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,d(this,n,nt).call(this),d(this,n,ht).call(this),i(this,a).removeObserver(this)}setOptions(t){const e=this.options,r=i(this,a);if(this.options=i(this,m).defaultQueryOptions(t),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof R(this.options.enabled,i(this,a))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");d(this,n,ot).call(this),i(this,a).setOptions(this.options),e._defaulted&&!q(this.options,e)&&i(this,m).getQueryCache().notify({type:"observerOptionsUpdated",query:i(this,a),observer:this});const h=this.hasListeners();h&&St(i(this,a),r,this.options,e)&&d(this,n,H).call(this),this.updateResult(),h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||W(this.options.staleTime,i(this,a))!==W(e.staleTime,i(this,a)))&&d(this,n,st).call(this);const o=d(this,n,it).call(this);h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||o!==i(this,T))&&d(this,n,rt).call(this,o)}getOptimisticResult(t){const e=i(this,m).getQueryCache().build(i(this,m),t),r=this.createResult(e,t);return Ut(this,r)&&(l(this,g,r),l(this,U,this.options),l(this,x,i(this,a).state)),r}getCurrentResult(){return i(this,g)}trackResult(t,e){return new Proxy(t,{get:(r,h)=>(this.trackProp(h),e==null||e(h),h==="promise"&&(this.trackProp("data"),!this.options.experimental_prefetchInRender&&i(this,E).status==="pending"&&i(this,E).reject(new Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(r,h))})}trackProp(t){i(this,L).add(t)}getCurrentQuery(){return i(this,a)}refetch({...t}={}){return this.fetch({...t})}fetchOptimistic(t){const e=i(this,m).defaultQueryOptions(t),r=i(this,m).getQueryCache().build(i(this,m),e);return r.fetch().then(()=>this.createResult(r,e))}fetch(t){return d(this,n,H).call(this,{...t,cancelRefetch:t.cancelRefetch??!0}).then(()=>(this.updateResult(),i(this,g)))}createResult(t,e){var ft;const r=i(this,a),h=this.options,o=i(this,g),c=i(this,x),S=i(this,U),N=t!==r?t.state:i(this,z),{state:b}=t;let u={...b},B=!1,f;if(e._optimisticResults){const v=this.hasListeners(),j=!v&&Rt(t,e),K=v&&St(t,r,e,h);(j||K)&&(u={...u,...xt(b.data,t.options)}),e._optimisticResults==="isRestoring"&&(u.fetchStatus="idle")}let{error:k,errorUpdatedAt:Q,status:y}=u;f=u.data;let O=!1;if(e.placeholderData!==void 0&&f===void 0&&y==="pending"){let v;o!=null&&o.isPlaceholderData&&e.placeholderData===(S==null?void 0:S.placeholderData)?(v=o.data,O=!0):v=typeof e.placeholderData=="function"?e.placeholderData((ft=i(this,P))==null?void 0:ft.state.data,i(this,P)):e.placeholderData,v!==void 0&&(y="success",f=vt(o==null?void 0:o.data,v,e),B=!0)}if(e.select&&f!==void 0&&!O)if(o&&f===(c==null?void 0:c.data)&&e.select===i(this,V))f=i(this,D);else try{l(this,V,e.select),f=e.select(f),f=vt(o==null?void 0:o.data,f,e),l(this,D,f),l(this,w,null)}catch(v){l(this,w,v)}i(this,w)&&(k=i(this,w),f=i(this,D),Q=Date.now(),y="error");const A=u.fetchStatus==="fetching",Y=y==="pending",Z=y==="error",ut=Y&&A,dt=f!==void 0,I={status:y,fetchStatus:u.fetchStatus,isPending:Y,isSuccess:y==="success",isError:Z,isInitialLoading:ut,isLoading:ut,data:f,dataUpdatedAt:u.dataUpdatedAt,error:k,errorUpdatedAt:Q,failureCount:u.fetchFailureCount,failureReason:u.fetchFailureReason,errorUpdateCount:u.errorUpdateCount,isFetched:t.isFetched(),isFetchedAfterMount:u.dataUpdateCount>N.dataUpdateCount||u.errorUpdateCount>N.errorUpdateCount,isFetching:A,isRefetching:A&&!Y,isLoadingError:Z&&!dt,isPaused:u.fetchStatus==="paused",isPlaceholderData:B,isRefetchError:Z&&dt,isStale:lt(t,e),refetch:this.refetch,promise:i(this,E),isEnabled:R(e.enabled,t)!==!1};if(this.options.experimental_prefetchInRender){const v=I.data!==void 0,j=I.status==="error"&&!v,K=G=>{j?G.reject(I.error):v&&G.resolve(I.data)},pt=()=>{const G=l(this,E,I.promise=gt());K(G)},J=i(this,E);switch(J.status){case"pending":t.queryHash===r.queryHash&&K(J);break;case"fulfilled":(j||I.data!==J.value)&&pt();break;case"rejected":(!j||I.error!==J.reason)&&pt();break}}return I}updateResult(){const t=i(this,g),e=this.createResult(i(this,a),this.options);if(l(this,x,i(this,a).state),l(this,U,this.options),i(this,x).data!==void 0&&l(this,P,i(this,a)),q(e,t))return;l(this,g,e);const r=()=>{if(!t)return!0;const{notifyOnChangeProps:h}=this.options,o=typeof h=="function"?h():h;if(o==="all"||!o&&!i(this,L).size)return!0;const c=new Set(o??i(this,L));return this.options.throwOnError&&c.add("error"),Object.keys(i(this,g)).some(S=>{const M=S;return i(this,g)[M]!==t[M]&&c.has(M)})};d(this,n,It).call(this,{listeners:r()})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&d(this,n,at).call(this)}},m=new WeakMap,a=new WeakMap,z=new WeakMap,g=new WeakMap,x=new WeakMap,U=new WeakMap,E=new WeakMap,w=new WeakMap,V=new WeakMap,D=new WeakMap,P=new WeakMap,_=new WeakMap,F=new WeakMap,T=new WeakMap,L=new WeakMap,n=new WeakSet,H=function(t){d(this,n,ot).call(this);let e=i(this,a).fetch(this.options,t);return t!=null&&t.throwOnError||(e=e.catch(tt)),e},st=function(){d(this,n,nt).call(this);const t=W(this.options.staleTime,i(this,a));if(et.isServer()||i(this,g).isStale||!mt(t))return;const r=Mt(i(this,g).dataUpdatedAt,t)+1;l(this,_,X.setTimeout(()=>{i(this,g).isStale||this.updateResult()},r))},it=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(i(this,a)):this.options.refetchInterval)??!1},rt=function(t){d(this,n,ht).call(this),l(this,T,t),!(et.isServer()||R(this.options.enabled,i(this,a))===!1||!mt(i(this,T))||i(this,T)===0)&&l(this,F,X.setInterval(()=>{(this.options.refetchIntervalInBackground||Qt.isFocused())&&d(this,n,H).call(this)},i(this,T)))},at=function(){d(this,n,st).call(this),d(this,n,rt).call(this,d(this,n,it).call(this))},nt=function(){i(this,_)!==void 0&&(X.clearTimeout(i(this,_)),l(this,_,void 0))},ht=function(){i(this,F)!==void 0&&(X.clearInterval(i(this,F)),l(this,F,void 0))},ot=function(){const t=i(this,m).getQueryCache().build(i(this,m),this.options);if(t===i(this,a))return;const e=i(this,a);l(this,a,t),l(this,z,t.state),this.hasListeners()&&(e==null||e.removeObserver(this),t.addObserver(this))},It=function(t){Ct.batch(()=>{t.listeners&&this.listeners.forEach(e=>{e(i(this,g))}),i(this,m).getQueryCache().notify({query:i(this,a),type:"observerResultsUpdated"})})},Et);function Ft(s,t){return R(t.enabled,s)!==!1&&s.state.data===void 0&&!(s.state.status==="error"&&R(t.retryOnMount,s)===!1)}function Rt(s,t){return Ft(s,t)||s.state.data!==void 0&&ct(s,t,t.refetchOnMount)}function ct(s,t,e){if(R(t.enabled,s)!==!1&&W(t.staleTime,s)!=="static"){const r=typeof e=="function"?e(s):e;return r==="always"||r!==!1&<(s,t)}return!1}function St(s,t,e,r){return(s!==t||R(r.enabled,s)===!1)&&(!e.suspense||s.state.status!=="error")&<(s,e)}function lt(s,t){return R(t.enabled,s)!==!1&&s.isStaleByTime(W(t.staleTime,s))}function Ut(s,t){return!q(s.getCurrentResult(),t)}var wt=C.createContext(!1),Dt=()=>C.useContext(wt);wt.Provider;function Pt(){let s=!1;return{clearReset:()=>{s=!1},reset:()=>{s=!0},isReset:()=>s}}var Lt=C.createContext(Pt()),Nt=()=>C.useContext(Lt),Bt=(s,t,e)=>{const r=e!=null&&e.state.error&&typeof s.throwOnError=="function"?Ot(s.throwOnError,[e.state.error,e]):s.throwOnError;(s.suspense||s.experimental_prefetchInRender||r)&&(t.isReset()||(s.retryOnMount=!1))},kt=s=>{C.useEffect(()=>{s.clearReset()},[s])},At=({result:s,errorResetBoundary:t,throwOnError:e,query:r,suspense:h})=>s.isError&&!t.isReset()&&!s.isFetching&&r&&(h&&s.data===void 0||Ot(e,[s.error,r])),jt=s=>{if(s.suspense){const e=h=>h==="static"?h:Math.max(h??1e3,1e3),r=s.staleTime;s.staleTime=typeof r=="function"?(...h)=>e(r(...h)):e(r),typeof s.gcTime=="number"&&(s.gcTime=Math.max(s.gcTime,1e3))}},Ht=(s,t)=>s.isLoading&&s.isFetching&&!t,Wt=(s,t)=>(s==null?void 0:s.suspense)&&t.isPending,yt=(s,t,e)=>t.fetchOptimistic(s).catch(()=>{e.clearReset()});function Xt(s,t,e){var f,k,Q,y;const r=Dt(),h=Nt(),o=_t(),c=o.defaultQueryOptions(s);(k=(f=o.getDefaultOptions().queries)==null?void 0:f._experimental_beforeQuery)==null||k.call(f,c);const S=o.getQueryCache().get(c.queryHash),M=s.subscribed!==!1;c._optimisticResults=r?"isRestoring":M?"optimistic":void 0,jt(c),Bt(c,h,S),kt(h);const N=!o.getQueryCache().get(c.queryHash),[b]=C.useState(()=>new t(o,c)),u=b.getOptimisticResult(c),B=!r&&M;if(C.useSyncExternalStore(C.useCallback(O=>{const A=B?b.subscribe(Ct.batchCalls(O)):tt;return b.updateResult(),A},[b,B]),()=>b.getCurrentResult(),()=>b.getCurrentResult()),C.useEffect(()=>{b.setOptions(c)},[c,b]),Wt(c,u))throw yt(c,b,h);if(At({result:u,errorResetBoundary:h,throwOnError:c.throwOnError,query:S,suspense:c.suspense}))throw u.error;if((y=(Q=o.getDefaultOptions().queries)==null?void 0:Q._experimental_afterQuery)==null||y.call(Q,c,u),c.experimental_prefetchInRender&&!et.isServer()&&Ht(u,r)){const O=N?yt(c,b,h):S==null?void 0:S.promise;O==null||O.catch(tt).finally(()=>{b.updateResult()})}return c.notifyOnChangeProps?u:b.trackResult(u)}export{Gt as Q,Nt as a,Bt as b,kt as c,Xt as d,jt as e,yt as f,At as g,Wt as s,Dt as u}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js index d0aebf54..1b42253f 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js @@ -1 +1 @@ -import{Q as v,d as p}from"./useBaseQuery.js";import{a0 as x,a1 as b}from"./App.js";var l=class extends v{constructor(e,t){super(e,t)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){e._type="infinite",super.setOptions(e)}getOptimisticResult(e){return e._type="infinite",super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"backward"}}})}createResult(e,t){var f,P;const{state:s}=e,i=super.createResult(e,t),{isFetching:a,isRefetching:g,isError:c,isRefetchError:d}=i,r=(P=(f=s.fetchMeta)==null?void 0:f.fetchMore)==null?void 0:P.direction,h=c&&r==="forward",n=a&&r==="forward",o=c&&r==="backward",u=a&&r==="backward";return{...i,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:b(t,s.data),hasPreviousPage:x(t,s.data),isFetchNextPageError:h,isFetchingNextPage:n,isFetchPreviousPageError:o,isFetchingPreviousPage:u,isRefetchError:d&&!h&&!o,isRefetching:g&&!n&&!u}}};function w(e,t){return p(e,l)}export{w as u}; +import{Q as v,d as p}from"./useBaseQuery.js";import{a2 as x,a3 as b}from"./App.js";var l=class extends v{constructor(e,t){super(e,t)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){e._type="infinite",super.setOptions(e)}getOptimisticResult(e){return e._type="infinite",super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"backward"}}})}createResult(e,t){var f,P;const{state:s}=e,i=super.createResult(e,t),{isFetching:a,isRefetching:g,isError:c,isRefetchError:d}=i,r=(P=(f=s.fetchMeta)==null?void 0:f.fetchMore)==null?void 0:P.direction,h=c&&r==="forward",n=a&&r==="forward",o=c&&r==="backward",u=a&&r==="backward";return{...i,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:b(t,s.data),hasPreviousPage:x(t,s.data),isFetchNextPageError:h,isFetchingNextPage:n,isFetchPreviousPageError:o,isFetchingPreviousPage:u,isRefetchError:d&&!h&&!o,isRefetching:g&&!n&&!u}}};function w(e,t){return p(e,l)}export{w as u}; From c770c17d9b4455191bd302af8e58de60395a3114 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 14:10:02 -0400 Subject: [PATCH 13/24] fix: isolate OTel defaults by database --- docs/database-schema.md | 5 ++++- src/codex_usage_tracker/store/api.py | 5 ++--- src/codex_usage_tracker/store/refresh.py | 9 +++++--- tests/store/test_otel_refresh.py | 28 ++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/docs/database-schema.md b/docs/database-schema.md index 54965693..b3eb65df 100644 --- a/docs/database-schema.md +++ b/docs/database-schema.md @@ -40,7 +40,10 @@ not have exact tier evidence; it is not interpreted as Standard. `otel_completion_sources` records device/inode identity, size, the last complete byte and line cursor, and an update timestamp for each local -`codex-completions*.jsonl` file. `otel_completion_events` stores one semantic +`codex-completions*.jsonl` file. The default directory is the `otel` sibling of +the selected database (`~/.codex-usage-tracker/otel` for the default database), +so alternate databases do not ingest another tracker instance's telemetry. +`otel_completion_events` stores one semantic fingerprint plus aggregate matching fields, normalized tier provenance, a bounded match status (`pending`, `matched`, `ambiguous`, `conflict`, or `invalid`), and the matched aggregate record id when available. diff --git a/src/codex_usage_tracker/store/api.py b/src/codex_usage_tracker/store/api.py index f995612e..5f91601f 100644 --- a/src/codex_usage_tracker/store/api.py +++ b/src/codex_usage_tracker/store/api.py @@ -15,7 +15,6 @@ from codex_usage_tracker.core.paths import ( DEFAULT_CODEX_HOME, DEFAULT_DB_PATH, - DEFAULT_OTEL_COMPLETIONS_DIR, ) from codex_usage_tracker.core.schema import ( DIAGNOSTIC_FACT_COLUMN_NAMES, @@ -177,7 +176,7 @@ def refresh_usage_index( db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, - otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, + otel_dir: Path | None = None, progress_callback: RefreshProgressCallback | None = None, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: @@ -203,7 +202,7 @@ def rebuild_usage_index( db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, - otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, + otel_dir: Path | None = None, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: """Drop and rebuild the usage index from all selected Codex logs.""" diff --git a/src/codex_usage_tracker/store/refresh.py b/src/codex_usage_tracker/store/refresh.py index 306bc020..d3e427b8 100644 --- a/src/codex_usage_tracker/store/refresh.py +++ b/src/codex_usage_tracker/store/refresh.py @@ -40,7 +40,7 @@ def refresh_usage_index( db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, - otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, + otel_dir: Path | None = None, progress_callback: RefreshProgressCallback | None = None, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: @@ -107,7 +107,10 @@ def refresh_usage_index( total=1, message="Reconciling aggregate OTel completion tiers", ) - otel_diagnostics = _refresh_otel_completions(db_path=db_path, otel_dir=otel_dir) + resolved_otel_dir = otel_dir or db_path.parent / DEFAULT_OTEL_COMPLETIONS_DIR.name + otel_diagnostics = _refresh_otel_completions( + db_path=db_path, otel_dir=resolved_otel_dir + ) emit_refresh_progress( progress_callback, phase="otel", @@ -215,7 +218,7 @@ def rebuild_usage_index( db_path: Path = DEFAULT_DB_PATH, include_archived: bool = False, aggregate_only: bool = False, - otel_dir: Path = DEFAULT_OTEL_COMPLETIONS_DIR, + otel_dir: Path | None = None, derived_fact_sync: DerivedFactSyncCallback | None = None, ) -> RefreshResult: """Clear aggregate rows and rescan local Codex logs.""" diff --git a/tests/store/test_otel_refresh.py b/tests/store/test_otel_refresh.py index a1db5ef4..185ab039 100644 --- a/tests/store/test_otel_refresh.py +++ b/tests/store/test_otel_refresh.py @@ -59,6 +59,34 @@ def test_absent_otel_directory_is_a_supported_noop(tmp_path: Path) -> None: assert result.parser_diagnostics.get("otel_files_scanned", 0) == 0 +def test_default_otel_directory_follows_database_directory(tmp_path: Path) -> None: + tracker_dir = tmp_path / "tracker" + codex_home = write_usage_session( + tmp_path, conversation_id="conversation-local-default", tokens=(90, 30, 20, 5) + ) + write_lines( + tracker_dir / "otel" / "codex-completions.jsonl", + [ + synthetic_otlp_line( + attributes=completion_attributes( + conversation_id="conversation-local-default", + tokens=(90, 30, 20, 5), + service_tier="priority", + ) + ) + ], + ) + db_path = tracker_dir / "usage.sqlite3" + + result = refresh_usage_index(codex_home=codex_home, db_path=db_path) + + with connect(db_path) as conn: + row = conn.execute("SELECT fast FROM usage_events").fetchone() + assert row is not None + assert row["fast"] == 1 + assert result.parser_diagnostics["otel_matched"] == 1 + + def test_refresh_records_protocol_confirmed_standard(tmp_path: Path) -> None: codex_home = write_usage_session( tmp_path, "conversation-standard", (100, 40, 30, 10) From a0bc88ca8013b40578ac0fd3cb102d1c8fc2f1bb Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 16:49:12 -0400 Subject: [PATCH 14/24] docs: refine service tier billing design --- ...-07-16-otel-fast-usage-ingestion-design.md | 110 +++++++++++++++--- 1 file changed, 92 insertions(+), 18 deletions(-) diff --git a/docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md b/docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md index 9d9cb950..9501fb38 100644 --- a/docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md +++ b/docs/superpowers/specs/2026-07-16-otel-fast-usage-ingestion-design.md @@ -2,9 +2,10 @@ ## Goal -Enrich existing aggregate Codex usage calls with reliable Fast-versus-Standard service-tier -metadata from the local OpenTelemetry `response.completed` stream, then use confirmed Fast -status when estimating ChatGPT credit consumption. +Enrich existing aggregate Codex usage calls with reliable response service-tier metadata from +the local OpenTelemetry `response.completed` stream, then use the exact observed tier together +with an explicit billing basis to estimate either ChatGPT credit consumption or API token cost +without conflating those two billing systems. The feature must remain local, aggregate-only, incremental, idempotent, and conservative. It must never create a second usage call for an OTel completion, guess when more than one logical @@ -15,12 +16,22 @@ or tool content. - Reconstruct Fast usage before completion-tier telemetry was emitted. - Treat response timing, reasoning effort, or latency as proof of Fast mode. -- Change USD text-token cost estimates based only on a service-tier label. +- Infer ChatGPT-versus-API billing from a service-tier label alone. - Replace session JSONL as the canonical source of usage calls and token totals. - Persist or expose raw OTel payloads through the database, dashboard, exports, support bundles, or tests. - Add remote telemetry export or change the user's collector configuration. +## Alternatives considered + +1. **Multiply every Fast USD estimate by the ChatGPT credit multiplier.** Rejected because API + Priority premiums are model-specific and can differ from ChatGPT Fast credit multipliers. +2. **Keep one globally selected API tier.** Rejected because an exact response tier can vary by + call, including Priority downgrades to Standard, so a global tier can misprice mixed history. +3. **Preserve the exact tier, cache all API tiers, and keep billing basis explicit.** Selected. + This keeps ChatGPT credits and API-token USD as separately labeled estimates, uses the actual + response tier for API-equivalent cost, and never infers authentication from OTel. + ## Source contract The optional local source is the file-exporter output under the tracker application directory: @@ -55,18 +66,21 @@ the offending content into SQLite or report payloads. The normalized call fields are: -- `service_tier`: `fast`, `standard`, another explicit non-Fast tier, or `NULL` when unknown. -- `fast`: `1` for confirmed Fast, `0` for confirmed non-Fast, or `NULL` when unknown. +- `service_tier`: the exact normalized response tier (`priority`, `default`, `flex`, another + explicit value), `standard` when established by versioned omission, or `NULL` when unknown. +- `fast`: `1` for the Codex accelerated path established by `priority`/`fast`, `0` for a + confirmed non-Fast tier, or `NULL` when unknown. This is a derived product classification, + not a billing-system discriminator. - `service_tier_source`: `otel_response_completed` for this ingestion path. - `service_tier_confidence`: `exact` for explicit tier values and `protocol` when Standard is established by versioned omission semantics. -Explicit `priority` and `fast` values normalize to `service_tier = fast` and `fast = 1`. -Explicit `default` and `standard` values normalize to `service_tier = standard` and `fast = 0`. -Other explicit values are preserved as normalized lower-case tier names with `fast = 0`. +Explicit tier names are preserved in normalized lower case. `priority` and `fast` set `fast = 1`; +`default`, `standard`, `flex`, and other explicit non-Fast values set `fast = 0`. The exact +response tier and the derived Fast classification must remain separately auditable. -Codex 0.143.0 and later emits `service_tier = priority` for Fast completions and omits the -field for Standard completions. Therefore, a missing service tier with a parseable +Codex 0.143.0 and later emits `service_tier = priority` for accelerated completions and omits +the field for Standard completions. Therefore, a missing service tier with a parseable `app.version >= 0.143.0` normalizes to `service_tier = standard`, `fast = 0`, and `service_tier_confidence = protocol`. A missing tier from an older or unparseable version remains unknown. @@ -158,8 +172,9 @@ These fields are additive to existing row and export contracts. Historical calls `NULL`/unknown unless a conservative OTel match exists. They are not identity fields and must not participate in usage fingerprints, canonical IDs, or duplicate classification. -Calls and call-detail payloads expose the four aggregate fields. Dashboard labels distinguish -Fast, Standard, and Unknown. Existing proxy analysis remains available for historical unknown +Calls and call-detail payloads expose the four aggregate fields. Dashboard labels preserve the +exact observed tier and distinguish Priority/Fast, Default/Standard, Flex, Batch, another +explicit tier, and Unknown. Existing proxy analysis remains available for historical unknown calls, but exact OTel enrichment takes precedence and proxy wording must not claim that direct tier data is unavailable for enriched rows. @@ -176,9 +191,61 @@ Confirmed Standard and unknown calls use multiplier `1.0`; unknown calls must re unknown rather than being labeled Standard. Credit annotations add the effective multiplier and tier provenance so totals remain explainable. -USD token-cost estimates remain unchanged. `priority` can represent ChatGPT Fast mode or API -Priority processing, and the retained aggregate fields do not prove the authentication or -billing path. Applying an API Priority price automatically would therefore be unsafe. +`priority` can represent ChatGPT Fast mode or API Priority processing, and the retained OTel +attributes do not prove the authentication or billing path. Reports therefore require an +explicit billing basis with three states: + +- `chatgpt_credits`: apply the documented, source-stamped Fast credit multiplier to confirmed + Fast calls; API USD remains an explicitly labeled equivalent estimate rather than actual spend. +- `api_tokens`: do not apply ChatGPT credit multipliers; select the exact API pricing table from + the observed response tier (`priority`, `default`/`standard`, `flex`, or `batch`). +- `unknown`: do not present one falsely precise billing result; expose the Standard and Priority + API-equivalent scenarios plus the unadjusted and Fast-adjusted ChatGPT credit scenarios when + the required rates exist. + +The local API pricing-v2 snapshot stores all published service-tier tables together under +`api_service_tiers`, while retaining `models` as the selected legacy projection. Existing +single-tier pricing-v1 files remain readable and keep their source tier as their only available +tier. `billing_basis` is an explicit local value (`chatgpt_credits`, `api_tokens`, or `unknown`) +preserved by pricing refreshes; it labels which estimate is applicable but never changes the +observed service tier. New costing APIs accept the row's observed service tier and never apply a +generic Fast multiplier to API USD because Priority premiums vary by model. + +Cost annotations remain additive and backward compatible. `estimated_cost_usd` uses the exact +observed API tier when a pricing-v2 rate exists, while `standard_cost_usd` and +`priority_cost_usd` expose bounded comparison scenarios. `pricing_service_tier` records the +table actually selected. Existing pricing-v1 files keep their current single-tier behavior. +Credit annotations retain `usage_credits` as the ChatGPT-equivalent estimate and +`standard_usage_credits` as its baseline; `fast_usage_credits` exposes the documented Fast +scenario when the model has a source-stamped multiplier. The dashboard uses `billing_basis` to +label these as applicable or equivalent scenarios rather than claiming both are actual spend. + +Fast credit multiplier metadata is part of the source-stamped Codex rate-card contract. Its +provenance is separate from `service_tier_source`: OTel proves which tier served the call, while +the rate card proves which numeric multiplier and effective source were used. Bundled and local +rate cards may define `fast_multipliers` by model family with `multiplier`, `source_url`, +`fetched_at`, and `confidence`. Row annotations expose that rate-card provenance through +`usage_credit_multiplier_source_url`, `usage_credit_multiplier_fetched_at`, and +`usage_credit_multiplier_confidence`; `usage_credit_multiplier_source` remains a bounded label. + +## Presentation semantics + +Dashboard and CSV rows preserve the exact service tier. Human labels distinguish Fast, +Priority, Default/Standard, Flex, Batch, another explicit tier, and Unknown. When billing basis +is unknown, the dashboard labels the tier as observed without claiming whether the call was +billed through ChatGPT credits or API tokens. + +## Reset and rotation semantics + +`rebuild-index` retains normalized OTel staging so tier enrichment can be reconstructed after +canonical usage rows are rebuilt. In contrast, confirmed `reset-db` clears both OTel staging +tables and their source cursors along with every other tracker-owned aggregate row. + +Incremental ingestion derives resume identity and final size from the open file descriptor. +If a path changes inode between discovery and open, or the descriptor identity changes during +the guarded read, ingestion resets/retries without saving an offset from one inode against +another. A concurrent rotation must never permanently skip the beginning of the replacement +file. ## Diagnostics and privacy @@ -217,9 +284,14 @@ Pricing and report tests cover: - Fast credit multipliers for GPT-5.6, GPT-5.5, and GPT-5.4. - Standard and unknown credit multiplier behavior. -- USD cost estimates remaining unchanged. +- Source-stamped Fast multiplier provenance separate from OTel tier provenance. +- Pricing-v1 compatibility and pricing-v2 all-tier parsing. +- Per-call Standard, Priority, Flex, and Batch API rate selection without a generic multiplier. +- Explicit `billing_basis` preservation and unknown-basis scenario labels. - Exact tier taking precedence over historical proxy labels. - Additive Calls, detail, export, and support-bundle contract behavior. +- Confirmed reset clearing OTel staging/cursors while rebuild retains staging. +- Rotation during an active read without cross-inode cursor persistence. ## Acceptance criteria @@ -228,8 +300,10 @@ Pricing and report tests cover: - Ambiguous or unmatched completions never alter usage calls. - Refresh, rotation, source replacement, and rebuild remain idempotent. - Credit estimates use documented Fast multipliers only for confirmed Fast calls. -- USD estimates do not change from service-tier enrichment. +- API USD estimates use the exact published tier table when that tier/model pair is available. +- ChatGPT credits and API USD remain separately labeled estimates, with explicit billing basis. - Historical unknown calls remain unknown. +- `reset-db --yes` clears OTel completion rows and source cursors. - No raw OTel content appears in SQLite, default reports, exports, support bundles, docs, or committed fixtures. - Focused parser, store, migration, pricing, report, and privacy tests pass before the full From 1deafa1eba1cc80c89a01b6a9028ac038bf0f409 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:00:42 -0400 Subject: [PATCH 15/24] docs: plan service tier billing fixes --- ...26-07-16-service-tier-billing-readiness.md | 577 ++++++++++++++++++ 1 file changed, 577 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-16-service-tier-billing-readiness.md diff --git a/docs/superpowers/plans/2026-07-16-service-tier-billing-readiness.md b/docs/superpowers/plans/2026-07-16-service-tier-billing-readiness.md new file mode 100644 index 00000000..1e0a66fa --- /dev/null +++ b/docs/superpowers/plans/2026-07-16-service-tier-billing-readiness.md @@ -0,0 +1,577 @@ +# Service Tier Billing Readiness Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make OTel service-tier enrichment release-ready by preserving the exact tier, selecting API prices per call, source-stamping ChatGPT Fast multipliers, correcting presentation, and closing reset and rotation safety gaps. + +**Architecture:** Keep `service_tier` as exact response evidence and `fast` as a derived speed classification. Pricing-v2 caches every published API tier while retaining the v1 `models` projection for compatibility; cost annotations expose exact-tier and comparison scenarios, while credit annotations use a source-stamped rate-card multiplier. OTel rebuild retention remains distinct from destructive database reset, and cursor identity comes from the open descriptor. + +**Tech Stack:** Python 3.10+, SQLite, pytest, TypeScript/React, Vitest, local JSON pricing/rate-card files. + +## Global Constraints + +- Never infer ChatGPT-versus-API authentication from OTel `service_tier`. +- Never apply ChatGPT Fast multipliers to API USD estimates. +- Preserve pricing-v1 files and stable existing output keys. +- Keep all new persisted and fixture data aggregate-only and synthetic. +- Write a failing test and observe the expected failure before each production change. +- Do not stage `.idea/`, `uv.lock`, local databases, OTel logs, or private data. + +--- + +### Task 1: Preserve Exact Response Tiers + +**Files:** +- Modify: `tests/parser/test_otel_parser.py` +- Modify: `src/codex_usage_tracker/parser/otel.py` +- Modify: `tests/store/test_otel_reconciliation.py` + +**Interfaces:** +- Produces: `OtelCompletion.service_tier` containing normalized upstream values such as `priority`, `fast`, `default`, `standard`, or `flex`. +- Produces: `OtelCompletion.fast` as the independent `1 | 0 | None` speed classification. + +- [ ] **Step 1: Write failing parser expectations** + +```python +@pytest.mark.parametrize( + ("raw_tier", "normalized_tier", "fast"), + [ + ("priority", "priority", 1), + ("fast", "fast", 1), + ("default", "default", 0), + ("standard", "standard", 0), + ("flex", "flex", 0), + ], +) +def test_explicit_tier_names_are_preserved(raw_tier, normalized_tier, fast): + completion = parse_otlp_json_line( + synthetic_otlp_line(attributes=completion_attributes(service_tier=raw_tier)) + ).completions[0] + assert (completion.service_tier, completion.fast) == (normalized_tier, fast) +``` + +- [ ] **Step 2: Run the parser test and verify RED** + +Run: `.venv/bin/python -m pytest tests/parser/test_otel_parser.py -q` +Expected: FAIL because `priority` currently becomes `fast` and `default` becomes `standard`. + +- [ ] **Step 3: Implement exact-tier normalization** + +```python +normalized = raw_tier.lower() +if normalized in {"priority", "fast"}: + return normalized, 1, "otel_response_completed", "exact" +return normalized, 0, "otel_response_completed", "exact" +``` + +Keep versioned omission as `service_tier="standard"`, `fast=0`, confidence `protocol`. + +- [ ] **Step 4: Update reconciliation fixtures and verify GREEN** + +Run: `.venv/bin/python -m pytest tests/parser/test_otel_parser.py tests/store/test_otel_reconciliation.py -q` +Expected: PASS. + +- [ ] **Step 5: Commit** + +```bash +git add -- tests/parser/test_otel_parser.py tests/store/test_otel_reconciliation.py src/codex_usage_tracker/parser/otel.py +git commit -m "fix: preserve exact OTel service tiers" +``` + +### Task 2: Cache All API Pricing Tiers Backward-Compatibly + +**Files:** +- Modify: `tests/pricing/test_pricing.py` +- Modify: `src/codex_usage_tracker/pricing/config.py` +- Modify: `src/codex_usage_tracker/pricing/openai.py` +- Modify: `src/codex_usage_tracker/pricing/api.py` + +**Interfaces:** +- Produces: `PRICING_SCHEMA = "codex-usage-tracker-pricing-v2"`. +- Produces: `PricingConfig.api_service_tiers: dict[str, dict[str, dict[str, float]]]`. +- Produces: `PricingConfig.billing_basis: str` with `unknown`, `chatgpt_credits`, or `api_tokens`. +- Produces: `PricingConfig.rates_for(model, service_tier=None)` and `pricing_tier_for(service_tier)`. +- Preserves: `PricingConfig.models`, `--tier`, `_source.tier`, aliases, estimates, pinning, and v1 loading. + +- [ ] **Step 1: Write failing v1/v2 config tests** + +```python +def test_pricing_v2_selects_rates_by_service_tier(tmp_path: Path) -> None: + path = tmp_path / "pricing.json" + path.write_text(json.dumps({ + "_schema": "codex-usage-tracker-pricing-v2", + "billing_basis": "api_tokens", + "models": {"gpt-5.6": { + "input_per_million": 5.0, + "cached_input_per_million": 0.5, + "output_per_million": 30.0, + }}, + "api_service_tiers": { + "standard": {"gpt-5.6": { + "input_per_million": 5.0, + "cached_input_per_million": 0.5, + "output_per_million": 30.0, + }}, + "priority": {"gpt-5.6": { + "input_per_million": 10.0, + "cached_input_per_million": 1.0, + "output_per_million": 60.0, + }}, + }, + }), encoding="utf-8") + config = load_pricing_config(path) + assert config.billing_basis == "api_tokens" + assert config.rates_for("gpt-5.6", service_tier="priority")["input_per_million"] == 10 + +def test_pricing_v1_ignores_row_tier_for_compatibility(tmp_path: Path) -> None: + config = load_v1_pricing(tmp_path, input_rate=5) + assert config.rates_for("gpt-5.6", service_tier="priority")["input_per_million"] == 5 +``` + +- [ ] **Step 2: Run config tests and verify RED** + +Run: `.venv/bin/python -m pytest tests/pricing/test_pricing.py -q` +Expected: FAIL because v2 tier maps and billing basis are unsupported. + +- [ ] **Step 3: Implement v2 loading and canonical tier selection** + +```python +def normalize_api_service_tier(value: object) -> str | None: + normalized = str(value or "").strip().lower() + return { + "fast": "priority", + "priority": "priority", + "default": "standard", + "standard": "standard", + "batch": "batch", + "flex": "flex", + }.get(normalized) + +def rates_for(self, model: object, service_tier: object | None = None): + tier = normalize_api_service_tier(service_tier) + if tier and tier in self.api_service_tiers: + return _rates_for_models(self.api_service_tiers[tier], self.aliases, model) + return _rates_for_models(self.models, self.aliases, model) +``` + +Invalid `billing_basis` makes the config invalid rather than guessing. + +- [ ] **Step 4: Write failing all-tier updater test** + +```python +def test_update_pricing_caches_every_api_tier(tmp_path: Path) -> None: + result = update_pricing_from_openai_docs( + tmp_path / "pricing.json", tier="batch", fetch_text=lambda _: ALL_TIER_FIXTURE + ) + raw = json.loads(result.path.read_text()) + assert set(raw["api_service_tiers"]) == {"standard", "batch", "flex", "priority"} + official_batch_models = { + model: rates + for model, rates in raw["models"].items() + if rates.get("estimated") is not True + } + assert official_batch_models == raw["api_service_tiers"]["batch"] + assert raw["_source"]["tier"] == "batch" +``` + +- [ ] **Step 5: Implement atomic all-tier parsing and cache writing** + +```python +def parse_all_openai_pricing_tiers(markdown: str): + return { + tier: parse_openai_pricing_markdown(markdown, tier=tier) + for tier in VALID_PRICING_TIERS + } +``` + +Fetch once, parse all four tiers before writing, keep `models` as the selected projection, add estimates only to that projection, and preserve the existing local `billing_basis` when refreshing. + +- [ ] **Step 6: Verify GREEN** + +Run: `.venv/bin/python -m pytest tests/pricing/test_pricing.py tests/cli/test_cli_module_entrypoints.py -q` +Expected: PASS. + +- [ ] **Step 7: Commit** + +```bash +git add -- tests/pricing/test_pricing.py src/codex_usage_tracker/pricing/config.py src/codex_usage_tracker/pricing/openai.py src/codex_usage_tracker/pricing/api.py +git commit -m "feat: cache all API pricing tiers" +``` + +### Task 3: Select Per-Call API Rates and Expose Scenarios + +**Files:** +- Modify: `tests/pricing/test_pricing.py` +- Modify: `src/codex_usage_tracker/pricing/costing.py` +- Modify: `src/codex_usage_tracker/core/schema.py` +- Modify: `frontend/dashboard/src/api/serviceTier.ts` +- Modify: `frontend/dashboard/src/api/types.ts` + +**Interfaces:** +- Adds row keys: `standard_cost_usd`, `priority_cost_usd`, `pricing_service_tier`, `billing_basis`, and `cost_semantics`. +- Preserves `estimated_cost_usd` as the API-equivalent estimate selected from the exact tier when available. + +- [ ] **Step 1: Write failing cost-selection tests** + +```python +def pricing_v2_config() -> PricingConfig: + standard = { + "input_per_million": 5.0, + "cached_input_per_million": 0.5, + "output_per_million": 30.0, + } + priority = { + "input_per_million": 10.0, + "cached_input_per_million": 1.0, + "output_per_million": 60.0, + } + return PricingConfig( + path=Path("/synthetic/pricing.json"), + models={"gpt-5.6": standard}, + loaded=True, + api_service_tiers={ + "standard": {"gpt-5.6": standard}, + "priority": {"gpt-5.6": priority}, + }, + billing_basis="unknown", + ) + +def cost_row(service_tier: str | None) -> dict[str, object]: + return { + "model": "gpt-5.6", + "input_tokens": 100, + "cached_input_tokens": 20, + "uncached_input_tokens": 80, + "output_tokens": 10, + "service_tier": service_tier, + } + +def test_v2_priority_row_uses_priority_table() -> None: + config = pricing_v2_config() + standard = estimate_cost_usd(cost_row(service_tier="standard"), config) + priority = estimate_cost_usd(cost_row(service_tier="priority"), config) + assert priority == pytest.approx(standard * 2) + +def test_cost_annotations_expose_standard_and_priority_scenarios() -> None: + annotated = annotate_rows_with_efficiency([cost_row(service_tier=None)], pricing_v2_config())[0] + assert annotated["standard_cost_usd"] is not None + assert annotated["priority_cost_usd"] is not None + assert annotated["billing_basis"] == "unknown" +``` + +- [ ] **Step 2: Verify RED** + +Run: `.venv/bin/python -m pytest tests/pricing/test_pricing.py -q` +Expected: FAIL because costing does not pass the row tier or emit scenarios. + +- [ ] **Step 3: Implement exact-tier and scenario costing** + +```python +rates = pricing.rates_for( + model if model is not None else row.get("model"), + service_tier=row.get("service_tier"), +) +copy["pricing_service_tier"] = pricing.pricing_tier_for(copy.get("service_tier")) +copy["standard_cost_usd"] = estimate_cost_usd_for_tier(copy, config, "standard") +copy["priority_cost_usd"] = estimate_cost_usd_for_tier(copy, config, "priority") +copy["billing_basis"] = config.billing_basis +copy["cost_semantics"] = "api_token_estimate" +``` + +- [ ] **Step 4: Verify GREEN and schema propagation** + +Run: `.venv/bin/python -m pytest tests/pricing/test_pricing.py tests/core/test_api_payloads.py tests/dashboard/test_dashboard_payload.py -q` +Expected: PASS. + +- [ ] **Step 5: Commit** + +```bash +git add -- tests/pricing/test_pricing.py tests/core/test_api_payloads.py tests/dashboard/test_dashboard_payload.py src/codex_usage_tracker/pricing/costing.py src/codex_usage_tracker/core/schema.py frontend/dashboard/src/api/serviceTier.ts frontend/dashboard/src/api/types.ts +git commit -m "feat: price calls by observed API tier" +``` + +### Task 4: Source-Stamp ChatGPT Fast Multipliers + +**Files:** +- Modify: `src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json` +- Modify: `src/codex_usage_tracker/pricing/allowance_rate_card.py` +- Modify: `src/codex_usage_tracker/pricing/allowance_config.py` +- Modify: `src/codex_usage_tracker/pricing/fast_tier.py` +- Modify: `src/codex_usage_tracker/pricing/allowance_usage.py` +- Modify: `tests/pricing/test_allowance.py` +- Modify: `tests/pricing/test_rate_card.py` + +**Interfaces:** +- Produces: `FastMultiplierMatch(multiplier, model_family, source_url, fetched_at, confidence)`. +- Adds row keys: `fast_usage_credits`, `usage_credit_multiplier_source_url`, `usage_credit_multiplier_fetched_at`, and `usage_credit_multiplier_confidence`. +- Allows local `allowance.json` `fast_multipliers` entries to override bundled entries with `user_override` confidence. + +- [ ] **Step 1: Write failing rate-card and annotation tests** + +```python +def test_fast_multiplier_provenance_comes_from_rate_card() -> None: + config = replace( + _synthetic_allowance_config(), + fast_multipliers={ + "gpt-5.6": FastMultiplierRate( + multiplier=2.5, + source_name="OpenAI Codex Fast mode docs", + source_url="https://learn.chatgpt.com/docs/agent-configuration/speed", + fetched_at="2026-07-16", + confidence="exact", + ) + }, + ) + row = annotate_rows_with_allowance( + [_credit_row(model="gpt-5.6", fast=1, service_tier="priority")], config + )[0] + assert row["usage_credit_multiplier"] == 2.5 + assert row["usage_credit_multiplier_source"] == "OpenAI Codex Fast mode docs" + assert row["usage_credit_multiplier_source_url"].endswith("/agent-configuration/speed") + assert row["usage_credit_multiplier_confidence"] == "exact" + assert row["service_tier_source"] == "otel_response_completed" + +def test_local_fast_multiplier_override_is_source_stamped() -> None: + config = load_allowance_config(write_allowance_override( + fast_multipliers={ + "gpt-5.6": { + "multiplier": 3.0, + "source_name": "Synthetic override", + "source_url": "https://example.invalid/synthetic-fast-rate", + "fetched_at": "2026-07-16", + } + } + )) + assert config.fast_multipliers["gpt-5.6"].confidence == "user_override" +``` + +Add `write_allowance_override()` as a local test helper that writes the shown dictionary beneath +the existing allowance template's `fast_multipliers` key to `tmp_path / "allowance.json"` and +returns that path. + +- [ ] **Step 2: Verify RED** + +Run: `.venv/bin/python -m pytest tests/pricing/test_allowance.py tests/pricing/test_rate_card.py -q` +Expected: FAIL because multipliers are hard-coded and provenance is conflated with OTel. + +- [ ] **Step 3: Move multipliers into the source-stamped rate card** + +```json +"fast_multipliers": { + "gpt-5.6": { + "multiplier": 2.5, + "source_name": "OpenAI Codex Fast mode docs", + "source_url": "https://learn.chatgpt.com/docs/agent-configuration/speed", + "fetched_at": "2026-07-16", + "confidence": "exact" + } +} +``` + +Add equivalent GPT-5.5 and GPT-5.4 entries. Parse only finite multipliers `>= 1.0`; reject malformed local overrides without discarding the valid bundled card. + +- [ ] **Step 4: Resolve multiplier by model family and annotate provenance** + +`fast_tier.py` performs family matching against parsed configuration rather than module constants. `allowance_usage.py` computes Standard and hypothetical Fast scenarios, applies the Fast scenario only when `fast == 1`, and keeps OTel tier evidence in the existing service-tier fields. + +- [ ] **Step 5: Verify GREEN** + +Run: `.venv/bin/python -m pytest tests/pricing/test_allowance.py tests/pricing/test_rate_card.py tests/dashboard/test_dashboard_payload.py -q` +Expected: PASS. + +- [ ] **Step 6: Commit** + +```bash +git add -- src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json src/codex_usage_tracker/pricing/allowance_rate_card.py src/codex_usage_tracker/pricing/allowance_config.py src/codex_usage_tracker/pricing/fast_tier.py src/codex_usage_tracker/pricing/allowance_usage.py tests/pricing/test_allowance.py tests/pricing/test_rate_card.py tests/dashboard/test_dashboard_payload.py +git commit -m "feat: source stamp Fast credit multipliers" +``` + +### Task 5: Correct Dashboard Tier Labels + +**Files:** +- Modify: `frontend/dashboard/src/features/calls/serviceTier.test.ts` +- Modify: `frontend/dashboard/src/features/shared/callPresentation.ts` +- Modify: `frontend/dashboard/src/features/shared/tables.test.ts` +- Modify: `frontend/dashboard/src/features/shared/tables.tsx` + +**Interfaces:** +- Produces: `serviceTierLabel()` labels derived from `serviceTier` first and `fast` only as fallback. +- Produces: tier detail that reports exact tier and confidence without claiming billing path. + +- [ ] **Step 1: Write failing presentation tests** + +```typescript +it.each([ + ['priority', true, 'Priority / Fast'], + ['fast', true, 'Fast'], + ['default', false, 'Default / Standard'], + ['standard', false, 'Standard'], + ['flex', false, 'Flex'], + ['batch', false, 'Batch'], +])('labels exact service tier %s', (serviceTier, fast, expected) => { + expect(serviceTierLabel({ ...baseCall, serviceTier, fast })).toBe(expected); +}); +``` + +- [ ] **Step 2: Verify RED** + +Run: `npm test -- --run frontend/dashboard/src/features/calls/serviceTier.test.ts` +Expected: FAIL because every `fast=false` row is currently Standard. + +- [ ] **Step 3: Implement exact-tier labels and details** + +Normalize the tier string, map known values explicitly, title-case bounded unknown values, and use `fast` only when no exact tier exists. Include `serviceTier` in `ServiceTierInput`. + +- [ ] **Step 4: Verify GREEN** + +Run: `npm test -- --run frontend/dashboard/src/features/calls/serviceTier.test.ts frontend/dashboard/src/features/shared/tables.test.ts` +Expected: PASS. + +- [ ] **Step 5: Commit** + +```bash +git add -- frontend/dashboard/src/features/calls/serviceTier.test.ts frontend/dashboard/src/features/shared/callPresentation.ts frontend/dashboard/src/features/shared/tables.test.ts frontend/dashboard/src/features/shared/tables.tsx +git commit -m "fix: label exact service tiers" +``` + +### Task 6: Make Reset Destructive and Rotation Cursor-Safe + +**Files:** +- Modify: `tests/store/test_source_records.py` +- Modify: `src/codex_usage_tracker/store/api.py` +- Modify: `tests/store/test_otel_ingest.py` +- Modify: `src/codex_usage_tracker/store/otel_ingest.py` + +**Interfaces:** +- `reset_usage_database()` deletes `otel_completion_events` and `otel_completion_sources`. +- OTel cursors persist descriptor identity and never mix offsets across inodes. + +- [ ] **Step 1: Write failing reset test** + +```python +def test_reset_usage_database_clears_otel_staging_and_cursors(tmp_path: Path) -> None: + db_path = tmp_path / "usage.sqlite3" + otel_dir = write_otel_directory( + tmp_path, + "synthetic-reset", + (120, 40, 30, 10), + ) + with connect(db_path) as conn: + init_db(conn) + ingest_otel_completion_files(conn, otel_dir) + reset_usage_database(db_path) + with connect(db_path) as conn: + assert conn.execute("SELECT COUNT(*) FROM otel_completion_events").fetchone()[0] == 0 + assert conn.execute("SELECT COUNT(*) FROM otel_completion_sources").fetchone()[0] == 0 +``` + +- [ ] **Step 2: Verify RED, implement deletion, and verify GREEN** + +Run: `.venv/bin/python -m pytest tests/store/test_source_records.py -q` +Expected before implementation: FAIL with retained rows. Add both fixed-table `DELETE` statements and rerun for PASS. + +- [ ] **Step 3: Write failing concurrent-rotation test** + +Use a small injected `open_file`/`after_open` seam in `ingest_otel_completion_files` so the test can replace the path after the initial discovery stat but before reading. Assert the replacement file is read from byte zero and its cursor matches its own `fstat()` identity. + +- [ ] **Step 4: Verify RED** + +Run: `.venv/bin/python -m pytest tests/store/test_otel_ingest.py -q` +Expected: FAIL because path stats and descriptor reads can refer to different inodes. + +- [ ] **Step 5: Implement descriptor-based cursor safety** + +Open first, call `os.fstat(handle.fileno())` for resume identity, read complete lines, call `os.fstat()` again, and persist only descriptor-derived state. If descriptor identity changes unexpectedly, discard the candidate cursor and retry from zero once; never combine `Path.stat()` identity with an offset read from another descriptor. + +- [ ] **Step 6: Verify GREEN and commit** + +Run: `.venv/bin/python -m pytest tests/store/test_source_records.py tests/store/test_otel_ingest.py tests/store/test_otel_refresh.py -q` +Expected: PASS. + +```bash +git add -- tests/store/test_source_records.py tests/store/test_otel_ingest.py src/codex_usage_tracker/store/api.py src/codex_usage_tracker/store/otel_ingest.py +git commit -m "fix: clear OTel state and harden rotation" +``` + +### Task 7: Update Contracts, Documentation, and Generated Dashboard Assets + +**Files:** +- Modify: `docs/pricing-and-credits.md` +- Modify: `docs/database-schema.md` +- Modify: `docs/privacy.md` +- Modify: `docs/dashboard-guide.md` +- Modify: `docs/cli-json-schemas.md` +- Modify: `CHANGELOG.md` +- Modify: generated files under `src/codex_usage_tracker/plugin_data/dashboard/react/assets/` +- Modify: affected API/dashboard/report tests. + +**Interfaces:** +- Documents pricing-v2, exact-tier semantics, billing basis, scenario fields, reset/rebuild distinction, and source-stamped multipliers. +- Generated dashboard assets match the reviewed TypeScript source. + +- [ ] **Step 1: Update contract tests before docs/assets** + +Add assertions for exact `priority`, pricing scenario fields, multiplier provenance, and billing-basis labels to the existing API payload, CSV, report, and dashboard tests. Run them and observe failures where propagation is missing. + +- [ ] **Step 2: Complete additive propagation and documentation** + +Keep existing stable keys. Explain that `usage_credits` is ChatGPT-equivalent, `estimated_cost_usd` is API-token-equivalent, `billing_basis` identifies applicability, and unknown basis exposes scenarios without claiming actual spend. + +- [ ] **Step 3: Build dashboard assets and run focused gates** + +Run the repository's existing frontend build/governance commands from `package.json`, followed by: + +```bash +.venv/bin/python -m pytest tests/core/test_api_payloads.py tests/dashboard/test_dashboard_payload.py tests/reports/test_support.py -q +python scripts/check_release.py +git diff --check +``` + +Expected: all PASS and generated assets match source. + +- [ ] **Step 4: Commit** + +```bash +git add -- CHANGELOG.md docs/pricing-and-credits.md docs/database-schema.md docs/privacy.md docs/dashboard-guide.md docs/cli-json-schemas.md frontend/dashboard/src src/codex_usage_tracker/plugin_data/dashboard/react/assets tests +git commit -m "docs: explain tier-aware billing estimates" +``` + +### Task 8: Final Verification and Review + +**Files:** +- No intended production edits; fix only verified failures within this feature scope. + +**Interfaces:** +- Produces release-readiness evidence for the complete branch. + +- [ ] **Step 1: Run focused Python and frontend suites** + +```bash +python -m pytest tests/parser/test_otel_parser.py tests/store/test_otel_ingest.py tests/store/test_otel_reconciliation.py tests/store/test_otel_refresh.py tests/pricing/test_allowance.py tests/pricing/test_pricing.py tests/store/test_source_records.py -q +``` + +Run the frontend service-tier and table tests plus every dashboard test affected by generated assets. + +- [ ] **Step 2: Run the full repository gates** + +```bash +python -m ruff check . +python -m mypy +python -m pytest +python -m pytest --cov=codex_usage_tracker --cov-report=term-missing +python -m compileall src +for file in src/codex_usage_tracker/plugin_data/dashboard/dashboard*.js; do node --check "$file"; done +python scripts/check_release.py +git diff --check +python -m build +python -m twine check dist/* +python scripts/check_release.py --dist +``` + +- [ ] **Step 3: Review status, diff, and privacy** + +Confirm only intended tracked files changed, no local logs/database/config/private values entered the diff, `.idea/` and `uv.lock` remain untracked, and the exact-tier/billing tests prove the reviewed blockers are closed. + +- [ ] **Step 4: Report readiness** + +Provide commits, validation counts, skipped checks with reasons, remaining risks, and whether the branch is ready to push/open as a PR. Do not push or open a PR unless requested. From e36f1ebc9976774594acf80d0eb10b72649c2aef Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:01:39 -0400 Subject: [PATCH 16/24] fix: preserve exact OTel service tiers --- src/codex_usage_tracker/parser/otel.py | 4 +--- tests/parser/test_otel_parser.py | 10 +++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/codex_usage_tracker/parser/otel.py b/src/codex_usage_tracker/parser/otel.py index 89668ddc..1e9af711 100644 --- a/src/codex_usage_tracker/parser/otel.py +++ b/src/codex_usage_tracker/parser/otel.py @@ -296,9 +296,7 @@ def _normalize_tier( return None, None, None, None normalized = raw_tier.lower() if normalized in {"priority", "fast"}: - return "fast", 1, "otel_response_completed", "exact" - if normalized in {"default", "standard"}: - return "standard", 0, "otel_response_completed", "exact" + return normalized, 1, "otel_response_completed", "exact" return normalized, 0, "otel_response_completed", "exact" parsed_version = _parse_version(app_version) diff --git a/tests/parser/test_otel_parser.py b/tests/parser/test_otel_parser.py index 46ed5e82..df801ab4 100644 --- a/tests/parser/test_otel_parser.py +++ b/tests/parser/test_otel_parser.py @@ -32,7 +32,7 @@ def test_parse_otlp_batch_extracts_only_completion_allowlist() -> None: assert len(result.completions) == 1 completion = result.completions[0] assert completion.conversation_id == "synthetic-conversation" - assert completion.service_tier == "fast" + assert completion.service_tier == "priority" assert completion.fast == 1 assert completion.service_tier_source == "otel_response_completed" assert completion.service_tier_confidence == "exact" @@ -74,13 +74,17 @@ def test_missing_service_tier_uses_versioned_protocol_semantics( @pytest.mark.parametrize( ("raw_tier", "normalized_tier", "fast"), [ + ("priority", "priority", 1), ("fast", "fast", 1), - ("default", "standard", 0), + ("default", "default", 0), ("standard", "standard", 0), ("flex", "flex", 0), + ("batch", "batch", 0), ], ) -def test_explicit_tier_aliases(raw_tier: str, normalized_tier: str, fast: int) -> None: +def test_explicit_tier_names_are_preserved( + raw_tier: str, normalized_tier: str, fast: int +) -> None: attributes = completion_attributes(service_tier=raw_tier) completion = parse_otlp_json_line( From 236f35930a786fe5324929ce852c60723d37f72d Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:03:51 -0400 Subject: [PATCH 17/24] feat: cache all API pricing tiers --- src/codex_usage_tracker/pricing/api.py | 2 + src/codex_usage_tracker/pricing/config.py | 118 +++++++++++++++++++--- src/codex_usage_tracker/pricing/openai.py | 34 ++++++- tests/pricing/test_pricing.py | 98 ++++++++++++++++++ 4 files changed, 237 insertions(+), 15 deletions(-) diff --git a/src/codex_usage_tracker/pricing/api.py b/src/codex_usage_tracker/pricing/api.py index 75329594..bca3964a 100644 --- a/src/codex_usage_tracker/pricing/api.py +++ b/src/codex_usage_tracker/pricing/api.py @@ -29,6 +29,7 @@ VALID_PRICING_TIERS, PricingParseError, PricingUpdateResult, + parse_all_openai_pricing_tiers, parse_openai_latest_model_id, parse_openai_pricing_markdown, update_pricing_from_openai_docs, @@ -52,6 +53,7 @@ "estimate_cache_savings_usd", "estimate_cost_usd", "load_pricing_config", + "parse_all_openai_pricing_tiers", "parse_openai_latest_model_id", "parse_openai_pricing_markdown", "pin_pricing_snapshot", diff --git a/src/codex_usage_tracker/pricing/config.py b/src/codex_usage_tracker/pricing/config.py index f731cce9..12904c20 100644 --- a/src/codex_usage_tracker/pricing/config.py +++ b/src/codex_usage_tracker/pricing/config.py @@ -10,13 +10,24 @@ from codex_usage_tracker.core.paths import DEFAULT_PRICING_PATH -PRICING_SCHEMA = "codex-usage-tracker-pricing-v1" +PRICING_SCHEMA = "codex-usage-tracker-pricing-v2" +BILLING_BASES = ("unknown", "chatgpt_credits", "api_tokens") +API_SERVICE_TIER_ALIASES = { + "fast": "priority", + "priority": "priority", + "default": "standard", + "standard": "standard", + "batch": "batch", + "flex": "flex", +} PRICING_TEMPLATE = { "_comment": ( "Fill in current prices in USD per 1 million tokens. The tracker does " "not fetch pricing during normal reports. Prefer update-pricing when " "you want to cache current OpenAI-published rates locally." ), + "_schema": PRICING_SCHEMA, + "billing_basis": "unknown", "models": { "replace-with-model-name": { "input_per_million": 0.0, @@ -41,17 +52,24 @@ class PricingConfig: estimated_models: set[str] | None = None source: dict[str, Any] | None = None error: str | None = None - - def rates_for(self, model: object) -> dict[str, float] | None: - if not isinstance(model, str) or not model: - return None - direct = self.models.get(model) - if direct is not None: - return direct - alias_target = (self.aliases or {}).get(model) - if not alias_target: - return None - return self.models.get(alias_target) + api_service_tiers: dict[str, dict[str, dict[str, float]]] | None = None + billing_basis: str = "unknown" + + def rates_for( + self, model: object, *, service_tier: object | None = None + ) -> dict[str, float] | None: + normalized_tier = normalize_api_service_tier(service_tier) + tier_models = (self.api_service_tiers or {}).get(normalized_tier or "") + if tier_models is not None: + return _rates_for_models(tier_models, self.aliases, model) + return _rates_for_models(self.models, self.aliases, model) + + def pricing_tier_for(self, service_tier: object | None) -> str | None: + normalized = normalize_api_service_tier(service_tier) + if normalized and normalized in (self.api_service_tiers or {}): + return normalized + source_tier = normalize_api_service_tier((self.source or {}).get("tier")) + return source_tier if source_tier else None def priced_as(self, model: object) -> str | None: if not isinstance(model, str) or not model: @@ -76,6 +94,8 @@ def load_pricing_config(path: Path = DEFAULT_PRICING_PATH) -> PricingConfig: try: raw = json.loads(path.read_text(encoding="utf-8")) models = parse_models(raw) + api_service_tiers = parse_api_service_tiers(raw) + billing_basis = parse_billing_basis(raw) except (OSError, ValueError, TypeError, json.JSONDecodeError) as exc: return PricingConfig(path=path, models={}, loaded=False, error=str(exc)) source = raw.get("_source") if isinstance(raw, dict) else None @@ -87,6 +107,8 @@ def load_pricing_config(path: Path = DEFAULT_PRICING_PATH) -> PricingConfig: aliases=aliases, estimated_models=parse_estimated_models(raw), source=source if isinstance(source, dict) else None, + api_service_tiers=api_service_tiers, + billing_basis=billing_basis, ) @@ -147,6 +169,69 @@ def parse_models(raw: object) -> dict[str, dict[str, float]]: return models +def parse_api_service_tiers( + raw: object, +) -> dict[str, dict[str, dict[str, float]]]: + if not isinstance(raw, dict): + return {} + tier_payload = raw.get("api_service_tiers") + if tier_payload is None: + return {} + if not isinstance(tier_payload, dict): + raise ValueError("pricing config 'api_service_tiers' must be an object") + parsed: dict[str, dict[str, dict[str, float]]] = {} + for raw_tier, models in tier_payload.items(): + tier = normalize_api_service_tier(raw_tier) + if tier is None or not isinstance(models, dict): + raise ValueError(f"invalid API service tier pricing entry: {raw_tier!r}") + parsed[tier] = _parse_model_payload(models) + return parsed + + +def parse_billing_basis(raw: object) -> str: + if not isinstance(raw, dict): + return "unknown" + value = raw.get("billing_basis", "unknown") + if not isinstance(value, str) or value not in BILLING_BASES: + raise ValueError( + f"unknown billing_basis {value!r}; expected one of {', '.join(BILLING_BASES)}" + ) + return value + + +def normalize_api_service_tier(value: object) -> str | None: + if not isinstance(value, str): + return None + return API_SERVICE_TIER_ALIASES.get(value.strip().lower()) + + +def _rates_for_models( + models: dict[str, dict[str, float]], + aliases: dict[str, str] | None, + model: object, +) -> dict[str, float] | None: + if not isinstance(model, str) or not model: + return None + direct = models.get(model) + if direct is not None: + return direct + alias_target = (aliases or {}).get(model) + return models.get(alias_target) if alias_target else None + + +def _parse_model_payload( + model_payload: dict[object, object], +) -> dict[str, dict[str, float]]: + models: dict[str, dict[str, float]] = {} + for model, rates in model_payload.items(): + if not _valid_model_name(model): + continue + parsed_rates = _parsed_model_rates(model, rates) + if parsed_rates is not None: + models[model] = parsed_rates + return models + + def _required_model_payload(raw: object) -> dict[object, object]: if not isinstance(raw, dict): raise ValueError("pricing config must be a JSON object") @@ -240,6 +325,15 @@ def load_existing_aliases(path: Path) -> dict[str, str]: return {} +def load_existing_billing_basis(path: Path) -> str: + if not path.exists(): + return "unknown" + try: + return parse_billing_basis(json.loads(path.read_text(encoding="utf-8"))) + except (OSError, ValueError, TypeError, json.JSONDecodeError): + return "unknown" + + def _required_rate(rates: dict[str, Any], key: str, model: str) -> float: value = _optional_rate(rates, key) if value is None: diff --git a/src/codex_usage_tracker/pricing/openai.py b/src/codex_usage_tracker/pricing/openai.py index dfc349dd..c0b0cc17 100644 --- a/src/codex_usage_tracker/pricing/openai.py +++ b/src/codex_usage_tracker/pricing/openai.py @@ -16,7 +16,11 @@ from codex_usage_tracker import __version__ from codex_usage_tracker.core.paths import DEFAULT_PRICING_PATH -from codex_usage_tracker.pricing.config import PRICING_SCHEMA, load_existing_aliases +from codex_usage_tracker.pricing.config import ( + PRICING_SCHEMA, + load_existing_aliases, + load_existing_billing_basis, +) from codex_usage_tracker.pricing.estimates import ESTIMATED_MODEL_PRICES, estimated_model_prices OPENAI_PRICING_MD_URL = "https://developers.openai.com/api/docs/pricing.md" @@ -65,7 +69,8 @@ def update_pricing_from_openai_docs( ) fetcher = fetch_text or _fetch_text text = fetcher(source_url) - parsed_models = parse_openai_pricing_markdown(text, tier=tier) + parsed_tiers = parse_all_openai_pricing_tiers(text) + parsed_models = parsed_tiers[tier] if not parsed_models: raise PricingParseError( f"pricing source schema changed: no text-token pricing rows were parsed " @@ -74,12 +79,18 @@ def update_pricing_from_openai_docs( models: dict[str, dict[str, Any]] = { model: dict(rates) for model, rates in parsed_models.items() } + available_official_models = { + model for tier_models in parsed_tiers.values() for model in tier_models + } aliases = { **{ - alias: target for alias, target in _OFFICIAL_PRICING_ALIASES.items() if target in models + alias: target + for alias, target in _OFFICIAL_PRICING_ALIASES.items() + if target in available_official_models }, **load_existing_aliases(path), } + billing_basis = load_existing_billing_basis(path) estimated_model_count = 0 if include_estimates: models.update(estimated_model_prices()) @@ -92,12 +103,18 @@ def update_pricing_from_openai_docs( "name": "OpenAI Developers pricing docs", "url": source_url, "tier": tier, + "tiers": list(VALID_PRICING_TIERS), + "tier_model_counts": { + name: len(tier_models) for name, tier_models in parsed_tiers.items() + }, "fetched_at": fetched_at, "model_count": len(models), "official_model_count": len(models) - estimated_model_count, "estimated_model_count": estimated_model_count, }, + "billing_basis": billing_basis, "models": models, + "api_service_tiers": parsed_tiers, } if aliases: payload["aliases"] = aliases @@ -159,6 +176,17 @@ def parse_openai_pricing_markdown( return models +def parse_all_openai_pricing_tiers( + markdown: str, +) -> dict[str, dict[str, dict[str, float]]]: + """Parse every published API service-tier table from one source document.""" + + return { + tier: parse_openai_pricing_markdown(markdown, tier=tier) + for tier in VALID_PRICING_TIERS + } + + def parse_openai_latest_model_id(markdown: str) -> str: """Return the canonical latest model ID from OpenAI's model guide front matter.""" diff --git a/tests/pricing/test_pricing.py b/tests/pricing/test_pricing.py index 74f9a01e..848c6e72 100644 --- a/tests/pricing/test_pricing.py +++ b/tests/pricing/test_pricing.py @@ -43,6 +43,21 @@ ["gpt-5.5 (<272K context length)", 2.5, 0.25, 15], ]} /> + + """ @@ -68,6 +83,60 @@ def test_service_tier_does_not_change_estimated_cost_usd() -> None: assert fast == standard +def test_pricing_v2_selects_rates_by_service_tier(tmp_path: Path) -> None: + pricing_path = tmp_path / "pricing.json" + standard = { + "input_per_million": 5.0, + "cached_input_per_million": 0.5, + "output_per_million": 30.0, + } + priority = { + "input_per_million": 10.0, + "cached_input_per_million": 1.0, + "output_per_million": 60.0, + } + pricing_path.write_text( + json.dumps( + { + "_schema": "codex-usage-tracker-pricing-v2", + "billing_basis": "api_tokens", + "models": {"gpt-5.6-sol": standard}, + "api_service_tiers": { + "standard": {"gpt-5.6-sol": standard}, + "priority": {"gpt-5.6-sol": priority}, + }, + "aliases": {"gpt-5.6": "gpt-5.6-sol"}, + } + ), + encoding="utf-8", + ) + + config = load_pricing_config(pricing_path) + + assert config.billing_basis == "api_tokens" + assert config.rates_for("gpt-5.6", service_tier="priority") == priority + assert config.rates_for("gpt-5.6", service_tier="fast") == priority + assert config.rates_for("gpt-5.6", service_tier="default") == standard + + +def test_pricing_v1_keeps_selected_projection_for_every_row_tier(tmp_path: Path) -> None: + pricing_path = tmp_path / "pricing.json" + selected = { + "input_per_million": 5.0, + "cached_input_per_million": 0.5, + "output_per_million": 30.0, + } + pricing_path.write_text( + json.dumps({"_schema": "codex-usage-tracker-pricing-v1", "models": {"gpt": selected}}), + encoding="utf-8", + ) + + config = load_pricing_config(pricing_path) + + assert config.rates_for("gpt", service_tier="priority") == selected + assert config.billing_basis == "unknown" + + def _credit_row_for_cost( *, fast: int | None, service_tier: str | None ) -> dict[str, object]: @@ -133,6 +202,14 @@ def test_parse_openai_pricing_markdown_uses_requested_tier() -> None: } +def test_parse_all_openai_pricing_tiers() -> None: + tiers = pricing_openai.parse_all_openai_pricing_tiers(OPENAI_PRICING_FIXTURE) + + assert set(tiers) == {"standard", "batch", "flex", "priority"} + assert tiers["standard"]["gpt-5.6-sol"]["input_per_million"] == 5 + assert tiers["priority"]["gpt-5.6-sol"]["input_per_million"] == 10 + + def test_parse_openai_pricing_markdown_does_not_invent_priority_long_context_rates() -> None: source = ( OPENAI_PRICING_FIXTURE @@ -209,6 +286,10 @@ def test_update_pricing_from_openai_docs_writes_source_metadata(tmp_path: Path) assert raw["_source"]["url"] == OPENAI_PRICING_MD_URL assert raw["_source"]["tier"] == "standard" assert raw["_source"]["estimated_model_count"] == 2 + assert raw["_source"]["tiers"] == ["standard", "batch", "flex", "priority"] + assert set(raw["api_service_tiers"]) == {"standard", "batch", "flex", "priority"} + assert raw["api_service_tiers"]["priority"]["gpt-5.6-sol"]["input_per_million"] == 10 + assert raw["billing_basis"] == "unknown" assert raw["aliases"]["gpt-5.6"] == "gpt-5.6-sol" assert raw["models"]["codex-auto-review"] == ESTIMATED_MODEL_PRICES["codex-auto-review"] assert raw["models"]["gpt-5.3-codex-spark"] == ESTIMATED_MODEL_PRICES["gpt-5.3-codex-spark"] @@ -223,6 +304,23 @@ def test_update_pricing_from_openai_docs_writes_source_metadata(tmp_path: Path) assert config.is_estimated_model("gpt-5.3-codex-spark") +def test_update_pricing_preserves_existing_billing_basis(tmp_path: Path) -> None: + pricing_path = tmp_path / "pricing.json" + pricing_path.write_text( + json.dumps({"billing_basis": "chatgpt_credits", "models": {}}), + encoding="utf-8", + ) + + update_pricing_from_openai_docs( + pricing_path, + fetch_text=lambda url: OPENAI_PRICING_FIXTURE, + include_estimates=False, + ) + + raw = json.loads(pricing_path.read_text(encoding="utf-8")) + assert raw["billing_basis"] == "chatgpt_credits" + + def test_update_pricing_from_openai_docs_can_skip_estimates(tmp_path: Path) -> None: pricing_path = tmp_path / "pricing.json" From 5592fb82d121c4d2bc95bc8b0e094a5f8f1a2c19 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:05:49 -0400 Subject: [PATCH 18/24] feat: price calls by observed API tier --- src/codex_usage_tracker/pricing/costing.py | 36 +++++++++++++++- tests/pricing/test_pricing.py | 50 ++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/codex_usage_tracker/pricing/costing.py b/src/codex_usage_tracker/pricing/costing.py index 8fdcc0e0..1d4e1bc3 100644 --- a/src/codex_usage_tracker/pricing/costing.py +++ b/src/codex_usage_tracker/pricing/costing.py @@ -96,6 +96,17 @@ def annotate_rows_with_efficiency( savings = estimate_cache_savings_usd(copy, config, model=model) copy["estimated_cost_usd"] = cost copy["estimated_cache_savings_usd"] = savings + copy["standard_cost_usd"] = _estimate_cost_usd_for_tier( + copy, config, model=model, service_tier="standard" + ) + copy["priority_cost_usd"] = _estimate_cost_usd_for_tier( + copy, config, model=model, service_tier="priority" + ) + copy["pricing_service_tier"] = config.pricing_tier_for( + copy.get("service_tier") + ) + copy["billing_basis"] = config.billing_basis + copy["cost_semantics"] = "api_token_estimate" copy["pricing_model"] = config.priced_as(model) copy["pricing_estimated"] = config.is_estimated_model(model) copy["efficiency_flags"] = efficiency_flags(copy) @@ -113,7 +124,25 @@ def estimate_cost_usd( ) -> float | None: """Estimate call cost from aggregate tokens and local model rates.""" - rates = pricing.rates_for(model if model is not None else row.get("model")) + return _estimate_cost_usd_for_tier( + row, + pricing, + model=model, + service_tier=row.get("service_tier"), + ) + + +def _estimate_cost_usd_for_tier( + row: dict[str, Any], + pricing: PricingConfig, + *, + model: object | None, + service_tier: object | None, +) -> float | None: + rates = pricing.rates_for( + model if model is not None else row.get("model"), + service_tier=service_tier, + ) if not rates: return None @@ -144,7 +173,10 @@ def estimate_cache_savings_usd( ) -> float | None: """Estimate local cache savings when cached input has a lower configured rate.""" - rates = pricing.rates_for(model if model is not None else row.get("model")) + rates = pricing.rates_for( + model if model is not None else row.get("model"), + service_tier=row.get("service_tier"), + ) if not rates: return None input_rate = rates.get("input_per_million") diff --git a/tests/pricing/test_pricing.py b/tests/pricing/test_pricing.py index 848c6e72..ea441304 100644 --- a/tests/pricing/test_pricing.py +++ b/tests/pricing/test_pricing.py @@ -152,6 +152,56 @@ def _credit_row_for_cost( } +def _tiered_pricing_config(*, billing_basis: str = "unknown") -> PricingConfig: + standard = { + "input_per_million": 5.0, + "cached_input_per_million": 0.5, + "output_per_million": 30.0, + } + priority = { + "input_per_million": 10.0, + "cached_input_per_million": 1.0, + "output_per_million": 60.0, + } + return PricingConfig( + path=Path("/synthetic/pricing-v2.json"), + models={"gpt-5.6": standard}, + loaded=True, + api_service_tiers={ + "standard": {"gpt-5.6": standard}, + "priority": {"gpt-5.6": priority}, + }, + billing_basis=billing_basis, + ) + + +def test_pricing_v2_service_tier_selects_api_cost() -> None: + pricing = _tiered_pricing_config(billing_basis="api_tokens") + standard = estimate_cost_usd( + _credit_row_for_cost(fast=0, service_tier="standard"), pricing + ) + priority = estimate_cost_usd( + _credit_row_for_cost(fast=1, service_tier="priority"), pricing + ) + + assert priority == pytest.approx(float(standard) * 2) + + +def test_efficiency_annotation_exposes_tier_cost_scenarios() -> None: + annotated = annotate_rows_with_efficiency( + [_credit_row_for_cost(fast=1, service_tier="priority")], + _tiered_pricing_config(), + )[0] + + assert annotated["estimated_cost_usd"] == annotated["priority_cost_usd"] + assert annotated["priority_cost_usd"] == pytest.approx( + annotated["standard_cost_usd"] * 2 + ) + assert annotated["pricing_service_tier"] == "priority" + assert annotated["billing_basis"] == "unknown" + assert annotated["cost_semantics"] == "api_token_estimate" + + def test_pricing_fetch_rejects_non_https_sources() -> None: with pytest.raises(ValueError, match="must use HTTPS"): pricing_openai._fetch_text("file:///tmp/pricing.md") From 03150f5b0448718acbc01a2957e31f4f16ccdeb3 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:10:33 -0400 Subject: [PATCH 19/24] feat: source stamp Fast credit multipliers --- .../rate_cards/codex-credit-rates.json | 23 +++++ src/codex_usage_tracker/pricing/allowance.py | 4 + .../pricing/allowance_config.py | 30 ++++++- .../pricing/allowance_rate_card.py | 67 +++++++++++++++ .../pricing/allowance_usage.py | 31 ++++++- src/codex_usage_tracker/pricing/fast_tier.py | 85 +++++++++++++++---- tests/pricing/test_allowance.py | 48 ++++++++++- tests/pricing/test_rate_card.py | 83 ++++++++++++++++++ 8 files changed, 350 insertions(+), 21 deletions(-) create mode 100644 tests/pricing/test_rate_card.py diff --git a/src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json b/src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json index 85768797..b35d41de 100644 --- a/src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json +++ b/src/codex_usage_tracker/plugin_data/rate_cards/codex-credit-rates.json @@ -83,6 +83,29 @@ "tier": "standard" } }, + "fast_multipliers": { + "gpt-5.6": { + "multiplier": 2.5, + "source_name": "OpenAI Codex Fast mode docs", + "source_url": "https://learn.chatgpt.com/docs/agent-configuration/speed", + "fetched_at": "2026-07-16", + "confidence": "exact" + }, + "gpt-5.5": { + "multiplier": 2.5, + "source_name": "OpenAI Codex Fast mode docs", + "source_url": "https://learn.chatgpt.com/docs/agent-configuration/speed", + "fetched_at": "2026-07-16", + "confidence": "exact" + }, + "gpt-5.4": { + "multiplier": 2.0, + "source_name": "OpenAI Codex Fast mode docs", + "source_url": "https://learn.chatgpt.com/docs/agent-configuration/speed", + "fetched_at": "2026-07-16", + "confidence": "exact" + } + }, "aliases": { "gpt-5.6": { "model": "gpt-5.6-sol", diff --git a/src/codex_usage_tracker/pricing/allowance.py b/src/codex_usage_tracker/pricing/allowance.py index dd893f87..25b26c4c 100644 --- a/src/codex_usage_tracker/pricing/allowance.py +++ b/src/codex_usage_tracker/pricing/allowance.py @@ -18,12 +18,14 @@ CODEX_RATE_CARD_URL, DEFAULT_SOURCE, RATE_CARD_SCHEMA, + FastMultiplierRate, RateCardUpdateResult, load_bundled_rate_card, parse_alias_metadata, parse_aliases, parse_credit_rate_metadata, parse_credit_rates, + parse_fast_multipliers, parse_rate_card_source, update_rate_card, ) @@ -40,6 +42,7 @@ "CODEX_PRICING_URL", "CODEX_RATE_CARD_URL", "DEFAULT_SOURCE", + "FastMultiplierRate", "RATE_CARD_SCHEMA", "ALLOWANCE_TEMPLATE", "AllowanceWindow", @@ -55,6 +58,7 @@ "parse_allowance_text", "parse_credit_rate_metadata", "parse_credit_rates", + "parse_fast_multipliers", "parse_rate_card_source", "parse_windows", "resolve_credit_rate", diff --git a/src/codex_usage_tracker/pricing/allowance_config.py b/src/codex_usage_tracker/pricing/allowance_config.py index bcdc185a..23deb9ad 100644 --- a/src/codex_usage_tracker/pricing/allowance_config.py +++ b/src/codex_usage_tracker/pricing/allowance_config.py @@ -3,13 +3,14 @@ from __future__ import annotations import json -from dataclasses import asdict, dataclass +from dataclasses import asdict, dataclass, field from datetime import datetime, timezone from pathlib import Path from typing import Any from codex_usage_tracker.core.paths import DEFAULT_ALLOWANCE_PATH, DEFAULT_RATE_CARD_PATH from codex_usage_tracker.pricing.allowance_rate_card import ( + FastMultiplierRate, load_bundled_rate_card, load_json_file, optional_positive_number, @@ -18,6 +19,7 @@ parse_aliases, parse_credit_rate_metadata, parse_credit_rates, + parse_fast_multipliers, parse_rate_card_source, ) from codex_usage_tracker.pricing.allowance_text import allowance_line_matches @@ -67,6 +69,7 @@ ], "credit_rates": {}, "aliases": {}, + "fast_multipliers": {}, } @@ -97,6 +100,7 @@ class UsageAllowanceConfig: loaded: bool rate_card_loaded: bool source: dict[str, Any] + fast_multipliers: dict[str, FastMultiplierRate] = field(default_factory=dict) error: str | None = None rate_card_error: str | None = None @@ -108,7 +112,8 @@ def load_allowance_config( ) -> UsageAllowanceConfig: """Load optional allowance settings while always keeping bundled rate-card data.""" - base_card = load_bundled_rate_card() + bundled_card = load_bundled_rate_card() + base_card = bundled_card rate_card_loaded = False rate_card_error = None if rate_card_path.expanduser().exists(): @@ -125,6 +130,13 @@ def load_allowance_config( base_card.get("credit_rates", {}), source=source, default_confidence="exact" ) alias_metadata = parse_alias_metadata(base_card.get("aliases", {}), source=source) + bundled_source = parse_rate_card_source(bundled_card) + fast_multipliers = parse_fast_multipliers( + bundled_card.get("fast_multipliers", {}), source=bundled_source + ) + fast_multipliers.update( + parse_fast_multipliers(base_card.get("fast_multipliers", {}), source=source) + ) windows: list[AllowanceWindow] = [] if not path.exists(): return UsageAllowanceConfig( @@ -138,6 +150,7 @@ def load_allowance_config( loaded=False, rate_card_loaded=rate_card_loaded, source=source, + fast_multipliers=fast_multipliers, rate_card_error=rate_card_error, ) @@ -168,6 +181,17 @@ def load_allowance_config( }, ) ) + fast_multipliers.update( + parse_fast_multipliers( + raw.get("fast_multipliers", {}), + source={ + "name": "Local allowance override", + "url": str(path.expanduser()), + "fetched_at": None, + }, + default_confidence="user_override", + ) + ) windows = parse_windows(raw.get("windows", [])) except (OSError, ValueError, TypeError, json.JSONDecodeError) as exc: return UsageAllowanceConfig( @@ -181,6 +205,7 @@ def load_allowance_config( loaded=False, rate_card_loaded=rate_card_loaded, source=source, + fast_multipliers=fast_multipliers, error=str(exc), rate_card_error=rate_card_error, ) @@ -196,6 +221,7 @@ def load_allowance_config( loaded=True, rate_card_loaded=rate_card_loaded, source=source, + fast_multipliers=fast_multipliers, rate_card_error=rate_card_error, ) diff --git a/src/codex_usage_tracker/pricing/allowance_rate_card.py b/src/codex_usage_tracker/pricing/allowance_rate_card.py index 1859a2f1..4bdccf33 100644 --- a/src/codex_usage_tracker/pricing/allowance_rate_card.py +++ b/src/codex_usage_tracker/pricing/allowance_rate_card.py @@ -3,6 +3,7 @@ from __future__ import annotations import json +import math import shutil from dataclasses import dataclass from datetime import datetime, timezone @@ -39,6 +40,17 @@ class RateCardUpdateResult: backup_path: Path | None = None +@dataclass(frozen=True) +class FastMultiplierRate: + """One source-stamped ChatGPT Fast credit multiplier.""" + + multiplier: float + source_name: str + source_url: str | None + fetched_at: str | None + confidence: str + + def load_bundled_rate_card() -> dict[str, Any]: """Load the package-bundled Codex credit rate-card snapshot.""" @@ -68,10 +80,17 @@ def update_rate_card( source = parse_rate_card_source(raw) credit_rates = parse_credit_rates(raw.get("credit_rates", {})) aliases = parse_aliases(raw.get("aliases", {})) + fast_multipliers = parse_fast_multipliers( + raw.get("fast_multipliers", {}), source=source + ) if not credit_rates: raise ValueError("rate card must contain at least one credit rate") parse_credit_rate_metadata(raw.get("credit_rates", {}), source=source) parse_alias_metadata(raw.get("aliases", {}), source=source) + if isinstance(raw.get("fast_multipliers"), dict) and len(fast_multipliers) != len( + raw["fast_multipliers"] + ): + raise ValueError("rate card contains an invalid Fast multiplier") path = path.expanduser() path.parent.mkdir(parents=True, exist_ok=True) @@ -107,6 +126,54 @@ def parse_credit_rates(raw: object) -> dict[str, dict[str, float]]: return parsed +def parse_fast_multipliers( + raw: object, + *, + source: dict[str, Any], + default_confidence: str = "exact", +) -> dict[str, FastMultiplierRate]: + """Parse valid source-stamped Fast multipliers, skipping malformed entries.""" + + if not isinstance(raw, dict): + return {} + parsed: dict[str, FastMultiplierRate] = {} + for family, value in raw.items(): + normalized = normalize_model(family) + if not normalized: + continue + entry = value if isinstance(value, dict) else {"multiplier": value} + multiplier = _fast_multiplier_number(entry.get("multiplier")) + if multiplier is None: + continue + confidence = ( + "user_override" + if default_confidence == "user_override" + else optional_str(entry.get("confidence")) or default_confidence + ) + parsed[normalized] = FastMultiplierRate( + multiplier=multiplier, + source_name=optional_str(entry.get("source_name")) + or optional_str(source.get("name")) + or "Codex Fast multiplier", + source_url=optional_str(entry.get("source_url")) + or optional_str(source.get("url")), + fetched_at=optional_str(entry.get("fetched_at")) + or optional_str(source.get("fetched_at")), + confidence=confidence, + ) + return parsed + + +def _fast_multiplier_number(value: object) -> float | None: + try: + multiplier = number_value(value) + except (TypeError, ValueError): + return None + if not math.isfinite(multiplier) or multiplier < 1.0: + return None + return multiplier + + def parse_aliases(raw: object) -> dict[str, dict[str, str]]: if not isinstance(raw, dict): return {} diff --git a/src/codex_usage_tracker/pricing/allowance_usage.py b/src/codex_usage_tracker/pricing/allowance_usage.py index 4ed41ec4..311c4fee 100644 --- a/src/codex_usage_tracker/pricing/allowance_usage.py +++ b/src/codex_usage_tracker/pricing/allowance_usage.py @@ -43,14 +43,32 @@ def annotate_rows_with_allowance( copy = dict(row) model = copy.get(model_field) match = resolve_credit_rate(model, resolved) - multiplier, multiplier_source = credit_multiplier_for_row(copy) + multiplier, multiplier_match, multiplier_fallback = credit_multiplier_for_row( + copy, resolved.fast_multipliers + ) + multiplier_source = ( + multiplier_match.source_name if multiplier_match else multiplier_fallback + ) + multiplier_source_url = ( + multiplier_match.source_url if multiplier_match else None + ) + multiplier_fetched_at = ( + multiplier_match.fetched_at if multiplier_match else None + ) + multiplier_confidence = ( + multiplier_match.confidence if multiplier_match else None + ) if match is None: copy.update( { "usage_credits": None, "standard_usage_credits": None, + "fast_usage_credits": None, "usage_credit_multiplier": multiplier, "usage_credit_multiplier_source": multiplier_source, + "usage_credit_multiplier_source_url": multiplier_source_url, + "usage_credit_multiplier_fetched_at": multiplier_fetched_at, + "usage_credit_multiplier_confidence": multiplier_confidence, "usage_credit_model": None, "usage_credit_confidence": "unpriced", "usage_credit_source": "No Codex credit rate", @@ -63,12 +81,21 @@ def annotate_rows_with_allowance( else: rated_model, rates, confidence, note, metadata = match standard_credits = estimate_standard_usage_credits(copy, rates) + fast_credits = ( + standard_credits * multiplier_match.multiplier + if multiplier_match is not None + else None + ) copy.update( { "usage_credits": standard_credits * multiplier, "standard_usage_credits": standard_credits, + "fast_usage_credits": fast_credits, "usage_credit_multiplier": multiplier, "usage_credit_multiplier_source": multiplier_source, + "usage_credit_multiplier_source_url": multiplier_source_url, + "usage_credit_multiplier_fetched_at": multiplier_fetched_at, + "usage_credit_multiplier_confidence": multiplier_confidence, "usage_credit_model": rated_model, "usage_credit_confidence": confidence, "usage_credit_source": metadata.get("source_name") @@ -217,5 +244,5 @@ def estimate_usage_credits(row: dict[str, Any], rates: dict[str, float]) -> floa """Estimate effective Codex credits, including confirmed Fast multipliers.""" standard = estimate_standard_usage_credits(row, rates) - multiplier, _source = credit_multiplier_for_row(row) + multiplier, _match, _source = credit_multiplier_for_row(row) return standard * multiplier diff --git a/src/codex_usage_tracker/pricing/fast_tier.py b/src/codex_usage_tracker/pricing/fast_tier.py index de8f4d67..7fb02f82 100644 --- a/src/codex_usage_tracker/pricing/fast_tier.py +++ b/src/codex_usage_tracker/pricing/fast_tier.py @@ -3,35 +3,88 @@ from __future__ import annotations from collections.abc import Mapping +from dataclasses import dataclass +from functools import lru_cache -DOCUMENTED_FAST_CREDIT_MULTIPLIERS = { - "gpt-5.6": 2.5, - "gpt-5.5": 2.5, - "gpt-5.4": 2.0, -} +from codex_usage_tracker.pricing.allowance_rate_card import ( + FastMultiplierRate, + load_bundled_rate_card, + parse_fast_multipliers, + parse_rate_card_source, +) + + +@dataclass(frozen=True) +class FastMultiplierMatch: + """A model-family multiplier match with independent numeric provenance.""" + multiplier: float + model_family: str + source_name: str + source_url: str | None + fetched_at: str | None + confidence: str -def documented_fast_credit_multiplier(model: object) -> float | None: + +def documented_fast_credit_multiplier( + model: object, + multipliers: Mapping[str, FastMultiplierRate] | None = None, +) -> float | None: """Return the documented Fast multiplier for a model family label.""" - normalized = str(model or "").strip().lower() - for family, multiplier in DOCUMENTED_FAST_CREDIT_MULTIPLIERS.items(): + match = match_fast_credit_multiplier(model, multipliers) + return match.multiplier if match is not None else None + + +def match_fast_credit_multiplier( + model: object, + multipliers: Mapping[str, FastMultiplierRate] | None = None, +) -> FastMultiplierMatch | None: + """Resolve the longest configured model-family prefix.""" + + normalized = str(model or "").strip().lower().replace("_", "-") + configured = multipliers if multipliers is not None else _bundled_fast_multipliers() + for family in sorted(configured, key=len, reverse=True): if ( normalized == family or normalized.startswith(f"{family}-") or normalized.startswith(f"{family} ") ): - return multiplier + rate = configured[family] + return FastMultiplierMatch( + multiplier=rate.multiplier, + model_family=family, + source_name=rate.source_name, + source_url=rate.source_url, + fetched_at=rate.fetched_at, + confidence=rate.confidence, + ) return None -def credit_multiplier_for_row(row: Mapping[str, object]) -> tuple[float, str]: - """Return an effective credit multiplier and bounded provenance label.""" +def credit_multiplier_for_row( + row: Mapping[str, object], + multipliers: Mapping[str, FastMultiplierRate] | None = None, +) -> tuple[float, FastMultiplierMatch | None, str]: + """Return the applied multiplier, available scenario match, and fallback label.""" + match = match_fast_credit_multiplier(row.get("model"), multipliers) if row.get("fast") != 1: fallback = "confirmed_standard" if row.get("fast") == 0 else "tier_unknown" - return 1.0, str(row.get("service_tier_source") or fallback) - multiplier = documented_fast_credit_multiplier(row.get("model")) - if multiplier is None: - return 1.0, "no_documented_fast_multiplier" - return multiplier, str(row.get("service_tier_source") or "confirmed_fast") + return 1.0, match, str(row.get("service_tier_source") or fallback) + if match is None: + return 1.0, None, "no_documented_fast_multiplier" + return match.multiplier, match, match.source_name + + +@lru_cache(maxsize=1) +def _bundled_fast_multipliers() -> dict[str, FastMultiplierRate]: + raw = load_bundled_rate_card() + return parse_fast_multipliers( + raw.get("fast_multipliers", {}), source=parse_rate_card_source(raw) + ) + + +DOCUMENTED_FAST_CREDIT_MULTIPLIERS = { + family: rate.multiplier for family, rate in _bundled_fast_multipliers().items() +} diff --git a/tests/pricing/test_allowance.py b/tests/pricing/test_allowance.py index 064bad2e..a9daa9cf 100644 --- a/tests/pricing/test_allowance.py +++ b/tests/pricing/test_allowance.py @@ -1,11 +1,13 @@ from __future__ import annotations import json +from dataclasses import replace from pathlib import Path import pytest from codex_usage_tracker.pricing.allowance import ( + FastMultiplierRate, UsageAllowanceConfig, annotate_rows_with_allowance, load_allowance_config, @@ -46,6 +48,12 @@ def _synthetic_allowance_config() -> UsageAllowanceConfig: "gpt-5.4", "synthetic-unknown", ) + multiplier_source = { + "source_name": "OpenAI Codex Fast mode docs", + "source_url": "https://learn.chatgpt.com/docs/agent-configuration/speed", + "fetched_at": "2026-07-16", + "confidence": "exact", + } return UsageAllowanceConfig( path=Path("/synthetic/allowance.json"), rate_card_path=Path("/synthetic/rate-card.json"), @@ -57,6 +65,11 @@ def _synthetic_allowance_config() -> UsageAllowanceConfig: loaded=True, rate_card_loaded=True, source={"name": "Synthetic credit rates"}, + fast_multipliers={ + "gpt-5.6": FastMultiplierRate(multiplier=2.5, **multiplier_source), + "gpt-5.5": FastMultiplierRate(multiplier=2.5, **multiplier_source), + "gpt-5.4": FastMultiplierRate(multiplier=2.0, **multiplier_source), + }, ) @@ -82,7 +95,39 @@ def test_confirmed_fast_multiplies_standard_credit_estimate( annotated["standard_usage_credits"] * multiplier ) assert annotated["usage_credit_multiplier"] == multiplier - assert annotated["usage_credit_multiplier_source"] == "otel_response_completed" + assert annotated["usage_credit_multiplier_source"] == "OpenAI Codex Fast mode docs" + + +def test_fast_multiplier_provenance_comes_from_rate_card() -> None: + config = replace( + _synthetic_allowance_config(), + fast_multipliers={ + "gpt-5.6": FastMultiplierRate( + multiplier=2.5, + source_name="OpenAI Codex Fast mode docs", + source_url="https://learn.chatgpt.com/docs/agent-configuration/speed", + fetched_at="2026-07-16", + confidence="exact", + ) + }, + ) + + annotated = annotate_rows_with_allowance( + [_credit_row(model="gpt-5.6", fast=1, service_tier="priority")], + config, + )[0] + + assert annotated["usage_credit_multiplier"] == 2.5 + assert annotated["usage_credit_multiplier_source"] == "OpenAI Codex Fast mode docs" + assert annotated["usage_credit_multiplier_source_url"].endswith( + "/agent-configuration/speed" + ) + assert annotated["usage_credit_multiplier_fetched_at"] == "2026-07-16" + assert annotated["usage_credit_multiplier_confidence"] == "exact" + assert annotated["fast_usage_credits"] == pytest.approx( + annotated["standard_usage_credits"] * 2.5 + ) + assert annotated["service_tier_source"] == "otel_response_completed" @pytest.mark.parametrize("fast", [0, None]) @@ -342,6 +387,7 @@ def test_update_rate_card_writes_bundled_snapshot(tmp_path: Path) -> None: assert config.credit_rates["gpt-5.6-sol"]["output_per_million"] == 1500.0 assert config.credit_rates["gpt-5.6-terra"]["output_per_million"] == 125.0 assert config.credit_rates["gpt-5.6-luna"]["output_per_million"] == 300.0 + assert config.fast_multipliers["gpt-5.6"].multiplier == 2.5 def test_write_allowance_template_refuses_to_overwrite(tmp_path: Path) -> None: diff --git a/tests/pricing/test_rate_card.py b/tests/pricing/test_rate_card.py new file mode 100644 index 00000000..f55692b9 --- /dev/null +++ b/tests/pricing/test_rate_card.py @@ -0,0 +1,83 @@ +from __future__ import annotations + +import json +from pathlib import Path + +from codex_usage_tracker.pricing.allowance import load_allowance_config + + +def test_local_fast_multiplier_override_is_source_stamped(tmp_path: Path) -> None: + path = tmp_path / "allowance.json" + path.write_text( + json.dumps( + { + "fast_multipliers": { + "gpt-5.6": { + "multiplier": 3.0, + "source_name": "Synthetic override", + "source_url": "https://example.invalid/synthetic-fast-rate", + "fetched_at": "2026-07-16", + } + } + } + ), + encoding="utf-8", + ) + + config = load_allowance_config( + path, rate_card_path=tmp_path / "missing-rate-card.json" + ) + rate = config.fast_multipliers["gpt-5.6"] + + assert rate.multiplier == 3.0 + assert rate.source_name == "Synthetic override" + assert rate.source_url == "https://example.invalid/synthetic-fast-rate" + assert rate.fetched_at == "2026-07-16" + assert rate.confidence == "user_override" + + +def test_malformed_local_multiplier_retains_valid_bundled_rate(tmp_path: Path) -> None: + path = tmp_path / "allowance.json" + path.write_text( + json.dumps( + {"fast_multipliers": {"gpt-5.6": {"multiplier": 0.5}}} + ), + encoding="utf-8", + ) + + config = load_allowance_config( + path, rate_card_path=tmp_path / "missing-rate-card.json" + ) + + assert config.loaded is True + assert config.fast_multipliers["gpt-5.6"].multiplier == 2.5 + assert config.fast_multipliers["gpt-5.6"].confidence == "exact" + + +def test_legacy_local_rate_card_inherits_bundled_fast_multipliers( + tmp_path: Path, +) -> None: + rate_card_path = tmp_path / "legacy-rate-card.json" + rate_card_path.write_text( + json.dumps( + { + "schema": "codex-usage-tracker-codex-rate-card-v1", + "credit_rates": { + "gpt-5.6": { + "input_per_million": 1, + "cached_input_per_million": 1, + "output_per_million": 1, + } + }, + "aliases": {}, + } + ), + encoding="utf-8", + ) + + config = load_allowance_config( + tmp_path / "missing-allowance.json", rate_card_path=rate_card_path + ) + + assert config.rate_card_loaded is True + assert config.fast_multipliers["gpt-5.6"].multiplier == 2.5 From c19e5f18f957c6446a27a1dec2b78dae13674ca2 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:12:27 -0400 Subject: [PATCH 20/24] fix: label exact service tiers --- .../src/features/calls/serviceTier.test.ts | 31 ++++++++++++++++++- .../src/features/shared/callPresentation.ts | 30 +++++++++++++++++- .../src/features/shared/tables.test.ts | 10 ++++++ .../dashboard/src/features/shared/tables.tsx | 2 +- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/frontend/dashboard/src/features/calls/serviceTier.test.ts b/frontend/dashboard/src/features/calls/serviceTier.test.ts index 03f2113c..810700e0 100644 --- a/frontend/dashboard/src/features/calls/serviceTier.test.ts +++ b/frontend/dashboard/src/features/calls/serviceTier.test.ts @@ -4,6 +4,25 @@ import { usageRowToCall } from '../../api/client'; import { serviceTierDetail, serviceTierLabel } from './serviceTier'; describe('service tier labels', () => { + it.each([ + ['priority', true, 'Priority / Fast'], + ['fast', true, 'Fast'], + ['default', false, 'Default / Standard'], + ['standard', false, 'Standard'], + ['flex', false, 'Flex'], + ['batch', false, 'Batch'], + ])('labels exact service tier %s', (serviceTier, fast, expected) => { + const call = usageRowToCall({ + service_tier: serviceTier, + fast: fast ? 1 : 0, + service_tier_source: 'otel_response_completed', + service_tier_confidence: 'exact', + }); + + expect(serviceTierLabel(call)).toBe(expected); + expect(serviceTierDetail(call)).toBe(`observed ${expected} · exact`); + }); + it('shows protocol-confirmed Standard separately from the throughput proxy', () => { const call = usageRowToCall({ service_tier: 'standard', @@ -15,7 +34,7 @@ describe('service tier labels', () => { }); expect(serviceTierLabel(call)).toBe('Standard'); - expect(serviceTierDetail(call)).toBe('confirmed Standard · protocol'); + expect(serviceTierDetail(call)).toBe('observed Standard · protocol'); expect(call.fastProxyCandidate).toBe(true); }); @@ -27,4 +46,14 @@ describe('service tier labels', () => { expect(serviceTierDetail(candidate)).toBe('tier unknown · Fast proxy candidate'); expect(serviceTierDetail(normal)).toBe('tier unknown · normal throughput proxy'); }); + + it('uses the derived Fast classification only when no exact tier is present', () => { + const legacy = usageRowToCall({ + fast: 1, + service_tier_confidence: 'exact', + }); + + expect(serviceTierLabel(legacy)).toBe('Fast'); + expect(serviceTierDetail(legacy)).toBe('confirmed Fast · exact'); + }); }); diff --git a/frontend/dashboard/src/features/shared/callPresentation.ts b/frontend/dashboard/src/features/shared/callPresentation.ts index 4f881304..b4ca2fed 100644 --- a/frontend/dashboard/src/features/shared/callPresentation.ts +++ b/frontend/dashboard/src/features/shared/callPresentation.ts @@ -17,18 +17,46 @@ type ContextWindowInput = { type TopCountStyle = 'parenthetical' | 'x'; type ServiceTierInput = { + serviceTier: string; fast: boolean | null; serviceTierConfidence: string; fastProxyCandidate: boolean; }; -export function serviceTierLabel(call: ServiceTierInput): 'Fast' | 'Standard' | 'Unknown' { +const knownServiceTierLabels: Record = { + priority: 'Priority / Fast', + fast: 'Fast', + default: 'Default / Standard', + standard: 'Standard', + flex: 'Flex', + batch: 'Batch', +}; + +function exactServiceTierLabel(value: string): string | null { + const normalized = value.trim().toLowerCase().replace(/[\s_]+/g, '-'); + if (!normalized) return null; + const known = knownServiceTierLabels[normalized]; + if (known) return known; + if (normalized.length > 48 || !/^[a-z0-9.-]+$/.test(normalized)) return 'Other'; + return normalized + .split(/[-.]+/) + .filter(Boolean) + .map(part => `${part.charAt(0).toUpperCase()}${part.slice(1)}`) + .join(' '); +} + +export function serviceTierLabel(call: ServiceTierInput): string { + const exactLabel = exactServiceTierLabel(call.serviceTier); + if (exactLabel) return exactLabel; if (call.fast === true) return 'Fast'; if (call.fast === false) return 'Standard'; return 'Unknown'; } export function serviceTierDetail(call: ServiceTierInput): string { + if (exactServiceTierLabel(call.serviceTier)) { + return `observed ${serviceTierLabel(call)} · ${call.serviceTierConfidence || 'exact'}`; + } if (call.fast !== null) { return `confirmed ${serviceTierLabel(call)} · ${call.serviceTierConfidence || 'exact'}`; } diff --git a/frontend/dashboard/src/features/shared/tables.test.ts b/frontend/dashboard/src/features/shared/tables.test.ts index 6700c1a6..93389ff7 100644 --- a/frontend/dashboard/src/features/shared/tables.test.ts +++ b/frontend/dashboard/src/features/shared/tables.test.ts @@ -120,6 +120,16 @@ expect(header).toContain('model_context_window'); it('includes an exact Service Tier column', () => { expect(callColumns.some(column => column.id === 'serviceTier')).toBe(true); }); + + it('renders Flex and Priority from the exact tier instead of the boolean fallback', () => { + const serviceTierColumn = callColumns.find(column => column.id === 'serviceTier'); + const accessor = serviceTierColumn && 'accessorFn' in serviceTierColumn + ? serviceTierColumn.accessorFn + : undefined; + + expect(accessor?.({ serviceTier: 'flex', fast: false } as CallRow, 0)).toBe('Flex'); + expect(accessor?.({ serviceTier: 'priority', fast: true } as CallRow, 0)).toBe('Priority / Fast'); + }); }); describe('call table columns', () => { diff --git a/frontend/dashboard/src/features/shared/tables.tsx b/frontend/dashboard/src/features/shared/tables.tsx index 68281742..45c6860a 100644 --- a/frontend/dashboard/src/features/shared/tables.tsx +++ b/frontend/dashboard/src/features/shared/tables.tsx @@ -78,7 +78,7 @@ export const callColumns: Array> = [ header: 'Service Tier', cell: info => { const label = String(info.getValue()); - const tone = label === 'Fast' ? 'green' : label === 'Standard' ? 'blue' : ''; + const tone = label.includes('Fast') ? 'green' : label.includes('Standard') ? 'blue' : ''; return {label}; }, }, From a17652f02ad6070afa746b4aacbcfc5d0c40e20b Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:14:44 -0400 Subject: [PATCH 21/24] fix: clear OTel state and harden rotation --- src/codex_usage_tracker/store/api.py | 2 + src/codex_usage_tracker/store/otel_ingest.py | 46 +++++++++++----- tests/store/test_otel_ingest.py | 57 ++++++++++++++++++++ tests/store/test_otel_refresh.py | 6 +-- tests/store/test_source_records.py | 29 ++++++++++ 5 files changed, 125 insertions(+), 15 deletions(-) diff --git a/src/codex_usage_tracker/store/api.py b/src/codex_usage_tracker/store/api.py index 5f91601f..d8c0d131 100644 --- a/src/codex_usage_tracker/store/api.py +++ b/src/codex_usage_tracker/store/api.py @@ -234,6 +234,8 @@ def reset_usage_database(db_path: Path = DEFAULT_DB_PATH) -> dict[str, Any]: conn.execute("DELETE FROM call_diagnostic_facts") conn.execute("DELETE FROM diagnostic_snapshots") conn.execute("DELETE FROM allowance_observations") + conn.execute("DELETE FROM otel_completion_events") + conn.execute("DELETE FROM otel_completion_sources") conn.execute("DELETE FROM source_records") conn.execute("DELETE FROM usage_events") conn.execute("DELETE FROM thread_summaries") diff --git a/src/codex_usage_tracker/store/otel_ingest.py b/src/codex_usage_tracker/store/otel_ingest.py index e74b6b0d..424d81de 100644 --- a/src/codex_usage_tracker/store/otel_ingest.py +++ b/src/codex_usage_tracker/store/otel_ingest.py @@ -66,18 +66,14 @@ def ingest_otel_completion_files( for path in discover_otel_sources(directory): source_path = str(path.resolve()) try: - initial_stat = path.stat() state = _source_state(conn, source_path) - offset, line_number = _resume_position(state, initial_stat) - next_offset, next_line = _ingest_complete_lines( + final_stat, next_offset, next_line = _ingest_complete_lines( conn, path, source_path, - offset, - line_number, + state, totals, ) - final_stat = path.stat() except FileNotFoundError: continue _upsert_source_cursor( @@ -127,13 +123,38 @@ def _ingest_complete_lines( conn: sqlite3.Connection, path: Path, source_path: str, - offset: int, - line_number: int, + state: _SourceState | None, totals: _MutableIngestTotals, -) -> tuple[int, int]: - next_offset = offset - next_line = line_number +) -> tuple[os.stat_result, int, int]: + for attempt in range(2): + result = _read_source_descriptor( + conn, + path, + source_path, + state if attempt == 0 else None, + totals, + ) + initial_stat, final_stat, next_offset, next_line = result + if ( + initial_stat.st_dev == final_stat.st_dev + and initial_stat.st_ino == final_stat.st_ino + ): + return final_stat, next_offset, next_line + raise FileNotFoundError("OTel source descriptor identity changed during retry") + + +def _read_source_descriptor( + conn: sqlite3.Connection, + path: Path, + source_path: str, + state: _SourceState | None, + totals: _MutableIngestTotals, +) -> tuple[os.stat_result, os.stat_result, int, int]: with path.open("rb") as handle: + initial_stat = os.fstat(handle.fileno()) + offset, line_number = _resume_position(state, initial_stat) + next_offset = offset + next_line = line_number handle.seek(offset) while line := handle.readline(): if not line.endswith(b"\n"): @@ -152,7 +173,8 @@ def _ingest_complete_lines( totals.imported += 1 else: totals.duplicates += 1 - return next_offset, next_line + final_stat = os.fstat(handle.fileno()) + return initial_stat, final_stat, next_offset, next_line def _insert_completion( diff --git a/tests/store/test_otel_ingest.py b/tests/store/test_otel_ingest.py index f1eecccc..67f10885 100644 --- a/tests/store/test_otel_ingest.py +++ b/tests/store/test_otel_ingest.py @@ -3,6 +3,8 @@ import json from pathlib import Path +import pytest + from codex_usage_tracker.store.otel_ingest import ( discover_otel_sources, ingest_otel_completion_files, @@ -100,6 +102,61 @@ def test_truncation_or_inode_replacement_resets_cursor_safely(tmp_path: Path) -> assert ingest_otel_completion_files(conn, directory).imported == 1 +def test_rotation_between_discovery_and_open_reads_replacement_from_zero( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + replacement = tmp_path / "replacement.jsonl" + write_lines(source, [synthetic_fast_completion("conversation-a", 100)]) + + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + write_lines( + replacement, + [ + synthetic_fast_completion( + "conversation-b-with-a-longer-synthetic-identifier", 200 + ), + synthetic_standard_completion("conversation-c", 300), + ], + ) + real_open = Path.open + rotated = False + + def rotate_before_open(path: Path, *args: object, **kwargs: object): + nonlocal rotated + if path == source and args and args[0] == "rb" and not rotated: + rotated = True + source.unlink() + replacement.replace(source) + return real_open(path, *args, **kwargs) + + monkeypatch.setattr(Path, "open", rotate_before_open) + result = ingest_otel_completion_files(conn, directory) + event_count = conn.execute( + "SELECT COUNT(*) FROM otel_completion_events" + ).fetchone()[0] + cursor = conn.execute( + """ + SELECT device, inode, parsed_offset + FROM otel_completion_sources + WHERE source_path = ? + """, + (str(source.resolve()),), + ).fetchone() + + source_stat = source.stat() + assert result.imported == 2 + assert event_count == 3 + assert tuple(cursor) == ( + source_stat.st_dev, + source_stat.st_ino, + source_stat.st_size, + ) + + def test_ingest_never_persists_body_or_arbitrary_attributes(tmp_path: Path) -> None: directory = tmp_path / "otel" attributes = completion_attributes() diff --git a/tests/store/test_otel_refresh.py b/tests/store/test_otel_refresh.py index 185ab039..9e74ad08 100644 --- a/tests/store/test_otel_refresh.py +++ b/tests/store/test_otel_refresh.py @@ -45,7 +45,7 @@ def test_refresh_ingests_session_rows_before_reconciling_otel(tmp_path: Path) -> record_id = str(conn.execute("SELECT record_id FROM usage_events").fetchone()[0]) row = query_usage_record(db_path=db_path, record_id=record_id) assert row is not None - assert row["service_tier"] == "fast" + assert row["service_tier"] == "priority" assert result.parser_diagnostics["otel_matched"] == 1 @@ -158,7 +158,7 @@ def test_otel_before_jsonl_matches_on_a_later_refresh(tmp_path: Path) -> None: refresh_usage_index(codex_home=codex_home, db_path=db_path, otel_dir=otel_dir) with connect(db_path) as conn: - assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "fast" + assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "priority" def test_rebuild_retains_staging_resets_match_pointer_and_reapplies_tier( @@ -177,7 +177,7 @@ def test_rebuild_retains_staging_resets_match_pointer_and_reapplies_tier( with connect(db_path) as conn: assert conn.execute("SELECT COUNT(*) FROM otel_completion_events").fetchone()[0] == 1 - assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "fast" + assert conn.execute("SELECT service_tier FROM usage_events").fetchone()[0] == "priority" state = conn.execute( "SELECT match_status, matched_record_id FROM otel_completion_events" ).fetchone() diff --git a/tests/store/test_source_records.py b/tests/store/test_source_records.py index aef8359b..f4f176b6 100644 --- a/tests/store/test_source_records.py +++ b/tests/store/test_source_records.py @@ -15,6 +15,8 @@ reset_usage_database, upsert_usage_events, ) +from codex_usage_tracker.store.otel_ingest import ingest_otel_completion_files +from tests.otel_helpers import write_otel_directory from tests.store_dashboard_helpers import _usage_event @@ -228,3 +230,30 @@ def test_reset_usage_database_clears_content_index_tables(tmp_path: Path) -> Non assert fragment_count is not None assert turn_count[0] == 0 assert fragment_count[0] == 0 + + +def test_reset_usage_database_clears_otel_staging_and_cursors( + tmp_path: Path, +) -> None: + db_path = tmp_path / "usage.sqlite3" + otel_dir = write_otel_directory( + tmp_path, + "synthetic-reset", + (120, 40, 30, 10), + ) + with connect(db_path) as conn: + init_db(conn) + ingest_otel_completion_files(conn, otel_dir) + + reset_usage_database(db_path) + + with connect(db_path) as conn: + event_count = conn.execute( + "SELECT COUNT(*) FROM otel_completion_events" + ).fetchone()[0] + source_count = conn.execute( + "SELECT COUNT(*) FROM otel_completion_sources" + ).fetchone()[0] + + assert event_count == 0 + assert source_count == 0 From 8d462dcfee16ad7ce707769dfa31f0f6b7ed8ebb Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:22:23 -0400 Subject: [PATCH 22/24] docs: explain tier-aware billing estimates --- .../dashboard-source-baseline.json | 4 +- CHANGELOG.md | 9 +++- docs/cli-json-schemas.md | 29 ++++++++-- docs/dashboard-guide.md | 22 ++++---- docs/database-schema.md | 10 +++- docs/pricing-and-credits.md | 33 ++++++++++-- docs/privacy.md | 12 +++++ frontend/dashboard/src/api/billing.ts | 34 ++++++++++++ frontend/dashboard/src/api/client.test.ts | 33 ++++++++++++ frontend/dashboard/src/api/client.ts | 4 +- frontend/dashboard/src/api/rowAnnotations.ts | 2 + frontend/dashboard/src/api/serviceTier.ts | 18 +++++++ frontend/dashboard/src/api/types.ts | 7 ++- .../CallInvestigatorPage.tsx | 4 +- .../src/features/calls/CallInspector.tsx | 4 +- .../features/shared/callPresentation.test.ts | 20 ++++++- .../src/features/shared/callPresentation.ts | 19 +++++++ .../src/features/shared/tables.test.ts | 14 +++++ .../dashboard/src/features/shared/tables.tsx | 9 ++++ .../src/test-fixtures/dashboardFixture.ts | 9 ++++ .../plugin_data/dashboard/react/assets/App.js | 54 +++++++++---------- .../react/assets/CallInvestigatorPage.js | 4 +- .../dashboard/react/assets/CallsPage.js | 8 +-- .../dashboard/react/assets/SettingsPage.js | 2 +- .../react/assets/contextEvidenceState.js | 2 +- .../dashboard/react/assets/dashboardRouter.js | 2 +- .../dashboard/react/assets/useBaseQuery.js | 2 +- .../react/assets/useInfiniteQuery.js | 2 +- src/codex_usage_tracker/reports/support.py | 3 ++ tests/dashboard/test_dashboard_payload.py | 17 +++++- tests/reports/test_support.py | 3 ++ 31 files changed, 320 insertions(+), 75 deletions(-) create mode 100644 frontend/dashboard/src/api/billing.ts create mode 100644 frontend/dashboard/src/api/rowAnnotations.ts diff --git a/.agent-maintainer/dashboard-source-baseline.json b/.agent-maintainer/dashboard-source-baseline.json index a127fc36..01fcb7c3 100644 --- a/.agent-maintainer/dashboard-source-baseline.json +++ b/.agent-maintainer/dashboard-source-baseline.json @@ -17,8 +17,8 @@ }, "frontend/dashboard/src/api/types.ts": { "group": "source", - "nonblank": 423, - "physical": 449 + "nonblank": 422, + "physical": 448 }, "frontend/dashboard/src/app/zh-Hans/advancedPages.ts": { "group": "source", diff --git a/CHANGELOG.md b/CHANGELOG.md index d17f06b3..63a9a719 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,15 @@ - Show exact service tier separately from the existing Fast proxy in Calls, details, and CSV exports; older or unmatched history remains Unknown. - Apply documented model-family Fast multipliers to confirmed Codex credit - estimates with explicit provenance while leaving USD token-cost estimates and + estimates with source URL/date/confidence and local overrides while leaving standard-credit allowance calibration unchanged. +- Cache Standard, Batch, Flex, and Priority API pricing together, select the + observed tier per call, and expose Standard/Priority cost scenarios plus an + explicit local billing basis without applying ChatGPT Fast multipliers to API + USD estimates. +- Preserve exact response tiers in dashboard labels and CSV contracts, clear + OTel staging on confirmed database reset, and make incremental source cursors + descriptor-safe across concurrent file rotation. ## 0.20.0 - 2026-07-16 diff --git a/docs/cli-json-schemas.md b/docs/cli-json-schemas.md index 3af9ea6b..3768f34d 100644 --- a/docs/cli-json-schemas.md +++ b/docs/cli-json-schemas.md @@ -1475,10 +1475,29 @@ localhost status is stable. These surfaces never expose OTel source paths, semantic fingerprints, response bodies, arbitrary attributes, or staging ids. Aggregate call rows may add nullable `service_tier`, `fast`, -`service_tier_source`, and `service_tier_confidence` fields. Credit-annotated -rows may also add `standard_usage_credits`, `usage_credit_multiplier`, and -`usage_credit_multiplier_source`. `fast: null` means Unknown; clients must not -replace it with the separate throughput proxy. CSV export includes both exact -tier fields and the separately named proxy candidate. +`service_tier_source`, and `service_tier_confidence` fields. `service_tier` +preserves the exact normalized response value such as `priority`, `default`, +`standard`, `flex`, or `batch`; `fast` is the derived speed classification. + +Cost-annotated rows may add `standard_cost_usd`, `priority_cost_usd`, +`pricing_service_tier`, `billing_basis`, and +`cost_semantics="api_token_estimate"`. `estimated_cost_usd` remains the +API-token-equivalent estimate selected from the observed tier when pricing-v2 +contains that table. `billing_basis` is `unknown`, `chatgpt_credits`, or +`api_tokens` and describes applicability rather than changing the observed tier. + +Credit-annotated rows may also add `standard_usage_credits`, +`fast_usage_credits`, `usage_credit_multiplier`, +`usage_credit_multiplier_source`, `usage_credit_multiplier_source_url`, +`usage_credit_multiplier_fetched_at`, and +`usage_credit_multiplier_confidence`. These are ChatGPT-equivalent credit +scenarios and are never used as generic multipliers for API USD. `fast: null` +means Unknown; clients must not replace it with the separate throughput proxy. +CSV export includes the exact tier, both scenario families, multiplier +provenance, and the separately named proxy candidate. + +`rebuild-index` retains aggregate OTel staging for reconciliation. Confirmed +`reset-db --yes` clears both `otel_completion_events` and +`otel_completion_sources` along with the other tracker-owned rows. `context` already returns JSON because it is an explicit on-demand context request. Treat `codex-usage-tracker-context-v1` output as sensitive local context even though it is redacted and size-limited by default. `max_entries=0` requests all matching entries and `max_chars=0` removes the character cap for that explicit request. Tool output and compacted replacement history are omitted unless explicitly requested. Compaction entries may include metadata such as `replacement_history_available`, `replacement_entry_count`, and `replacement_history_included`; replacement text appears only when `include_compaction_history` is true for that local request. Evidence responses include `action_timing`, derived from timestamps in the same selected-turn source scan, plus per-entry `action_timing` fields such as `since_turn_start_ms`, `since_previous_entry_ms`, and `reported_duration_ms` when available. MCP returns `codex-usage-tracker-context-disabled-v1` when raw context loading has not been explicitly enabled with `CODEX_USAGE_TRACKER_ALLOW_RAW_CONTEXT=1`. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index 3bfe664a..69944ffe 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -117,10 +117,11 @@ Use `Calls` view when you want to inspect individual model calls. - Time values are shown in your browser's local date/time format while sorting and time filtering still use the logged timestamp. - Calls include `Duration`, derived from turn start for a new turn or the previous same-turn call end for continuations, and `Prev gap`, the elapsed time since the previous call in the resolved thread. - Calls view token columns separate total tokens, cached input, uncached input, and output so the accounting can be scanned without expanding a row. -- The `Service Tier` column shows `Fast` or `Standard` only when local completion - telemetry supplies exact/protocol-confirmed evidence; otherwise it shows - `Unknown`. The detail view keeps the older latency/effort heuristic labeled as - a separate Fast proxy candidate rather than presenting it as historical proof. +- The `Service Tier` column preserves the exact response value with distinct + labels for Priority/Fast, Fast, Default/Standard, Standard, Flex, Batch, and + other bounded explicit tiers. It shows `Unknown` when completion telemetry is + absent. The detail view keeps the older throughput heuristic labeled as a + separate Fast proxy candidate rather than historical proof. - Source pucks are call-level estimates derived from local event metadata. `User` means the token-count segment included a user message, `Codex` means it followed tool output, compaction, or agent-continuation metadata, and `Unknown` means the source event metadata was unavailable or ambiguous. - Click a column header like `Time`, `Thread`, `Tokens`, `Cost`, or `Cache` to sort. Use the sort menu for `Highest Codex credits`. Click the same header again to reverse the direction. - Hover a row to scan a compact aggregate preview in `Call Details`; click a Calls row to open the dedicated call investigator. @@ -140,11 +141,14 @@ Useful interpretation notes: - `Cached input` and `Uncached input` are split so cache behavior is visible without storing transcript text. - A cost with `*` means the pricing row is marked as a best-guess estimate. - Codex credits are estimated from aggregate input, cached-input, and output token counters. Direct model matches use the bundled OpenAI Codex rate-card snapshot; inferred labels are marked estimated, and local credit-rate overrides are marked user-provided. -- Confirmed Fast rows apply the documented model-family multiplier to Codex - credits and show the multiplier provenance. Standard and Unknown rows remain - at `1.0x`; USD estimates are unchanged. -- CSV exports include `service_tier`, `fast`, tier source/confidence, the separate - Fast proxy flag, standard credits, and credit multiplier provenance. Missing +- Confirmed Fast rows apply the source-stamped model-family multiplier to + ChatGPT-equivalent Codex credits. API-equivalent USD estimates instead select + the exact API tier table; the cost detail identifies whether the configured + billing basis is API tokens, ChatGPT credits, or Unknown without claiming + actual spend when the basis is unknown. +- CSV exports include exact tier/provenance, the separate Fast proxy, + Standard/Priority API cost scenarios, Standard/Fast credit scenarios, + `billing_basis`, and credit multiplier source URL/date/confidence. Missing exact tier evidence remains blank/Unknown instead of being reconstructed from duration or reasoning effort. - `Usage observed` is not a live account query. It uses the latest local Codex `token_count.rate_limits` snapshot when present; otherwise configure `~/.codex-usage-tracker/allowance.json` with values copied from Codex Settings > Usage, the Codex Usage dashboard, or `/status` when you want current remaining allowance context. diff --git a/docs/database-schema.md b/docs/database-schema.md index b3eb65df..2715a932 100644 --- a/docs/database-schema.md +++ b/docs/database-schema.md @@ -44,18 +44,24 @@ byte and line cursor, and an update timestamp for each local the selected database (`~/.codex-usage-tracker/otel` for the default database), so alternate databases do not ingest another tracker instance's telemetry. `otel_completion_events` stores one semantic -fingerprint plus aggregate matching fields, normalized tier provenance, a +fingerprint plus aggregate matching fields, the exact normalized response tier, +derived Fast classification, tier provenance, a bounded match status (`pending`, `matched`, `ambiguous`, `conflict`, or `invalid`), and the matched aggregate record id when available. Append refresh resumes after the last complete JSONL line, retries a partial -trailing line, and restarts a cursor after rotation or truncation. Rebuild keeps +trailing line, and restarts a cursor after rotation or truncation. Cursor +identity, size, and offsets come from the open descriptor so a path rotation +cannot persist an offset from one inode against another. Rebuild keeps the aggregate OTel staging rows, resets their match pointers, and reconciles them against the rebuilt canonical calls. A match requires conversation id plus input, cached-input, output, and reasoning-output counters to resolve to exactly one canonical group. Existing contradictory tier values are preserved and the completion is marked as a conflict. +`reset-db --yes` is intentionally different from rebuild: it deletes both OTel +staging tables and their source cursors along with the other tracker-owned rows. + ## Allowance Intelligence Materializations `allowance_observations` stores normalized structured weekly and 5-hour snapshots, diff --git a/docs/pricing-and-credits.md b/docs/pricing-and-credits.md index a667d11e..c01ffd74 100644 --- a/docs/pricing-and-credits.md +++ b/docs/pricing-and-credits.md @@ -14,7 +14,7 @@ Enable optional cost estimates: codex-usage-tracker update-pricing ``` -This fetches OpenAI text-token pricing from `https://developers.openai.com/api/docs/pricing.md`, parses the selected tier, and writes a source-stamped local cache to `~/.codex-usage-tracker/pricing.json`. The default tier is `standard`; other supported tiers are `batch`, `flex`, and `priority`. +This fetches OpenAI text-token pricing from `https://developers.openai.com/api/docs/pricing.md` once, parses the `standard`, `batch`, `flex`, and `priority` tables, and writes a source-stamped pricing-v2 cache to `~/.codex-usage-tracker/pricing.json`. The top-level `models` object remains the selected-tier compatibility projection, while `api_service_tiers` retains every published table so mixed historical calls can be priced by their observed response tier. The updater supports both the older four-value pricing rows and the newer five-value rows used by GPT-5.6 for input, cached input, cache writes, and output. GPT-5.6 Sol, Terra, and Luna are loaded from the published table, and the documented `gpt-5.6` alias resolves to `gpt-5.6-sol`. Current Codex logs do not expose a separate cache-write token counter, so cost estimates use the logged uncached input, cached input, and output counters without adding an explicit cache-write charge. @@ -39,6 +39,20 @@ codex-usage-tracker init-pricing Edit `~/.codex-usage-tracker/pricing.json` with USD-per-million-token rates for local overrides or models that are not present in the OpenAI pricing table. Normal reports never contact the network; only `update-pricing` refreshes the local pricing cache. +### Billing Basis And Tier Scenarios + +OTel `service_tier=priority` proves the response tier, but it does not prove whether the call used ChatGPT/Codex credits or an API key. Set the top-level local `billing_basis` only when you know the billing path: + +```json +{ + "billing_basis": "unknown" +} +``` + +Supported values are `unknown`, `chatgpt_credits`, and `api_tokens`. `update-pricing` preserves this local value. Invalid values make the pricing config invalid instead of silently guessing. + +`estimated_cost_usd` is always an API-token-equivalent estimate. With pricing-v2, it selects the exact observed API table for `priority`, `default`/`standard`, `flex`, or `batch`; it never applies a generic ChatGPT Fast multiplier. Each annotated row also exposes `standard_cost_usd`, `priority_cost_usd`, `pricing_service_tier`, `billing_basis`, and `cost_semantics` so an unknown billing path can be reported as bounded scenarios rather than false actual spend. Pricing-v1 files remain readable and keep their existing single-table behavior. + ## Codex Credits `Codex Credits` is a calculated usage number, not a dashboard-only unit. The tracker uses Codex's logged aggregate token counters and the bundled OpenAI Codex rate-card snapshot to estimate credits consumed by local Codex calls. @@ -72,15 +86,21 @@ multiplier to produce `usage_credits`: - GPT-5.5 family: `2.5x` - GPT-5.4 family: `2.0x` -The row also exposes `usage_credit_multiplier` and -`usage_credit_multiplier_source` so the adjustment is auditable. A confirmed +The row also exposes `fast_usage_credits`, `usage_credit_multiplier`, and +source URL/date/confidence fields so the adjustment is auditable independently +from OTel tier evidence. A confirmed Fast call whose model has no documented multiplier stays at `1.0x` and is marked `no_documented_fast_multiplier`; the tracker does not guess. Standard and Unknown-tier calls also stay at `1.0x`. +The bundled `fast_multipliers` rate-card entries are source-stamped. A local +`allowance.json` may override a model-family entry with `multiplier`, +`source_name`, `source_url`, and `fetched_at`; valid local entries are marked +`user_override`, while malformed entries do not replace the bundled value. + This adjustment applies only to Codex/ChatGPT usage-credit estimates. It never -changes USD token-cost estimates, because those continue to use the selected -pricing tier and aggregate token counters. Allowance-drain calibration uses the +changes API USD estimates, which use the observed API service-tier table and +aggregate token counters. Allowance-drain calibration uses the standard-credit baseline so a newly observed Fast label does not redefine the historical credit-to-percentage relationship. @@ -116,6 +136,9 @@ Configure the usage component: Codex `0.143.0` or newer establishes Standard through omission. Older or unmatched history remains Unknown; latency and reasoning effort cannot prove Fast usage. +- `priority` can describe ChatGPT Fast mode or API Priority processing. The + retained telemetry does not identify authentication or billing, so leave + `billing_basis` as `unknown` unless you have independent evidence. - Live account allowance cannot be read automatically by this local tracker, and the dashboard does not infer live remaining allowance from the logged-in account plan. - Observed local-log snapshots may be stale until Codex records another model call, and may omit other agentic surfaces that share the same allowance. - Pricing can change after a report is generated. Use `pin-pricing` when you need reproducible historical cost estimates. diff --git a/docs/privacy.md b/docs/privacy.md index 4f912cb5..d2f1fa3a 100644 --- a/docs/privacy.md +++ b/docs/privacy.md @@ -37,6 +37,13 @@ tier classification. It never persists OTLP response bodies or arbitrary attributes. Default exports do not expose staging fingerprints, source paths, or matched record pointers. Support bundles report only whether the configured completion directory exists and bounded aggregate refresh/reconciliation counts. +The exact response tier does not reveal whether ChatGPT credits or an API key +paid for the call; the tracker keeps that billing basis as separate local +configuration and defaults it to Unknown. + +`rebuild-index` retains aggregate OTel staging so it can reconcile tiers after +canonical rows are recreated. Confirmed `reset-db --yes` deletes that staging +and its cursors. Neither operation changes or deletes the source exporter files. Cloned Codex tasks can copy historical calls into another local JSONL file. The tracker keeps every physical row and its source metadata in SQLite, but default dashboard, CLI, MCP, report, recommendation, allowance, compression, and export totals use one canonical representative for strict fingerprint matches. Similar calls are never excluded on fuzzy evidence. Deduplication diagnostics expose aggregate totals plus bounded provenance metadata for excluded rows; they never include prompt, response, tool-output, or raw-log content. @@ -53,6 +60,11 @@ Default shareable outputs omit indexed or raw content. That includes: - allowance exports - source coverage reports +Tier-aware shareable rows may include exact service-tier labels, API-equivalent +Standard/Priority cost scenarios, ChatGPT-equivalent credit scenarios, billing +basis, and source-stamped multiplier metadata. These are aggregate pricing +annotations and do not include authentication tokens or raw OTel payloads. + Those outputs should not include prompts, assistant messages, tool output, pasted secrets, raw snippets, reconstructed transcript evidence, indexed fragments, or full JSONL records unless a future command is explicitly documented as a local raw/content export. Default totals and allowance intelligence use canonical usage rows. High-confidence diff --git a/frontend/dashboard/src/api/billing.ts b/frontend/dashboard/src/api/billing.ts new file mode 100644 index 00000000..5dca320a --- /dev/null +++ b/frontend/dashboard/src/api/billing.ts @@ -0,0 +1,34 @@ +export type UsageBillingFields = { + estimated_cost_usd?: number | null; + standard_cost_usd?: number | null; + priority_cost_usd?: number | null; + pricing_service_tier?: string | null; + billing_basis?: string | null; + cost_semantics?: string | null; +}; + +export type CallBillingFields = { + cost: number; + standardCost: number | null; + priorityCost: number | null; + pricingServiceTier: string; + billingBasis: string; + costSemantics: string; +}; + +export function usageBillingFields(row: UsageBillingFields): CallBillingFields { + return { + cost: Number(row.estimated_cost_usd ?? 0), + standardCost: optionalNumber(row.standard_cost_usd), + priorityCost: optionalNumber(row.priority_cost_usd), + pricingServiceTier: String(row.pricing_service_tier ?? ''), + billingBasis: String(row.billing_basis ?? 'unknown'), + costSemantics: String(row.cost_semantics ?? 'api_token_estimate'), + }; +} + +function optionalNumber(value: unknown): number | null { + if (value === null || value === undefined || value === '') return null; + const numeric = Number(value); + return Number.isFinite(numeric) ? numeric : null; +} diff --git a/frontend/dashboard/src/api/client.test.ts b/frontend/dashboard/src/api/client.test.ts index 3636817c..e32dc1ce 100644 --- a/frontend/dashboard/src/api/client.test.ts +++ b/frontend/dashboard/src/api/client.test.ts @@ -22,6 +22,39 @@ describe('dashboard API model builder', () => { expect(call.serviceTier).toBe('standard'); }); + it('preserves billing scenarios and Fast multiplier provenance', () => { + const call = usageRowToCall({ + service_tier: 'priority', + fast: 1, + estimated_cost_usd: 0.2, + standard_cost_usd: 0.1, + priority_cost_usd: 0.2, + pricing_service_tier: 'priority', + billing_basis: 'unknown', + cost_semantics: 'api_token_estimate', + standard_usage_credits: 4, + fast_usage_credits: 10, + usage_credit_multiplier: 2.5, + usage_credit_multiplier_source: 'OpenAI Codex Fast mode docs', + usage_credit_multiplier_source_url: 'https://example.invalid/fast', + usage_credit_multiplier_fetched_at: '2026-07-16', + usage_credit_multiplier_confidence: 'exact', + }); + + expect(call).toEqual(expect.objectContaining({ + standardCost: 0.1, + priorityCost: 0.2, + pricingServiceTier: 'priority', + billingBasis: 'unknown', + costSemantics: 'api_token_estimate', + standardUsageCredits: 4, + fastUsageCredits: 10, + usageCreditMultiplierSourceUrl: 'https://example.invalid/fast', + usageCreditMultiplierFetchedAt: '2026-07-16', + usageCreditMultiplierConfidence: 'exact', + })); + }); + it('derives model cost bars from live aggregate rows', () => { const payload: DashboardBootPayload = { loaded_row_count: 3, diff --git a/frontend/dashboard/src/api/client.ts b/frontend/dashboard/src/api/client.ts index 6c27caea..12f3fb2f 100644 --- a/frontend/dashboard/src/api/client.ts +++ b/frontend/dashboard/src/api/client.ts @@ -8,7 +8,7 @@ import { import { buildFindings, buildModelCosts, buildReports } from './modelInsights'; import { buildOverviewSeriesFromDailyValues } from './overviewSeries'; import { scopeSummaryFromBootPayload, summaryNumber } from './dashboardScopeSummary'; -import { usageServiceTierFields } from './serviceTier'; +import { usageBillingFields, usageServiceTierFields } from './rowAnnotations'; import type { CallRow, ContextRuntime, DashboardBootPayload, DashboardModel, MetricCard, Series, ThreadRow, UsageRow, WeeklyWindow } from './types'; import { loadAllUsagePayloadPaged, @@ -555,7 +555,7 @@ export function usageRowToCall(row: UsageRow, index = 0): CallRow { cachedInput: cached, uncachedInput, cachedPct, - cost: Number(row.estimated_cost_usd ?? 0), + ...usageBillingFields(row), duration: formatDuration(durationSeconds), durationSeconds, previousCallGap: formatDuration(previousCallGapSeconds), diff --git a/frontend/dashboard/src/api/rowAnnotations.ts b/frontend/dashboard/src/api/rowAnnotations.ts new file mode 100644 index 00000000..b490ee9d --- /dev/null +++ b/frontend/dashboard/src/api/rowAnnotations.ts @@ -0,0 +1,2 @@ +export { usageBillingFields } from './billing'; +export { usageServiceTierFields } from './serviceTier'; diff --git a/frontend/dashboard/src/api/serviceTier.ts b/frontend/dashboard/src/api/serviceTier.ts index f6ec3dc9..495f4486 100644 --- a/frontend/dashboard/src/api/serviceTier.ts +++ b/frontend/dashboard/src/api/serviceTier.ts @@ -1,7 +1,11 @@ export type UsageServiceTierFields = { standard_usage_credits?: number | null; + fast_usage_credits?: number | null; usage_credit_multiplier?: number | null; usage_credit_multiplier_source?: string | null; + usage_credit_multiplier_source_url?: string | null; + usage_credit_multiplier_fetched_at?: string | null; + usage_credit_multiplier_confidence?: string | null; service_tier?: string | null; fast?: number | boolean | null; service_tier_source?: string | null; @@ -16,8 +20,12 @@ export type CallServiceTierFields = { serviceTierConfidence: string; fastProxyCandidate: boolean; standardUsageCredits: number; + fastUsageCredits: number | null; usageCreditMultiplier: number; usageCreditMultiplierSource: string; + usageCreditMultiplierSourceUrl: string; + usageCreditMultiplierFetchedAt: string; + usageCreditMultiplierConfidence: string; }; export function usageServiceTierFields( @@ -39,7 +47,17 @@ export function usageServiceTierFields( serviceTierConfidence: String(row.service_tier_confidence ?? ''), fastProxyCandidate: durationSeconds > 0 && totalTokens / Math.max(durationSeconds, 1) > 4_000, standardUsageCredits: Number(row.standard_usage_credits ?? row.usage_credits ?? 0), + fastUsageCredits: optionalNumber(row.fast_usage_credits), usageCreditMultiplier: Number(row.usage_credit_multiplier ?? 1), usageCreditMultiplierSource: String(row.usage_credit_multiplier_source ?? ''), + usageCreditMultiplierSourceUrl: String(row.usage_credit_multiplier_source_url ?? ''), + usageCreditMultiplierFetchedAt: String(row.usage_credit_multiplier_fetched_at ?? ''), + usageCreditMultiplierConfidence: String(row.usage_credit_multiplier_confidence ?? ''), }; } + +function optionalNumber(value: unknown): number | null { + if (value === null || value === undefined || value === '') return null; + const numeric = Number(value); + return Number.isFinite(numeric) ? numeric : null; +} diff --git a/frontend/dashboard/src/api/types.ts b/frontend/dashboard/src/api/types.ts index 948f57d5..75435744 100644 --- a/frontend/dashboard/src/api/types.ts +++ b/frontend/dashboard/src/api/types.ts @@ -1,7 +1,8 @@ +import type { CallBillingFields, UsageBillingFields } from './billing'; import type { DashboardDataScope, DashboardModelScope } from './dashboardDataScope'; import type { CallServiceTierFields, UsageServiceTierFields } from './serviceTier'; -export type UsageRow = UsageServiceTierFields & { +export type UsageRow = UsageBillingFields & UsageServiceTierFields & { id?: string; record_id?: string; session_id?: string; @@ -43,7 +44,6 @@ export type UsageRow = UsageServiceTierFields & { reasoning_output_tokens?: number; total_tokens?: number; uncached_input_tokens?: number; - estimated_cost_usd?: number; usage_credits?: number; rate_limit_plan_type?: string | null; rate_limit_limit_id?: string | null; @@ -291,7 +291,7 @@ export type Finding = { summary: string; }; -export type CallRow = CallServiceTierFields & { +export type CallRow = CallBillingFields & CallServiceTierFields & { id: string; threadKey?: string; rawTime: string; @@ -308,7 +308,6 @@ export type CallRow = CallServiceTierFields & { cachedInput: number; uncachedInput: number; cachedPct: number; - cost: number; duration: string; durationSeconds: number; previousCallGap: string; diff --git a/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx b/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx index 40de7fa5..ea61f0d5 100644 --- a/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx +++ b/frontend/dashboard/src/features/call-investigator/CallInvestigatorPage.tsx @@ -14,7 +14,7 @@ import { ContextEntryMetadata } from '../shared/ContextEntryMetadata'; import { CallSourceMetadata } from '../shared/CallSourceMetadata'; import { TokenPricingBreakdown } from '../shared/TokenPricingBreakdown'; import { ThreadCallTimeline } from '../shared/ThreadCallTimeline'; -import { cacheState, contextWindowLabel, serviceTierDetail, sourceLine, summarizeTopCounts } from '../shared/callPresentation'; +import { billingBasisDetail, cacheState, contextWindowLabel, serviceTierDetail, sourceLine, summarizeTopCounts } from '../shared/callPresentation'; import { copyText } from '../shared/copyText'; import { CallSignalPucks } from '../shared/tables'; import { @@ -209,7 +209,7 @@ throw new Error('Clipboard unavailable'); - + diff --git a/frontend/dashboard/src/features/calls/CallInspector.tsx b/frontend/dashboard/src/features/calls/CallInspector.tsx index bc045a4a..032978cf 100644 --- a/frontend/dashboard/src/features/calls/CallInspector.tsx +++ b/frontend/dashboard/src/features/calls/CallInspector.tsx @@ -20,7 +20,7 @@ import { CallDecisionCard } from '../shared/CallDecisionCard'; import { CallSourceMetadata } from '../shared/CallSourceMetadata'; import { TokenPricingBreakdown } from '../shared/TokenPricingBreakdown'; import { ThreadCallTimeline } from '../shared/ThreadCallTimeline'; -import { cacheState, summarizeTopCounts } from '../shared/callPresentation'; +import { billingBasisDetail, cacheState, summarizeTopCounts } from '../shared/callPresentation'; import { copyText } from '../shared/copyText'; import { formatCompact, formatNumber, money, pct } from '../shared/format'; import { CallSignalPucks } from '../shared/tables'; @@ -166,7 +166,7 @@ function SummaryTab({ call }: { call: CallRow }) { - + diff --git a/frontend/dashboard/src/features/shared/callPresentation.test.ts b/frontend/dashboard/src/features/shared/callPresentation.test.ts index 8d033710..9683dffe 100644 --- a/frontend/dashboard/src/features/shared/callPresentation.test.ts +++ b/frontend/dashboard/src/features/shared/callPresentation.test.ts @@ -1,5 +1,11 @@ import { describe, expect, it } from 'vitest'; -import { cacheState, contextWindowLabel, sourceLine, summarizeTopCounts } from './callPresentation'; +import { + billingBasisDetail, + cacheState, + contextWindowLabel, + sourceLine, + summarizeTopCounts, +} from './callPresentation'; describe('call presentation helpers', () => { it('labels cache state thresholds consistently across call surfaces', () => { @@ -30,4 +36,16 @@ describe('call presentation helpers', () => { ); expect(summarizeTopCounts([], { emptyLabel: 'no model mix' })).toBe('no model mix'); }); + + it('labels API-equivalent scenarios without claiming actual billing', () => { + expect(billingBasisDetail({ billingBasis: 'unknown', pricingServiceTier: 'priority' })).toBe( + 'API-equivalent scenario · billing basis unknown', + ); + expect(billingBasisDetail({ billingBasis: 'api_tokens', pricingServiceTier: 'priority' })).toBe( + 'API token estimate · Priority rates', + ); + expect(billingBasisDetail({ billingBasis: 'chatgpt_credits', pricingServiceTier: 'priority' })).toBe( + 'API-equivalent scenario · ChatGPT credits selected', + ); + }); }); diff --git a/frontend/dashboard/src/features/shared/callPresentation.ts b/frontend/dashboard/src/features/shared/callPresentation.ts index b4ca2fed..02813a11 100644 --- a/frontend/dashboard/src/features/shared/callPresentation.ts +++ b/frontend/dashboard/src/features/shared/callPresentation.ts @@ -23,6 +23,11 @@ type ServiceTierInput = { fastProxyCandidate: boolean; }; +type BillingBasisInput = { + billingBasis: string; + pricingServiceTier: string; +}; + const knownServiceTierLabels: Record = { priority: 'Priority / Fast', fast: 'Fast', @@ -65,6 +70,20 @@ export function serviceTierDetail(call: ServiceTierInput): string { : 'tier unknown · normal throughput proxy'; } +export function billingBasisDetail(call: BillingBasisInput): string { + if (call.billingBasis === 'api_tokens') { + const tier = call.pricingServiceTier.trim(); + const label = tier + ? `${tier.charAt(0).toUpperCase()}${tier.slice(1).toLowerCase()} rates` + : 'configured rates'; + return `API token estimate · ${label}`; + } + if (call.billingBasis === 'chatgpt_credits') { + return 'API-equivalent scenario · ChatGPT credits selected'; + } + return 'API-equivalent scenario · billing basis unknown'; +} + export function cacheState(call: CacheStateInput): string { if (call.cachedPct < 25) return 'cold or weak cache'; if (call.cachedPct < 50) return 'partial cache reuse'; diff --git a/frontend/dashboard/src/features/shared/tables.test.ts b/frontend/dashboard/src/features/shared/tables.test.ts index 93389ff7..e9b1dc6d 100644 --- a/frontend/dashboard/src/features/shared/tables.test.ts +++ b/frontend/dashboard/src/features/shared/tables.test.ts @@ -23,6 +23,11 @@ describe('call CSV columns', () => { uncachedInput: 600, cachedPct: 40, cost: 0.123456, + standardCost: 0.1, + priorityCost: 0.2, + pricingServiceTier: 'standard', + billingBasis: 'unknown', + costSemantics: 'api_token_estimate', credits: 4.5, duration: '2m 0s', durationSeconds: 120, @@ -38,8 +43,12 @@ describe('call CSV columns', () => { serviceTierConfidence: 'protocol', fastProxyCandidate: true, standardUsageCredits: 4.5, + fastUsageCredits: 9, usageCreditMultiplier: 1, usageCreditMultiplierSource: 'otel_response_completed', + usageCreditMultiplierSourceUrl: 'https://example.invalid/fast', + usageCreditMultiplierFetchedAt: '2026-07-16', + usageCreditMultiplierConfidence: 'exact', usageCreditConfidence: 'credit-estimated', usageCreditModel: 'codex-1', usageCreditSource: 'rate-card', @@ -99,6 +108,11 @@ expect(header).toContain('usage_credit_confidence'); expect(header).toContain('service_tier_confidence'); expect(header).toContain('fast_proxy_candidate'); expect(header).toContain('usage_credit_multiplier'); + expect(header).toContain('standard_cost_usd'); + expect(header).toContain('priority_cost_usd'); + expect(header).toContain('billing_basis'); + expect(header).toContain('fast_usage_credits'); + expect(header).toContain('usage_credit_multiplier_source_url'); expect(header).toContain('thread_attachment'); expect(header).toContain('model_context_window'); expect(values).toContain('record-csv-1'); diff --git a/frontend/dashboard/src/features/shared/tables.tsx b/frontend/dashboard/src/features/shared/tables.tsx index 45c6860a..c0f4abec 100644 --- a/frontend/dashboard/src/features/shared/tables.tsx +++ b/frontend/dashboard/src/features/shared/tables.tsx @@ -118,8 +118,14 @@ export const callCsvColumns: Array> = [ { header: 'output_tokens', value: row => row.output }, { header: 'reasoning_output_tokens', value: row => row.reasoningOutput }, { header: 'estimated_cost_usd', value: row => row.cost.toFixed(6) }, + { header: 'standard_cost_usd', value: row => row.standardCost?.toFixed(6) ?? '' }, + { header: 'priority_cost_usd', value: row => row.priorityCost?.toFixed(6) ?? '' }, + { header: 'pricing_service_tier', value: row => row.pricingServiceTier }, + { header: 'billing_basis', value: row => row.billingBasis }, + { header: 'cost_semantics', value: row => row.costSemantics }, { header: 'usage_credits', value: row => row.credits.toFixed(6) }, { header: 'standard_usage_credits', value: row => row.standardUsageCredits.toFixed(6) }, + { header: 'fast_usage_credits', value: row => row.fastUsageCredits?.toFixed(6) ?? '' }, { header: 'service_tier', value: row => row.serviceTier }, { header: 'fast', value: row => row.fast === null ? '' : row.fast ? 1 : 0 }, { header: 'service_tier_source', value: row => row.serviceTierSource }, @@ -127,6 +133,9 @@ export const callCsvColumns: Array> = [ { header: 'fast_proxy_candidate', value: row => String(row.fastProxyCandidate) }, { header: 'usage_credit_multiplier', value: row => row.usageCreditMultiplier }, { header: 'usage_credit_multiplier_source', value: row => row.usageCreditMultiplierSource }, + { header: 'usage_credit_multiplier_source_url', value: row => row.usageCreditMultiplierSourceUrl }, + { header: 'usage_credit_multiplier_fetched_at', value: row => row.usageCreditMultiplierFetchedAt }, + { header: 'usage_credit_multiplier_confidence', value: row => row.usageCreditMultiplierConfidence }, { header: 'cache_ratio', value: row => row.cachedPct.toFixed(2) }, { header: 'context_window_percent', value: row => row.contextWindowPct?.toFixed(2) ?? '' }, { header: 'pricing_model', value: row => row.pricingModel }, diff --git a/frontend/dashboard/src/test-fixtures/dashboardFixture.ts b/frontend/dashboard/src/test-fixtures/dashboardFixture.ts index 77cf2ce1..f005098e 100644 --- a/frontend/dashboard/src/test-fixtures/dashboardFixture.ts +++ b/frontend/dashboard/src/test-fixtures/dashboardFixture.ts @@ -141,6 +141,11 @@ export const fixtureModel: DashboardModel = { uncachedInput, cachedPct: cachedPercent, cost: index === 4 ? 0 : Number(cost), + standardCost: index === 4 ? 0 : Number(cost), + priorityCost: index === 4 ? 0 : Number(cost) * 2, + pricingServiceTier: 'standard', + billingBasis: 'unknown', + costSemantics: 'api_token_estimate', credits: (index === 4 ? 0 : Number(cost)) * 25, duration: String(duration), durationSeconds: Number.parseFloat(String(duration)) || 0, @@ -156,8 +161,12 @@ export const fixtureModel: DashboardModel = { serviceTierConfidence: '', fastProxyCandidate: Boolean(fast), standardUsageCredits: (index === 4 ? 0 : Number(cost)) * 25, + fastUsageCredits: (index === 4 ? 0 : Number(cost)) * 50, usageCreditMultiplier: 1, usageCreditMultiplierSource: 'tier_unknown', + usageCreditMultiplierSourceUrl: 'https://example.invalid/fixture-fast', + usageCreditMultiplierFetchedAt: '2026-07-16', + usageCreditMultiplierConfidence: 'exact', usageCreditConfidence: index === 7 ? 'user_override' : index % 4 === 0 ? 'exact' : index % 4 === 1 ? 'estimated' : index % 4 === 2 ? 'missing' : 'fixture', usageCreditModel: index === 4 ? '' : `${model}-credits`, usageCreditSource: index === 4 ? '' : 'fixture-rate-card', diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js index a8334962..b70b4803 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/App.js @@ -1,128 +1,128 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ThreadsPage.js","assets/dashboard-react.js","assets/index.css","assets/useInfiniteQuery.js","assets/useBaseQuery.js","assets/exploreQueries.js","assets/queryOptions.js","assets/infiniteQueryOptions.js","assets/ExploreWorkspaceSwitcher.js","assets/Primitives.js","assets/Primitives.css","assets/EvidenceGridControls.js","assets/router.js","assets/EvidenceGridControls.css","assets/filtering.js","assets/threadSummaryAdapter.js","assets/UsageConstellation.js","assets/triangle-alert.js","assets/UsageConstellation.css","assets/StatusBadge.js","assets/PageLoadProgress.js","assets/PageLoadProgress.css","assets/index2.js","assets/rowActionEvents.js","assets/search.js","assets/locale-zh-Hans.js","assets/dashboardRouter.js","assets/ThreadsPage.css","assets/CacheContextPage.js","assets/LineChart.js","assets/DataTable.js","assets/overviewQueries.js","assets/gauge.js","assets/Panel.js","assets/useQuery.js","assets/tableActions.js","assets/UsageDrainPage.js","assets/chevron-right.js","assets/shield-check.js","assets/UsageDrainPage.css","assets/DiagnosticsPage.js","assets/diagnosticsQueries.js","assets/ReportsPage.js","assets/ReportsPage.css","assets/CallsPage.js","assets/EvidenceGrid.js","assets/contextEvidenceState.js","assets/lock-keyhole.js","assets/CallsPage.css","assets/OverviewPage.js","assets/OverviewPage.css","assets/InvestigatorPage.js","assets/InvestigatorPage.css","assets/CompressionLabPage.js","assets/CompressionLabPage.css","assets/ExploreRoutePage.js","assets/ExploreRoutePage.css","assets/CallInvestigatorPage.js","assets/SettingsPage.js","assets/SettingsPage.css"])))=>i.map(i=>d[i]); -var qn=e=>{throw TypeError(e)};var Kt=(e,t,n)=>t.has(e)||qn("Cannot "+n);var l=(e,t,n)=>(Kt(e,t,"read from private field"),n?n.call(e):t.get(e)),P=(e,t,n)=>t.has(e)?qn("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),x=(e,t,n,a)=>(Kt(e,t,"write to private field"),a?a.call(e,n):t.set(e,n),n),V=(e,t,n)=>(Kt(e,t,"access private method"),n);var Ct=(e,t,n,a)=>({set _(r){x(e,t,r,n)},get _(){return l(e,t,a)}});import{r as C,j as c,_ as O}from"./dashboard-react.js";import{t as bs}from"./locale-zh-Hans.js";import{i as ws}from"./dashboardRouter.js";import{a9 as se}from"./router.js";/** +var Hn=e=>{throw TypeError(e)};var Kt=(e,t,n)=>t.has(e)||Hn("Cannot "+n);var l=(e,t,n)=>(Kt(e,t,"read from private field"),n?n.call(e):t.get(e)),P=(e,t,n)=>t.has(e)?Hn("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),x=(e,t,n,a)=>(Kt(e,t,"write to private field"),a?a.call(e,n):t.set(e,n),n),V=(e,t,n)=>(Kt(e,t,"access private method"),n);var Ct=(e,t,n,a)=>({set _(r){x(e,t,r,n)},get _(){return l(e,t,a)}});import{r as C,j as c,_ as O}from"./dashboard-react.js";import{t as ys}from"./locale-zh-Hans.js";import{i as _s}from"./dashboardRouter.js";import{a9 as se}from"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const ys=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),Na=(...e)=>e.filter((t,n,a)=>!!t&&t.trim()!==""&&a.indexOf(t)===n).join(" ").trim();/** + */const Ss=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),Fa=(...e)=>e.filter((t,n,a)=>!!t&&t.trim()!==""&&a.indexOf(t)===n).join(" ").trim();/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */var _s={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** + */var Cs={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ss=C.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:n=2,absoluteStrokeWidth:a,className:r="",children:s,iconNode:i,...o},d)=>C.createElement("svg",{ref:d,..._s,width:t,height:t,stroke:e,strokeWidth:a?Number(n)*24/Number(t):n,className:Na("lucide",r),...o},[...i.map(([f,h])=>C.createElement(f,h)),...Array.isArray(s)?s:[s]]));/** + */const xs=C.forwardRef(({color:e="currentColor",size:t=24,strokeWidth:n=2,absoluteStrokeWidth:a,className:r="",children:s,iconNode:i,...o},d)=>C.createElement("svg",{ref:d,...Cs,width:t,height:t,stroke:e,strokeWidth:a?Number(n)*24/Number(t):n,className:Fa("lucide",r),...o},[...i.map(([f,h])=>C.createElement(f,h)),...Array.isArray(s)?s:[s]]));/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const I=(e,t)=>{const n=C.forwardRef(({className:a,...r},s)=>C.createElement(Ss,{ref:s,iconNode:t,className:Na(`lucide-${ys(e)}`,a),...r}));return n.displayName=`${e}`,n};/** + */const $=(e,t)=>{const n=C.forwardRef(({className:a,...r},s)=>C.createElement(xs,{ref:s,iconNode:t,className:Fa(`lucide-${Ss(e)}`,a),...r}));return n.displayName=`${e}`,n};/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Cs=I("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);/** + */const ks=$("Activity",[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",key:"169zse"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const xs=I("ArrowUp",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/** + */const Ts=$("ArrowUp",[["path",{d:"m5 12 7-7 7 7",key:"hav0vg"}],["path",{d:"M12 19V5",key:"x0mq9r"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const ks=I("BookOpen",[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]]);/** + */const Ls=$("BookOpen",[["path",{d:"M12 7v14",key:"1akyts"}],["path",{d:"M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z",key:"ruj8y"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ts=I("Boxes",[["path",{d:"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z",key:"lc1i9w"}],["path",{d:"m7 16.5-4.74-2.85",key:"1o9zyk"}],["path",{d:"m7 16.5 5-3",key:"va8pkn"}],["path",{d:"M7 16.5v5.17",key:"jnp8gn"}],["path",{d:"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z",key:"8zsnat"}],["path",{d:"m17 16.5-5-3",key:"8arw3v"}],["path",{d:"m17 16.5 4.74-2.85",key:"8rfmw"}],["path",{d:"M17 16.5v5.17",key:"k6z78m"}],["path",{d:"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z",key:"1xygjf"}],["path",{d:"M12 8 7.26 5.15",key:"1vbdud"}],["path",{d:"m12 8 4.74-2.85",key:"3rx089"}],["path",{d:"M12 13.5V8",key:"1io7kd"}]]);/** + */const Rs=$("Boxes",[["path",{d:"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z",key:"lc1i9w"}],["path",{d:"m7 16.5-4.74-2.85",key:"1o9zyk"}],["path",{d:"m7 16.5 5-3",key:"va8pkn"}],["path",{d:"M7 16.5v5.17",key:"jnp8gn"}],["path",{d:"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z",key:"8zsnat"}],["path",{d:"m17 16.5-5-3",key:"8arw3v"}],["path",{d:"m17 16.5 4.74-2.85",key:"8rfmw"}],["path",{d:"M17 16.5v5.17",key:"k6z78m"}],["path",{d:"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z",key:"1xygjf"}],["path",{d:"M12 8 7.26 5.15",key:"1vbdud"}],["path",{d:"m12 8 4.74-2.85",key:"3rx089"}],["path",{d:"M12 13.5V8",key:"1io7kd"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ls=I("BrainCircuit",[["path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z",key:"l5xja"}],["path",{d:"M9 13a4.5 4.5 0 0 0 3-4",key:"10igwf"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5",key:"105sqy"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396",key:"ql3yin"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516",key:"2e4loj"}],["path",{d:"M12 13h4",key:"1ku699"}],["path",{d:"M12 18h6a2 2 0 0 1 2 2v1",key:"105ag5"}],["path",{d:"M12 8h8",key:"1lhi5i"}],["path",{d:"M16 8V5a2 2 0 0 1 2-2",key:"u6izg6"}],["circle",{cx:"16",cy:"13",r:".5",key:"ry7gng"}],["circle",{cx:"18",cy:"3",r:".5",key:"1aiba7"}],["circle",{cx:"20",cy:"21",r:".5",key:"yhc1fs"}],["circle",{cx:"20",cy:"8",r:".5",key:"1e43v0"}]]);/** + */const Ms=$("BrainCircuit",[["path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z",key:"l5xja"}],["path",{d:"M9 13a4.5 4.5 0 0 0 3-4",key:"10igwf"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5",key:"105sqy"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396",key:"ql3yin"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516",key:"2e4loj"}],["path",{d:"M12 13h4",key:"1ku699"}],["path",{d:"M12 18h6a2 2 0 0 1 2 2v1",key:"105ag5"}],["path",{d:"M12 8h8",key:"1lhi5i"}],["path",{d:"M16 8V5a2 2 0 0 1 2-2",key:"u6izg6"}],["circle",{cx:"16",cy:"13",r:".5",key:"ry7gng"}],["circle",{cx:"18",cy:"3",r:".5",key:"1aiba7"}],["circle",{cx:"20",cy:"21",r:".5",key:"yhc1fs"}],["circle",{cx:"20",cy:"8",r:".5",key:"1e43v0"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Rs=I("ChartColumn",[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"M18 17V9",key:"2bz60n"}],["path",{d:"M13 17V5",key:"1frdt8"}],["path",{d:"M8 17v-3",key:"17ska0"}]]);/** + */const Ps=$("ChartColumn",[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16",key:"c24i48"}],["path",{d:"M18 17V9",key:"2bz60n"}],["path",{d:"M13 17V5",key:"1frdt8"}],["path",{d:"M8 17v-3",key:"17ska0"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ms=I("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/** + */const js=$("Copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ps=I("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/** + */const As=$("Database",[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3",key:"msslwz"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5",key:"1wlel7"}],["path",{d:"M3 12A9 3 0 0 0 21 12",key:"mv7ke4"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const js=I("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/** + */const Ns=$("Download",[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["polyline",{points:"7 10 12 15 17 10",key:"2ggqvy"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3",key:"1vk2je"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const As=I("FileText",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]]);/** + */const Es=$("FileText",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M10 9H8",key:"b1mrlr"}],["path",{d:"M16 13H8",key:"t4e002"}],["path",{d:"M16 17H8",key:"z1uh3a"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ns=I("Filter",[["polygon",{points:"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3",key:"1yg77f"}]]);/** + */const Fs=$("Filter",[["polygon",{points:"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3",key:"1yg77f"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Es=I("FlaskConical",[["path",{d:"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2",key:"18mbvz"}],["path",{d:"M6.453 15h11.094",key:"3shlmq"}],["path",{d:"M8.5 2h7",key:"csnxdl"}]]);/** + */const Ds=$("FlaskConical",[["path",{d:"M14 2v6a2 2 0 0 0 .245.96l5.51 10.08A2 2 0 0 1 18 22H6a2 2 0 0 1-1.755-2.96l5.51-10.08A2 2 0 0 0 10 8V2",key:"18mbvz"}],["path",{d:"M6.453 15h11.094",key:"3shlmq"}],["path",{d:"M8.5 2h7",key:"csnxdl"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ds=I("House",[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"1d0kgt"}]]);/** + */const $s=$("House",[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"1d0kgt"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Fs=I("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** + */const Is=$("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Is=I("Settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/** + */const Os=$("Settings",[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z",key:"1qme2f"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const $s=I("ShieldAlert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);/** + */const Us=$("ShieldAlert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Os=I("Table2",[["path",{d:"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18",key:"gugj83"}]]);/** + */const Vs=$("Table2",[["path",{d:"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18",key:"gugj83"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Us=I("Terminal",[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]]);/** + */const Ks=$("Terminal",[["polyline",{points:"4 17 10 11 4 5",key:"akl6gq"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19",key:"q2wloq"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Vs=I("TimerReset",[["path",{d:"M10 2h4",key:"n1abiw"}],["path",{d:"M12 14v-4",key:"1evpnu"}],["path",{d:"M4 13a8 8 0 0 1 8-7 8 8 0 1 1-5.3 14L4 17.6",key:"1ts96g"}],["path",{d:"M9 17H4v5",key:"8t5av"}]]);/** + */const qs=$("TimerReset",[["path",{d:"M10 2h4",key:"n1abiw"}],["path",{d:"M12 14v-4",key:"1evpnu"}],["path",{d:"M4 13a8 8 0 0 1 8-7 8 8 0 1 1-5.3 14L4 17.6",key:"1ts96g"}],["path",{d:"M9 17H4v5",key:"8t5av"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Ks=I("Workflow",[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2",key:"by2w9f"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4",key:"xkn7yn"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2",key:"1cgmvn"}]]);/** + */const Hs=$("Workflow",[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2",key:"by2w9f"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4",key:"xkn7yn"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2",key:"1cgmvn"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const un=I("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),Ea="codex-usage-dashboard-language",qs={"button.back_to_dashboard":"Back to dashboard","button.clear":"Clear","button.copy_link":"Copy link","button.enable_context_loading":"Enable context loading","button.export_csv":"Export CSV","button.full_serialized_analysis":"Run full serialized analysis","button.hide_details":"Hide details","button.include_tool_output":"Include tool output","button.load_more":"Load more","button.load_older_context":"Load older entries","button.next_call":"Next call","button.no_char_limit":"No char limit","button.open_investigator":"Open investigator","button.previous_call":"Previous call","button.refresh":"Refresh","button.show_compaction_history":"Show compacted replacement","button.show_tool_output":"Show tool output","button.top":"Top","button.show_turn_evidence":"Show turn log evidence","badge.live":"Live","dashboard.eyebrow":"Local Codex analytics","dashboard.call_details":"Call Details","dashboard.title":"Usage Dashboard","dashboard.view.call":"Call Investigator","dashboard.view.calls":"Calls","dashboard.view.insights":"Overview","dashboard.view.overview":"Overview","dashboard.view.threads":"Threads","detail.next_action":"Next action","filter.search":"Search dashboard","filter.search_placeholder":"Search calls, threads, models, diagnostics...","language.label":"Language","nav.history":"History","nav.load":"Load","nav.live":"Live","option.active_sessions_only":"Active","option.all_history":"All history","status.paused":"Paused","status.static":"Static"},Hs={overview:"dashboard.view.overview",calls:"dashboard.view.calls",call:"dashboard.view.call",threads:"dashboard.view.threads"};function Nl(e,t){return typeof t=="string"?e.translateText(t):e.formatText(t.template,t.values)}function Da(e,t){const n=Fa(e),a=Ia(t,n),r=(e==null?void 0:e.translation_catalog)??{},s=r[a]??((e==null?void 0:e.language)===a?e==null?void 0:e.translations:void 0)??{},i=r.en??((e==null?void 0:e.language)==="en"?e.translations:void 0)??{},o={...qs,...i,...s},d=Qs(i,s),f=Ws(i,s),h=n.find(p=>p.code===a),b=(h==null?void 0:h.dir)==="rtl"||!h&&(e==null?void 0:e.language_direction)==="rtl"?"rtl":"ltr",u=p=>a==="zh-Hans"?bs(p,d,f):d.get(p)??p;return{language:a,direction:b,languages:n,t:(p,g)=>o[p]??g??p,translateText:u,formatText:(p,g)=>u(p).replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu,(v,w)=>String(g[String(w)]??v)),navLabel:(p,g)=>{const v=Hs[p];return v?o[v]??g:g}}}function Ws(e,t){const n=[];for(const[a,r]of Object.entries(e)){const s=t[a];if(!s||s===r||!r.includes("{"))continue;const i=[],o=[];let d=0;for(const f of r.matchAll(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu)){const h=f.index??d;o.push(Hn(r.slice(d,h))),o.push("(.+?)"),i.push(f[1]),d=h+f[0].length}o.push(Hn(r.slice(d))),n.push({pattern:new RegExp(`^${o.join("")}$`,"u"),placeholders:i,translatedTemplate:s})}return n.sort((a,r)=>r.translatedTemplate.length-a.translatedTemplate.length)}function Hn(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function Qs(e,t){const n=new Map;for(const[a,r]of Object.entries(e)){const s=t[a];s&&s!==r&&n.set(r,s)}return n}function Fa(e){var n;const t=((n=e==null?void 0:e.available_languages)==null?void 0:n.filter(a=>a.code))??[];return t.length?t:[{code:"en",english_name:"English",native_name:"English",dir:"ltr"}]}function zs(e){return Ia(Gs()||(e==null?void 0:e.language)||"en",Fa(e))}function Bs(e){var t;try{(t=window.localStorage)==null||t.setItem(Ea,e)}catch{}}function Gs(){var e;try{return((e=window.localStorage)==null?void 0:e.getItem(Ea))??""}catch{return""}}function Ia(e,t){if(new Set(t.map(s=>s.code)).has(e))return e;const a=e.toLowerCase(),r=t.find(s=>s.code.toLowerCase()===a);return(r==null?void 0:r.code)??"en"}const Js=Da(null,"en"),$a=C.createContext(Js);function Zs({value:e,children:t}){return c.jsx($a.Provider,{value:e,children:t})}function Oa(){return C.useContext($a)}var Et=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Ne,we,Be,xa,Xs=(xa=class extends Et{constructor(){super();P(this,Ne);P(this,we);P(this,Be);x(this,Be,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t();return window.addEventListener("visibilitychange",n,!1),()=>{window.removeEventListener("visibilitychange",n)}}})}onSubscribe(){l(this,we)||this.setEventListener(l(this,Be))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,we))==null||t.call(this),x(this,we,void 0))}setEventListener(t){var n;x(this,Be,t),(n=l(this,we))==null||n.call(this),x(this,we,t(a=>{typeof a=="boolean"?this.setFocused(a):this.onFocus()}))}setFocused(t){l(this,Ne)!==t&&(x(this,Ne,t),this.onFocus())}onFocus(){const t=this.isFocused();this.listeners.forEach(n=>{n(t)})}isFocused(){var t;return typeof l(this,Ne)=="boolean"?l(this,Ne):((t=globalThis.document)==null?void 0:t.visibilityState)!=="hidden"}},Ne=new WeakMap,we=new WeakMap,Be=new WeakMap,xa),Ua=new Xs,Ys={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},ye,ln,ka,ei=(ka=class{constructor(){P(this,ye,Ys);P(this,ln,!1)}setTimeoutProvider(e){x(this,ye,e)}setTimeout(e,t){return l(this,ye).setTimeout(e,t)}clearTimeout(e){l(this,ye).clearTimeout(e)}setInterval(e,t){return l(this,ye).setInterval(e,t)}clearInterval(e){l(this,ye).clearInterval(e)}},ye=new WeakMap,ln=new WeakMap,ka),Bt=new ei;function ti(e){setTimeout(e,0)}var ni=typeof window>"u"||"Deno"in globalThis;function ne(){}function ai(e,t){return typeof e=="function"?e(t):e}function ri(e){return typeof e=="number"&&e>=0&&e!==1/0}function si(e,t){return Math.max(e+(t||0)-Date.now(),0)}function Gt(e,t){return typeof e=="function"?e(t):e}function ii(e,t){return typeof e=="function"?e(t):e}function Wn(e,t){const{type:n="all",exact:a,fetchStatus:r,predicate:s,queryKey:i,stale:o}=e;if(i){if(a){if(t.queryHash!==dn(i,t.options))return!1}else if(!ut(t.queryKey,i))return!1}if(n!=="all"){const d=t.isActive();if(n==="active"&&!d||n==="inactive"&&d)return!1}return!(typeof o=="boolean"&&t.isStale()!==o||r&&r!==t.state.fetchStatus||s&&!s(t))}function Qn(e,t){const{exact:n,status:a,predicate:r,mutationKey:s}=e;if(s){if(!t.options.mutationKey)return!1;if(n){if(lt(t.options.mutationKey)!==lt(s))return!1}else if(!ut(t.options.mutationKey,s))return!1}return!(a&&t.state.status!==a||r&&!r(t))}function dn(e,t){return((t==null?void 0:t.queryKeyHashFn)||lt)(e)}function lt(e){return JSON.stringify(e,(t,n)=>Jt(n)?Object.keys(n).sort().reduce((a,r)=>(a[r]=n[r],a),{}):n)}function ut(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="object"&&typeof t=="object"?Object.keys(t).every(n=>ut(e[n],t[n])):!1}var oi=Object.prototype.hasOwnProperty;function Va(e,t,n=0){if(e===t)return e;if(n>500)return t;const a=zn(e)&&zn(t);if(!a&&!(Jt(e)&&Jt(t)))return t;const s=(a?e:Object.keys(e)).length,i=a?t:Object.keys(t),o=i.length,d=a?new Array(o):{};let f=0;for(let h=0;h{Bt.setTimeout(t,e)})}function li(e,t,n){return typeof n.structuralSharing=="function"?n.structuralSharing(e,t):n.structuralSharing!==!1?Va(e,t):t}function ui(e,t,n=0){const a=[...e,t];return n&&a.length>n?a.slice(1):a}function di(e,t,n=0){const a=[t,...e];return n&&a.length>n?a.slice(0,-1):a}var hn=Symbol();function Ka(e,t){return!e.queryFn&&(t!=null&&t.initialPromise)?()=>t.initialPromise:!e.queryFn||e.queryFn===hn?()=>Promise.reject(new Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function Dl(e,t){return typeof e=="function"?e(...t):!!e}function hi(e,t,n){let a=!1,r;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(r??(r=t()),a||(a=!0,r.aborted?n():r.addEventListener("abort",n,{once:!0})),r)}),e}var qa=(()=>{let e=()=>ni;return{isServer(){return e()},setIsServer(t){e=t}}})();function fi(){let e,t;const n=new Promise((r,s)=>{e=r,t=s});n.status="pending",n.catch(()=>{});function a(r){Object.assign(n,r),delete n.resolve,delete n.reject}return n.resolve=r=>{a({status:"fulfilled",value:r}),e(r)},n.reject=r=>{a({status:"rejected",reason:r}),t(r)},n}var mi=ti;function gi(){let e=[],t=0,n=o=>{o()},a=o=>{o()},r=mi;const s=o=>{t?e.push(o):r(()=>{n(o)})},i=()=>{const o=e;e=[],o.length&&r(()=>{a(()=>{o.forEach(d=>{n(d)})})})};return{batch:o=>{let d;t++;try{d=o()}finally{t--,t||i()}return d},batchCalls:o=>(...d)=>{s(()=>{o(...d)})},schedule:s,setNotifyFunction:o=>{n=o},setBatchNotifyFunction:o=>{a=o},setScheduler:o=>{r=o}}}var z=gi(),Ge,_e,Je,Ta,pi=(Ta=class extends Et{constructor(){super();P(this,Ge,!0);P(this,_e);P(this,Je);x(this,Je,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t(!0),a=()=>t(!1);return window.addEventListener("online",n,!1),window.addEventListener("offline",a,!1),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",a)}}})}onSubscribe(){l(this,_e)||this.setEventListener(l(this,Je))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,_e))==null||t.call(this),x(this,_e,void 0))}setEventListener(t){var n;x(this,Je,t),(n=l(this,_e))==null||n.call(this),x(this,_e,t(this.setOnline.bind(this)))}setOnline(t){l(this,Ge)!==t&&(x(this,Ge,t),this.listeners.forEach(a=>{a(t)}))}isOnline(){return l(this,Ge)}},Ge=new WeakMap,_e=new WeakMap,Je=new WeakMap,Ta),Tt=new pi;function vi(e){return Math.min(1e3*2**e,3e4)}function Ha(e){return(e??"online")==="online"?Tt.isOnline():!0}var Lt=class extends Error{constructor(e){super("CancelledError"),this.revert=e==null?void 0:e.revert,this.silent=e==null?void 0:e.silent}};function bi(e){return e instanceof Lt}function Wa(e){let t=!1,n=0,a;const r=fi(),s=()=>r.status!=="pending",i=v=>{var w;if(!s()){const T=new Lt(v);u(T),(w=e.onCancel)==null||w.call(e,T)}},o=()=>{t=!0},d=()=>{t=!1},f=()=>Ua.isFocused()&&(e.networkMode==="always"||Tt.isOnline())&&e.canRun(),h=()=>Ha(e.networkMode)&&e.canRun(),b=v=>{s()||(a==null||a(),r.resolve(v))},u=v=>{s()||(a==null||a(),r.reject(v))},p=()=>new Promise(v=>{var w;a=T=>{(s()||f())&&v(T)},(w=e.onPause)==null||w.call(e)}).then(()=>{var v;a=void 0,s()||(v=e.onContinue)==null||v.call(e)}),g=()=>{if(s())return;let v;const w=n===0?e.initialPromise:void 0;try{v=w??e.fn()}catch(T){v=Promise.reject(T)}Promise.resolve(v).then(b).catch(T=>{var y;if(s())return;const N=e.retry??(qa.isServer()?0:3),R=e.retryDelay??vi,_=typeof R=="function"?R(n,T):R,L=N===!0||typeof N=="number"&&nf()?void 0:p()).then(()=>{t?u(T):g()})})};return{promise:r,status:()=>r.status,cancel:i,continue:()=>(a==null||a(),r),cancelRetry:o,continueRetry:d,canStart:h,start:()=>(h()?g():p().then(g),r)}}var Ee,La,Qa=(La=class{constructor(){P(this,Ee)}destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),ri(this.gcTime)&&x(this,Ee,Bt.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(qa.isServer()?1/0:300*1e3))}clearGcTimeout(){l(this,Ee)!==void 0&&(Bt.clearTimeout(l(this,Ee)),x(this,Ee,void 0))}},Ee=new WeakMap,La);function wi(e){return{onFetch:(t,n)=>{var h,b,u,p,g;const a=t.options,r=(u=(b=(h=t.fetchOptions)==null?void 0:h.meta)==null?void 0:b.fetchMore)==null?void 0:u.direction,s=((p=t.state.data)==null?void 0:p.pages)||[],i=((g=t.state.data)==null?void 0:g.pageParams)||[];let o={pages:[],pageParams:[]},d=0;const f=async()=>{let v=!1;const w=R=>{hi(R,()=>t.signal,()=>v=!0)},T=Ka(t.options,t.fetchOptions),N=async(R,_,L)=>{if(v)return Promise.reject(t.signal.reason);if(_==null&&R.pages.length)return Promise.resolve(R);const k=(()=>{const me={client:t.client,queryKey:t.queryKey,pageParam:_,direction:L?"backward":"forward",meta:t.options.meta};return w(me),me})(),j=await T(k),{maxPages:E}=t.options,D=L?di:ui;return{pages:D(R.pages,j,E),pageParams:D(R.pageParams,_,E)}};if(r&&s.length){const R=r==="backward",_=R?za:Zt,L={pages:s,pageParams:i},y=_(a,L);o=await N(L,y,R)}else{const R=e??s.length;do{const _=d===0?i[0]??a.initialPageParam:Zt(a,o);if(d>0&&_==null)break;o=await N(o,_),d++}while(d{var v,w;return(w=(v=t.options).persister)==null?void 0:w.call(v,f,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},n)}:t.fetchFn=f}}}function Zt(e,{pages:t,pageParams:n}){const a=t.length-1;return t.length>0?e.getNextPageParam(t[a],t,n[a],n):void 0}function za(e,{pages:t,pageParams:n}){var a;return t.length>0?(a=e.getPreviousPageParam)==null?void 0:a.call(e,t[0],t,n[0],n):void 0}function Fl(e,t){return t?Zt(e,t)!=null:!1}function Il(e,t){return!t||!e.getPreviousPageParam?!1:za(e,t)!=null}var Ze,De,Xe,X,Fe,U,ft,Ie,Z,Ba,he,Ra,yi=(Ra=class extends Qa{constructor(t){super();P(this,Z);P(this,Ze);P(this,De);P(this,Xe);P(this,X);P(this,Fe);P(this,U);P(this,ft);P(this,Ie);x(this,Ie,!1),x(this,ft,t.defaultOptions),this.setOptions(t.options),this.observers=[],x(this,Fe,t.client),x(this,X,l(this,Fe).getQueryCache()),this.queryKey=t.queryKey,this.queryHash=t.queryHash,x(this,De,Jn(this.options)),this.state=t.state??l(this,De),this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return l(this,Ze)}get promise(){var t;return(t=l(this,U))==null?void 0:t.promise}setOptions(t){if(this.options={...l(this,ft),...t},t!=null&&t._type&&x(this,Ze,t._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){const n=Jn(this.options);n.data!==void 0&&(this.setState(Gn(n.data,n.dataUpdatedAt)),x(this,De,n))}}optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"&&l(this,X).remove(this)}setData(t,n){const a=li(this.state.data,t,this.options);return V(this,Z,he).call(this,{data:a,type:"success",dataUpdatedAt:n==null?void 0:n.updatedAt,manual:n==null?void 0:n.manual}),a}setState(t){V(this,Z,he).call(this,{type:"setState",state:t})}cancel(t){var a,r;const n=(a=l(this,U))==null?void 0:a.promise;return(r=l(this,U))==null||r.cancel(t),n?n.then(ne).catch(ne):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return l(this,De)}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(t=>ii(t.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===hn||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0?this.observers.some(t=>Gt(t.options.staleTime,this)==="static"):!1}isStale(){return this.getObserversCount()>0?this.observers.some(t=>t.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(t=0){return this.state.data===void 0?!0:t==="static"?!1:this.state.isInvalidated?!0:!si(this.state.dataUpdatedAt,t)}onFocus(){var n;const t=this.observers.find(a=>a.shouldFetchOnWindowFocus());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}onOnline(){var n;const t=this.observers.find(a=>a.shouldFetchOnReconnect());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}addObserver(t){this.observers.includes(t)||(this.observers.push(t),this.clearGcTimeout(),l(this,X).notify({type:"observerAdded",query:this,observer:t}))}removeObserver(t){this.observers.includes(t)&&(this.observers=this.observers.filter(n=>n!==t),this.observers.length||(l(this,U)&&(l(this,Ie)||V(this,Z,Ba).call(this)?l(this,U).cancel({revert:!0}):l(this,U).cancelRetry()),this.scheduleGc()),l(this,X).notify({type:"observerRemoved",query:this,observer:t}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||V(this,Z,he).call(this,{type:"invalidate"})}async fetch(t,n){var f,h,b,u,p,g,v,w,T,N,R;if(this.state.fetchStatus!=="idle"&&((f=l(this,U))==null?void 0:f.status())!=="rejected"){if(this.state.data!==void 0&&(n!=null&&n.cancelRefetch))this.cancel({silent:!0});else if(l(this,U))return l(this,U).continueRetry(),l(this,U).promise}if(t&&this.setOptions(t),!this.options.queryFn){const _=this.observers.find(L=>L.options.queryFn);_&&this.setOptions(_.options)}const a=new AbortController,r=_=>{Object.defineProperty(_,"signal",{enumerable:!0,get:()=>(x(this,Ie,!0),a.signal)})},s=()=>{const _=Ka(this.options,n),y=(()=>{const k={client:l(this,Fe),queryKey:this.queryKey,meta:this.meta};return r(k),k})();return x(this,Ie,!1),this.options.persister?this.options.persister(_,y,this):_(y)},o=(()=>{const _={fetchOptions:n,options:this.options,queryKey:this.queryKey,client:l(this,Fe),state:this.state,fetchFn:s};return r(_),_})(),d=l(this,Ze)==="infinite"?wi(this.options.pages):this.options.behavior;d==null||d.onFetch(o,this),x(this,Xe,this.state),(this.state.fetchStatus==="idle"||this.state.fetchMeta!==((h=o.fetchOptions)==null?void 0:h.meta))&&V(this,Z,he).call(this,{type:"fetch",meta:(b=o.fetchOptions)==null?void 0:b.meta}),x(this,U,Wa({initialPromise:n==null?void 0:n.initialPromise,fn:o.fetchFn,onCancel:_=>{_ instanceof Lt&&_.revert&&this.setState({...l(this,Xe),fetchStatus:"idle"}),a.abort()},onFail:(_,L)=>{V(this,Z,he).call(this,{type:"failed",failureCount:_,error:L})},onPause:()=>{V(this,Z,he).call(this,{type:"pause"})},onContinue:()=>{V(this,Z,he).call(this,{type:"continue"})},retry:o.options.retry,retryDelay:o.options.retryDelay,networkMode:o.options.networkMode,canRun:()=>!0}));try{const _=await l(this,U).start();if(_===void 0)throw new Error(`${this.queryHash} data is undefined`);return this.setData(_),(p=(u=l(this,X).config).onSuccess)==null||p.call(u,_,this),(v=(g=l(this,X).config).onSettled)==null||v.call(g,_,this.state.error,this),_}catch(_){if(_ instanceof Lt){if(_.silent)return l(this,U).promise;if(_.revert){if(this.state.data===void 0)throw _;return this.state.data}}throw V(this,Z,he).call(this,{type:"error",error:_}),(T=(w=l(this,X).config).onError)==null||T.call(w,_,this),(R=(N=l(this,X).config).onSettled)==null||R.call(N,this.state.data,_,this),_}finally{this.scheduleGc()}}},Ze=new WeakMap,De=new WeakMap,Xe=new WeakMap,X=new WeakMap,Fe=new WeakMap,U=new WeakMap,ft=new WeakMap,Ie=new WeakMap,Z=new WeakSet,Ba=function(){return this.state.fetchStatus==="paused"&&this.state.status==="pending"},he=function(t){const n=a=>{switch(t.type){case"failed":return{...a,fetchFailureCount:t.failureCount,fetchFailureReason:t.error};case"pause":return{...a,fetchStatus:"paused"};case"continue":return{...a,fetchStatus:"fetching"};case"fetch":return{...a,..._i(a.data,this.options),fetchMeta:t.meta??null};case"success":const r={...a,...Gn(t.data,t.dataUpdatedAt),dataUpdateCount:a.dataUpdateCount+1,...!t.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return x(this,Xe,t.manual?r:void 0),r;case"error":const s=t.error;return{...a,error:s,errorUpdateCount:a.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:a.fetchFailureCount+1,fetchFailureReason:s,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...a,isInvalidated:!0};case"setState":return{...a,...t.state}}};this.state=n(this.state),z.batch(()=>{this.observers.forEach(a=>{a.onQueryUpdate()}),l(this,X).notify({query:this,type:"updated",action:t})})},Ra);function _i(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Ha(t.networkMode)?"fetching":"paused",...e===void 0&&{error:null,status:"pending"}}}function Gn(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:"success"}}function Jn(e){const t=typeof e.initialData=="function"?e.initialData():e.initialData,n=t!==void 0,a=n?typeof e.initialDataUpdatedAt=="function"?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:n?a??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:n?"success":"pending",fetchStatus:"idle"}}var mt,le,K,$e,ue,ve,Ma,Si=(Ma=class extends Qa{constructor(t){super();P(this,ue);P(this,mt);P(this,le);P(this,K);P(this,$e);x(this,mt,t.client),this.mutationId=t.mutationId,x(this,K,t.mutationCache),x(this,le,[]),this.state=t.state||Ci(),this.setOptions(t.options),this.scheduleGc()}setOptions(t){this.options=t,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(t){l(this,le).includes(t)||(l(this,le).push(t),this.clearGcTimeout(),l(this,K).notify({type:"observerAdded",mutation:this,observer:t}))}removeObserver(t){x(this,le,l(this,le).filter(n=>n!==t)),this.scheduleGc(),l(this,K).notify({type:"observerRemoved",mutation:this,observer:t})}optionalRemove(){l(this,le).length||(this.state.status==="pending"?this.scheduleGc():l(this,K).remove(this))}continue(){var t;return((t=l(this,$e))==null?void 0:t.continue())??this.execute(this.state.variables)}async execute(t){var i,o,d,f,h,b,u,p,g,v,w,T,N,R,_,L,y,k;const n=()=>{V(this,ue,ve).call(this,{type:"continue"})},a={client:l(this,mt),meta:this.options.meta,mutationKey:this.options.mutationKey};x(this,$e,Wa({fn:()=>this.options.mutationFn?this.options.mutationFn(t,a):Promise.reject(new Error("No mutationFn found")),onFail:(j,E)=>{V(this,ue,ve).call(this,{type:"failed",failureCount:j,error:E})},onPause:()=>{V(this,ue,ve).call(this,{type:"pause"})},onContinue:n,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>l(this,K).canRun(this)}));const r=this.state.status==="pending",s=!l(this,$e).canStart();try{if(r)n();else{V(this,ue,ve).call(this,{type:"pending",variables:t,isPaused:s}),l(this,K).config.onMutate&&await l(this,K).config.onMutate(t,this,a);const E=await((o=(i=this.options).onMutate)==null?void 0:o.call(i,t,a));E!==this.state.context&&V(this,ue,ve).call(this,{type:"pending",context:E,variables:t,isPaused:s})}const j=await l(this,$e).start();return await((f=(d=l(this,K).config).onSuccess)==null?void 0:f.call(d,j,t,this.state.context,this,a)),await((b=(h=this.options).onSuccess)==null?void 0:b.call(h,j,t,this.state.context,a)),await((p=(u=l(this,K).config).onSettled)==null?void 0:p.call(u,j,null,this.state.variables,this.state.context,this,a)),await((v=(g=this.options).onSettled)==null?void 0:v.call(g,j,null,t,this.state.context,a)),V(this,ue,ve).call(this,{type:"success",data:j}),j}catch(j){try{await((T=(w=l(this,K).config).onError)==null?void 0:T.call(w,j,t,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((R=(N=this.options).onError)==null?void 0:R.call(N,j,t,this.state.context,a))}catch(E){Promise.reject(E)}try{await((L=(_=l(this,K).config).onSettled)==null?void 0:L.call(_,void 0,j,this.state.variables,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((k=(y=this.options).onSettled)==null?void 0:k.call(y,void 0,j,t,this.state.context,a))}catch(E){Promise.reject(E)}throw V(this,ue,ve).call(this,{type:"error",error:j}),j}finally{l(this,K).runNext(this)}}},mt=new WeakMap,le=new WeakMap,K=new WeakMap,$e=new WeakMap,ue=new WeakSet,ve=function(t){const n=a=>{switch(t.type){case"failed":return{...a,failureCount:t.failureCount,failureReason:t.error};case"pause":return{...a,isPaused:!0};case"continue":return{...a,isPaused:!1};case"pending":return{...a,context:t.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:t.isPaused,status:"pending",variables:t.variables,submittedAt:Date.now()};case"success":return{...a,data:t.data,failureCount:0,failureReason:null,error:null,status:"success",isPaused:!1};case"error":return{...a,data:void 0,error:t.error,failureCount:a.failureCount+1,failureReason:t.error,isPaused:!1,status:"error"}}};this.state=n(this.state),z.batch(()=>{l(this,le).forEach(a=>{a.onMutationUpdate(t)}),l(this,K).notify({mutation:this,type:"updated",action:t})})},Ma);function Ci(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:"idle",variables:void 0,submittedAt:0}}var fe,ae,gt,Pa,xi=(Pa=class extends Et{constructor(t={}){super();P(this,fe);P(this,ae);P(this,gt);this.config=t,x(this,fe,new Set),x(this,ae,new Map),x(this,gt,0)}build(t,n,a){const r=new Si({client:t,mutationCache:this,mutationId:++Ct(this,gt)._,options:t.defaultMutationOptions(n),state:a});return this.add(r),r}add(t){l(this,fe).add(t);const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n);a?a.push(t):l(this,ae).set(n,[t])}this.notify({type:"added",mutation:t})}remove(t){if(l(this,fe).delete(t)){const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n);if(a)if(a.length>1){const r=a.indexOf(t);r!==-1&&a.splice(r,1)}else a[0]===t&&l(this,ae).delete(n)}}this.notify({type:"removed",mutation:t})}canRun(t){const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n),r=a==null?void 0:a.find(s=>s.state.status==="pending");return!r||r===t}else return!0}runNext(t){var a;const n=xt(t);if(typeof n=="string"){const r=(a=l(this,ae).get(n))==null?void 0:a.find(s=>s!==t&&s.state.isPaused);return(r==null?void 0:r.continue())??Promise.resolve()}else return Promise.resolve()}clear(){z.batch(()=>{l(this,fe).forEach(t=>{this.notify({type:"removed",mutation:t})}),l(this,fe).clear(),l(this,ae).clear()})}getAll(){return Array.from(l(this,fe))}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Qn(n,a))}findAll(t={}){return this.getAll().filter(n=>Qn(t,n))}notify(t){z.batch(()=>{this.listeners.forEach(n=>{n(t)})})}resumePausedMutations(){const t=this.getAll().filter(n=>n.state.isPaused);return z.batch(()=>Promise.all(t.map(n=>n.continue().catch(ne))))}},fe=new WeakMap,ae=new WeakMap,gt=new WeakMap,Pa);function xt(e){var t;return(t=e.options.scope)==null?void 0:t.id}var de,ja,ki=(ja=class extends Et{constructor(t={}){super();P(this,de);this.config=t,x(this,de,new Map)}build(t,n,a){const r=n.queryKey,s=n.queryHash??dn(r,n);let i=this.get(s);return i||(i=new yi({client:t,queryKey:r,queryHash:s,options:t.defaultQueryOptions(n),state:a,defaultOptions:t.getQueryDefaults(r)}),this.add(i)),i}add(t){l(this,de).has(t.queryHash)||(l(this,de).set(t.queryHash,t),this.notify({type:"added",query:t}))}remove(t){const n=l(this,de).get(t.queryHash);n&&(t.destroy(),n===t&&l(this,de).delete(t.queryHash),this.notify({type:"removed",query:t}))}clear(){z.batch(()=>{this.getAll().forEach(t=>{this.remove(t)})})}get(t){return l(this,de).get(t)}getAll(){return[...l(this,de).values()]}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Wn(n,a))}findAll(t={}){const n=this.getAll();return Object.keys(t).length>0?n.filter(a=>Wn(t,a)):n}notify(t){z.batch(()=>{this.listeners.forEach(n=>{n(t)})})}onFocus(){z.batch(()=>{this.getAll().forEach(t=>{t.onFocus()})})}onOnline(){z.batch(()=>{this.getAll().forEach(t=>{t.onOnline()})})}},de=new WeakMap,ja),F,Se,Ce,Ye,et,xe,tt,nt,Aa,Ti=(Aa=class{constructor(e={}){P(this,F);P(this,Se);P(this,Ce);P(this,Ye);P(this,et);P(this,xe);P(this,tt);P(this,nt);x(this,F,e.queryCache||new ki),x(this,Se,e.mutationCache||new xi),x(this,Ce,e.defaultOptions||{}),x(this,Ye,new Map),x(this,et,new Map),x(this,xe,0)}mount(){Ct(this,xe)._++,l(this,xe)===1&&(x(this,tt,Ua.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onFocus())})),x(this,nt,Tt.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,F).onOnline())})))}unmount(){var e,t;Ct(this,xe)._--,l(this,xe)===0&&((e=l(this,tt))==null||e.call(this),x(this,tt,void 0),(t=l(this,nt))==null||t.call(this),x(this,nt,void 0))}isFetching(e){return l(this,F).findAll({...e,fetchStatus:"fetching"}).length}isMutating(e){return l(this,Se).findAll({...e,status:"pending"}).length}getQueryData(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,F).get(t.queryHash))==null?void 0:n.state.data}ensureQueryData(e){const t=this.defaultQueryOptions(e),n=l(this,F).build(this,t),a=n.state.data;return a===void 0?this.fetchQuery(e):(e.revalidateIfStale&&n.isStaleByTime(Gt(t.staleTime,n))&&this.prefetchQuery(t),Promise.resolve(a))}getQueriesData(e){return l(this,F).findAll(e).map(({queryKey:t,state:n})=>{const a=n.data;return[t,a]})}setQueryData(e,t,n){const a=this.defaultQueryOptions({queryKey:e}),r=l(this,F).get(a.queryHash),s=r==null?void 0:r.state.data,i=ai(t,s);if(i!==void 0)return l(this,F).build(this,a).setData(i,{...n,manual:!0})}setQueriesData(e,t,n){return z.batch(()=>l(this,F).findAll(e).map(({queryKey:a})=>[a,this.setQueryData(a,t,n)]))}getQueryState(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,F).get(t.queryHash))==null?void 0:n.state}removeQueries(e){const t=l(this,F);z.batch(()=>{t.findAll(e).forEach(n=>{t.remove(n)})})}resetQueries(e,t){const n=l(this,F);return z.batch(()=>(n.findAll(e).forEach(a=>{a.reset()}),this.refetchQueries({type:"active",...e},t)))}cancelQueries(e,t={}){const n={revert:!0,...t},a=z.batch(()=>l(this,F).findAll(e).map(r=>r.cancel(n)));return Promise.all(a).then(ne).catch(ne)}invalidateQueries(e,t={}){return z.batch(()=>(l(this,F).findAll(e).forEach(n=>{n.invalidate()}),(e==null?void 0:e.refetchType)==="none"?Promise.resolve():this.refetchQueries({...e,type:(e==null?void 0:e.refetchType)??(e==null?void 0:e.type)??"active"},t)))}refetchQueries(e,t={}){const n={...t,cancelRefetch:t.cancelRefetch??!0},a=z.batch(()=>l(this,F).findAll(e).filter(r=>!r.isDisabled()&&!r.isStatic()).map(r=>{let s=r.fetch(void 0,n);return n.throwOnError||(s=s.catch(ne)),r.state.fetchStatus==="paused"?Promise.resolve():s}));return Promise.all(a).then(ne)}fetchQuery(e){const t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);const n=l(this,F).build(this,t);return n.isStaleByTime(Gt(t.staleTime,n))?n.fetch(t):Promise.resolve(n.state.data)}prefetchQuery(e){return this.fetchQuery(e).then(ne).catch(ne)}fetchInfiniteQuery(e){return e._type="infinite",this.fetchQuery(e)}prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(ne).catch(ne)}ensureInfiniteQueryData(e){return e._type="infinite",this.ensureQueryData(e)}resumePausedMutations(){return Tt.isOnline()?l(this,Se).resumePausedMutations():Promise.resolve()}getQueryCache(){return l(this,F)}getMutationCache(){return l(this,Se)}getDefaultOptions(){return l(this,Ce)}setDefaultOptions(e){x(this,Ce,e)}setQueryDefaults(e,t){l(this,Ye).set(lt(e),{queryKey:e,defaultOptions:t})}getQueryDefaults(e){const t=[...l(this,Ye).values()],n={};return t.forEach(a=>{ut(e,a.queryKey)&&Object.assign(n,a.defaultOptions)}),n}setMutationDefaults(e,t){l(this,et).set(lt(e),{mutationKey:e,defaultOptions:t})}getMutationDefaults(e){const t=[...l(this,et).values()],n={};return t.forEach(a=>{ut(e,a.mutationKey)&&Object.assign(n,a.defaultOptions)}),n}defaultQueryOptions(e){if(e._defaulted)return e;const t={...l(this,Ce).queries,...this.getQueryDefaults(e.queryKey),...e,_defaulted:!0};return t.queryHash||(t.queryHash=dn(t.queryKey,t)),t.refetchOnReconnect===void 0&&(t.refetchOnReconnect=t.networkMode!=="always"),t.throwOnError===void 0&&(t.throwOnError=!!t.suspense),!t.networkMode&&t.persister&&(t.networkMode="offlineFirst"),t.queryFn===hn&&(t.enabled=!1),t}defaultMutationOptions(e){return e!=null&&e._defaulted?e:{...l(this,Ce).mutations,...(e==null?void 0:e.mutationKey)&&this.getMutationDefaults(e.mutationKey),...e,_defaulted:!0}}clear(){l(this,F).clear(),l(this,Se).clear()}},F=new WeakMap,Se=new WeakMap,Ce=new WeakMap,Ye=new WeakMap,et=new WeakMap,xe=new WeakMap,tt=new WeakMap,nt=new WeakMap,Aa),Ga=C.createContext(void 0),$l=e=>{const t=C.useContext(Ga);if(!t)throw new Error("No QueryClient set, use QueryClientProvider to set one");return t},Li=({client:e,children:t})=>(C.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),c.jsx(Ga.Provider,{value:e,children:t}));function Ri(e,t=window.location.href){var a;const n=(a=new URL(t).searchParams.get("record"))==null?void 0:a.trim();if(n){const r=e.calls.find(s=>s.id===n);return r?[r]:[]}return e.calls[0]?[e.calls[0]]:[]}function Ol({calls:e,recordId:t,detail:n}){const a=e.findIndex(b=>b.id===t),r=a>=0?a:!t&&e.length?0:-1,s=(n==null?void 0:n.record.id)===t?n:null,i=(s==null?void 0:s.record)??(r>=0?e[r]:null),o=(s==null?void 0:s.previousRecord)??(r>0?e[r-1]:null),d=(s==null?void 0:s.nextRecord)??(r>=0&&r=0?`${r+1} of ${e.length} loaded calls`:"Record outside loaded snapshot";return{modelIndex:a,activeIndex:r,hydratedDetail:s,call:i,previous:o,next:d,threadCalls:f,positionLabel:h}}function Mi(e,t,n){const a=e.filter(i=>i.thread===t.thread),r=[n==null?void 0:n.previousRecord,n==null?void 0:n.record,n==null?void 0:n.nextRecord].filter(Pi),s=new Map;for(const i of[...a,...r,t])s.set(i.id,i);return[...s.values()].sort(ji)}function Pi(e){return!!(e!=null&&e.id)}function ji(e,t){return Date.parse(t.rawTime||t.time)-Date.parse(e.rawTime||e.time)}function Ai(e,t){const n=t.map(r=>Zn(r.header)).join(","),a=e.map(r=>t.map(s=>Zn(s.value(r))).join(","));return[n,...a].join(` -`)}function Ni(e,t){const n=new Blob([t],{type:"text/csv;charset=utf-8"}),a=typeof URL.createObjectURL=="function"?URL.createObjectURL(n):`data:text/csv;charset=utf-8,${encodeURIComponent(t)}`,r=document.createElement("a");r.href=a,r.download=e,r.rel="noopener",document.body.append(r),r.click(),r.remove(),a.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(a)}function Ei(e=new Date){return e.toISOString().slice(0,10)}function Zn(e){const t=String(e??"");return/[",\n\r]/.test(t)?`"${t.replaceAll('"','""')}"`:t}function Le(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function be(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Xt(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function dt(e){return`${e.toFixed(1)}%`}function Ja(e){return e.fast===!0?"Fast":e.fast===!1?"Standard":"Unknown"}function Ul(e){return e.fast!==null?`confirmed ${Ja(e)} · ${e.serviceTierConfidence||"exact"}`:e.fastProxyCandidate?"tier unknown · Fast proxy candidate":"tier unknown · normal throughput proxy"}function Vl(e){return e.cachedPct<25?"cold or weak cache":e.cachedPct<50?"partial cache reuse":"healthy cache reuse"}function Kl(e){return e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available"}function ql(e){if(e.contextWindowPct===null||e.contextWindowPct===void 0)return"Not reported";const t=e.modelContextWindow?` of ${be(e.modelContextWindow)}`:"";return`${dt(e.contextWindowPct)}${t}`}function Hl(e,{limit:t=2,emptyLabel:n="No related calls",unknownLabel:a="Unknown",style:r="parenthetical"}={}){const s=new Map;for(const o of e){const d=o||a;s.set(d,(s.get(d)??0)+1)}const i=[...s.entries()].sort((o,d)=>d[1]-o[1]||o[0].localeCompare(d[0])).slice(0,t).map(([o,d])=>r==="x"?`${o} x${d}`:`${o} (${d})`);return i.length?i.join(", "):n}const Wl=[{id:"time",accessorFn:e=>Number(Date.parse(e.eventTimestamp||e.callStartedAt||e.rawTime||e.time))||0,header:"Time",cell:e=>e.row.original.time},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:e=>c.jsx("span",{className:`pill effort-${String(e.getValue())}`,children:String(e.getValue())})},{accessorKey:"input",header:"Input Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"output",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:e=>c.jsx("span",{className:"cache-pill",children:dt(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"contextWindowPct",header:"Context %",cell:e=>{const t=e.getValue(),n=typeof t=="number"?t:Number.NaN;return c.jsx("span",{className:"num",children:Number.isFinite(n)?dt(n):"-"})}},{accessorKey:"duration",header:"Duration"},{id:"serviceTier",accessorFn:e=>Ja(e),header:"Service Tier",cell:e=>{const t=String(e.getValue()),n=t==="Fast"?"green":t==="Standard"?"blue":"";return c.jsx("span",{className:`status-badge ${n}`.trim(),children:t})}},{accessorKey:"previousCallGap",header:"Prev Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiator",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"signal",header:"Signals",cell:e=>c.jsx(Fi,{call:e.row.original})}],ce=[{header:"timestamp",value:e=>e.eventTimestamp||e.rawTime||e.time},{header:"thread",value:e=>e.thread},{header:"call_started_at",value:e=>e.callStartedAt||e.rawTime||e.time},{header:"call_duration_seconds",value:e=>e.durationSeconds},{header:"previous_call_event_timestamp",value:e=>e.previousCallEventTimestamp},{header:"previous_call_delta_seconds",value:e=>e.previousCallGapSeconds},{header:"initiated",value:e=>e.initiator},{header:"initiated_reason",value:e=>e.initiatorReason},{header:"project",value:e=>e.project},{header:"model",value:e=>e.model},{header:"effort",value:e=>e.effort},{header:"total_tokens",value:e=>e.totalTokens},{header:"input_tokens",value:e=>e.input},{header:"cached_input_tokens",value:e=>e.cachedInput},{header:"uncached_input_tokens",value:e=>e.uncachedInput},{header:"output_tokens",value:e=>e.output},{header:"reasoning_output_tokens",value:e=>e.reasoningOutput},{header:"estimated_cost_usd",value:e=>e.cost.toFixed(6)},{header:"usage_credits",value:e=>e.credits.toFixed(6)},{header:"standard_usage_credits",value:e=>e.standardUsageCredits.toFixed(6)},{header:"service_tier",value:e=>e.serviceTier},{header:"fast",value:e=>e.fast===null?"":e.fast?1:0},{header:"service_tier_source",value:e=>e.serviceTierSource},{header:"service_tier_confidence",value:e=>e.serviceTierConfidence},{header:"fast_proxy_candidate",value:e=>String(e.fastProxyCandidate)},{header:"usage_credit_multiplier",value:e=>e.usageCreditMultiplier},{header:"usage_credit_multiplier_source",value:e=>e.usageCreditMultiplierSource},{header:"cache_ratio",value:e=>e.cachedPct.toFixed(2)},{header:"context_window_percent",value:e=>{var t;return((t=e.contextWindowPct)==null?void 0:t.toFixed(2))??""}},{header:"pricing_model",value:e=>e.pricingModel},{header:"usage_credit_confidence",value:e=>e.usageCreditConfidence},{header:"recommendation",value:e=>e.recommendation},{header:"record_id",value:e=>e.id},{header:"thread_attachment",value:e=>e.threadAttachmentLabel},{header:"thread_source",value:e=>e.threadSource},{header:"parent_thread",value:e=>e.parentThread},{header:"session_id",value:e=>e.sessionId},{header:"turn_id",value:e=>e.turnId},{header:"parent_session_id",value:e=>e.parentSessionId},{header:"parent_session_updated_at",value:e=>e.parentSessionUpdatedAt},{header:"project_relative_cwd",value:e=>e.projectRelativeCwd},{header:"cwd",value:e=>e.cwd},{header:"source_file",value:e=>e.sourceFile},{header:"source_line",value:e=>e.lineNumber??""},{header:"git_branch",value:e=>e.gitBranch},{header:"git_remote_label",value:e=>e.gitRemoteLabel},{header:"git_remote_hash",value:e=>e.gitRemoteHash},{header:"pricing_estimated",value:e=>String(e.pricingEstimated)},{header:"usage_credit_model",value:e=>e.usageCreditModel},{header:"usage_credit_source",value:e=>e.usageCreditSource},{header:"usage_credit_tier",value:e=>e.usageCreditTier},{header:"usage_credit_fetched_at",value:e=>e.usageCreditFetchedAt},{header:"usage_credit_note",value:e=>e.usageCreditNote},{header:"model_context_window",value:e=>e.modelContextWindow??""},{header:"cumulative_total_tokens",value:e=>e.cumulativeTotalTokens??""},{header:"estimated_cache_savings_usd",value:e=>e.estimatedCacheSavings.toFixed(6)},{header:"initiated_confidence",value:e=>e.initiatorConfidence},{header:"signal",value:e=>e.signal},{header:"tags",value:e=>e.tags.join("|")},{header:"efficiency_flags",value:e=>e.efficiencyFlags.join("|")}];function Di(e,t=3){const a=Ii([e.signal,...e.efficiencyFlags]).map((r,s)=>({key:`${r}-${s}`,label:Za(r),shortLabel:$i(r)}));return{visible:a.slice(0,t),hidden:a.slice(t)}}function Fi({call:e}){const t=Oa(),{visible:n,hidden:a}=Di(e);if(!n.length)return c.jsx("span",{className:"muted",children:"None"});const r=n.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),s=a.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),i=s.map(o=>o.label).join("、");return c.jsxs("span",{className:"flags compact-flags","aria-label":t.language==="zh-Hans"?`信号:${[...r,...s].map(o=>o.label).join("、")}`:`Signals: ${[...n,...a].map(o=>o.label).join(", ")}`,children:[r.map(o=>c.jsx("span",{className:"flag signal-puck",title:o.label,children:o.shortLabel},o.key)),s.length?c.jsxs("span",{className:"flag signal-puck more",title:i,children:["+",s.length]}):null]})}function Ii(e){const t=new Set;return e.map(n=>n.trim()).filter(n=>n&&n!=="aggregate").filter(n=>{const a=n.toLowerCase();return t.has(a)?!1:(t.add(a),!0)})}function Za(e){return e.replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function $i(e){const t=e.toLowerCase().replace(/[_\s]+/g,"-"),n={"cache-drop":"CACHE","cache-risk":"CACHE","context-bloat":"CTX","context-heavy":"CTX","elevated-context":"CTX","elevated-context-use":"CTX","estimated-pricing":"EST","expensive-low-output-call":"LO","high-context-use":"CTX","high-cost":"$","high-estimated-cost":"$","high-reasoning-share":"RSN","large-thread":"BIG","low-cache":"CACHE","low-cache-reuse":"CACHE","low-output":"LO","pricing-gap":"PRICE","reasoning-spike":"RSN","subagent-attribution":"SUB"};if(n[t])return n[t];const a=Za(e).split(/\s+/).filter(Boolean);return a.length?a.length===1?a[0].slice(0,4).toUpperCase():a.slice(0,3).map(r=>r[0]).join("").toUpperCase():"?"}const Ql=[{accessorKey:"name",header:"Thread"},{accessorKey:"latestActivity",header:"Latest"},{accessorKey:"turns",header:"Turns",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalDuration",header:"Duration"},{accessorKey:"averageGap",header:"Avg Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiatorSummary",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"modelSummary",header:"Models",cell:e=>c.jsx("span",{className:"pill model-pill",children:String(e.getValue())})},{accessorKey:"effortSummary",header:"Effort Mix"},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"outputTokens",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:be(Number(e.getValue()))})},{accessorKey:"cachePct",header:"Cache %",cell:e=>c.jsx("span",{className:"cache-pill",children:dt(Number(e.getValue()))})},{accessorKey:"contextPct",header:"Context %",cell:e=>{const t=e.getValue();return c.jsx("span",{className:"num",children:typeof t=="number"?dt(t):"-"})}},{accessorKey:"costPerCall",header:"Cost / Call",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"coldResumeRisk",header:"Cold Resume Risk",cell:e=>c.jsx("span",{className:`status-badge ${Oi(String(e.getValue()))}`,children:String(e.getValue())})},{accessorKey:"productivity",header:"Productivity",cell:e=>c.jsx("span",{className:"score",children:Number(e.getValue())})}],zl=[{id:"name",label:"Thread",locked:!0},{id:"latestActivity",label:"Latest"},{id:"turns",label:"Turns"},{id:"totalDuration",label:"Duration"},{id:"averageGap",label:"Avg Gap"},{id:"initiatorSummary",label:"Initiated"},{id:"modelSummary",label:"Models"},{id:"effortSummary",label:"Effort Mix"},{id:"totalTokens",label:"Total Tokens"},{id:"cachedInput",label:"Cached Input"},{id:"uncachedInput",label:"Uncached Input"},{id:"outputTokens",label:"Output Tokens"},{id:"reasoningOutput",label:"Reasoning Output"},{id:"cost",label:"Est. Cost"},{id:"credits",label:"Codex Credits"},{id:"cachePct",label:"Cache %"},{id:"contextPct",label:"Context %"},{id:"costPerCall",label:"Cost / Call"},{id:"coldResumeRisk",label:"Cold Resume Risk"},{id:"productivity",label:"Productivity"},{id:"investigate",label:"Investigate",locked:!0}];function Oi(e){return e==="High"?"red":e==="Medium"?"orange":e==="Low"?"green":"neutral"}const ht=1,re=0,qt=100,Xa=1e3,Ya=500,er="codexUsageDashboardLoadSettings",Ui={day:1440*60*1e3,week:10080*60*1e3};function ct(e,t=Ya){if((e==null?void 0:e.limit_label)==="All"||t===re&&(e==null?void 0:e.limit)==null)return re;const n=Number((e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??t);return Number.isFinite(n)&&n>=0?n:t}function pt(e){return Number.isFinite(e)?e<=re?re:Math.max(ht,Math.round(e)):ht}function je(...e){const t=e.find(n=>typeof n=="number"&&Number.isFinite(n)&&n>0);return t?Math.max(ht,Math.round(t)):ht}function Vi(e,t,n=null,a="rows"){const r=pt(e);return{historyScope:t,loadWindow:a,limit:r===re?null:r,since:n}}function Ki(e){return e.limit??re}function fn(e){return mn(e==null?void 0:e.load_window)?e.load_window:e!=null&&e.since?"week":(e==null?void 0:e.limit_label)==="All"||(e==null?void 0:e.limit)==null?"all":"rows"}function qi(e){return mn(e==null?void 0:e.default_load_window)?e.default_load_window:fn(e)}function Ht(e,t=new Date){const n=Ui[e];if(!n)return null;const a=Math.floor(t.getTime()/6e4)*6e4;return new Date(a-n).toISOString()}function Re(e,t=Ya){return e==="day"?"Last 24 hours":e==="week"?"Last 7 days":e==="all"?"All time":`Most recent ${pt(t).toLocaleString()}`}function Hi(e=tr()){if(!e)return null;try{const t=e.getItem(er);if(!t)return null;const n=JSON.parse(t),a=typeof n.loadLimit=="number"&&Number.isFinite(n.loadLimit)?pt(n.loadLimit):void 0,r=n.historyScope==="active"||n.historyScope==="all"?n.historyScope:void 0,s=mn(n.loadWindow)?n.loadWindow:void 0;return a===void 0&&r===void 0&&s===void 0?null:{loadLimit:a,historyScope:r,loadWindow:s}}catch{return null}}function Wi(e,t,n="rows",a=tr()){if(a)try{a.setItem(er,JSON.stringify({loadLimit:pt(e),historyScope:t,loadWindow:n}))}catch{}}function mn(e){return e==="day"||e==="week"||e==="rows"||e==="all"}function Qi({currentLimit:e,loadedRows:t,pendingLimit:n}){const a=n===re?0:n+qt,s=Math.max(ht,e===re?0:e,a,t);return Math.ceil((s+Xa)/qt)*qt}function zi({currentLimit:e,loadedRows:t,pendingLimit:n}){return Math.max(je(e),je(n),je(t))+Xa}function Bi({loadedRows:e,limit:t,totalRows:n}){return t===re&&e>0?`Loaded all ${e.toLocaleString()}`:n>e?`Loaded ${e.toLocaleString()} of ${n.toLocaleString()}`:`Loaded ${e.toLocaleString()} rows`}function tr(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}async function Gi(e,t,n,a="",r=""){const s=Ei();switch(e){case"threads":{const{threadCallsForCurrentUrl:i}=await O(async()=>{const{threadCallsForCurrentUrl:o}=await import("./ThreadsPage.js");return{threadCallsForCurrentUrl:o}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]));return te(`codex-thread-filtered-calls-${s}.csv`,i(t,a),ce,"call rows")}case"cache-context":{const{cacheContextCallsForCurrentUrl:i}=await O(async()=>{const{cacheContextCallsForCurrentUrl:o}=await import("./CacheContextPage.js");return{cacheContextCallsForCurrentUrl:o}},__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12]));return te(`codex-${e}-calls-${s}.csv`,i(t),ce,"call rows")}case"usage-drain":{const{usageDrainCallsForCurrentUrl:i}=await O(async()=>{const{usageDrainCallsForCurrentUrl:o}=await import("./UsageDrainPage.js");return{usageDrainCallsForCurrentUrl:o}},__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39]));return te(`codex-usage-drain-calls-${s}.csv`,i(t),ce,"call rows")}case"diagnostics":{const{diagnosticsCallsForCurrentUrl:i}=await O(async()=>{const{diagnosticsCallsForCurrentUrl:o}=await import("./DiagnosticsPage.js");return{diagnosticsCallsForCurrentUrl:o}},__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12]));return te(`codex-diagnostics-calls-${s}.csv`,i(t),ce,"call rows")}case"reports":{const{reportCallsForCurrentUrl:i}=await O(async()=>{const{reportCallsForCurrentUrl:o}=await import("./ReportsPage.js");return{reportCallsForCurrentUrl:o}},__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43]));return te(`codex-reports-evidence-${s}.csv`,i(t),ce,"call rows")}case"settings":return te(`codex-dashboard-settings-${s}.csv`,Zi(t,n),Ji,"settings rows");case"calls":{const{callsForCurrentUrl:i}=await O(async()=>{const{callsForCurrentUrl:o}=await import("./CallsPage.js");return{callsForCurrentUrl:o}},__vite__mapDeps([44,1,2,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48]));return te(`codex-calls-${s}.csv`,i(t.calls,a,r),ce,"call rows")}case"overview":{const{overviewCallsForQuery:i}=await O(async()=>{const{overviewCallsForQuery:o}=await import("./OverviewPage.js");return{overviewCallsForQuery:o}},__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50]));return te(`codex-overview-calls-${s}.csv`,i(t.calls,a),ce,"call rows")}case"investigator":{const{investigatorCallsForCurrentUrl:i}=await O(async()=>{const{investigatorCallsForCurrentUrl:o}=await import("./InvestigatorPage.js");return{investigatorCallsForCurrentUrl:o}},__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52]));return te(`codex-investigator-calls-${s}.csv`,i(t),ce,"call rows")}case"compression-lab":return te(`codex-compression-lab-scope-${s}.csv`,t.calls,ce,"call rows");case"call":return te(`codex-call-calls-${s}.csv`,Ri(t),ce,"call rows")}}function te(e,t,n,a){return{filename:e,csv:Ai(t,n),rowCount:t.length,label:a}}const Ji=[{header:"Field",value:e=>e.field},{header:"Value",value:e=>e.value}];function Zi(e,t){return[{field:"live_api",value:t.canUseLiveApi?"available":"static snapshot"},{field:"context_api",value:t.contextRuntime.contextApiEnabled?"enabled":"gated"},{field:"history_scope",value:t.historyScope},{field:"data_window",value:Re(t.loadWindow,t.loadLimit)},{field:"scope_since",value:t.scopeSince??"none"},{field:"row_request",value:t.loadLimit===re?"no cap":String(t.loadLimit)},{field:"loaded_rows",value:String(t.loadedRowCount)},{field:"total_available_rows",value:String(t.totalAvailableRows)},{field:"auto_refresh",value:t.autoRefreshEnabled?"enabled":"paused"},{field:"refresh_state",value:t.refreshState},{field:"visible_calls",value:String(e.calls.length)},{field:"visible_threads",value:String(e.threads.length)}]}function Xi(e){return e instanceof Error?e.message:String(e)}function Xn(e,t){const n=t==="all"?"all history":"active history",a=e.message||"Refreshing usage index",r=typeof e.percent=="number"?` ${Math.round(e.percent)}%`:"";return`${a}${r} (${n})`}function Wt(e,t="active"){return e?typeof e.include_archived=="boolean"?e.include_archived?"all":"active":e.history_scope==="all-history"||e.history_scope==="all"?"all":e.history_scope==="active"?"active":t:t}function Yi({historyScope:e,activeRows:t,allRows:n,archivedRows:a}){const r=eo({activeRows:t,allRows:n,archivedRows:a});return e==="all"?r===null?"All history selected":r>0?`All history includes ${r.toLocaleString()} archived calls`:"All history selected; no archived calls are indexed yet":r===null||r<=0?"Active sessions only":`Active sessions only; ${r.toLocaleString()} archived calls hidden`}function eo({activeRows:e,allRows:t,archivedRows:n}){const a=Qt(n);if(a!==null)return a;const r=Qt(e),s=Qt(t);return r!==null&&s!==null?Math.max(s-r,0):null}function Qt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.round(e):null}const nr=["aria-description","aria-label","aria-valuetext","title","placeholder","alt"],to="data-localization-attributes",no=new Set(["CODE","KBD","PRE","SAMP","SCRIPT","STYLE","TEXTAREA"]),Yt=new WeakMap,en=new WeakMap;function ao({value:e,children:t}){return c.jsxs(Zs,{value:e,children:[c.jsx(ro,{}),t]})}function ro(){const e=Oa();return C.useLayoutEffect(()=>{const t=document.querySelector("[data-dashboard-localization-root]");if(!t)return;if(e.language!=="zh-Hans"){io(t),document.title="Codex Usage Tracker React Dashboard";return}document.title="Codex Usage Tracker · 用量仪表盘",Yn(t,e.translateText);const n=new MutationObserver(a=>{for(const r of a){if(r.type==="characterData"&&r.target instanceof Text){tn(r.target,e.translateText);continue}if(r.type==="attributes"&&r.target instanceof Element){nn(r.target,e.translateText);continue}for(const s of r.addedNodes)s instanceof Text?tn(s,e.translateText):s instanceof Element&&Yn(s,e.translateText)}});return n.observe(t,{attributes:!0,attributeFilter:[...nr],characterData:!0,childList:!0,subtree:!0}),()=>n.disconnect()},[e]),null}function Yn(e,t){if(Rt(e))return;nn(e,t);const n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);let a=n.nextNode();for(;a;){if(a instanceof Element){if(Rt(a)){a=so(n,a,e);continue}nn(a,t)}else a instanceof Text&&tn(a,t);a=n.nextNode()}}function so(e,t,n){let a=t;for(;a&&a!==n;){const r=e.nextSibling();if(r)return r;a=a.parentNode,a&&(e.currentNode=a)}return null}function tn(e,t){const n=e.parentElement;if(!n||Rt(n))return;const a=e.nodeValue??"",r=Yt.get(e),s=r&&(a===r.source||a===r.translated)?r.source:a,i=s.match(/^(\s*)([\s\S]*?)(\s*)$/u);if(!i||!i[2])return;const o=t(i[2]),d=`${i[1]}${o}${i[3]}`;Yt.set(e,{source:s,translated:d}),d!==a&&(e.nodeValue=d)}function nn(e,t){if(Rt(e))return;const n=new Set((e.getAttribute(to)??"").split(/[\s,]+/u).filter(Boolean));if(!n.size)return;const a=en.get(e)??new Map;for(const r of nr){if(!n.has(r))continue;const s=e.getAttribute(r);if(!s)continue;const i=a.get(r),o=i&&(s===i.source||s===i.translated)?i.source:s,d=t(o);a.set(r,{source:o,translated:d}),d!==s&&e.setAttribute(r,d)}a.size&&en.set(e,a)}function io(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);ea(e);let n=t.nextNode();for(;n;){if(n instanceof Text){const a=Yt.get(n);a&&n.nodeValue===a.translated&&(n.nodeValue=a.source)}else n instanceof Element&&ea(n);n=t.nextNode()}}function ea(e){const t=en.get(e);if(t)for(const[n,a]of t)e.getAttribute(n)===a.translated&&e.setAttribute(n,a.source)}function Rt(e){return no.has(e.tagName)||!!e.closest('[data-localization-skip="true"]')}const Mt=["May 12","May 19","May 26","Jun 02","Jun 09","Jun 16","Jun 23","Jun 30"],it=Mt.slice(2),ar={contextRuntime:{apiToken:"",contextApiEnabled:!1,fileMode:!1},cards:[{label:"Total Tokens",value:"24.83M",detail:"7-day total: 12.56M",trend:"up 18.7% vs prior 7 days",tone:"blue"},{label:"Estimated Cost",value:"$42.67",detail:"7-day total: $24.81",trend:"up 14.2% vs prior 7 days",tone:"green"},{label:"Cache Hit Rate",value:"38.7%",detail:"7-day average: 42.3%",trend:"down 3.6pp vs prior 7 days",tone:"purple"},{label:"Total Calls",value:"1,342",detail:"678 calls in last 7 days",trend:"up 11.3% vs prior 7 days",tone:"blue"},{label:"Usage Remaining",value:"32.4%",detail:"~15.9K credits estimated",trend:"resets in 4d 12h",tone:"green"}],tokenSeries:[W("input","Input","#2563eb",[5.2,6.4,7.5,9.2,6.7,7.5,6.6,9],1e6),W("output","Output","#059669",[2.5,3,3.6,5.1,3.7,5,4,5.4],1e6),W("cached","Cached","#7c3aed",[1.1,1.4,1.7,2.4,1.8,2.3,1.8,2.6],1e6,!0)],costSeries:[W("cost","Estimated Cost","#2563eb",[8.4,10.1,14.3,9.9,11.4,7.8,12.7,16.5])],cacheSeries:[W("cache","Cache Hit Rate","#059669",[58,61,39,45,50,44,48,41])],weeklyCreditSeries:[{id:"pro",label:"Pro observed",color:"#2563eb",points:Mt.map((e,t)=>({label:e,value:[59800,44900,45e3,40500,42800,38900,31400,35900][t]??0,low:[52100,38800,38900,34700,36200,32200,26100,29900][t]??0,high:[67400,51200,51100,46800,49200,45100,37300,41900][t]??0}))},W("pro-trend","Pro trend","#1d4ed8",[54.2,51,47.8,44.6,41.4,38.2,35,31.8],1e3,!0),W("prolite","Prolite observed","#0f766e",[15.9,15.8,15.9,16.1,15.7,15.6,15.9,15.8],1e3)],usageRemainingSeries:[W("remaining","Usage remaining","#059669",[87,71,63,56,56,48,50,54]),W("allowance","Allowance guide","#0f766e",[86,85,84,83,82,81,80,79],1,!0)],actualVsPredictedSeries:[W("observed","Observed drain","#2563eb",[18.7,22.1,45.3,31,34.8],1e3),W("predicted","Predicted baseline","#1d4ed8",[17.9,21.4,41.2,29.6,33.9],1e3,!0)],findings:[{rank:1,title:"Long Thread: data-engine-refactor",severity:"High",credits:12847,share:25.6,summary:"Very long duration with high model effort."},{rank:2,title:"Cache Misses (Large Inputs)",severity:"High",credits:9612,share:19.1,summary:"Large uncached inputs across 214 calls."},{rank:3,title:"High Model Effort",severity:"Medium",credits:7404,share:14.7,summary:"Reasoning and output token volume are concentrated."},{rank:4,title:"Tool Output Volume",severity:"Medium",credits:5231,share:10.4,summary:"Large tool outputs returned to the model."}],calls:[["2026-06-01T10:24:00Z","Jun 1, 10:24 AM","thread-9f3a1c","codex-1","high",128542,45231,62,.42,"18.4s",!1,["review"]],["2026-06-01T10:18:00Z","Jun 1, 10:18 AM","thread-7b2e91","o4-mini","medium",98731,32104,41,.31,"12.7s",!0,["analysis"]],["2026-06-01T10:12:00Z","Jun 1, 10:12 AM","thread-3c8d4e","o3","high",64221,18903,28,.12,"9.3s",!0,["uncached"]],["2026-06-01T10:06:00Z","Jun 1, 10:06 AM","thread-1a2b3c","codex-1","high",245123,98112,71,.87,"27.6s",!1,["large"]],["2026-06-01T10:01:00Z","Jun 1, 10:01 AM","thread-8d7c6b","gpt-4.1","low",12543,4231,12,.03,"3.6s",!0,["quick"]],["2026-06-01T09:55:00Z","Jun 1, 09:55 AM","thread-2f9e7d","o4-mini","medium",76881,28442,39,.24,"11.2s",!1,["subagent"]],["2026-06-01T09:50:00Z","Jun 1, 09:50 AM","thread-6a5b4c","codex-1","high",312654,112991,67,1.12,"31.8s",!1,["file-heavy"]],["2026-06-01T09:47:00Z","Jun 1, 09:47 AM","thread-0f1e2d","o3","low",8221,2903,15,.02,"2.8s",!0,["fast"]]].map(([e,t,n,a,r,s,i,o,d,f,h,b],u)=>{const p=Number(s),g=Number(i),v=Number(o),w=Math.round(p*Math.max(100-v,0)/100);return{id:`fixture-call-${u}`,rawTime:String(e),eventTimestamp:String(e),callStartedAt:String(e),time:String(t),thread:String(n),model:String(a),effort:String(r),input:p,output:g,reasoningOutput:Math.round(g*.2),totalTokens:p+g,cachedInput:Math.round(p*v/100),uncachedInput:w,cachedPct:v,cost:u===4?0:Number(d),credits:(u===4?0:Number(d))*25,duration:String(f),durationSeconds:Number.parseFloat(String(f))||0,previousCallGap:u===0?"-":`${u*7}m 0s`,previousCallEventTimestamp:u===0?"":`2026-06-01T09:${String(40+u).padStart(2,"0")}:00Z`,previousCallGapSeconds:u*420,initiator:u%3===0?"user":u%3===1?"assistant":"tool",initiatorReason:u%3===0?"direct user request":u%3===1?"assistant follow-up":"tool-driven continuation",initiatorConfidence:u%2===0?"exact":"estimated",serviceTier:"",fast:null,serviceTierSource:"",serviceTierConfidence:"",fastProxyCandidate:!!h,standardUsageCredits:(u===4?0:Number(d))*25,usageCreditMultiplier:1,usageCreditMultiplierSource:"tier_unknown",usageCreditConfidence:u===7?"user_override":u%4===0?"exact":u%4===1?"estimated":u%4===2?"missing":"fixture",usageCreditModel:u===4?"":`${a}-credits`,usageCreditSource:u===4?"":"fixture-rate-card",usageCreditFetchedAt:u===4?"":"2026-06-01T10:00:00Z",usageCreditTier:u%2===0?"standard":"estimated",usageCreditNote:u===2?"fixture inherited rate card":"",pricingModel:u===4?"":`${a}-pricing`,pricingEstimated:u===1||u===5,signal:w>5e4?"cache-risk":"aggregate",recommendation:w>5e4?"Review uncached aggregate input before continuing this thread.":"",tags:b,sessionId:`fixture-session-${u}`,turnId:`fixture-turn-${u}`,parentSessionId:u%3===0?"fixture-parent-session":"",parentSessionUpdatedAt:u%3===0?"2026-06-01T09:30:00Z":"",parentThread:u%3===0?"parent-thread-analysis":"",threadAttachmentLabel:u%3===0?"spawned child thread":"direct active thread",threadSource:u%3===0?"subagent":"user",subagentType:u%3===0?"analysis":"",agentRole:u%3===0?"reviewer":"",agentNickname:u%3===0?"usage-reviewer":"",project:u%2===0?"codex-usage-tracker":"local-ops",projectRelativeCwd:u%2===0?"frontend/dashboard":".",projectTags:u%2===0?["dashboard","rewrite"]:["local"],cwd:`/fixtures/${u%2===0?"codex-usage-tracker":"local-ops"}`,sourceFile:`fixture-thread-${u}.jsonl`,lineNumber:120+u,gitBranch:"experiment/frontend-rewrite",gitRemoteLabel:"origin",gitRemoteHash:`fixture-${u}`,contextWindowPct:Math.min(18+v,96),modelContextWindow:128e3,cumulativeTotalTokens:p+g+u*1e4,estimatedCacheSavings:Math.round((p-w)*1e-5*100)/100,efficiencyFlags:w>5e4?["cache-risk"]:[]}}),threads:[["thread-9f3a",142,58400,8.76,12,1.38,"High",42],["thread-7c2b",87,31200,4.21,22,1.12,"Medium",55],["thread-1a8c",64,22700,3.02,18,.98,"High",48],["thread-d3e1",53,18100,2.11,41,.81,"Low",72],["thread-b7f0",41,13600,1.65,47,.73,"Low",75],["thread-3c5d",36,9900,1.18,35,.66,"Medium",63],["thread-0e16",28,6400,.72,56,.58,"Low",82]].map(([e,t,n,a,r,s,i,o],d)=>{const f=Number(t),h=Number(n),b=Number(r),u=f*48,p=(d+1)*420;return{name:String(e),latestCallId:`fixture-call-${d}`,latestActivity:`Jun ${d+1}, 10:${String(24-d).padStart(2,"0")} AM`,latestActivityRaw:`2026-06-${String(d+1).padStart(2,"0")}T10:${String(24-d).padStart(2,"0")}:00Z`,turns:f,totalDurationSeconds:u,totalDuration:`${Math.floor(u/60)}m ${u%60}s`,averageGapSeconds:p,averageGap:`${Math.floor(p/60)}m ${p%60}s`,initiatorSummary:d%2===0?"user x4, assistant x2":"assistant x3, tool x1",modelSummary:d%2===0?"codex-1 x5, o4-mini x2":"o4-mini x3, o3 x1",effortSummary:d%2===0?"high x5, medium x2":"medium x3, low x1",totalTokens:h,cachedInput:Math.round(h*b/100),uncachedInput:Math.round(h*Math.max(100-b,0)/100),outputTokens:Math.round(h*.28),reasoningOutput:Math.round(h*.08),cost:Number(a),credits:Number(a)*25,cachePct:b,contextPct:Math.min(96,28+d*7),costPerCall:Number(s),coldResumeRisk:i,productivity:Number(o)}}),weeklyWindows:Mt.map((e,t)=>({week:e,plan:t===0?"Prolite":"Pro",observedPct:[61.4,49.2,47.7,48.3,44.5,37.4,40.1,35.8][t]??0,credits:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,projected:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,ciLow:[42156,34892,33424,34021,31241,26164,28234,29450][t]??0,ciHigh:[57467,47657,46349,47105,43326,36676,39450,41900][t]??0,confidence:t===0?"Medium":"High",note:["Prolite baseline","Drop in credits","Stable","Slight uptick","Down again","Lowest window","Recovery","Latest"][t]??""})),modelCosts:[{label:"codex-1",value:16.21,color:"#2563eb"},{label:"o3",value:12.43,color:"#1d4ed8"},{label:"o4-mini",value:7.62,color:"#059669"},{label:"gpt-4.1",value:4.91,color:"#f59e0b"},{label:"other",value:1.5,color:"#94a3b8"}],commandActions:[{title:"Show highest uncached calls",status:"Ready",owner:"Calls",description:"214 calls above the uncached threshold."},{title:"Compare Pro weeks",status:"Ready",owner:"Usage Drain",description:"Allowance windows with confidence intervals."},{title:"Find cold resumes",status:"Ready",owner:"Cache",description:"14 threads with long idle gaps."},{title:"Export support bundle",status:"Planned",owner:"Reports",description:"Local aggregate artifacts only."}],cacheSegments:[{label:"Cache read",value:38.7,color:"#2563eb"},{label:"Cache write",value:29.6,color:"#059669"},{label:"Uncached",value:31.7,color:"#7c3aed"}],cacheHeatmap:[{thread:"thread-8c1e",labels:it,values:[62,71,89,82,74,31]},{thread:"thread-2b9d",labels:it,values:[42,58,77,61,51,24]},{thread:"thread-713a",labels:it,values:[78,81,83,66,59,37]},{thread:"thread-4af2",labels:it,values:[24,36,63,54,71,44]},{thread:"thread-f9c3",labels:it,values:[18,25,41,38,52,22]}],diagnostics:[{title:"Usage Drain",status:"Ready",finding:"Projected weekly credits declined from the baseline and partially recovered in the latest window.",confidence:"High",metric:"33,842 credits / week",series:[W("usage-drain","Projected credits","#2563eb",[41.8,46.7,45.9,32.1,33.8],1e3)]},{title:"Cache Behavior",status:"Ready",finding:"Cache hit rate is healthy overall, with spikes aligned to large cache misses and cold resumes.",confidence:"Medium",metric:"41.1% hit rate",series:[W("cache","Cache hit %","#059669",[44,48,38,33,40])]},{title:"Thread Efficiency",status:"Ready",finding:"Long threads account for most estimated cost and are the clearest optimization target.",confidence:"High",metric:"65% cost share",series:[W("threads","Cost share","#1d4ed8",[65,23,8,4])]},{title:"Tool And Command Activity",status:"Stale",finding:"Command volume is stable with a slight upward trend; read and shell commands dominate.",confidence:"Medium",metric:"912 commands",series:[W("commands","Commands","#7c3aed",[542,488,611,883,912])]}],reports:[{title:"Weekly Credits",status:"Ready",owner:"Usage Drain",description:"Plan-specific weekly credits, trend lines, and confidence intervals."},{title:"Usage Remaining",status:"Ready",owner:"Usage Drain",description:"Observed remaining usage over time with reset handling."},{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Cumulative estimated cost by thread and concentration metrics."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Actual-vs-predicted drain and feature group comparisons."},{title:"Fast Mode Proxy",status:"Planned",owner:"Calls",description:"Candidate detection, speedup histogram, and confidence breakdowns."},{title:"Allowance Change",status:"Planned",owner:"Reports",description:"Week-to-week allowance estimate changes with careful language."}]};function W(e,t,n,a,r=1,s=!1){return{id:e,label:t,color:n,dashed:s,points:a.map((i,o)=>({label:Mt[o]??`Point ${o+1}`,value:i*r}))}}function rr(e){if(window.location.protocol==="file:")throw new Error("Live refresh requires the localhost dashboard server.");if(!(e!=null&&e.api_token))throw new Error("Live refresh requires localhost dashboard API token.")}function gn(e){return{Accept:"application/json","X-Codex-Usage-Token":e.api_token||""}}function oo(e,t){return new Promise((n,a)=>{if(t!=null&&t.aborted){a(ta(t));return}const r=window.setTimeout(()=>{t==null||t.removeEventListener("abort",s),n()},e);function s(){window.clearTimeout(r),a(ta(t))}t==null||t.addEventListener("abort",s,{once:!0})})}function sr(e){return(e instanceof DOMException||e instanceof Error)&&e.name==="AbortError"}function ta(e){return(e==null?void 0:e.reason)instanceof Error?e.reason:new DOMException("The request was cancelled.","AbortError")}const co=["#2563eb","#1d4ed8","#059669","#f59e0b","#94a3b8"];function ir(e){const t=new Map;e.forEach(r=>{const s=r.model||"unknown";t.set(s,(t.get(s)??0)+r.cost)});const n=[...t.entries()].sort((r,s)=>s[1]-r[1]||r[0].localeCompare(s[0]));return(n.length>5?[...n.slice(0,4),["other",n.slice(4).reduce((r,s)=>r+s[1],0)]]:n).map(([r,s],i)=>({label:r,value:s,color:co[i]??"#94a3b8"}))}function or(e){if(!e.length)return[];const t=Math.max(e.reduce((n,a)=>n+vt(a),0),1);return[lo(e,t),uo(e,t),ho(e,t),fo(e,t)].filter(n=>!!n).sort((n,a)=>a.credits-n.credits).map((n,a)=>({...n,rank:a+1}))}function cr(e){if(!e.length)return[];const t=[{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Estimated cost concentration by loaded aggregate thread."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Highest estimated credit-impact calls from loaded aggregate rows."}];return e.some(n=>n.fastProxyCandidate||n.effort.toLowerCase()==="low")&&t.push({title:"Fast Mode Proxy",status:"Ready",owner:"Calls",description:"Low-effort and fast-call candidates inferred from aggregate rows."}),t}function lo(e,t){const n=new Map;e.forEach(i=>n.set(i.thread,[...n.get(i.thread)??[],i]));const[a,r]=[...n.entries()].sort((i,o)=>Ae(o[1],f=>f.totalTokens)-Ae(i[1],f=>f.totalTokens)||o[1].length-i[1].length)[0]??[];if(!a||!(r!=null&&r.length)||r.length<2)return null;const s=Ae(r,vt);return{rank:0,title:`Long Thread: ${a}`,severity:s/t>=.25||r.length>=8?"High":"Medium",credits:Math.round(s),share:s/t*100,summary:`${r.length.toLocaleString()} loaded calls and ${Ae(r,i=>i.totalTokens).toLocaleString()} tokens in this thread.`}}function uo(e,t){const n=e.filter(r=>r.signal==="cache-risk"||r.cachedPct<35||r.uncachedInput>5e4);if(!n.length)return null;const a=Ae(n,vt);return{rank:0,title:"Cache Misses (Large Inputs)",severity:n.some(r=>r.cachedPct<20||r.uncachedInput>5e4)?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls show low cache reuse or large uncached input.`}}function ho(e,t){const n=e.filter(r=>r.effort.toLowerCase()==="high"||r.reasoningOutput>0);if(!n.length)return null;const a=Ae(n,vt);return{rank:0,title:"High Model Effort",severity:a/t>=.25?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls use high effort or report reasoning output.`}}function fo(e,t){const n=Math.max(25e3,mo(e.map(s=>s.output),.75)),a=e.filter(s=>s.output>=n||s.tags.some(i=>["file-heavy","subagent","large"].includes(i)));if(!a.length)return null;const r=Ae(a,vt);return{rank:0,title:"Tool Output Volume",severity:a.some(s=>s.output>5e4)?"High":"Medium",credits:Math.round(r),share:r/t*100,summary:`${a.length.toLocaleString()} loaded calls have high output volume or file-heavy/subagent tags.`}}function vt(e){return e.credits>0?e.credits:e.cost*25}function Ae(e,t){return e.reduce((n,a)=>n+t(a),0)}function mo(e,t){const n=e.filter(a=>Number.isFinite(a)).sort((a,r)=>a-r);return n.length?n[Math.min(n.length-1,Math.max(0,Math.floor((n.length-1)*t)))]??0:0}function lr(e){const t=new Map;for(const a of e){if(!Number.isFinite(a.timestamp))continue;const r=ur(a.timestamp),s=t.get(r)??{label:dr(a.timestamp),timestamp:po(a.timestamp),cached:0,cost:0,input:0,output:0};s.cached+=a.cached,s.cost+=a.cost,s.input+=a.input,s.output+=a.output,t.set(r,s)}const n=go(t);return n.length?{tokenSeries:[{id:"input",label:"Input",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input}))},{id:"output",label:"Output",color:"#059669",points:n.map(a=>({label:a.label,value:a.output}))},{id:"cached",label:"Cached",color:"#7c3aed",dashed:!0,points:n.map(a=>({label:a.label,value:a.cached}))}],costSeries:[{id:"cost",label:"Estimated Cost",color:"#f59e0b",points:n.map(a=>({label:a.label,value:a.cost}))}],cacheSeries:[{id:"cache",label:"Cache hit %",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input>0?a.cached/a.input*100:0}))}]}:{tokenSeries:[],costSeries:[],cacheSeries:[]}}function go(e){const t=[...e.values()].sort((s,i)=>s.timestamp-i.timestamp),n=t.at(0),a=t.at(-1);if(!n||!a)return[];const r=[];for(const s=new Date(n.timestamp);s.getTime()<=a.timestamp;s.setDate(s.getDate()+1)){const i=s.getTime(),o=ur(i);r.push(e.get(o)??{label:dr(i),timestamp:i,cached:0,cost:0,input:0,output:0})}return r}function ur(e){const t=new Date(e),n=String(t.getMonth()+1).padStart(2,"0"),a=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${n}-${a}`}function po(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}function dr(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function Q(e,t){var a;const n=Number(((a=e.summary)==null?void 0:a[t])??0);return Number.isFinite(n)?n:0}function vo(e){if(!(!e.summary||e.load_window==="rows"))return{visibleCalls:Q(e,"visible_calls"),inputTokens:Q(e,"input_tokens"),cachedInputTokens:Q(e,"cached_input_tokens"),uncachedInputTokens:Q(e,"uncached_input_tokens"),outputTokens:Q(e,"output_tokens"),reasoningOutputTokens:Q(e,"reasoning_output_tokens"),totalTokens:Q(e,"total_tokens"),estimatedCostUsd:Q(e,"estimated_cost_usd"),usageCredits:Q(e,"usage_credits")}}function bo(e,t,n){const a=e.fast,r=a===!0||a===1?!0:a===!1||a===0?!1:null;return{credits:Number(e.usage_credits??0),serviceTier:String(e.service_tier??""),fast:r,serviceTierSource:String(e.service_tier_source??""),serviceTierConfidence:String(e.service_tier_confidence??""),fastProxyCandidate:t>0&&n/Math.max(t,1)>4e3,standardUsageCredits:Number(e.standard_usage_credits??e.usage_credits??0),usageCreditMultiplier:Number(e.usage_credit_multiplier??1),usageCreditMultiplierSource:String(e.usage_credit_multiplier_source??"")}}const wo=1e4,yo=500;async function na(e,t,n){var s,i;const a=t.limit&&t.limit>0?t.limit:yo,r=await n(e,{...t,limit:a});return(i=t.onProgress)==null||i.call(t,{status:"completed",phase:"loading_rows",message:`Loaded ${t.loadWindow==="all"?"all-history":t.loadWindow} evidence window`,completed:Number(r.loaded_row_count??((s=r.rows)==null?void 0:s.length)??0),total:Number(r.total_available_rows??r.loaded_row_count??0),percent:100}),r}async function aa(e,t,n){var o,d;const a=[];let r=0,s=null,i=Number((e==null?void 0:e.total_available_rows)??0);for(let f=0;f<1e3;f+=1){(o=t.signal)==null||o.throwIfAborted();const h=await n(e,{...t,refresh:f===0?t.refresh:!1,limit:wo,offset:r}),b=h.rows??[];s=h,a.push(...b),i=Number(h.total_available_rows??i??a.length);const u=a.length>=i||!h.has_more;if((d=t.onProgress)==null||d.call(t,{status:u?"completed":"running",phase:"loading_rows",message:"Loading all rows",completed:a.length,total:i,percent:u?100:i>0?Math.min(99,Math.floor(a.length/i*100)):0}),r+=b.length,!h.has_more||b.length===0||a.length>=i)break}return{...s??e??{},rows:a,loaded_row_count:a.length,limit:null,limit_label:"All",has_more:!1,total_available_rows:i||a.length}}function _o(){if(window.__CODEX_USAGE_BOOT__)return window.__CODEX_USAGE_BOOT__;const e=document.getElementById("usage-data");if(!(e!=null&&e.textContent))return null;try{return JSON.parse(e.textContent)}catch{return null}}async function So(e,t={}){if(t.refresh&&(e!=null&&e.refresh_jobs_available)){const n=await Co(e,t),a={...t,refresh:!n};return a.loadWindow&&a.loadWindow!=="rows"?na(e,a,He):a.limit===0?aa(e,a,He):He(e,a)}return t.loadWindow&&t.loadWindow!=="rows"?na(e,t,He):t.limit===0?aa(e,t,He):He(e,t)}async function Co(e,t){try{return await xo(e,t),!0}catch(n){if(sr(n)||n instanceof hr)throw n;return!1}}async function He(e,t={}){rr(e);const n=new URLSearchParams({refresh:t.refresh?"1":"0",limit:String(t.limit??(e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??500),_:String(Date.now())});t.loadWindow&&n.set("load_window",t.loadWindow),t.since&&n.set("since",t.since),t.offset&&t.offset>0&&n.set("offset",String(t.offset)),(t.includeArchived??wr(e))&&n.set("include_archived","1");const r=await fetch(`/api/usage?${n.toString()}`,{headers:gn(e),cache:"no-store",signal:t.signal});return await pn(r,"Usage refresh")}async function xo(e,t){var o;rr(e);const n=new URLSearchParams({_:String(Date.now())});(t.includeArchived??wr(e))&&n.set("include_archived","1");const r=await fetch(`/api/refresh/start?${n.toString()}`,{headers:gn(e),cache:"no-store",signal:t.signal}),s=await pn(r,"Usage refresh start");(o=t.onProgress)==null||o.call(t,s);const i=typeof s.job_id=="string"?s.job_id:"";if(!i)throw new Error("Usage refresh start did not return a job id.");return ko(e,i,t.onProgress,t.signal)}async function ko(e,t,n,a){for(let r=0;r<600;r+=1){a==null||a.throwIfAborted();const s=new URLSearchParams({job_id:t,_:String(Date.now())}),i=await fetch(`/api/refresh/status?${s.toString()}`,{headers:gn(e),cache:"no-store",signal:a}),o=await pn(i,"Usage refresh status");if(n==null||n(o),o.status==="completed")return o;if(o.status==="failed")throw new hr(o.error||o.message||"Usage refresh failed.");await oo(Math.min(1e3,150+r*50),a)}throw new Error("Usage refresh did not complete before the polling timeout.")}class hr extends Error{}function ra(e){if(!e)return{...ar,contextRuntime:rn(e)};const t=e.rows??[],n=t.map(mr),a=t.length?Te(t,v=>Number(v.total_tokens??0)):Q(e,"total_tokens"),r=t.length?Te(t,v=>Number(v.estimated_cost_usd??0)):Q(e,"estimated_cost_usd"),s=t.length?Te(t,v=>Number(v.cached_input_tokens??0)):Q(e,"cached_input_tokens"),i=t.length?Te(t,v=>Number(v.input_tokens??0)):Q(e,"input_tokens"),o=t.length?Te(t,v=>{const w=Number(v.input_tokens??0),T=Number(v.cached_input_tokens??0);return Number(v.uncached_input_tokens??Math.max(w-T,0))}):Math.max(i-s,0),d=t.length?Te(t,v=>Number(v.output_tokens??0)):Q(e,"output_tokens"),f=t.length?Te(t,v=>Number(v.reasoning_output_tokens??0)):Q(e,"reasoning_output_tokens"),h=i>0?s/i*100:0,b=n.length||Math.max(0,Number(e.loaded_row_count??0)),u=Lo(t),p=Ro(t),g=Ao({cachePct:h,cachedTokens:s,estimatedCost:r,historyScope:e.history_scope??"active",totalCalls:b,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:o,output:d,reasoningOutput:f},usageRemainingCard:No(e)});return{...To(e),contextRuntime:rn(e),scopeSummary:vo(e),cards:g,...u,...p,calls:n,threads:yr(n),findings:or(n),modelCosts:ir(n),reports:cr(n),cacheSegments:[{label:"Cache read",value:h,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-h,0),color:"#7c3aed"}]}}function To(e){return{...ar,contextRuntime:rn(e),tokenSeries:[],costSeries:[],cacheSeries:[],weeklyCreditSeries:[],usageRemainingSeries:[],actualVsPredictedSeries:[],calls:[],threads:[],findings:[],weeklyWindows:[],modelCosts:[],commandActions:[],cacheSegments:[],cacheHeatmap:[],diagnostics:[],reports:[]}}function Lo(e){return lr(e.map(t=>({timestamp:bn(t),cached:Number(t.cached_input_tokens??0),cost:Number(t.estimated_cost_usd??0),input:Number(t.input_tokens??0),output:Number(t.output_tokens??0)})))}function Ro(e){const t=[...e].map(f=>({row:f,timestamp:bn(f)})).filter(f=>Number.isFinite(f.timestamp)).sort((f,h)=>f.timestamp-h.timestamp),n=new Map;for(const{row:f,timestamp:h}of t){const b=an(h),u=n.get(b)??{timestamp:h,credits:0,weeklyUsedPercent:null};u.credits+=Math.max(0,Number(f.usage_credits??0));const p=Oe(f.rate_limit_secondary_used_percent);p!==null&&(u.weeklyUsedPercent=p),n.set(b,u)}const a=[...n.entries()].map(([f,h])=>({label:f,...h}));let r=0;const s=a.map(f=>(r+=f.credits,{label:f.label,value:r})),i=s.map((f,h)=>{var b;return{label:f.label,value:s.length>1?(((b=s.at(-1))==null?void 0:b.value)??0)*((h+1)/s.length):f.value}}),o=a.filter(f=>f.weeklyUsedPercent!==null).map(f=>({label:f.label,value:Pt(100-(f.weeklyUsedPercent??0))})),d=Mo(e);return{weeklyCreditSeries:Po(d),usageRemainingSeries:o.length?[{id:"weekly-remaining",label:"Weekly remaining",color:"#059669",points:o}]:[],actualVsPredictedSeries:s.length?[{id:"observed-drain",label:"Observed drain",color:"#2563eb",points:s},{id:"loaded-baseline",label:"Loaded-row baseline",color:"#1d4ed8",dashed:!0,points:i}]:[],weeklyWindows:d}}function Mo(e){const t=new Map;for(const n of e){const a=bn(n);if(!Number.isFinite(a))continue;const r=jo(n,a),s=t.get(r)??{rows:[],latestTimestamp:0,latestUsedPercent:null};s.rows.push(n),a>=s.latestTimestamp&&(s.latestTimestamp=a,s.latestUsedPercent=Oe(n.rate_limit_secondary_used_percent)),t.set(r,s)}return[...t.entries()].map(([n,a])=>{var i;const r=a.rows.reduce((o,d)=>o+Math.max(0,Number(d.usage_credits??0)),0),s=a.latestUsedPercent??0;return{week:n,plan:String(((i=a.rows[0])==null?void 0:i.rate_limit_plan_type)??"unknown"),observedPct:s,credits:r,projected:s>0?r/(s/100):r,ciLow:s>0?r/(s/100)*.85:r,ciHigh:s>0?r/(s/100)*1.15:r,confidence:a.rows.length>=20?"Medium":"Low",note:`Loaded ${vn(a.rows.length)} rows`}}).sort((n,a)=>n.week.localeCompare(a.week))}function Po(e){return e.length?[{id:"weekly-projected",label:"Projected weekly credits",color:"#2563eb",points:e.map(t=>({label:t.week,value:t.projected,low:t.ciLow,high:t.ciHigh}))},{id:"loaded-credits",label:"Loaded-row credits",color:"#0f766e",dashed:!0,points:e.map(t=>({label:t.week,value:t.credits}))}]:[]}function jo(e,t){const n=Qe(e.rate_limit_secondary_resets_at);return n!==null&&n>0?an(n*1e3):an(t)}function an(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function rn(e){return{apiToken:String((e==null?void 0:e.api_token)??""),contextApiEnabled:!!(e!=null&&e.context_api_enabled),fileMode:window.location.protocol==="file:"}}function Ao(e){return[{label:"Total Tokens",value:Me(e.totalTokens),detail:`${e.historyScope} history scope`,trend:"loaded aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Me(e.tokenBreakdown.cachedInput)},{label:"Uncached",value:Me(e.tokenBreakdown.uncachedInput)},{label:"Output",value:Me(e.tokenBreakdown.output)},{label:"Reasoning",value:Me(e.tokenBreakdown.reasoningOutput)}]},{label:"Estimated Cost",value:Uo(e.estimatedCost),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.cachePct.toFixed(1)}%`,detail:`${Me(e.cachedTokens)} cached input`,trend:e.cachePct>=40?"healthy cache reuse":"cache risk",tone:e.cachePct>=40?"purple":"orange"},{label:"Total Calls",value:vn(e.totalCalls),detail:"loaded calls in this dashboard",trend:"privacy-safe",tone:"blue"},e.usageRemainingCard]}function No(e){const t=Eo(e.observed_usage);if(t)return t;const n=Do(e.allowance_windows);return n||{label:"Usage Remaining",value:"Unknown",detail:e.allowance_configured?"allowance configured; no current window":"no observed usage or allowance window",trend:e.allowance_error?`config issue: ${e.allowance_error}`:"not available in payload",tone:e.allowance_error?"red":"orange"}}function Eo(e){const t=Array.isArray(e==null?void 0:e.windows)?e.windows:[];if(!(e!=null&&e.available)||!t.length)return null;const n=fr(t,s=>Oe(s.used_percent)!==null);if(!n)return null;const a=Oe(n.used_percent)??0,r=Pt(100-a);return{label:"Usage Remaining",value:gr(r),detail:`${vr(n.label||n.key,"Observed usage")} observed usage`,trend:pr(n.resets_at)||e.source||"observed locally",tone:br(r)}}function Do(e){if(!Array.isArray(e)||!e.length)return null;const t=fr(e,o=>{const d=Oe(o.remaining_percent),f=Qe(o.remaining_credits),h=Qe(o.total_credits);return d!==null||f!==null||h!==null&&h>0});if(!t)return null;const n=Qe(t.remaining_credits),a=Qe(t.total_credits),r=n!==null&&a!==null&&a>0?n/a*100:null,s=Oe(t.remaining_percent)??r;return{label:"Usage Remaining",value:s!==null?gr(Pt(s)):`${sa(n??0)} left`,detail:`${vr(t.label||t.key,"Allowance")} allowance window`,trend:[n===null?"":`${sa(n)} left`,pr(t.reset_at)].filter(Boolean).join(" · ")||"configured allowance",tone:s===null?"green":br(Pt(s))}}function fr(e,t){const n=e.filter(t);return n.find(Fo)??n[0]??null}function Fo(e){const t=Qe(e.window_minutes),n=`${e.key??""} ${e.label??""}`.toLowerCase();return t===10080||/\b(weekly|week|7d|7-day|7 day)\b/.test(n)}function mr(e,t=0){const n=String(e.event_timestamp??e.time??e.turn_timestamp??e.started_at??e.call_started_at??""),a=n,r=String(e.call_started_at??e.started_at??n),s=Number(e.input_tokens??0),i=Number(e.output_tokens??0),o=Number(e.reasoning_output_tokens??0),d=Number(e.cached_input_tokens??0),f=Number(e.cache_hit_ratio??e.cache_ratio??0),h=s>0?d/s*100:f*100,b=Number(e.total_tokens??s+i),u=Number(e.duration_seconds??e.call_duration_seconds??0),p=String(e.previous_call_event_timestamp??""),g=Number(e.previous_call_delta_seconds??0),v=Number(e.uncached_input_tokens??Math.max(s-d,0)),w=String(e.record_id??e.id??`${a||"row"}-${t}`),T=String(e.primary_signal??"").trim(),N=Number(e.line_number),R=Oe(e.context_window_percent),_=Number(e.model_context_window),L=Number(e.cumulative_total_tokens);return{id:w,threadKey:String(e.thread_key??""),rawTime:a,eventTimestamp:n,callStartedAt:r,time:_r(a),thread:$o(e),model:String(e.model??"unknown"),effort:String(e.effort??"blank"),input:s,output:i,reasoningOutput:o,totalTokens:b,cachedInput:d,uncachedInput:v,cachedPct:h,cost:Number(e.estimated_cost_usd??0),duration:jt(u),durationSeconds:u,previousCallGap:jt(g),previousCallEventTimestamp:p,previousCallGapSeconds:Number.isFinite(g)?g:0,initiator:String(e.call_initiator??"unknown"),initiatorReason:String(e.call_initiator_reason??""),initiatorConfidence:String(e.call_initiator_confidence??""),...bo(e,u,b),usageCreditConfidence:String(e.usage_credit_confidence??"unknown"),usageCreditModel:String(e.usage_credit_model??""),usageCreditSource:String(e.usage_credit_source??""),usageCreditFetchedAt:String(e.usage_credit_fetched_at??""),usageCreditTier:String(e.usage_credit_tier??""),usageCreditNote:String(e.usage_credit_note??""),pricingModel:String(e.pricing_model??""),pricingEstimated:!!e.pricing_estimated,signal:T||(h<25?"cache-risk":"aggregate"),recommendation:String(e.recommended_action??""),tags:h<25?["uncached"]:h>60?["healthy-cache"]:[],sessionId:String(e.session_id??""),turnId:String(e.turn_id??""),parentSessionId:String(e.parent_session_id??""),parentSessionUpdatedAt:String(e.resolved_parent_session_updated_at??e.parent_session_updated_at??""),parentThread:String(e.resolved_parent_thread_name??e.parent_thread_name??""),threadAttachmentLabel:String(e.thread_attachment_label??""),threadSource:String(e.thread_source??""),subagentType:String(e.subagent_type??""),agentRole:String(e.agent_role??""),agentNickname:String(e.agent_nickname??""),project:String(e.project_name??""),projectRelativeCwd:String(e.project_relative_cwd??""),projectTags:Array.isArray(e.project_tags)?e.project_tags.map(y=>String(y)):[],cwd:String(e.cwd??""),sourceFile:String(e.source_file??""),lineNumber:Number.isFinite(N)&&N>0?N:null,gitBranch:String(e.git_branch??""),gitRemoteLabel:String(e.git_remote_label??""),gitRemoteHash:String(e.git_remote_hash??""),contextWindowPct:R,modelContextWindow:Number.isFinite(_)&&_>0?_:null,cumulativeTotalTokens:Number.isFinite(L)&&L>0?L:null,estimatedCacheSavings:Number(e.estimated_cache_savings_usd??0),efficiencyFlags:Array.isArray(e.efficiency_flags)?e.efficiency_flags.map(y=>String(y)):[]}}function Oe(e){const t=Number(e);return Number.isFinite(t)?t<=1?t*100:t:null}function Qe(e){const t=Number(e);return Number.isFinite(t)?t:null}function Pt(e){return Math.max(0,Math.min(100,e))}function gr(e){const t=Math.abs(e)>=10?0:1;return`${e.toFixed(t)}%`}function sa(e){return`${Me(e)} cr`}function pr(e){if(e==null||e==="")return"";const t=typeof e=="number"?e*1e3:Date.parse(e);return Number.isFinite(t)?`resets ${Io(t)}`:""}function Io(e){const t=new Date(e);return Number.isNaN(t.getTime())?String(e):`${t.toISOString().slice(0,16).replace("T"," ")} UTC`}function vr(e,t){return(e==null?void 0:e.trim())||t}function br(e){return e<20?"red":e<40?"orange":"green"}function wr(e){return typeof e.include_archived=="boolean"?e.include_archived:e.history_scope==="all-history"||e.history_scope==="all"}function $o(e){const t=e.thread_name??e.thread??e.resolved_parent_thread_name??e.parent_thread_name;if(t&&String(t).trim())return String(t);const n=e.project_name??e.project_relative_cwd,a=e.session_id?e.session_id.slice(-6):"";return n&&a?`${n} ${a}`:e.thread_attachment_label?String(e.thread_attachment_label):"Untitled thread"}function yr(e){const t=new Map;for(const n of e)t.set(n.thread,[...t.get(n.thread)??[],n]);return[...t.entries()].map(([n,a])=>{const r=a.length,i=[...a].sort((y,k)=>ia(k)-ia(y))[0]??null,o=(i==null?void 0:i.rawTime)||(i==null?void 0:i.time)||"",d=a.reduce((y,k)=>y+k.totalTokens,0),f=a.reduce((y,k)=>y+k.cachedInput,0),h=a.reduce((y,k)=>y+k.uncachedInput,0),b=a.reduce((y,k)=>y+k.output,0),u=a.reduce((y,k)=>y+k.reasoningOutput,0),p=a.reduce((y,k)=>y+k.cost,0),g=a.reduce((y,k)=>y+k.credits,0),v=a.reduce((y,k)=>y+k.durationSeconds,0),w=a.filter(y=>y.previousCallGapSeconds>0),T=w.reduce((y,k)=>y+k.previousCallGapSeconds,0)/Math.max(w.length,1),N=f+h,R=N>0?f/N*100:a.reduce((y,k)=>y+k.cachedPct,0)/Math.max(r,1),_=a.map(y=>y.contextWindowPct).filter(y=>typeof y=="number"&&Number.isFinite(y)),L=R<25?"High":R<45?"Medium":"Low";return{name:n,latestCallId:(i==null?void 0:i.id)??"",latestActivity:_r(o),latestActivityRaw:o,turns:r,totalDurationSeconds:v,totalDuration:jt(v),averageGapSeconds:T,averageGap:jt(T),initiatorSummary:zt(a.map(y=>y.initiator)),modelSummary:zt(a.map(y=>y.model)),effortSummary:zt(a.map(y=>y.effort)),totalTokens:d,cachedInput:f,uncachedInput:h,outputTokens:b,reasoningOutput:u,cost:p,credits:g,cachePct:R,contextPct:_.length?Math.max(..._):null,costPerCall:p/Math.max(r,1),coldResumeRisk:L,productivity:Math.max(20,Math.round(R-p/Math.max(r,1)*4))}}).sort((n,a)=>a.cost-n.cost).slice(0,20)}function ia(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function zt(e,t=3){const n=new Map;for(const a of e){const r=a.trim()||"unknown";n.set(r,(n.get(r)??0)+1)}return[...n.entries()].sort((a,r)=>r[1]-a[1]||a[0].localeCompare(r[0])).slice(0,t).map(([a,r])=>`${a} x${vn(r)}`).join(", ")||"unknown"}function Te(e,t){return e.reduce((n,a)=>n+t(a),0)}async function pn(e,t){let n;try{n=await e.json()}catch(a){if(e.ok)throw new Error(`${t} response could not be read as JSON: ${Oo(a)}`);n={}}if(!e.ok){const a=typeof n.error=="string"?n.error:`${t} request failed (${e.status})`;throw new Error(a)}return n}function Oo(e){return e instanceof Error?e.message:String(e)}function vn(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Me(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Uo(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function jt(e){if(!Number.isFinite(e)||e<=0)return"-";if(e<60)return`${e.toFixed(0)}s`;const t=Math.floor(e/60),n=Math.round(e%60);return`${t}m ${n}s`}function _r(e){const t=new Date(e);return Number.isNaN(t.getTime())?e||"-":new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).format(t)}function bn(e){return Date.parse(String(e.started_at??e.call_started_at??e.time??e.event_timestamp??e.turn_timestamp??""))}const Pe=1440*60*1e3;function Vo(e,t,n=window.location.search){const a=Sr(n);if(!a.active)return e;const r=e.calls.filter(s=>Ko(s,a));return r.length===e.calls.length?e:Bo(e,r,`${t} filtered`)}function Sr(e){var d,f,h,b,u,p;const t=new URLSearchParams(e),n=((d=t.get("model"))==null?void 0:d.trim())??"",a=((f=t.get("effort"))==null?void 0:f.trim())??"",r=((h=t.get("confidence")||t.get("pricing"))==null?void 0:h.trim())??"",s=((b=t.get("date")||t.get("time"))==null?void 0:b.trim())??"",i=((u=t.get("from"))==null?void 0:u.trim())??"",o=((p=t.get("to"))==null?void 0:p.trim())??"";return{model:n,effort:a,confidence:r,datePreset:s,dateStart:i,dateEnd:o,active:!!(n||a||r||s||i||o)}}function Ko(e,t){return!(t.model&&e.model!==t.model||t.effort&&e.effort!==t.effort||t.confidence&&!qo(e,t.confidence)||!Ho(e,t))}function qo(e,t){return t==="official"||t==="cost-exact"?!!(e.pricingModel&&!e.pricingEstimated):t==="estimated"||t==="cost-estimated"?e.pricingEstimated:t==="unpriced"||t==="cost-unpriced"?!e.pricingModel:t==="credit-exact"?e.usageCreditConfidence==="exact":t==="credit-estimated"?e.usageCreditConfidence==="estimated":t==="credit-override"?e.usageCreditConfidence==="user_override":t==="credit-missing"?e.usageCreditConfidence==="missing"||e.usageCreditConfidence==="unknown":!0}function Ho(e,t){const n=Wo(t);if(!n.active)return!0;if(n.invalid)return!1;const a=Date.parse(e.rawTime||e.time);return!(!Number.isFinite(a)||n.start!==null&&a=n.endExclusive)}function Wo(e){if(e.datePreset&&e.datePreset!=="all"&&e.datePreset!=="custom"){const a=Qo(e.datePreset);return a?{active:!0,invalid:!1,...a}:{active:!1,invalid:!1,start:null,endExclusive:null}}const t=oa(e.dateStart),n=oa(e.dateEnd);return t!==null&&n!==null&&t>n?{active:!0,invalid:!0,start:t,endExclusive:n+Pe}:{active:t!==null||n!==null,invalid:!1,start:t,endExclusive:n===null?null:n+Pe}}function Qo(e){const t=zo(new Date);if(e==="today")return{start:t,endExclusive:t+Pe};if(e==="last-7-days")return{start:t-6*Pe,endExclusive:t+Pe};if(e==="this-week"){const a=new Date(t).getDay(),r=a===0?-6:1-a,s=t+r*Pe;return{start:s,endExclusive:s+7*Pe}}if(e==="this-month"){const n=new Date(t),a=new Date(n.getFullYear(),n.getMonth(),1).getTime(),r=new Date(n.getFullYear(),n.getMonth()+1,1).getTime();return{start:a,endExclusive:r}}return null}function oa(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function zo(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function Bo(e,t,n="filtered"){const a=t.reduce((u,p)=>u+p.totalTokens,0),r=t.reduce((u,p)=>u+p.cost,0),s=t.reduce((u,p)=>u+p.cachedInput,0),i=t.reduce((u,p)=>u+p.uncachedInput,0),o=t.reduce((u,p)=>u+p.output,0),d=t.reduce((u,p)=>u+p.reasoningOutput,0),f=t.reduce((u,p)=>u+p.input,0),h=f>0?s/f*100:0,b=e.cards.find(u=>u.label==="Usage Remaining")??{label:"Usage Remaining",value:"Unknown",detail:"not available in filtered view",trend:"not available in payload",tone:"orange"};return{...e,cards:Go({cachePct:h,cachedTokens:s,estimatedCost:r,historyScope:n,totalCalls:t.length,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:i,output:o,reasoningOutput:d},usageRemainingCard:b}),...Jo(t),calls:t,threads:yr(t),findings:or(t),modelCosts:ir(t),reports:cr(t),cacheSegments:[{label:"Cache read",value:h,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-h,0),color:"#7c3aed"}]}}function Go({cachePct:e,cachedTokens:t,estimatedCost:n,historyScope:a,totalCalls:r,totalTokens:s,tokenBreakdown:i,usageRemainingCard:o}){return[{label:"Total Tokens",value:We(s),detail:`${a} history scope`,trend:"filtered aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:We(i.cachedInput)},{label:"Uncached",value:We(i.uncachedInput)},{label:"Output",value:We(i.output)},{label:"Reasoning",value:We(i.reasoningOutput)}]},{label:"Estimated Cost",value:Xo(n),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.toFixed(1)}%`,detail:`${We(t)} cached input`,trend:e>=40?"healthy cache reuse":"cache risk",tone:e>=40?"purple":"orange"},{label:"Total Calls",value:Zo(r),detail:"loaded calls matching filters",trend:"legacy shell filters",tone:"blue"},o]}function Jo(e){return lr(e.map(t=>({timestamp:Date.parse(t.rawTime||t.time),cached:t.cachedInput,cost:t.cost,input:t.input,output:t.output})))}function We(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Zo(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Xo(e){return new Intl.NumberFormat("en-US",{currency:"USD",maximumFractionDigits:2,minimumFractionDigits:2,style:"currency"}).format(e)}const Cr=[{id:"overview",label:"Overview",description:"High-level telemetry",icon:Ds},{id:"investigator",label:"Investigate",description:"Root-cause evidence",icon:Es},{id:"compression-lab",label:"Compression Lab",description:"Context savings",icon:Ls},{id:"calls",label:"Calls",description:"Model-call table",icon:Os},{id:"threads",label:"Threads",description:"Thread efficiency",icon:Ks},{id:"usage-drain",label:"Limits",description:"Allowance intelligence",icon:Vs},{id:"cache-context",label:"Cache And Context",description:"Cache and cold resumes",icon:Ps},{id:"diagnostics",label:"Diagnostics Notebook",description:"Technical report",icon:ks},{id:"reports",label:"Reports",description:"Generated analyses",icon:Rs},{id:"settings",label:"Settings",description:"Local configuration",icon:Is}],xr=[{label:"Files",icon:As,target:"settings"},{label:"Commands",icon:Cs,target:"investigator"},{label:"Models",icon:Ts,target:"calls"}];function kr(e){return ws(e)}const Yo=[{value:"day",label:"24 hours",ariaLabel:"Last 24h"},{value:"week",label:"7 days",ariaLabel:"Last 7 days"},{value:"rows",label:"Recent",ariaLabel:"Recent rows"},{value:"all",label:"All time",ariaLabel:"All time"}];function ec(e){const t=e.refreshing||!e.canUseLiveApi,n=e.loadWindow==="rows",a=`${e.loadedRowCount.toLocaleString()} detail row${e.loadedRowCount===1?"":"s"} cached`,r=n?`${e.loadedRowCount.toLocaleString()} loaded / ${e.totalAvailableRows.toLocaleString()} total`:`${e.totalAvailableRows.toLocaleString()} calls analyzed · ${a}`,s=n?`${e.loadedRowCount.toLocaleString()} of ${e.totalAvailableRows.toLocaleString()} evidence rows loaded`:`Focused pages analyze all ${e.totalAvailableRows.toLocaleString()} calls in scope; ${e.loadedRowCount.toLocaleString()} call rows are cached for immediate detail views.`,i=n?e.rowLoadStatus:`${e.rowLoadModeLabel} analysis uses ${e.totalAvailableRows.toLocaleString()} calls; ${a}`;return c.jsxs("section",{className:"data-window-control","aria-label":"Analysis scope",children:[c.jsxs("div",{className:"data-window-summary",children:[c.jsx("span",{children:"Analysis scope"}),c.jsx("strong",{children:e.rowLoadModeLabel}),c.jsx("small",{title:s,children:r})]}),c.jsx("div",{className:"data-window-options",role:"group","aria-label":"Choose loaded call window",children:Yo.map(o=>c.jsx("button",{type:"button","aria-label":o.ariaLabel,"aria-pressed":e.loadWindow===o.value,disabled:t,onClick:()=>e.onWindowChange(o.value),children:o.label},o.value))}),e.loadWindow==="rows"?c.jsxs("div",{className:"row-window-editor",children:[c.jsx("input",{"aria-label":"Rows to load slider","aria-valuetext":`${e.finitePendingLoadLimit.toLocaleString()} recent rows`,type:"range",min:1,max:e.rowLimitSliderMax,step:100,value:e.rowLimitSliderValue,onChange:o=>e.onSliderChange(o.target.value),disabled:t}),c.jsx("input",{"aria-label":"Rows to load",type:"number",min:1,step:100,value:e.pendingLoadLimit,onChange:o=>e.onDraftChange(o.target.value),disabled:t}),c.jsx("button",{type:"button","data-primary":"true",onClick:e.onApply,disabled:t||!e.rowLimitChanged,children:e.loadLabel}),c.jsx("button",{type:"button",onClick:e.onLoadMore,disabled:t||!e.hasMoreRows,children:e.loadMoreLabel})]}):null,e.refreshing?c.jsxs("div",{className:"row-load-progress","aria-label":"Row loading progress",children:[c.jsx("div",{className:"row-load-progress-track",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":e.refreshProgressPercent??void 0,children:c.jsx("span",{style:{width:`${e.refreshProgressPercent??8}%`}})}),c.jsxs("span",{children:[e.refreshProgressPercent===null?e.refreshProgressText:`${Math.round(e.refreshProgressPercent)}% loaded`,c.jsx("button",{className:"icon-button",type:"button",onClick:()=>void e.onCancel(),"aria-label":"Cancel refresh",title:"Cancel refresh",children:c.jsx(un,{size:13})})]})]}):null,c.jsx("span",{className:"sr-only",role:"status","aria-live":"polite",children:i})]})}const wn=[{value:"all",label:"All time"},{value:"today",label:"Today"},{value:"this-week",label:"This week"},{value:"last-7-days",label:"Last 7 days"},{value:"this-month",label:"This month"},{value:"custom",label:"Custom"}],Tr=[{value:"all",label:"All confidence"},{value:"cost-exact",label:"Exact cost"},{value:"cost-estimated",label:"Estimated cost"},{value:"cost-unpriced",label:"Unpriced cost"},{value:"credit-exact",label:"Exact credit"},{value:"credit-estimated",label:"Estimated credit"},{value:"credit-override",label:"Credit override"},{value:"credit-missing",label:"Missing credit"}];function tc({activeView:e,locationSearch:t,model:n,onUrlChange:a}){const r=Sr(t),s=C.useMemo(()=>ca(n.calls.map(g=>g.model)),[n.calls]),i=C.useMemo(()=>ca(n.calls.map(g=>g.effort)),[n.calls]),o=r.dateStart||r.dateEnd?"custom":nc(r.datePreset),d=rc(r,o);if(e==="calls"||e==="call"||!n.calls.length)return null;function f(g){const v=new URL(window.location.href);g(v),a(v)}function h(g,v){f(w=>{g==="confidence"&&w.searchParams.delete("pricing"),!v||v==="all"?w.searchParams.delete(g):w.searchParams.set(g,v)})}function b(g){f(v=>{if(!g||g==="all"){v.searchParams.delete("date"),v.searchParams.delete("time"),v.searchParams.delete("from"),v.searchParams.delete("to");return}v.searchParams.set("date",g),v.searchParams.set("time",g),g!=="custom"&&(v.searchParams.delete("from"),v.searchParams.delete("to"))})}function u(g,v){f(w=>{v?(w.searchParams.set(g,v),w.searchParams.set("date","custom"),w.searchParams.set("time","custom")):(w.searchParams.delete(g),!w.searchParams.get("from")&&!w.searchParams.get("to")&&(w.searchParams.delete("date"),w.searchParams.delete("time")))})}function p(){f(g=>{for(const v of["model","effort","confidence","pricing","date","time","from","to"])g.searchParams.delete(v)})}return c.jsxs("section",{className:"global-filter-strip span-all","aria-label":"Dashboard filters",children:[c.jsxs("strong",{children:[c.jsx(Ns,{size:15}),"Filters"]}),c.jsxs("label",{children:[c.jsx("span",{children:"Model"}),c.jsxs("select",{"aria-label":"Global model filter",value:r.model||"all",onChange:g=>h("model",g.target.value),children:[c.jsx("option",{value:"all",children:"All models"}),s.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Effort"}),c.jsxs("select",{"aria-label":"Global effort filter",value:r.effort||"all",onChange:g=>h("effort",g.target.value),children:[c.jsx("option",{value:"all",children:"All effort"}),i.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Confidence"}),c.jsx("select",{"aria-label":"Global confidence filter",value:ac(r.confidence),onChange:g=>h("confidence",g.target.value),children:Tr.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Time"}),c.jsx("select",{"aria-label":"Global time filter",value:o,onChange:g=>b(g.target.value),children:wn.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))}),d?c.jsx("span",{className:"filter-status","data-state":d.state,"aria-live":"polite",children:d.label}):null]}),c.jsxs("label",{children:[c.jsx("span",{children:"Start"}),c.jsx("input",{"aria-label":"Global start date",type:"date",value:r.dateStart,onChange:g=>u("from",g.target.value)})]}),c.jsxs("label",{children:[c.jsx("span",{children:"End"}),c.jsx("input",{"aria-label":"Global end date",type:"date",value:r.dateEnd,onChange:g=>u("to",g.target.value)})]}),c.jsxs("button",{className:"toolbar-button",type:"button",disabled:!r.active,onClick:p,children:[c.jsx(un,{size:15}),"Clear filters"]})]})}function ca(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean))).sort((t,n)=>t.localeCompare(n))}function nc(e){return wn.some(t=>t.value===e)?e:"all"}function ac(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":Tr.some(t=>t.value===e)?e:"all"}function rc(e,t){var r;const n=ua(e.dateStart),a=ua(e.dateEnd);if(n!==null&&a!==null&&n>a)return{label:"Invalid date range",state:"error"};if(t==="custom"&&(e.dateStart||e.dateEnd))return{label:sc(e.dateStart,e.dateEnd),state:"active"};if(t!=="all"){const s=((r=wn.find(o=>o.value===t))==null?void 0:r.label)??t,i=ic(t);return{label:i?`${s}: ${la(i.start)} to ${la(ze(i.endExclusive,-1))}`:s,state:"active"}}return null}function sc(e,t){return e&&t?`Custom: ${e} to ${t}`:e?`Custom: from ${e}`:t?`Custom: through ${t}`:"Custom range"}function ic(e){const t=oc();if(e==="today")return{start:t,endExclusive:ze(t,1)};if(e==="this-week"){const n=cc(t);return{start:n,endExclusive:ze(n,7)}}return e==="last-7-days"?{start:ze(t,-6),endExclusive:ze(t,1)}:e==="this-month"?{start:new Date(t.getFullYear(),t.getMonth(),1),endExclusive:new Date(t.getFullYear(),t.getMonth()+1,1)}:null}function oc(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function cc(e){const t=e.getDay();return ze(e,t===0?-6:1-t)}function ze(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function la(e){const t=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${e.getFullYear()}-${t}-${n}`}function ua(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function lc(e){return kr(e)&&e!=="call"}function sn(e,t="overview"){return e==="insights"?"overview":kr(e)?e:t}function da(e=window.location.search,t="calls"){const n=new URLSearchParams(e).get("return"),a=sn(n,t);return lc(a)?a:t}function ha(e=window.location.search){return new URLSearchParams(e).has("return")}function uc(e){var t,n;return((t=Cr.find(a=>a.id===e))==null?void 0:t.label)??((n=xr.find(a=>a.target===e))==null?void 0:n.label)??"Calls"}function fa(e,t=window.location.search){return new URLSearchParams(t).get("history")==="all"?"all":e}function ma(e,t=window.location.href){const n=new URL(t);return e==="all"?n.searchParams.set("history","all"):n.searchParams.delete("history"),n}const dc={investigator:["finding"],threads:["thread","expand","threads","thread_q","risk","thread_call_sort","thread_call_page"],"cache-context":["cache_thread"],reports:["report"],"usage-drain":["usage_plan","usage_effort","usage_subagents","usage_sample","usage_confidence","limit_window","limit_hypothesis"],diagnostics:["diagnostic_source","diagnostic_fact"],calls:["explore","detail","call_q","source","sort","direction","density","page"],call:["record","return","mode","max_entries","max_chars","include_tool_output","include_compaction_history"]};function kt(e,t,n=[]){const a=new Set([t,...Array.isArray(n)?n:[n]]);for(const[r,s]of Object.entries(dc))if(!a.has(r))for(const i of s)e.searchParams.delete(i)}function ga(e){let t=!1;return e.searchParams.get("view")==="insights"&&(e.searchParams.set("view","overview"),t=!0),e.searchParams.get("return")==="insights"&&(e.searchParams.set("return","overview"),t=!0),t}const Lr=[{key:"overview",title:"Overview",path:"/api/diagnostics/overview",refreshPath:"/api/diagnostics/overview/refresh"},{key:"toolOutput",title:"Tool Output",path:"/api/diagnostics/tool-output",refreshPath:"/api/diagnostics/tool-output/refresh"},{key:"commands",title:"Commands",path:"/api/diagnostics/commands",refreshPath:"/api/diagnostics/commands/refresh"},{key:"gitInteractions",title:"Git Interactions",path:"/api/diagnostics/git-interactions",refreshPath:"/api/diagnostics/git-interactions/refresh"},{key:"fileReads",title:"File Reads",path:"/api/diagnostics/file-reads",refreshPath:"/api/diagnostics/file-reads/refresh"},{key:"fileModifications",title:"File Modifications",path:"/api/diagnostics/file-modifications",refreshPath:"/api/diagnostics/file-modifications/refresh"},{key:"readProductivity",title:"Read Productivity",path:"/api/diagnostics/read-productivity",refreshPath:"/api/diagnostics/read-productivity/refresh"},{key:"concentration",title:"Concentration",path:"/api/diagnostics/concentration",refreshPath:"/api/diagnostics/concentration/refresh"},{key:"guidedSummary",title:"What Is Driving Usage?",path:"/api/diagnostics/guided-summary",refreshPath:"/api/diagnostics/guided-summary/refresh"},{key:"usageDrain",title:"Usage Drain",path:"/api/diagnostics/usage-drain",refreshPath:"/api/diagnostics/usage-drain/refresh"}],At=new Map,Dt=new Map;function hc(){At.clear(),Dt.clear()}async function Bl(e,t,n={}){Sn(t);const a=vc(e);return n.signal?Nt(a,t,n.signal):pc(Dt,_n(e,t,n.cacheKey),()=>Nt(a,t))}async function Gl(e,t={}){Sn(e);const n=await fetch(`/api/diagnostics/refresh?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:t.signal}),a=await Ft(n,"Diagnostic snapshot refresh"),r=a.sections??(Mr(a)?await fc(e,await Rr(a,e,t),t.signal):{});At.set(yn(e),r);for(const[s,i]of Object.entries(r))Dt.set(_n(s,e),i);return r}async function Jl(e,t,n={}){Sn(t);const a=await fetch(`${e.refreshPath}?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),r=await Ft(a,e.title),s=Mr(r)?await mc(t,e,await Rr(r,t,n),n.signal):r,i=yn(t),o=At.get(i),d=o?await Promise.resolve(o):{};return At.set(i,{...d,[e.key]:s}),Dt.set(_n(e.key,t),s),s}async function Rr(e,t,n){var r,s,i,o;let a=e;for((r=n.onProgress)==null||r.call(n,a);a.status==="pending"||a.status==="running";){const d=n.pollIntervalMs??((s=a.next)==null?void 0:s.poll_after_ms)??250;await gc(d,n.signal);const f=new URLSearchParams({job_id:a.job_id,_:String(Date.now())}),h=await fetch(`/api/diagnostics/refresh/status?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});a=await Ft(h,"Diagnostic refresh status"),(i=n.onProgress)==null||i.call(n,a)}if(a.status!=="completed")throw new Error(`Diagnostic refresh failed: ${((o=a.error)==null?void 0:o.code)??a.status}`);return a}async function fc(e,t,n){const a=await Promise.all(Lr.map(async r=>[r.key,await Nt(r,e,n)]));return Object.fromEntries(a)}async function mc(e,t,n,a){return Nt(t,e,a)}function Mr(e){if(!e||typeof e!="object")return!1;const t=e;return t.schema==="codex-usage-tracker-analysis-job-v1"&&t.job_kind==="diagnostic-refresh"&&typeof t.job_id=="string"}function gc(e,t){return t!=null&&t.aborted?Promise.reject(t.reason??new DOMException("Aborted","AbortError")):e<=0?Promise.resolve():new Promise((n,a)=>{const r=()=>{window.clearTimeout(s),t==null||t.removeEventListener("abort",r),a((t==null?void 0:t.reason)??new DOMException("Aborted","AbortError"))},s=window.setTimeout(()=>{t==null||t.removeEventListener("abort",r),n()},e);t==null||t.addEventListener("abort",r,{once:!0})})}function pc(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function yn(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function _n(e,t,n=""){return`snapshot:${yn(t)}:${n}:${e}`}function vc(e){const t=Lr.find(n=>n.key===e);if(!t)throw new Error(`Unknown diagnostic snapshot: ${e}`);return t}async function Nt(e,t,n){const a=await fetch(`${e.path}?_=${Date.now()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n});return await Ft(a,e.title)}function Sn(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Ft(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(typeof n.error=="string"&&n.error)throw new Error(n.error);return n}const pa=[{key:"facts",label:"Top Facts",title:"Top Diagnostic Facts",path:"/api/diagnostics/facts",limit:50},{key:"tools",label:"Tools",title:"Tool and Function Activity",path:"/api/diagnostics/tools",limit:25},{key:"compactions",label:"Compactions",title:"Compaction Activity",path:"/api/diagnostics/compactions",limit:25}],Pr=new Map,jr=new Map;function bc(){hc(),Pr.clear(),jr.clear()}async function Zl(e,t,n={}){Dr(t);const a=pa.find(f=>f.key===e)??pa[0],r=yc(n.sort??"uncached"),s=n.direction??"desc",i=Math.max(1,Math.round(n.limit??a.limit)),o=Math.max(0,Math.round(n.offset??0)),d=async()=>{const f=new URLSearchParams({limit:String(i),offset:String(o),sort:r,direction:s});Er(f,"include_archived",n.includeArchived);const h=await fetch(`${a.path}?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});return await Fr(h,a.title)};return n.signal?d():Ar(Pr,wc(a.key,t,i,o,r,s,n.cacheKey,n.includeArchived),d)}async function Xl(e,t,n={}){Dr(t);const a=Math.max(1,Math.round(n.limit??8)),r=Math.max(0,Math.round(n.offset??0)),s=n.sort??"tokens",i=n.direction??"desc",o=async()=>{const d=String(e.fact_type??""),f=String(e.fact_name??"");if(!d||!f)throw new Error("Diagnostic fact type and name are required.");const h=new URLSearchParams({fact_type:d,fact_name:f,limit:String(a),offset:String(r),sort:s,direction:i});Er(h,"include_archived",n.includeArchived);const b=await fetch(`/api/diagnostics/fact-calls?${h.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),u=await Fr(b,"Diagnostic fact calls");return{calls:(u.rows??[]).map((p,g)=>mr(p,g)),rawPayload:u}};return n.signal?o():Ar(jr,_c(e,t,a,r,s,i,n.cacheKey,n.includeArchived),o)}function Ar(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function Nr(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function wc(e,t,n,a,r,s,i="",o){return["facts",e,Nr(t),i,o??"default",n,a,r,s].join(":")}function yc(e){return e==="total"?"tokens":e==="latest"?"time":e}function _c(e,t,n,a,r,s,i="",o){return["fact-calls",Nr(t),i,o??"default",String(e.fact_type??""),String(e.fact_name??""),n,a,r,s].join(":")}function Er(e,t,n){n!==void 0&&e.set(t,String(n))}function Dr(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Fr(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(n.error)throw new Error(n.error);return n}const Sc=[{id:"usage-snapshot",endpoint:"/api/usage",dataClass:"snapshot",schema:"codex-usage-tracker-dashboard-v1"},{id:"overview-summary",endpoint:"/api/summary",dataClass:"aggregate",schema:"codex-usage-tracker-summary-v1"},{id:"overview-recommendations",endpoint:"/api/recommendations",dataClass:"aggregate",schema:"codex-usage-tracker-recommendations-v1"},{id:"calls",endpoint:"/api/calls",dataClass:"aggregate",schema:"codex-usage-tracker-calls-v1"},{id:"threads",endpoint:"/api/threads",dataClass:"aggregate",schema:"codex-usage-tracker-threads-v1"},{id:"thread-calls",endpoint:"/api/thread-calls",dataClass:"detail",schema:"codex-usage-tracker-thread-calls-v1"},{id:"investigator-agentic",endpoint:"/api/investigations/agentic",dataClass:"aggregate",schema:"codex-usage-tracker-agentic-investigation-v1"},{id:"investigator-walk",endpoint:"/api/investigations/walk",dataClass:"userAction",schema:"codex-usage-tracker-investigation-walk-v1"},{id:"diagnostics-facts",endpoint:"/api/diagnostics/facts",dataClass:"aggregate",schema:null},{id:"diagnostics-fact-calls",endpoint:"/api/diagnostics/fact-calls",dataClass:"detail",schema:null},{id:"diagnostics-dedupe",endpoint:"/api/diagnostics/dedupe",dataClass:"aggregate",schema:"codex-usage-tracker-dedupe-diagnostics-v1"},{id:"diagnostics-snapshot",endpoint:"/api/diagnostics/{snapshot}",dataClass:"aggregate",schema:null},{id:"compression-profile",endpoint:"/api/compression/profile",dataClass:"aggregate",schema:"codex-usage-tracker-compression-api-v1"},{id:"reports",endpoint:"/api/reports/pack",dataClass:"aggregate",schema:"codex-usage-tracker-reports-pack-v1"}],Cc=Sc,xc=new Map(Cc.map(e=>[e.id,e])),kc=15*6e4,Tc=3e4,Ir={snapshot:ot({persistedCache:"aggregate-only"}),aggregate:ot({persistedCache:"aggregate-only"}),detail:ot(),heavyJob:ot({cancellation:"shared-job",staleTime:1e3}),userAction:ot({retry:0,staleTime:0})};function Lc({sourceKey:e,sourceRevision:t}){return{sourceKey:va(e,"local-api"),sourceRevision:va(t,"unversioned")}}function Rc(e,t,n={},...a){return["dashboard",e.id,t.sourceKey,t.sourceRevision,jc(n),...a]}function Mc(e){return["dashboard",e.id]}function Pc(e){const t=xc.get(e);if(!t)throw new Error(`Unknown dashboard query definition: ${e}`);return t}function $r(e){const t=Ir[e];return{gcTime:t.gcTime,refetchOnReconnect:t.refetchOnReconnect,refetchOnWindowFocus:t.refetchOnWindowFocus,retry:t.retry,staleTime:t.staleTime}}function Yl({enabled:e,hasData:t,isError:n,isFetching:a,isPending:r}){return e?t?a?"updating":"ready":n?"error":a||r?"loading":"waiting":"waiting"}function eu(e){const t=e.filter(a=>a==="ready"||a==="updating").length,n=e.length;return{ready:t,total:n,percent:n===0?100:Math.round(t/n*100),loading:e.filter(a=>a==="loading").length,errors:e.filter(a=>a==="error").length}}function jc(e){return{historyScope:e.historyScope??"active",loadWindow:e.loadWindow??"all",limit:e.limit??null,since:e.since??""}}function va(e,t){return(e==null?void 0:e.trim())||t}function ot(e={}){return{staleTime:Tc,gcTime:kc,retry:1,refetchOnReconnect:!1,refetchOnWindowFocus:!1,cancellation:"observer",persistedCache:"none",...e}}const Ac=new Set(["command_text","content_fragment","content_fragments","excerpt","indexed_content","indexed_fragment","indexed_fragments","prompt","raw_context","raw_output","snippet","tool_output"]),Nc=new Set(["includes_indexed_content","includes_raw_fragment","includes_raw_fragments","indexed_content_included","raw_content_included","raw_context_included"]),Ec=new Set(["codex-usage-tracker-context-v1"]);function ba(e){return on(e,new WeakSet)}function on(e,t){if(!e||typeof e!="object")return!0;if(t.has(e))return!1;t.add(e);const n=Array.isArray(e)?e.every(a=>on(a,t)):Object.entries(e).every(([a,r])=>{const s=a.toLowerCase();return Ac.has(s)||Nc.has(s)&&r===!0||s==="schema"&&typeof r=="string"&&Ec.has(r)?!1:on(r,t)});return t.delete(e),n}const Dc="codexUsageDashboard",Fc=1,Y="usageSnapshots",Ic=6,$c=10080*60*1e3,Oc={async read(e){if(!e.sourceRevision)return null;try{const t=await ya();if(!t)return null;const n=await Or(t.transaction(Y,"readonly").objectStore(Y).get(wa(e)));return!n||n.sourceRevision!==e.sourceRevision||Date.now()-n.storedAt>$c?null:ba(n.payload)?n.payload:(await Uc(t,n.cacheKey),null)}catch{return null}},async write(e,t){if(!(!e.sourceRevision||!ba(t)))try{const n=await ya();if(!n)return;const a=n.transaction(Y,"readwrite");a.objectStore(Y).put({...e,cacheKey:wa(e),payload:t,storedAt:Date.now()}),await Cn(a),await Vc(n)}catch{}}};async function Uc(e,t){const n=e.transaction(Y,"readwrite");n.objectStore(Y).delete(t),await Cn(n)}function wa(e){const{historyScope:t,loadWindow:n,limit:a,since:r}=e.scope;return JSON.stringify([e.sourceKey,t,n,a,r])}function ya(){return typeof indexedDB>"u"?Promise.resolve(null):new Promise(e=>{const t=indexedDB.open(Dc,Fc);t.onupgradeneeded=()=>{t.result.objectStoreNames.contains(Y)||t.result.createObjectStore(Y,{keyPath:"cacheKey"})},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)})}function Or(e){return new Promise((t,n)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>n(e.error??new Error("IndexedDB request failed"))})}function Cn(e){return new Promise((t,n)=>{e.oncomplete=()=>t(),e.onerror=()=>n(e.error??new Error("IndexedDB transaction failed")),e.onabort=()=>n(e.error??new Error("IndexedDB transaction aborted"))})}async function Vc(e){const t=e.transaction(Y,"readonly"),a=(await Or(t.objectStore(Y).getAll())).sort((i,o)=>o.storedAt-i.storedAt).slice(Ic);if(!a.length)return;const r=e.transaction(Y,"readwrite"),s=r.objectStore(Y);a.forEach(i=>s.delete(i.cacheKey)),await Cn(r)}const Kc={kind:"production",load:So},qc="codexUsageDashboardRuntimeMetadata",Hc=2048,cn=Pc("usage-snapshot"),Ur={all:Mc(cn),snapshot:(e,t,n)=>Rc(cn,Lc({sourceKey:e,sourceRevision:t}),n)};function Wc(){return new Ti({defaultOptions:{queries:{...$r("aggregate")}}})}const xn=Wc();async function Qc({currentPayload:e,historyScope:t,loadWindow:n,loadLimit:a,since:r=null,onProgress:s,queryClient:i=xn,refresh:o=!1,snapshotStore:d=Oc,transport:f=Kc}){const h=Vi(a,t,r,n),b=kn(e),u=Ur.snapshot(b.sourceKey,b.sourceRevision,h);!i.getQueryData(u)&&Zc(e,h)&&i.setQueryData(u,e),o&&await i.invalidateQueries({queryKey:u,exact:!0});const p=_a(e,h),g=await i.fetchQuery({queryKey:u,...$r(cn.dataClass),queryFn:async({signal:v})=>{var R;const w=!o&&p?await d.read(p):null;if(w)return s==null||s({status:"completed",phase:"loading_rows",message:"Loaded cached dashboard snapshot",completed:Number(w.loaded_row_count??((R=w.rows)==null?void 0:R.length)??0),total:Number(w.total_available_rows??w.loaded_row_count??0),percent:100}),w;const T=await f.load(e,{refresh:o,limit:Ki(h),includeArchived:h.historyScope==="all",loadWindow:n,since:h.since,onProgress:s,signal:v}),N=p?{...p,sourceRevision:String(T.latest_refresh_at??p.sourceRevision)}:_a(T,h);return N&&await d.write(N,T),T},staleTime:o?0:Ir.snapshot.staleTime});return Jc(Gc(g,h)),g}function _a(e,t){if(!(e!=null&&e.api_token))return null;const n=String(e.latest_refresh_at??"");return n?{sourceKey:Vr(e),sourceRevision:n,scope:t}:null}async function zc(e=xn){await e.cancelQueries({queryKey:Ur.all})}function Bc(e){return bi(e)||sr(e)}function Gc(e,t){return{schema:"codex-usage-dashboard-runtime-v1",...kn(e),scope:t,updatedAt:Date.now()}}function kn(e){return{sourceKey:Vr(e),sourceRevision:Xc(e)}}function Jc(e,t=Yc()){if(t)try{const n=JSON.stringify(e);n.length<=Hc&&t.setItem(qc,n)}catch{}}function Zc(e,t){var o;if(!e||!(((o=e.rows)==null?void 0:o.length)??0))return!1;const n=ct(e),a=t.limit===null?n===0:n===t.limit,r=(e.since??null)===t.since,s=fn(e)===t.loadWindow,i=e.include_archived||e.history_scope==="all-history"?"all":"active";return a&&r&&s&&i===t.historyScope}function Vr(e){const t=e,n=Number((t==null?void 0:t.payload_cache_version)??0),a=String((t==null?void 0:t.payload_cache_key)??(e!=null&&e.api_token?"live":"static"));return`${n}:${a}`}function Xc(e){return String((e==null?void 0:e.latest_refresh_at)??"unversioned")}function Yc(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}const el=new Set(["duplicate_cumulative_total"]);function tl({canUseLiveApi:e,payload:t,shellI18n:n}){const a=nl(t,e,n);return c.jsxs("section",{className:"environment-status","aria-label":n.t("aria.dashboard_status","Dashboard status"),children:[c.jsx("span",{className:"environment-status-title",children:n.t("aria.dashboard_status","Dashboard status")}),c.jsx("div",{className:"environment-status-grid",children:a.map(r=>c.jsx("span",{className:"environment-chip","data-state":r.state,title:r.title,children:r.label},r.label))})]})}function nl(e,t,n){const a=ol(e==null?void 0:e.parser_diagnostics,n);return[{label:n.t("badge.unofficial_project","Unofficial project"),state:"neutral",title:n.t("badge.unofficial_project_title","Codex Usage Tracker is independent and is not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI. OpenAI and Codex are trademarks of OpenAI.")},{label:t?`${n.t("badge.live","Live")} API`:n.t("badge.static","Static"),state:t?"ready":"warn",title:t?"Local API token present for refresh actions.":"Static embedded snapshot; live refresh is unavailable."},rl(e,n),sl(e,n),il(e,n),al(e),...a?[a]:[]]}function al(e){const t=e==null?void 0:e.dedupe,n=Number((t==null?void 0:t.excluded_copied_rows)||0),a=Number((t==null?void 0:t.canonical_rows)||0),r=Number((t==null?void 0:t.physical_rows)||0);return{label:`Deduped · ${n.toLocaleString()} copied excluded`,state:"ready",title:`Billable totals use ${a.toLocaleString()} canonical rows while preserving ${r.toLocaleString()} physical source rows.`}}function rl(e,t){var s;const n=!!(e!=null&&e.pricing_configured),a=((s=e==null?void 0:e.pricing_snapshot_warning)==null?void 0:s.trim())??"",r=Kr(e==null?void 0:e.pricing_source);return{label:n?t.t("badge.costs","Costs"):t.t("badge.no_costs","No costs"),state:n?a?"warn":"ready":"missing",title:n?[r||"Pricing configured",a].filter(Boolean).join(" - "):t.t("pricing.configure_hint","Run codex-usage-tracker update-pricing to configure estimated costs.")}}function sl(e,t){var s,i;const n=((s=e==null?void 0:e.allowance_error)==null?void 0:s.trim())??"",a=((i=e==null?void 0:e.rate_card_error)==null?void 0:i.trim())??"",r=Kr(e==null?void 0:e.allowance_source)||"Codex credit rates";return n?{label:t.t("state.allowance_config_error","Allowance config error"),state:"missing",title:`Config error: ${n}`}:a?{label:"Rate-card error",state:"missing",title:`Rate-card error: ${a}`}:e!=null&&e.allowance_configured?{label:t.t("state.allowance_configured","Allowance configured"),state:"ready",title:r}:e!=null&&e.rate_card_configured?{label:"Credit rates loaded",state:"ready",title:r}:{label:t.t("action.set_limits","Set limits"),state:"warn",title:"No local allowance windows are configured."}}function il(e,t){const n=e==null?void 0:e.project_metadata_privacy,a=(n==null?void 0:n.mode)||(e==null?void 0:e.privacy_mode)||"normal",r=a==="normal",s=[n!=null&&n.cwd_redacted?"cwd redacted":"",n!=null&&n.project_names_redacted?"project names redacted":"",n!=null&&n.git_remote_label_hidden?"git remote hidden":"",n!=null&&n.relative_cwd_hidden?"relative cwd hidden":"",n!=null&&n.git_branch_hidden?"git branch hidden":"",n!=null&&n.tags_hidden?"tags hidden":""].filter(Boolean);return{label:r?t.t("badge.metadata_normal","Metadata normal"):qr(t.t("badge.metadata_mode","Metadata {mode}"),{mode:a}),state:r?"ready":"warn",title:r?"Project metadata is shown normally.":[`Metadata mode: ${a}`,...s].join(" - ")}}function ol(e,t){const n=Object.entries(e??{}).filter(([s,i])=>Number(i||0)>0&&!el.has(s));if(!n.length)return null;const a=n.reduce((s,[,i])=>s+Number(i||0),0),r=n.map(([s,i])=>`${s}=${Number(i||0)}`).join(", ");return{label:t.t("badge.parser_warnings","Parser warnings"),state:"missing",title:qr(t.t("parser.warnings_title","Latest refresh reported {count} parser diagnostics: {entries}. Run codex-usage-tracker inspect-log to investigate schema drift."),{count:a.toLocaleString(),entries:r})}}function Kr(e){if(!e)return"";if(typeof e=="string")return e;const t=e.label??e.name??e.type??e.path??"";return typeof t=="string"?t:""}function qr(e,t){return e.replace(/\{([a-zA-Z0-9_]+)\}/g,(n,a)=>t[a]??n)}async function Sa(e){var n;if((n=navigator.clipboard)!=null&&n.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly","readonly"),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}const cl={"highest-cost":"Highest Cost Threads","context-bloat":"Context Bloat","cache-misses":"Cache Misses","pricing-gaps":"Pricing Gaps","codex-credits":"Codex Credits","reasoning-spike":"Reasoning Spike"};function tu(e,t){return t==="context-bloat"?Number(e.contextWindowPct??0)>=60||e.totalTokens>=2e5:t==="cache-misses"?e.signal==="cache-risk"||e.cachedPct<30||e.uncachedInput>=5e4:t==="pricing-gaps"?e.pricingEstimated||!Number.isFinite(e.cost):t==="codex-credits"?e.credits>0:t==="reasoning-spike"?e.reasoningOutput>0:!0}function ll(e){return cl[e]??e}const ul=se(()=>O(()=>import("./OverviewPage.js"),__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50])),"OverviewPage"),dl=se(()=>O(()=>import("./InvestigatorPage.js"),__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52])),"InvestigatorPage"),hl=se(()=>O(()=>import("./CompressionLabPage.js"),__vite__mapDeps([53,1,2,34,4,6,9,10,17,25,26,12,54])),"CompressionLabPage"),fl=se(()=>O(()=>import("./ExploreRoutePage.js"),__vite__mapDeps([55,1,2,44,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48,8,9,10,56])),"ExploreRoutePage"),ml=se(()=>O(()=>import("./CallInvestigatorPage.js"),__vite__mapDeps([57,1,2,46,33,19,37,38,47,25,26,12])),"CallInvestigatorPage"),gl=se(()=>O(()=>import("./ThreadsPage.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27])),"ThreadsPage"),pl=se(()=>O(()=>import("./UsageDrainPage.js"),__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39])),"UsageDrainPage"),vl=se(()=>O(()=>import("./CacheContextPage.js"),__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12])),"CacheContextPage"),bl=se(()=>O(()=>import("./DiagnosticsPage.js"),__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12])),"DiagnosticsPage"),wl=se(()=>O(()=>import("./ReportsPage.js"),__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43])),"ReportsPage"),yl=se(()=>O(()=>import("./SettingsPage.js"),__vite__mapDeps([58,1,2,33,19,32,38,47,17,25,26,12,59])),"SettingsPage");function _l(e){return c.jsx(C.Suspense,{fallback:c.jsx(Cl,{activeView:e.activeView}),children:Sl(e)})}function Sl(e){const{activePreset:t,activeRecordId:n,activeView:a,autoRefreshEnabled:r,applicationI18n:s,backFromCallInvestigator:i,callBackLabel:o,canLoadAllRows:d,canUseLiveApi:f,contextRuntime:h,copyCallInvestigatorLink:b,dashboardPayload:u,globalFilters:p,globalQuery:g,hasMoreRows:v,historyScope:w,loadWindow:T,loadAllRows:N,loadedRowCount:R,loadLimit:_,loadMoreRows:L,scopeSince:y,model:k,navigateView:j,onRefresh:E,openCallInvestigator:D,refreshing:me,refreshState:bt,setContextApiEnabled:wt,sourceIdentity:$,totalAvailableRows:at}=e;switch(a){case"overview":return c.jsx(ul,{model:k,contextRuntime:h,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onRefresh:E,globalQuery:g,runtime:{historyScope:w,loadLimit:_,loadWindow:T,loadedRowCount:R,scopeSince:y,totalAvailableRows:at},refreshing:me,canLoadMoreRows:f&&v,onLoadMoreRows:L,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:j,globalFilters:p});case"investigator":return c.jsx(dl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:j});case"compression-lab":return c.jsx(hl,{contextRuntime:h,includeArchived:w==="all",since:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision});case"calls":return c.jsx(fl,{model:k,globalQuery:g,activePreset:t,onRefresh:E,contextRuntime:h,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onContextApiEnabledChange:wt,onOpenInvestigator:D,onCopyCallLink:b,onNavigateView:j});case"call":return c.jsx(ml,{model:k,recordId:n,contextRuntime:h,onContextApiEnabledChange:wt,onNavigateRecord:D,onCopyCallLink:b,onBackToCalls:i,backLabel:o});case"threads":return c.jsx(gl,{model:k,globalQuery:g,onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p,contextRuntime:h,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onNavigateView:j});case"usage-drain":return c.jsx(pl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"cache-context":return c.jsx(vl,{model:k,contextRuntime:h,includeArchived:w==="all",scopeSince:y,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"diagnostics":return c.jsx(bl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,rowLoadControls:{loadedRowCount:R,totalAvailableRows:at,canLoadMoreRows:f&&v,canLoadAllRows:d,refreshing:me,onLoadMoreRows:L,onLoadAllRows:N},onOpenInvestigator:D,onCopyCallLink:b,globalFilters:p});case"reports":return c.jsx(wl,{model:k,refreshState:bt,includeArchived:w==="all",loadWindow:T,loadLimit:_,sourceKey:$.sourceKey,sourceRevision:$.sourceRevision,onOpenInvestigator:D,onCopyCallLink:b});case"settings":return c.jsx(yl,{model:k,payload:u,historyScope:w,loadWindow:T,loadLimit:_,scopeSince:y,loadedRowCount:R,totalAvailableRows:at,canUseLiveApi:f,autoRefreshEnabled:r,refreshState:bt,applicationI18n:s})}}function Cl({activeView:e}){return c.jsxs("section",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:["Loading ",e.replace("-"," "),"..."]})}const Ca=1e4,xl={1:"overview",2:"calls",3:"threads",4:"diagnostics"},kl=new Set(["call","compression-lab","diagnostics","investigator"]);function Hr(e){return!kl.has(e)}function Tl(e){return e instanceof Element?!!e.closest('input, select, textarea, button, [contenteditable="true"]'):!1}function Wr(){var Un;const e=C.useRef(null),t=C.useMemo(()=>_o(),[]),[n,a]=C.useState(t),[r,s]=C.useState(()=>ra(t)),[i,o]=C.useState(()=>{const m=new URLSearchParams(window.location.search);return sn(m.get("view"))}),[d,f]=C.useState(()=>new URLSearchParams(window.location.search).get("record")??""),[h,b]=C.useState(()=>da()),[u,p]=C.useState(()=>ha()),[g,v]=C.useState(()=>new URLSearchParams(window.location.search).get("q")??""),[w,T]=C.useState(()=>new URLSearchParams(window.location.search).get("preset")??""),[N,R]=C.useState(()=>window.location.search),[_,L]=C.useState("Stored snapshot loaded just now"),[y,k]=C.useState(null),[j,E]=C.useState(!1),[D,me]=C.useState(!1),[bt,wt]=C.useState(!1),[$,at]=C.useState(()=>zs(t)),It=C.useRef(!1),[G,Tn]=C.useState(()=>je(ct(t),500)),[Ue,yt]=C.useState(()=>je(ct(t),500)),[q,Ln]=C.useState(()=>qi(t)),[J,_t]=C.useState(()=>fa(Wt(t))),[Rn,Mn]=C.useState(r.contextRuntime.contextApiEnabled),H=!!(n!=null&&n.api_token),Qr=C.useMemo(()=>kn(n),[n]),A=C.useMemo(()=>Da(n,$),[n,$]),Pn=C.useMemo(()=>({...r.contextRuntime,contextApiEnabled:Rn}),[Rn,r.contextRuntime]),zr=C.useMemo(()=>Vo(r,J,N),[J,N,r]),jn=i==="calls"||i==="call"?r:zr,rt=Hr(i),$t=je(Ue,G,500),ge=Math.max(0,Number((n==null?void 0:n.loaded_row_count)??((Un=n==null?void 0:n.rows)==null?void 0:Un.length)??r.calls.length??0)),Ve=Math.max(0,Number((n==null?void 0:n.total_available_rows)??ge)),Br=Ue!==G,An=Qi({currentLimit:G,loadedRows:ge,pendingLimit:Ue}),Gr=Math.min($t,An),Nn=!!(n!=null&&n.has_more)||Ve>0&&ge{const m=new URL(window.location.href);ga(m)&&Ke(m)},[]),C.useEffect(()=>{function m(){const S=window.location.search,M=new URLSearchParams(S);o(sn(M.get("view"))),f(M.get("record")??""),b(da(S)),p(ha(S)),v(M.get("q")??""),T(M.get("preset")??""),_t(fa(Wt(n),S)),R(S)}return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[n]),C.useEffect(()=>{function m(S){var oe;if(Tl(S.target))return;if(S.key==="/"){S.preventDefault(),(oe=e.current)==null||oe.focus();return}const M=xl[S.key];M&&(S.preventDefault(),st(M))}return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[]),C.useEffect(()=>{function m(){wt(window.scrollY>320)}return m(),window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]);function ns(m){const S=i==="call"?h:i;b(S),p(i==="call"?u:!0),o("call"),f(m);const M=new URL(window.location.href);kt(M,i,i==="call"?h:[]),M.searchParams.set("view","call"),M.searchParams.set("record",m),M.searchParams.set("return",S),Fn(M)}function as(){st(h)}function rs(m){v(m),T("");const S=new URL(window.location.href);S.searchParams.delete("preset"),m?S.searchParams.set("q",m):S.searchParams.delete("q"),Ke(S)}async function ie(m={}){var St;if(j)return;It.current=!0;const S=m.loadLimit??G,M=m.loadWindow??q,oe=Ht(M),pe=m.historyScope??J,ee=m.refresh??!0,Ot=!!(n!=null&&n.refresh_jobs_available);E(!0),k(Ot?{status:"running",phase:ee?"refreshing_index":"loading_rows",message:`${ee?"Refreshing":"Loading"} ${Re(M,S)}`}:null),L(`${ee?"Refreshing index for":"Loading"} ${Re(M,S)}...`);let qe=!1;try{const B=await Qc({currentPayload:n,refresh:ee,loadLimit:S,loadWindow:M,since:oe,historyScope:pe,onProgress:Vt=>{qe||(qe=Vt.message==="Loaded cached dashboard snapshot"),k(Vt),L(Xn(Vt,pe))}});bc(),a(B),s(ra(B)),Mn(!!B.context_api_enabled);const ke=M==="rows"?je(ct(B,S),S):S;Tn(ke),yt(ke),Ln(M);const Vn=Wt(B,pe);_t(Vn),Wi(ke,Vn,M);const Ut=B.loaded_row_count??((St=B.rows)==null?void 0:St.length)??0,Kn=B.total_available_rows??Ut;L(M==="rows"?`${qe?"Cache hit; l":ee?"Refreshed index; l":"L"}oaded ${Ut.toLocaleString()} of ${Kn.toLocaleString()} calls from ${Re(M,ke)}`:`${qe?"Cache hit; ":ee?"Refreshed index; ":""}${Re(M,ke)} analysis ready across ${Kn.toLocaleString()} calls; ${Ut.toLocaleString()} detail rows cached`)}catch(B){if(k(null),Bc(B)){L("Refresh cancelled; stored snapshot remains visible");return}const ke=new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});L(`${Xi(B)} Stored snapshot kept at ${ke}`)}finally{k(null),E(!1)}}async function ss(){await zc(),k(null),E(!1),L("Refresh cancelled; stored snapshot remains visible")}C.useEffect(()=>{document.documentElement.lang=A.language,document.documentElement.dir=A.direction},[A.direction,A.language]),C.useEffect(()=>{var B;const m=Number((n==null?void 0:n.total_available_rows)??0),S=Number((n==null?void 0:n.loaded_row_count)??((B=n==null?void 0:n.rows)==null?void 0:B.length)??0),M=Hi(),oe=(M==null?void 0:M.historyScope)??J,pe=(M==null?void 0:M.loadLimit)??G,ee=(M==null?void 0:M.loadWindow)??q,Ot=fn(n),qe=oe!==J||ee!==Ot||ee==="rows"&&pe!==ct(n),St=S>0;!H||!qe&&St||m<=0||j||It.current||(It.current=!0,qe&&(_t(oe),Tn(pe),yt(pe),Ln(ee),Ke(ma(oe))),ie({refresh:!1,historyScope:oe,loadLimit:pe,loadWindow:ee}))},[H,n,J,G,q,j]),C.useEffect(()=>{!H&&D&&me(!1)},[D,H]),C.useEffect(()=>{if(!D||!H||!rt)return;const m=window.setInterval(()=>{ie()},Ca);return()=>window.clearInterval(m)},[D,rt,H,n,J,G,q,j]),C.useEffect(()=>{if(!D||!H||!rt)return;function m(){document.visibilityState==="visible"&&ie()}return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[D,rt,H,n,J,G,q,j]);function In(m){const S=m.trim();yt(Math.max(1,pt(S===""?Number.NaN:Number(S))))}function is(m){In(m)}function os(){ie({refresh:!1,loadLimit:Ue,loadWindow:"rows"})}function cs(){ie({refresh:!1,loadWindow:"all"})}function $n(){yt(En),ie({refresh:!1,loadLimit:En,loadWindow:q})}function ls(m){m!==q&&ie({refresh:!1,loadWindow:m})}function us(m){const S=m==="all"?"all":"active";_t(S),Ke(ma(S)),ie({refresh:!1,historyScope:S})}function ds(m){if(me(m),m){if(!rt){L("Auto refresh pauses on this evidence-heavy view");return}L(`Auto refresh every ${Ca/1e3}s`),ie()}else L("Auto refresh paused")}function hs(m){at(m),Bs(m)}async function fs(){try{const m=new URL(window.location.href);if(ga(m),kt(m,i,i==="call"?h:[]),!await Sa(m.toString()))throw new Error("Clipboard unavailable");L("Copied current view link")}catch{L("Copy unavailable in browser")}}async function ms(m){try{const S=new URL(window.location.href);kt(S,i,i==="call"?h:[]);const M=i==="call"?h:i;if(S.searchParams.set("view","call"),S.searchParams.set("record",m),S.searchParams.set("return",M),!await Sa(S.toString()))throw new Error("Clipboard unavailable");L("Copied call investigator link")}catch{L("Copy unavailable in browser")}}async function gs(){const m=await Gi(i,jn,{contextRuntime:Pn,historyScope:J,loadWindow:q,loadLimit:G,scopeSince:(n==null?void 0:n.since)??Ht(q),loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,refreshState:_},g,w);if(!m.rowCount){L(`No ${m.label} to export`);return}Ni(m.filename,m.csv),L(`Exported ${m.rowCount} ${m.label}`)}function ps(){T("");const m=new URL(window.location.href);m.searchParams.delete("preset"),Ke(m),L("Investigation preset cleared")}function vs(){window.scrollTo({top:0,behavior:"smooth"})}return c.jsx(ao,{value:A,children:c.jsxs("div",{className:"app-shell","data-dashboard-localization-root":!0,children:[c.jsxs("aside",{className:"sidebar",children:[c.jsxs("div",{className:"brand",children:[c.jsx("div",{className:"brand-mark",children:c.jsx(Us,{size:22})}),c.jsxs("div",{children:[c.jsx("strong",{children:"Codex Usage Tracker"}),c.jsx("span",{children:A.t("dashboard.eyebrow","Local telemetry console")})]})]}),c.jsxs("div",{className:"local-pill",children:[c.jsx("span",{"aria-hidden":"true"}),"Local data only"]}),c.jsx(tl,{payload:n,canUseLiveApi:H,shellI18n:A}),c.jsx("nav",{className:"primary-nav","aria-label":"Primary",children:Cr.map(m=>{const S=m.icon,M=i===m.id||i==="call"&&m.id==="calls";return c.jsxs("button",{type:"button","aria-pressed":M,className:M?"active":"",onClick:()=>st(m.id),children:[c.jsx(S,{size:18}),c.jsx("span",{children:A.navLabel(m.id,m.label)})]},m.id)})}),c.jsxs("div",{className:"secondary-block",role:"group","aria-label":"Quick Links",children:[c.jsx("span",{children:"Quick Links"}),xr.map(m=>{const S=m.icon;return c.jsxs("button",{type:"button",onClick:()=>st(m.target),children:[c.jsx(S,{size:16}),m.label]},m.label)})]})]}),c.jsxs("main",{className:"workspace",children:[c.jsxs("div",{className:"unofficial-banner",role:"note","aria-label":"Unofficial project notice",children:[c.jsx($s,{size:16}),c.jsxs("span",{children:[c.jsx("strong",{children:"Unofficial project."})," Not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI."]})]}),c.jsxs("header",{className:"topbar","aria-label":"Dashboard toolbar",children:[c.jsxs("label",{className:"global-search",children:[c.jsx("span",{className:"sr-only",children:A.t("filter.search","Search dashboard")}),c.jsx("input",{ref:e,"aria-label":A.t("filter.search","Search dashboard"),value:g,onChange:m=>rs(m.target.value),placeholder:A.t("filter.search_placeholder","Search calls, threads, models, diagnostics...")})]}),c.jsxs("div",{className:"topbar-actions",children:[c.jsxs("div",{className:"topbar-scope-controls",children:[A.languages.length>1?c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("language.label","Language")}),c.jsx("select",{"data-localization-skip":"true","aria-label":A.t("language.label","Language"),value:A.language,onChange:m=>hs(m.target.value),children:A.languages.map(m=>c.jsx("option",{value:m.code,children:m.native_name||m.english_name||m.code},m.code))})]}):null,c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("nav.history","History")}),c.jsxs("select",{"aria-label":"History scope",title:Dn,value:J,onChange:m=>us(m.target.value),disabled:j||!H,children:[c.jsx("option",{value:"active",children:A.t("option.active_sessions_only","Active")}),c.jsx("option",{value:"all",children:A.t("option.all_history","All history")})]}),c.jsx("small",{className:"sr-only",children:Dn})]})]}),c.jsx(ec,{canUseLiveApi:H,finitePendingLoadLimit:$t,hasMoreRows:Nn,loadLabel:A.t("nav.load","Load"),loadMoreLabel:A.t("button.load_more","Load more"),loadWindow:q,loadedRowCount:ge,pendingLoadLimit:Ue,refreshProgressPercent:Yr,refreshProgressText:es,refreshing:j,rowLimitChanged:Br,rowLimitSliderMax:An,rowLimitSliderValue:Gr,rowLoadModeLabel:Zr,rowLoadStatus:Jr,totalAvailableRows:Ve,onApply:os,onCancel:ss,onDraftChange:In,onLoadMore:$n,onSliderChange:is,onWindowChange:ls}),c.jsxs("div",{className:"topbar-meta",children:[c.jsxs("div",{className:"topbar-statuses",children:[w?c.jsxs("button",{className:"toolbar-button",type:"button",onClick:ps,children:[c.jsx(un,{size:15}),A.t("button.clear","Clear")," ",ll(w)]}):null,c.jsxs("label",{className:"topbar-toggle",children:[c.jsx("input",{"aria-label":"Auto refresh",type:"checkbox",checked:D,onChange:m=>ds(m.target.checked),disabled:j||!H}),c.jsx("span",{children:"Auto"})]})]}),c.jsxs("div",{className:"topbar-icon-actions",children:[c.jsx("button",{className:"icon-button",type:"button",onClick:fs,"aria-label":A.t("button.copy_link","Copy link"),title:A.t("button.copy_link","Copy link"),children:c.jsx(Ms,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:gs,"aria-label":A.t("button.export_csv","Export CSV"),title:A.t("button.export_csv","Export CSV"),children:c.jsx(js,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:On,"aria-label":A.t("button.refresh","Refresh"),title:A.t("button.refresh","Refresh"),disabled:j,children:c.jsx(Fs,{size:17})})]})]})]})]}),c.jsx("p",{className:"sr-only",role:"status","aria-live":"polite",children:_}),c.jsx(_l,{activeView:i,model:jn,navigateView:st,onRefresh:On,refreshState:_,globalQuery:g,activePreset:w,activeRecordId:d,contextRuntime:Pn,setContextApiEnabled:Mn,openCallInvestigator:ns,copyCallInvestigatorLink:ms,callBackLabel:u?`Back to ${uc(h)}`:A.t("button.back_to_dashboard","Back to dashboard"),backFromCallInvestigator:as,dashboardPayload:n,sourceIdentity:Qr,historyScope:J,loadWindow:q,scopeSince:(n==null?void 0:n.since)??Ht(q),loadLimit:G,loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:D,applicationI18n:A,refreshing:j,hasMoreRows:Nn,canLoadAllRows:ts,loadMoreRows:$n,loadAllRows:cs,globalFilters:c.jsx(tc,{activeView:i,locationSearch:N,model:r,onUrlChange:Ke})})]}),bt?c.jsxs("button",{className:"to-top-button",type:"button",onClick:vs,"aria-label":"Back to top",children:[c.jsx(xs,{size:18}),A.t("button.top","Top")]}):null]})});function On(){ie()}}function Ll(){return c.jsx(Li,{client:xn,children:c.jsx(Wr,{})})}const nu=Object.freeze(Object.defineProperty({__proto__:null,App:Wr,RoutedApp:Ll,shouldAutoRefreshUsageView:Hr},Symbol.toStringTag,{value:"Module"}));export{Ns as $,xs as A,Nl as B,Fi as C,js as D,Wl as E,Es as F,Cs as G,Ps as H,ba as I,Et as J,z as K,El as L,Va as M,ne as N,Zl as O,yc as P,Bl as Q,Fs as R,Is as S,Xl as T,Rs as U,Os as V,tu as W,Sa as X,Vl as Y,Ul as Z,Hl as _,Ms as a,un as a0,ll as a1,Il as a2,Fl as a3,fi as a4,ii as a5,Gt as a6,qa as a7,ri as a8,si as a9,Bt as aa,Ua as ab,_i as ac,li as ad,Dl as ae,Ol as af,ql as ag,kt as ah,da as ai,Kl as aj,Re as ak,nu as al,Ql as b,I as c,Ni as d,ce as e,be as f,Ei as g,eu as h,Yl as i,Le as j,lr as k,$l as l,Xt as m,Lr as n,Jl as o,dt as p,Gl as q,Ai as r,pa as s,zl as t,Oa as u,mr as v,$r as w,Rc as x,Lc as y,Pc as z}; + */const dn=$("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]),Da="codex-usage-dashboard-language",Ws={"button.back_to_dashboard":"Back to dashboard","button.clear":"Clear","button.copy_link":"Copy link","button.enable_context_loading":"Enable context loading","button.export_csv":"Export CSV","button.full_serialized_analysis":"Run full serialized analysis","button.hide_details":"Hide details","button.include_tool_output":"Include tool output","button.load_more":"Load more","button.load_older_context":"Load older entries","button.next_call":"Next call","button.no_char_limit":"No char limit","button.open_investigator":"Open investigator","button.previous_call":"Previous call","button.refresh":"Refresh","button.show_compaction_history":"Show compacted replacement","button.show_tool_output":"Show tool output","button.top":"Top","button.show_turn_evidence":"Show turn log evidence","badge.live":"Live","dashboard.eyebrow":"Local Codex analytics","dashboard.call_details":"Call Details","dashboard.title":"Usage Dashboard","dashboard.view.call":"Call Investigator","dashboard.view.calls":"Calls","dashboard.view.insights":"Overview","dashboard.view.overview":"Overview","dashboard.view.threads":"Threads","detail.next_action":"Next action","filter.search":"Search dashboard","filter.search_placeholder":"Search calls, threads, models, diagnostics...","language.label":"Language","nav.history":"History","nav.load":"Load","nav.live":"Live","option.active_sessions_only":"Active","option.all_history":"All history","status.paused":"Paused","status.static":"Static"},Bs={overview:"dashboard.view.overview",calls:"dashboard.view.calls",call:"dashboard.view.call",threads:"dashboard.view.threads"};function Il(e,t){return typeof t=="string"?e.translateText(t):e.formatText(t.template,t.values)}function $a(e,t){const n=Ia(e),a=Oa(t,n),r=(e==null?void 0:e.translation_catalog)??{},s=r[a]??((e==null?void 0:e.language)===a?e==null?void 0:e.translations:void 0)??{},i=r.en??((e==null?void 0:e.language)==="en"?e.translations:void 0)??{},o={...Ws,...i,...s},d=zs(i,s),f=Qs(i,s),h=n.find(p=>p.code===a),v=(h==null?void 0:h.dir)==="rtl"||!h&&(e==null?void 0:e.language_direction)==="rtl"?"rtl":"ltr",u=p=>a==="zh-Hans"?ys(p,d,f):d.get(p)??p;return{language:a,direction:v,languages:n,t:(p,g)=>o[p]??g??p,translateText:u,formatText:(p,g)=>u(p).replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu,(b,w)=>String(g[String(w)]??b)),navLabel:(p,g)=>{const b=Bs[p];return b?o[b]??g:g}}}function Qs(e,t){const n=[];for(const[a,r]of Object.entries(e)){const s=t[a];if(!s||s===r||!r.includes("{"))continue;const i=[],o=[];let d=0;for(const f of r.matchAll(/\{([A-Za-z][A-Za-z0-9_]*)\}/gu)){const h=f.index??d;o.push(Wn(r.slice(d,h))),o.push("(.+?)"),i.push(f[1]),d=h+f[0].length}o.push(Wn(r.slice(d))),n.push({pattern:new RegExp(`^${o.join("")}$`,"u"),placeholders:i,translatedTemplate:s})}return n.sort((a,r)=>r.translatedTemplate.length-a.translatedTemplate.length)}function Wn(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function zs(e,t){const n=new Map;for(const[a,r]of Object.entries(e)){const s=t[a];s&&s!==r&&n.set(r,s)}return n}function Ia(e){var n;const t=((n=e==null?void 0:e.available_languages)==null?void 0:n.filter(a=>a.code))??[];return t.length?t:[{code:"en",english_name:"English",native_name:"English",dir:"ltr"}]}function Gs(e){return Oa(Zs()||(e==null?void 0:e.language)||"en",Ia(e))}function Js(e){var t;try{(t=window.localStorage)==null||t.setItem(Da,e)}catch{}}function Zs(){var e;try{return((e=window.localStorage)==null?void 0:e.getItem(Da))??""}catch{return""}}function Oa(e,t){if(new Set(t.map(s=>s.code)).has(e))return e;const a=e.toLowerCase(),r=t.find(s=>s.code.toLowerCase()===a);return(r==null?void 0:r.code)??"en"}const Xs=$a(null,"en"),Ua=C.createContext(Xs);function Ys({value:e,children:t}){return c.jsx(Ua.Provider,{value:e,children:t})}function Va(){return C.useContext(Ua)}var Et=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},Ne,we,ze,Ta,ei=(Ta=class extends Et{constructor(){super();P(this,Ne);P(this,we);P(this,ze);x(this,ze,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t();return window.addEventListener("visibilitychange",n,!1),()=>{window.removeEventListener("visibilitychange",n)}}})}onSubscribe(){l(this,we)||this.setEventListener(l(this,ze))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,we))==null||t.call(this),x(this,we,void 0))}setEventListener(t){var n;x(this,ze,t),(n=l(this,we))==null||n.call(this),x(this,we,t(a=>{typeof a=="boolean"?this.setFocused(a):this.onFocus()}))}setFocused(t){l(this,Ne)!==t&&(x(this,Ne,t),this.onFocus())}onFocus(){const t=this.isFocused();this.listeners.forEach(n=>{n(t)})}isFocused(){var t;return typeof l(this,Ne)=="boolean"?l(this,Ne):((t=globalThis.document)==null?void 0:t.visibilityState)!=="hidden"}},Ne=new WeakMap,we=new WeakMap,ze=new WeakMap,Ta),Ka=new ei,ti={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},ye,un,La,ni=(La=class{constructor(){P(this,ye,ti);P(this,un,!1)}setTimeoutProvider(e){x(this,ye,e)}setTimeout(e,t){return l(this,ye).setTimeout(e,t)}clearTimeout(e){l(this,ye).clearTimeout(e)}setInterval(e,t){return l(this,ye).setInterval(e,t)}clearInterval(e){l(this,ye).clearInterval(e)}},ye=new WeakMap,un=new WeakMap,La),zt=new ni;function ai(e){setTimeout(e,0)}var ri=typeof window>"u"||"Deno"in globalThis;function ne(){}function si(e,t){return typeof e=="function"?e(t):e}function ii(e){return typeof e=="number"&&e>=0&&e!==1/0}function oi(e,t){return Math.max(e+(t||0)-Date.now(),0)}function Gt(e,t){return typeof e=="function"?e(t):e}function ci(e,t){return typeof e=="function"?e(t):e}function Bn(e,t){const{type:n="all",exact:a,fetchStatus:r,predicate:s,queryKey:i,stale:o}=e;if(i){if(a){if(t.queryHash!==hn(i,t.options))return!1}else if(!ut(t.queryKey,i))return!1}if(n!=="all"){const d=t.isActive();if(n==="active"&&!d||n==="inactive"&&d)return!1}return!(typeof o=="boolean"&&t.isStale()!==o||r&&r!==t.state.fetchStatus||s&&!s(t))}function Qn(e,t){const{exact:n,status:a,predicate:r,mutationKey:s}=e;if(s){if(!t.options.mutationKey)return!1;if(n){if(lt(t.options.mutationKey)!==lt(s))return!1}else if(!ut(t.options.mutationKey,s))return!1}return!(a&&t.state.status!==a||r&&!r(t))}function hn(e,t){return((t==null?void 0:t.queryKeyHashFn)||lt)(e)}function lt(e){return JSON.stringify(e,(t,n)=>Jt(n)?Object.keys(n).sort().reduce((a,r)=>(a[r]=n[r],a),{}):n)}function ut(e,t){return e===t?!0:typeof e!=typeof t?!1:e&&t&&typeof e=="object"&&typeof t=="object"?Object.keys(t).every(n=>ut(e[n],t[n])):!1}var li=Object.prototype.hasOwnProperty;function qa(e,t,n=0){if(e===t)return e;if(n>500)return t;const a=zn(e)&&zn(t);if(!a&&!(Jt(e)&&Jt(t)))return t;const s=(a?e:Object.keys(e)).length,i=a?t:Object.keys(t),o=i.length,d=a?new Array(o):{};let f=0;for(let h=0;h{zt.setTimeout(t,e)})}function di(e,t,n){return typeof n.structuralSharing=="function"?n.structuralSharing(e,t):n.structuralSharing!==!1?qa(e,t):t}function hi(e,t,n=0){const a=[...e,t];return n&&a.length>n?a.slice(1):a}function fi(e,t,n=0){const a=[t,...e];return n&&a.length>n?a.slice(0,-1):a}var fn=Symbol();function Ha(e,t){return!e.queryFn&&(t!=null&&t.initialPromise)?()=>t.initialPromise:!e.queryFn||e.queryFn===fn?()=>Promise.reject(new Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function Ul(e,t){return typeof e=="function"?e(...t):!!e}function mi(e,t,n){let a=!1,r;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(r??(r=t()),a||(a=!0,r.aborted?n():r.addEventListener("abort",n,{once:!0})),r)}),e}var Wa=(()=>{let e=()=>ri;return{isServer(){return e()},setIsServer(t){e=t}}})();function gi(){let e,t;const n=new Promise((r,s)=>{e=r,t=s});n.status="pending",n.catch(()=>{});function a(r){Object.assign(n,r),delete n.resolve,delete n.reject}return n.resolve=r=>{a({status:"fulfilled",value:r}),e(r)},n.reject=r=>{a({status:"rejected",reason:r}),t(r)},n}var pi=ai;function bi(){let e=[],t=0,n=o=>{o()},a=o=>{o()},r=pi;const s=o=>{t?e.push(o):r(()=>{n(o)})},i=()=>{const o=e;e=[],o.length&&r(()=>{a(()=>{o.forEach(d=>{n(d)})})})};return{batch:o=>{let d;t++;try{d=o()}finally{t--,t||i()}return d},batchCalls:o=>(...d)=>{s(()=>{o(...d)})},schedule:s,setNotifyFunction:o=>{n=o},setBatchNotifyFunction:o=>{a=o},setScheduler:o=>{r=o}}}var Q=bi(),Ge,_e,Je,Ra,vi=(Ra=class extends Et{constructor(){super();P(this,Ge,!0);P(this,_e);P(this,Je);x(this,Je,t=>{if(typeof window<"u"&&window.addEventListener){const n=()=>t(!0),a=()=>t(!1);return window.addEventListener("online",n,!1),window.addEventListener("offline",a,!1),()=>{window.removeEventListener("online",n),window.removeEventListener("offline",a)}}})}onSubscribe(){l(this,_e)||this.setEventListener(l(this,Je))}onUnsubscribe(){var t;this.hasListeners()||((t=l(this,_e))==null||t.call(this),x(this,_e,void 0))}setEventListener(t){var n;x(this,Je,t),(n=l(this,_e))==null||n.call(this),x(this,_e,t(this.setOnline.bind(this)))}setOnline(t){l(this,Ge)!==t&&(x(this,Ge,t),this.listeners.forEach(a=>{a(t)}))}isOnline(){return l(this,Ge)}},Ge=new WeakMap,_e=new WeakMap,Je=new WeakMap,Ra),Tt=new vi;function wi(e){return Math.min(1e3*2**e,3e4)}function Ba(e){return(e??"online")==="online"?Tt.isOnline():!0}var Lt=class extends Error{constructor(e){super("CancelledError"),this.revert=e==null?void 0:e.revert,this.silent=e==null?void 0:e.silent}};function yi(e){return e instanceof Lt}function Qa(e){let t=!1,n=0,a;const r=gi(),s=()=>r.status!=="pending",i=b=>{var w;if(!s()){const T=new Lt(b);u(T),(w=e.onCancel)==null||w.call(e,T)}},o=()=>{t=!0},d=()=>{t=!1},f=()=>Ka.isFocused()&&(e.networkMode==="always"||Tt.isOnline())&&e.canRun(),h=()=>Ba(e.networkMode)&&e.canRun(),v=b=>{s()||(a==null||a(),r.resolve(b))},u=b=>{s()||(a==null||a(),r.reject(b))},p=()=>new Promise(b=>{var w;a=T=>{(s()||f())&&b(T)},(w=e.onPause)==null||w.call(e)}).then(()=>{var b;a=void 0,s()||(b=e.onContinue)==null||b.call(e)}),g=()=>{if(s())return;let b;const w=n===0?e.initialPromise:void 0;try{b=w??e.fn()}catch(T){b=Promise.reject(T)}Promise.resolve(b).then(v).catch(T=>{var y;if(s())return;const N=e.retry??(Wa.isServer()?0:3),R=e.retryDelay??wi,_=typeof R=="function"?R(n,T):R,L=N===!0||typeof N=="number"&&nf()?void 0:p()).then(()=>{t?u(T):g()})})};return{promise:r,status:()=>r.status,cancel:i,continue:()=>(a==null||a(),r),cancelRetry:o,continueRetry:d,canStart:h,start:()=>(h()?g():p().then(g),r)}}var Ee,Ma,za=(Ma=class{constructor(){P(this,Ee)}destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),ii(this.gcTime)&&x(this,Ee,zt.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(Wa.isServer()?1/0:300*1e3))}clearGcTimeout(){l(this,Ee)!==void 0&&(zt.clearTimeout(l(this,Ee)),x(this,Ee,void 0))}},Ee=new WeakMap,Ma);function _i(e){return{onFetch:(t,n)=>{var h,v,u,p,g;const a=t.options,r=(u=(v=(h=t.fetchOptions)==null?void 0:h.meta)==null?void 0:v.fetchMore)==null?void 0:u.direction,s=((p=t.state.data)==null?void 0:p.pages)||[],i=((g=t.state.data)==null?void 0:g.pageParams)||[];let o={pages:[],pageParams:[]},d=0;const f=async()=>{let b=!1;const w=R=>{mi(R,()=>t.signal,()=>b=!0)},T=Ha(t.options,t.fetchOptions),N=async(R,_,L)=>{if(b)return Promise.reject(t.signal.reason);if(_==null&&R.pages.length)return Promise.resolve(R);const k=(()=>{const me={client:t.client,queryKey:t.queryKey,pageParam:_,direction:L?"backward":"forward",meta:t.options.meta};return w(me),me})(),j=await T(k),{maxPages:E}=t.options,F=L?fi:hi;return{pages:F(R.pages,j,E),pageParams:F(R.pageParams,_,E)}};if(r&&s.length){const R=r==="backward",_=R?Ga:Zt,L={pages:s,pageParams:i},y=_(a,L);o=await N(L,y,R)}else{const R=e??s.length;do{const _=d===0?i[0]??a.initialPageParam:Zt(a,o);if(d>0&&_==null)break;o=await N(o,_),d++}while(d{var b,w;return(w=(b=t.options).persister)==null?void 0:w.call(b,f,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},n)}:t.fetchFn=f}}}function Zt(e,{pages:t,pageParams:n}){const a=t.length-1;return t.length>0?e.getNextPageParam(t[a],t,n[a],n):void 0}function Ga(e,{pages:t,pageParams:n}){var a;return t.length>0?(a=e.getPreviousPageParam)==null?void 0:a.call(e,t[0],t,n[0],n):void 0}function Vl(e,t){return t?Zt(e,t)!=null:!1}function Kl(e,t){return!t||!e.getPreviousPageParam?!1:Ga(e,t)!=null}var Ze,Fe,Xe,X,De,U,ft,$e,Z,Ja,he,Pa,Si=(Pa=class extends za{constructor(t){super();P(this,Z);P(this,Ze);P(this,Fe);P(this,Xe);P(this,X);P(this,De);P(this,U);P(this,ft);P(this,$e);x(this,$e,!1),x(this,ft,t.defaultOptions),this.setOptions(t.options),this.observers=[],x(this,De,t.client),x(this,X,l(this,De).getQueryCache()),this.queryKey=t.queryKey,this.queryHash=t.queryHash,x(this,Fe,Zn(this.options)),this.state=t.state??l(this,Fe),this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return l(this,Ze)}get promise(){var t;return(t=l(this,U))==null?void 0:t.promise}setOptions(t){if(this.options={...l(this,ft),...t},t!=null&&t._type&&x(this,Ze,t._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){const n=Zn(this.options);n.data!==void 0&&(this.setState(Jn(n.data,n.dataUpdatedAt)),x(this,Fe,n))}}optionalRemove(){!this.observers.length&&this.state.fetchStatus==="idle"&&l(this,X).remove(this)}setData(t,n){const a=di(this.state.data,t,this.options);return V(this,Z,he).call(this,{data:a,type:"success",dataUpdatedAt:n==null?void 0:n.updatedAt,manual:n==null?void 0:n.manual}),a}setState(t){V(this,Z,he).call(this,{type:"setState",state:t})}cancel(t){var a,r;const n=(a=l(this,U))==null?void 0:a.promise;return(r=l(this,U))==null||r.cancel(t),n?n.then(ne).catch(ne):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return l(this,Fe)}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(t=>ci(t.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===fn||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0?this.observers.some(t=>Gt(t.options.staleTime,this)==="static"):!1}isStale(){return this.getObserversCount()>0?this.observers.some(t=>t.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(t=0){return this.state.data===void 0?!0:t==="static"?!1:this.state.isInvalidated?!0:!oi(this.state.dataUpdatedAt,t)}onFocus(){var n;const t=this.observers.find(a=>a.shouldFetchOnWindowFocus());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}onOnline(){var n;const t=this.observers.find(a=>a.shouldFetchOnReconnect());t==null||t.refetch({cancelRefetch:!1}),(n=l(this,U))==null||n.continue()}addObserver(t){this.observers.includes(t)||(this.observers.push(t),this.clearGcTimeout(),l(this,X).notify({type:"observerAdded",query:this,observer:t}))}removeObserver(t){this.observers.includes(t)&&(this.observers=this.observers.filter(n=>n!==t),this.observers.length||(l(this,U)&&(l(this,$e)||V(this,Z,Ja).call(this)?l(this,U).cancel({revert:!0}):l(this,U).cancelRetry()),this.scheduleGc()),l(this,X).notify({type:"observerRemoved",query:this,observer:t}))}getObserversCount(){return this.observers.length}invalidate(){this.state.isInvalidated||V(this,Z,he).call(this,{type:"invalidate"})}async fetch(t,n){var f,h,v,u,p,g,b,w,T,N,R;if(this.state.fetchStatus!=="idle"&&((f=l(this,U))==null?void 0:f.status())!=="rejected"){if(this.state.data!==void 0&&(n!=null&&n.cancelRefetch))this.cancel({silent:!0});else if(l(this,U))return l(this,U).continueRetry(),l(this,U).promise}if(t&&this.setOptions(t),!this.options.queryFn){const _=this.observers.find(L=>L.options.queryFn);_&&this.setOptions(_.options)}const a=new AbortController,r=_=>{Object.defineProperty(_,"signal",{enumerable:!0,get:()=>(x(this,$e,!0),a.signal)})},s=()=>{const _=Ha(this.options,n),y=(()=>{const k={client:l(this,De),queryKey:this.queryKey,meta:this.meta};return r(k),k})();return x(this,$e,!1),this.options.persister?this.options.persister(_,y,this):_(y)},o=(()=>{const _={fetchOptions:n,options:this.options,queryKey:this.queryKey,client:l(this,De),state:this.state,fetchFn:s};return r(_),_})(),d=l(this,Ze)==="infinite"?_i(this.options.pages):this.options.behavior;d==null||d.onFetch(o,this),x(this,Xe,this.state),(this.state.fetchStatus==="idle"||this.state.fetchMeta!==((h=o.fetchOptions)==null?void 0:h.meta))&&V(this,Z,he).call(this,{type:"fetch",meta:(v=o.fetchOptions)==null?void 0:v.meta}),x(this,U,Qa({initialPromise:n==null?void 0:n.initialPromise,fn:o.fetchFn,onCancel:_=>{_ instanceof Lt&&_.revert&&this.setState({...l(this,Xe),fetchStatus:"idle"}),a.abort()},onFail:(_,L)=>{V(this,Z,he).call(this,{type:"failed",failureCount:_,error:L})},onPause:()=>{V(this,Z,he).call(this,{type:"pause"})},onContinue:()=>{V(this,Z,he).call(this,{type:"continue"})},retry:o.options.retry,retryDelay:o.options.retryDelay,networkMode:o.options.networkMode,canRun:()=>!0}));try{const _=await l(this,U).start();if(_===void 0)throw new Error(`${this.queryHash} data is undefined`);return this.setData(_),(p=(u=l(this,X).config).onSuccess)==null||p.call(u,_,this),(b=(g=l(this,X).config).onSettled)==null||b.call(g,_,this.state.error,this),_}catch(_){if(_ instanceof Lt){if(_.silent)return l(this,U).promise;if(_.revert){if(this.state.data===void 0)throw _;return this.state.data}}throw V(this,Z,he).call(this,{type:"error",error:_}),(T=(w=l(this,X).config).onError)==null||T.call(w,_,this),(R=(N=l(this,X).config).onSettled)==null||R.call(N,this.state.data,_,this),_}finally{this.scheduleGc()}}},Ze=new WeakMap,Fe=new WeakMap,Xe=new WeakMap,X=new WeakMap,De=new WeakMap,U=new WeakMap,ft=new WeakMap,$e=new WeakMap,Z=new WeakSet,Ja=function(){return this.state.fetchStatus==="paused"&&this.state.status==="pending"},he=function(t){const n=a=>{switch(t.type){case"failed":return{...a,fetchFailureCount:t.failureCount,fetchFailureReason:t.error};case"pause":return{...a,fetchStatus:"paused"};case"continue":return{...a,fetchStatus:"fetching"};case"fetch":return{...a,...Ci(a.data,this.options),fetchMeta:t.meta??null};case"success":const r={...a,...Jn(t.data,t.dataUpdatedAt),dataUpdateCount:a.dataUpdateCount+1,...!t.manual&&{fetchStatus:"idle",fetchFailureCount:0,fetchFailureReason:null}};return x(this,Xe,t.manual?r:void 0),r;case"error":const s=t.error;return{...a,error:s,errorUpdateCount:a.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:a.fetchFailureCount+1,fetchFailureReason:s,fetchStatus:"idle",status:"error",isInvalidated:!0};case"invalidate":return{...a,isInvalidated:!0};case"setState":return{...a,...t.state}}};this.state=n(this.state),Q.batch(()=>{this.observers.forEach(a=>{a.onQueryUpdate()}),l(this,X).notify({query:this,type:"updated",action:t})})},Pa);function Ci(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:Ba(t.networkMode)?"fetching":"paused",...e===void 0&&{error:null,status:"pending"}}}function Jn(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:"success"}}function Zn(e){const t=typeof e.initialData=="function"?e.initialData():e.initialData,n=t!==void 0,a=n?typeof e.initialDataUpdatedAt=="function"?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:n?a??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:n?"success":"pending",fetchStatus:"idle"}}var mt,le,K,Ie,ue,be,ja,xi=(ja=class extends za{constructor(t){super();P(this,ue);P(this,mt);P(this,le);P(this,K);P(this,Ie);x(this,mt,t.client),this.mutationId=t.mutationId,x(this,K,t.mutationCache),x(this,le,[]),this.state=t.state||ki(),this.setOptions(t.options),this.scheduleGc()}setOptions(t){this.options=t,this.updateGcTime(this.options.gcTime)}get meta(){return this.options.meta}addObserver(t){l(this,le).includes(t)||(l(this,le).push(t),this.clearGcTimeout(),l(this,K).notify({type:"observerAdded",mutation:this,observer:t}))}removeObserver(t){x(this,le,l(this,le).filter(n=>n!==t)),this.scheduleGc(),l(this,K).notify({type:"observerRemoved",mutation:this,observer:t})}optionalRemove(){l(this,le).length||(this.state.status==="pending"?this.scheduleGc():l(this,K).remove(this))}continue(){var t;return((t=l(this,Ie))==null?void 0:t.continue())??this.execute(this.state.variables)}async execute(t){var i,o,d,f,h,v,u,p,g,b,w,T,N,R,_,L,y,k;const n=()=>{V(this,ue,be).call(this,{type:"continue"})},a={client:l(this,mt),meta:this.options.meta,mutationKey:this.options.mutationKey};x(this,Ie,Qa({fn:()=>this.options.mutationFn?this.options.mutationFn(t,a):Promise.reject(new Error("No mutationFn found")),onFail:(j,E)=>{V(this,ue,be).call(this,{type:"failed",failureCount:j,error:E})},onPause:()=>{V(this,ue,be).call(this,{type:"pause"})},onContinue:n,retry:this.options.retry??0,retryDelay:this.options.retryDelay,networkMode:this.options.networkMode,canRun:()=>l(this,K).canRun(this)}));const r=this.state.status==="pending",s=!l(this,Ie).canStart();try{if(r)n();else{V(this,ue,be).call(this,{type:"pending",variables:t,isPaused:s}),l(this,K).config.onMutate&&await l(this,K).config.onMutate(t,this,a);const E=await((o=(i=this.options).onMutate)==null?void 0:o.call(i,t,a));E!==this.state.context&&V(this,ue,be).call(this,{type:"pending",context:E,variables:t,isPaused:s})}const j=await l(this,Ie).start();return await((f=(d=l(this,K).config).onSuccess)==null?void 0:f.call(d,j,t,this.state.context,this,a)),await((v=(h=this.options).onSuccess)==null?void 0:v.call(h,j,t,this.state.context,a)),await((p=(u=l(this,K).config).onSettled)==null?void 0:p.call(u,j,null,this.state.variables,this.state.context,this,a)),await((b=(g=this.options).onSettled)==null?void 0:b.call(g,j,null,t,this.state.context,a)),V(this,ue,be).call(this,{type:"success",data:j}),j}catch(j){try{await((T=(w=l(this,K).config).onError)==null?void 0:T.call(w,j,t,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((R=(N=this.options).onError)==null?void 0:R.call(N,j,t,this.state.context,a))}catch(E){Promise.reject(E)}try{await((L=(_=l(this,K).config).onSettled)==null?void 0:L.call(_,void 0,j,this.state.variables,this.state.context,this,a))}catch(E){Promise.reject(E)}try{await((k=(y=this.options).onSettled)==null?void 0:k.call(y,void 0,j,t,this.state.context,a))}catch(E){Promise.reject(E)}throw V(this,ue,be).call(this,{type:"error",error:j}),j}finally{l(this,K).runNext(this)}}},mt=new WeakMap,le=new WeakMap,K=new WeakMap,Ie=new WeakMap,ue=new WeakSet,be=function(t){const n=a=>{switch(t.type){case"failed":return{...a,failureCount:t.failureCount,failureReason:t.error};case"pause":return{...a,isPaused:!0};case"continue":return{...a,isPaused:!1};case"pending":return{...a,context:t.context,data:void 0,failureCount:0,failureReason:null,error:null,isPaused:t.isPaused,status:"pending",variables:t.variables,submittedAt:Date.now()};case"success":return{...a,data:t.data,failureCount:0,failureReason:null,error:null,status:"success",isPaused:!1};case"error":return{...a,data:void 0,error:t.error,failureCount:a.failureCount+1,failureReason:t.error,isPaused:!1,status:"error"}}};this.state=n(this.state),Q.batch(()=>{l(this,le).forEach(a=>{a.onMutationUpdate(t)}),l(this,K).notify({mutation:this,type:"updated",action:t})})},ja);function ki(){return{context:void 0,data:void 0,error:null,failureCount:0,failureReason:null,isPaused:!1,status:"idle",variables:void 0,submittedAt:0}}var fe,ae,gt,Aa,Ti=(Aa=class extends Et{constructor(t={}){super();P(this,fe);P(this,ae);P(this,gt);this.config=t,x(this,fe,new Set),x(this,ae,new Map),x(this,gt,0)}build(t,n,a){const r=new xi({client:t,mutationCache:this,mutationId:++Ct(this,gt)._,options:t.defaultMutationOptions(n),state:a});return this.add(r),r}add(t){l(this,fe).add(t);const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n);a?a.push(t):l(this,ae).set(n,[t])}this.notify({type:"added",mutation:t})}remove(t){if(l(this,fe).delete(t)){const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n);if(a)if(a.length>1){const r=a.indexOf(t);r!==-1&&a.splice(r,1)}else a[0]===t&&l(this,ae).delete(n)}}this.notify({type:"removed",mutation:t})}canRun(t){const n=xt(t);if(typeof n=="string"){const a=l(this,ae).get(n),r=a==null?void 0:a.find(s=>s.state.status==="pending");return!r||r===t}else return!0}runNext(t){var a;const n=xt(t);if(typeof n=="string"){const r=(a=l(this,ae).get(n))==null?void 0:a.find(s=>s!==t&&s.state.isPaused);return(r==null?void 0:r.continue())??Promise.resolve()}else return Promise.resolve()}clear(){Q.batch(()=>{l(this,fe).forEach(t=>{this.notify({type:"removed",mutation:t})}),l(this,fe).clear(),l(this,ae).clear()})}getAll(){return Array.from(l(this,fe))}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Qn(n,a))}findAll(t={}){return this.getAll().filter(n=>Qn(t,n))}notify(t){Q.batch(()=>{this.listeners.forEach(n=>{n(t)})})}resumePausedMutations(){const t=this.getAll().filter(n=>n.state.isPaused);return Q.batch(()=>Promise.all(t.map(n=>n.continue().catch(ne))))}},fe=new WeakMap,ae=new WeakMap,gt=new WeakMap,Aa);function xt(e){var t;return(t=e.options.scope)==null?void 0:t.id}var de,Na,Li=(Na=class extends Et{constructor(t={}){super();P(this,de);this.config=t,x(this,de,new Map)}build(t,n,a){const r=n.queryKey,s=n.queryHash??hn(r,n);let i=this.get(s);return i||(i=new Si({client:t,queryKey:r,queryHash:s,options:t.defaultQueryOptions(n),state:a,defaultOptions:t.getQueryDefaults(r)}),this.add(i)),i}add(t){l(this,de).has(t.queryHash)||(l(this,de).set(t.queryHash,t),this.notify({type:"added",query:t}))}remove(t){const n=l(this,de).get(t.queryHash);n&&(t.destroy(),n===t&&l(this,de).delete(t.queryHash),this.notify({type:"removed",query:t}))}clear(){Q.batch(()=>{this.getAll().forEach(t=>{this.remove(t)})})}get(t){return l(this,de).get(t)}getAll(){return[...l(this,de).values()]}find(t){const n={exact:!0,...t};return this.getAll().find(a=>Bn(n,a))}findAll(t={}){const n=this.getAll();return Object.keys(t).length>0?n.filter(a=>Bn(t,a)):n}notify(t){Q.batch(()=>{this.listeners.forEach(n=>{n(t)})})}onFocus(){Q.batch(()=>{this.getAll().forEach(t=>{t.onFocus()})})}onOnline(){Q.batch(()=>{this.getAll().forEach(t=>{t.onOnline()})})}},de=new WeakMap,Na),D,Se,Ce,Ye,et,xe,tt,nt,Ea,Ri=(Ea=class{constructor(e={}){P(this,D);P(this,Se);P(this,Ce);P(this,Ye);P(this,et);P(this,xe);P(this,tt);P(this,nt);x(this,D,e.queryCache||new Li),x(this,Se,e.mutationCache||new Ti),x(this,Ce,e.defaultOptions||{}),x(this,Ye,new Map),x(this,et,new Map),x(this,xe,0)}mount(){Ct(this,xe)._++,l(this,xe)===1&&(x(this,tt,Ka.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,D).onFocus())})),x(this,nt,Tt.subscribe(async e=>{e&&(await this.resumePausedMutations(),l(this,D).onOnline())})))}unmount(){var e,t;Ct(this,xe)._--,l(this,xe)===0&&((e=l(this,tt))==null||e.call(this),x(this,tt,void 0),(t=l(this,nt))==null||t.call(this),x(this,nt,void 0))}isFetching(e){return l(this,D).findAll({...e,fetchStatus:"fetching"}).length}isMutating(e){return l(this,Se).findAll({...e,status:"pending"}).length}getQueryData(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,D).get(t.queryHash))==null?void 0:n.state.data}ensureQueryData(e){const t=this.defaultQueryOptions(e),n=l(this,D).build(this,t),a=n.state.data;return a===void 0?this.fetchQuery(e):(e.revalidateIfStale&&n.isStaleByTime(Gt(t.staleTime,n))&&this.prefetchQuery(t),Promise.resolve(a))}getQueriesData(e){return l(this,D).findAll(e).map(({queryKey:t,state:n})=>{const a=n.data;return[t,a]})}setQueryData(e,t,n){const a=this.defaultQueryOptions({queryKey:e}),r=l(this,D).get(a.queryHash),s=r==null?void 0:r.state.data,i=si(t,s);if(i!==void 0)return l(this,D).build(this,a).setData(i,{...n,manual:!0})}setQueriesData(e,t,n){return Q.batch(()=>l(this,D).findAll(e).map(({queryKey:a})=>[a,this.setQueryData(a,t,n)]))}getQueryState(e){var n;const t=this.defaultQueryOptions({queryKey:e});return(n=l(this,D).get(t.queryHash))==null?void 0:n.state}removeQueries(e){const t=l(this,D);Q.batch(()=>{t.findAll(e).forEach(n=>{t.remove(n)})})}resetQueries(e,t){const n=l(this,D);return Q.batch(()=>(n.findAll(e).forEach(a=>{a.reset()}),this.refetchQueries({type:"active",...e},t)))}cancelQueries(e,t={}){const n={revert:!0,...t},a=Q.batch(()=>l(this,D).findAll(e).map(r=>r.cancel(n)));return Promise.all(a).then(ne).catch(ne)}invalidateQueries(e,t={}){return Q.batch(()=>(l(this,D).findAll(e).forEach(n=>{n.invalidate()}),(e==null?void 0:e.refetchType)==="none"?Promise.resolve():this.refetchQueries({...e,type:(e==null?void 0:e.refetchType)??(e==null?void 0:e.type)??"active"},t)))}refetchQueries(e,t={}){const n={...t,cancelRefetch:t.cancelRefetch??!0},a=Q.batch(()=>l(this,D).findAll(e).filter(r=>!r.isDisabled()&&!r.isStatic()).map(r=>{let s=r.fetch(void 0,n);return n.throwOnError||(s=s.catch(ne)),r.state.fetchStatus==="paused"?Promise.resolve():s}));return Promise.all(a).then(ne)}fetchQuery(e){const t=this.defaultQueryOptions(e);t.retry===void 0&&(t.retry=!1);const n=l(this,D).build(this,t);return n.isStaleByTime(Gt(t.staleTime,n))?n.fetch(t):Promise.resolve(n.state.data)}prefetchQuery(e){return this.fetchQuery(e).then(ne).catch(ne)}fetchInfiniteQuery(e){return e._type="infinite",this.fetchQuery(e)}prefetchInfiniteQuery(e){return this.fetchInfiniteQuery(e).then(ne).catch(ne)}ensureInfiniteQueryData(e){return e._type="infinite",this.ensureQueryData(e)}resumePausedMutations(){return Tt.isOnline()?l(this,Se).resumePausedMutations():Promise.resolve()}getQueryCache(){return l(this,D)}getMutationCache(){return l(this,Se)}getDefaultOptions(){return l(this,Ce)}setDefaultOptions(e){x(this,Ce,e)}setQueryDefaults(e,t){l(this,Ye).set(lt(e),{queryKey:e,defaultOptions:t})}getQueryDefaults(e){const t=[...l(this,Ye).values()],n={};return t.forEach(a=>{ut(e,a.queryKey)&&Object.assign(n,a.defaultOptions)}),n}setMutationDefaults(e,t){l(this,et).set(lt(e),{mutationKey:e,defaultOptions:t})}getMutationDefaults(e){const t=[...l(this,et).values()],n={};return t.forEach(a=>{ut(e,a.mutationKey)&&Object.assign(n,a.defaultOptions)}),n}defaultQueryOptions(e){if(e._defaulted)return e;const t={...l(this,Ce).queries,...this.getQueryDefaults(e.queryKey),...e,_defaulted:!0};return t.queryHash||(t.queryHash=hn(t.queryKey,t)),t.refetchOnReconnect===void 0&&(t.refetchOnReconnect=t.networkMode!=="always"),t.throwOnError===void 0&&(t.throwOnError=!!t.suspense),!t.networkMode&&t.persister&&(t.networkMode="offlineFirst"),t.queryFn===fn&&(t.enabled=!1),t}defaultMutationOptions(e){return e!=null&&e._defaulted?e:{...l(this,Ce).mutations,...(e==null?void 0:e.mutationKey)&&this.getMutationDefaults(e.mutationKey),...e,_defaulted:!0}}clear(){l(this,D).clear(),l(this,Se).clear()}},D=new WeakMap,Se=new WeakMap,Ce=new WeakMap,Ye=new WeakMap,et=new WeakMap,xe=new WeakMap,tt=new WeakMap,nt=new WeakMap,Ea),Za=C.createContext(void 0),ql=e=>{const t=C.useContext(Za);if(!t)throw new Error("No QueryClient set, use QueryClientProvider to set one");return t},Mi=({client:e,children:t})=>(C.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),c.jsx(Za.Provider,{value:e,children:t}));function Pi(e,t=window.location.href){var a;const n=(a=new URL(t).searchParams.get("record"))==null?void 0:a.trim();if(n){const r=e.calls.find(s=>s.id===n);return r?[r]:[]}return e.calls[0]?[e.calls[0]]:[]}function Hl({calls:e,recordId:t,detail:n}){const a=e.findIndex(v=>v.id===t),r=a>=0?a:!t&&e.length?0:-1,s=(n==null?void 0:n.record.id)===t?n:null,i=(s==null?void 0:s.record)??(r>=0?e[r]:null),o=(s==null?void 0:s.previousRecord)??(r>0?e[r-1]:null),d=(s==null?void 0:s.nextRecord)??(r>=0&&r=0?`${r+1} of ${e.length} loaded calls`:"Record outside loaded snapshot";return{modelIndex:a,activeIndex:r,hydratedDetail:s,call:i,previous:o,next:d,threadCalls:f,positionLabel:h}}function ji(e,t,n){const a=e.filter(i=>i.thread===t.thread),r=[n==null?void 0:n.previousRecord,n==null?void 0:n.record,n==null?void 0:n.nextRecord].filter(Ai),s=new Map;for(const i of[...a,...r,t])s.set(i.id,i);return[...s.values()].sort(Ni)}function Ai(e){return!!(e!=null&&e.id)}function Ni(e,t){return Date.parse(t.rawTime||t.time)-Date.parse(e.rawTime||e.time)}function Ei(e,t){const n=t.map(r=>Xn(r.header)).join(","),a=e.map(r=>t.map(s=>Xn(s.value(r))).join(","));return[n,...a].join(` +`)}function Fi(e,t){const n=new Blob([t],{type:"text/csv;charset=utf-8"}),a=typeof URL.createObjectURL=="function"?URL.createObjectURL(n):`data:text/csv;charset=utf-8,${encodeURIComponent(t)}`,r=document.createElement("a");r.href=a,r.download=e,r.rel="noopener",document.body.append(r),r.click(),r.remove(),a.startsWith("blob:")&&typeof URL.revokeObjectURL=="function"&&URL.revokeObjectURL(a)}function Di(e=new Date){return e.toISOString().slice(0,10)}function Xn(e){const t=String(e??"");return/[",\n\r]/.test(t)?`"${t.replaceAll('"','""')}"`:t}function Le(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function ve(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Xt(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function dt(e){return`${e.toFixed(1)}%`}const $i={priority:"Priority / Fast",fast:"Fast",default:"Default / Standard",standard:"Standard",flex:"Flex",batch:"Batch"};function Xa(e){const t=e.trim().toLowerCase().replace(/[\s_]+/g,"-");if(!t)return null;const n=$i[t];return n||(t.length>48||!/^[a-z0-9.-]+$/.test(t)?"Other":t.split(/[-.]+/).filter(Boolean).map(a=>`${a.charAt(0).toUpperCase()}${a.slice(1)}`).join(" "))}function Yt(e){const t=Xa(e.serviceTier);return t||(e.fast===!0?"Fast":e.fast===!1?"Standard":"Unknown")}function Wl(e){return Xa(e.serviceTier)?`observed ${Yt(e)} · ${e.serviceTierConfidence||"exact"}`:e.fast!==null?`confirmed ${Yt(e)} · ${e.serviceTierConfidence||"exact"}`:e.fastProxyCandidate?"tier unknown · Fast proxy candidate":"tier unknown · normal throughput proxy"}function Bl(e){if(e.billingBasis==="api_tokens"){const t=e.pricingServiceTier.trim();return`API token estimate · ${t?`${t.charAt(0).toUpperCase()}${t.slice(1).toLowerCase()} rates`:"configured rates"}`}return e.billingBasis==="chatgpt_credits"?"API-equivalent scenario · ChatGPT credits selected":"API-equivalent scenario · billing basis unknown"}function Ql(e){return e.cachedPct<25?"cold or weak cache":e.cachedPct<50?"partial cache reuse":"healthy cache reuse"}function zl(e){return e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available"}function Gl(e){if(e.contextWindowPct===null||e.contextWindowPct===void 0)return"Not reported";const t=e.modelContextWindow?` of ${ve(e.modelContextWindow)}`:"";return`${dt(e.contextWindowPct)}${t}`}function Jl(e,{limit:t=2,emptyLabel:n="No related calls",unknownLabel:a="Unknown",style:r="parenthetical"}={}){const s=new Map;for(const o of e){const d=o||a;s.set(d,(s.get(d)??0)+1)}const i=[...s.entries()].sort((o,d)=>d[1]-o[1]||o[0].localeCompare(d[0])).slice(0,t).map(([o,d])=>r==="x"?`${o} x${d}`:`${o} (${d})`);return i.length?i.join(", "):n}const Zl=[{id:"time",accessorFn:e=>Number(Date.parse(e.eventTimestamp||e.callStartedAt||e.rawTime||e.time))||0,header:"Time",cell:e=>e.row.original.time},{accessorKey:"thread",header:"Thread"},{accessorKey:"model",header:"Model"},{accessorKey:"effort",header:"Effort",cell:e=>c.jsx("span",{className:`pill effort-${String(e.getValue())}`,children:String(e.getValue())})},{accessorKey:"input",header:"Input Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"output",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"cachedPct",header:"Cached %",cell:e=>c.jsx("span",{className:"cache-pill",children:dt(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:ve(Number(e.getValue()))})},{accessorKey:"contextWindowPct",header:"Context %",cell:e=>{const t=e.getValue(),n=typeof t=="number"?t:Number.NaN;return c.jsx("span",{className:"num",children:Number.isFinite(n)?dt(n):"-"})}},{accessorKey:"duration",header:"Duration"},{id:"serviceTier",accessorFn:e=>Yt(e),header:"Service Tier",cell:e=>{const t=String(e.getValue()),n=t.includes("Fast")?"green":t.includes("Standard")?"blue":"";return c.jsx("span",{className:`status-badge ${n}`.trim(),children:t})}},{accessorKey:"previousCallGap",header:"Prev Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiator",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"signal",header:"Signals",cell:e=>c.jsx(Oi,{call:e.row.original})}],ce=[{header:"timestamp",value:e=>e.eventTimestamp||e.rawTime||e.time},{header:"thread",value:e=>e.thread},{header:"call_started_at",value:e=>e.callStartedAt||e.rawTime||e.time},{header:"call_duration_seconds",value:e=>e.durationSeconds},{header:"previous_call_event_timestamp",value:e=>e.previousCallEventTimestamp},{header:"previous_call_delta_seconds",value:e=>e.previousCallGapSeconds},{header:"initiated",value:e=>e.initiator},{header:"initiated_reason",value:e=>e.initiatorReason},{header:"project",value:e=>e.project},{header:"model",value:e=>e.model},{header:"effort",value:e=>e.effort},{header:"total_tokens",value:e=>e.totalTokens},{header:"input_tokens",value:e=>e.input},{header:"cached_input_tokens",value:e=>e.cachedInput},{header:"uncached_input_tokens",value:e=>e.uncachedInput},{header:"output_tokens",value:e=>e.output},{header:"reasoning_output_tokens",value:e=>e.reasoningOutput},{header:"estimated_cost_usd",value:e=>e.cost.toFixed(6)},{header:"standard_cost_usd",value:e=>{var t;return((t=e.standardCost)==null?void 0:t.toFixed(6))??""}},{header:"priority_cost_usd",value:e=>{var t;return((t=e.priorityCost)==null?void 0:t.toFixed(6))??""}},{header:"pricing_service_tier",value:e=>e.pricingServiceTier},{header:"billing_basis",value:e=>e.billingBasis},{header:"cost_semantics",value:e=>e.costSemantics},{header:"usage_credits",value:e=>e.credits.toFixed(6)},{header:"standard_usage_credits",value:e=>e.standardUsageCredits.toFixed(6)},{header:"fast_usage_credits",value:e=>{var t;return((t=e.fastUsageCredits)==null?void 0:t.toFixed(6))??""}},{header:"service_tier",value:e=>e.serviceTier},{header:"fast",value:e=>e.fast===null?"":e.fast?1:0},{header:"service_tier_source",value:e=>e.serviceTierSource},{header:"service_tier_confidence",value:e=>e.serviceTierConfidence},{header:"fast_proxy_candidate",value:e=>String(e.fastProxyCandidate)},{header:"usage_credit_multiplier",value:e=>e.usageCreditMultiplier},{header:"usage_credit_multiplier_source",value:e=>e.usageCreditMultiplierSource},{header:"usage_credit_multiplier_source_url",value:e=>e.usageCreditMultiplierSourceUrl},{header:"usage_credit_multiplier_fetched_at",value:e=>e.usageCreditMultiplierFetchedAt},{header:"usage_credit_multiplier_confidence",value:e=>e.usageCreditMultiplierConfidence},{header:"cache_ratio",value:e=>e.cachedPct.toFixed(2)},{header:"context_window_percent",value:e=>{var t;return((t=e.contextWindowPct)==null?void 0:t.toFixed(2))??""}},{header:"pricing_model",value:e=>e.pricingModel},{header:"usage_credit_confidence",value:e=>e.usageCreditConfidence},{header:"recommendation",value:e=>e.recommendation},{header:"record_id",value:e=>e.id},{header:"thread_attachment",value:e=>e.threadAttachmentLabel},{header:"thread_source",value:e=>e.threadSource},{header:"parent_thread",value:e=>e.parentThread},{header:"session_id",value:e=>e.sessionId},{header:"turn_id",value:e=>e.turnId},{header:"parent_session_id",value:e=>e.parentSessionId},{header:"parent_session_updated_at",value:e=>e.parentSessionUpdatedAt},{header:"project_relative_cwd",value:e=>e.projectRelativeCwd},{header:"cwd",value:e=>e.cwd},{header:"source_file",value:e=>e.sourceFile},{header:"source_line",value:e=>e.lineNumber??""},{header:"git_branch",value:e=>e.gitBranch},{header:"git_remote_label",value:e=>e.gitRemoteLabel},{header:"git_remote_hash",value:e=>e.gitRemoteHash},{header:"pricing_estimated",value:e=>String(e.pricingEstimated)},{header:"usage_credit_model",value:e=>e.usageCreditModel},{header:"usage_credit_source",value:e=>e.usageCreditSource},{header:"usage_credit_tier",value:e=>e.usageCreditTier},{header:"usage_credit_fetched_at",value:e=>e.usageCreditFetchedAt},{header:"usage_credit_note",value:e=>e.usageCreditNote},{header:"model_context_window",value:e=>e.modelContextWindow??""},{header:"cumulative_total_tokens",value:e=>e.cumulativeTotalTokens??""},{header:"estimated_cache_savings_usd",value:e=>e.estimatedCacheSavings.toFixed(6)},{header:"initiated_confidence",value:e=>e.initiatorConfidence},{header:"signal",value:e=>e.signal},{header:"tags",value:e=>e.tags.join("|")},{header:"efficiency_flags",value:e=>e.efficiencyFlags.join("|")}];function Ii(e,t=3){const a=Ui([e.signal,...e.efficiencyFlags]).map((r,s)=>({key:`${r}-${s}`,label:Ya(r),shortLabel:Vi(r)}));return{visible:a.slice(0,t),hidden:a.slice(t)}}function Oi({call:e}){const t=Va(),{visible:n,hidden:a}=Ii(e);if(!n.length)return c.jsx("span",{className:"muted",children:"None"});const r=n.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),s=a.map(o=>({...o,label:t.translateText(o.label),shortLabel:t.translateText(o.shortLabel)})),i=s.map(o=>o.label).join("、");return c.jsxs("span",{className:"flags compact-flags","aria-label":t.language==="zh-Hans"?`信号:${[...r,...s].map(o=>o.label).join("、")}`:`Signals: ${[...n,...a].map(o=>o.label).join(", ")}`,children:[r.map(o=>c.jsx("span",{className:"flag signal-puck",title:o.label,children:o.shortLabel},o.key)),s.length?c.jsxs("span",{className:"flag signal-puck more",title:i,children:["+",s.length]}):null]})}function Ui(e){const t=new Set;return e.map(n=>n.trim()).filter(n=>n&&n!=="aggregate").filter(n=>{const a=n.toLowerCase();return t.has(a)?!1:(t.add(a),!0)})}function Ya(e){return e.replace(/[-_]+/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function Vi(e){const t=e.toLowerCase().replace(/[_\s]+/g,"-"),n={"cache-drop":"CACHE","cache-risk":"CACHE","context-bloat":"CTX","context-heavy":"CTX","elevated-context":"CTX","elevated-context-use":"CTX","estimated-pricing":"EST","expensive-low-output-call":"LO","high-context-use":"CTX","high-cost":"$","high-estimated-cost":"$","high-reasoning-share":"RSN","large-thread":"BIG","low-cache":"CACHE","low-cache-reuse":"CACHE","low-output":"LO","pricing-gap":"PRICE","reasoning-spike":"RSN","subagent-attribution":"SUB"};if(n[t])return n[t];const a=Ya(e).split(/\s+/).filter(Boolean);return a.length?a.length===1?a[0].slice(0,4).toUpperCase():a.slice(0,3).map(r=>r[0]).join("").toUpperCase():"?"}const Xl=[{accessorKey:"name",header:"Thread"},{accessorKey:"latestActivity",header:"Latest"},{accessorKey:"turns",header:"Turns",cell:e=>c.jsx("span",{className:"num",children:Le(Number(e.getValue()))})},{accessorKey:"totalDuration",header:"Duration"},{accessorKey:"averageGap",header:"Avg Gap",cell:e=>c.jsx("span",{className:"num",children:String(e.getValue())})},{accessorKey:"initiatorSummary",header:"Initiated",cell:e=>c.jsx("span",{className:"status-badge blue",children:String(e.getValue())})},{accessorKey:"modelSummary",header:"Models",cell:e=>c.jsx("span",{className:"pill model-pill",children:String(e.getValue())})},{accessorKey:"effortSummary",header:"Effort Mix"},{accessorKey:"totalTokens",header:"Total Tokens",cell:e=>c.jsx("span",{className:"num",children:ve(Number(e.getValue()))})},{accessorKey:"cachedInput",header:"Cached Input",cell:e=>c.jsx("span",{className:"num",children:ve(Number(e.getValue()))})},{accessorKey:"uncachedInput",header:"Uncached Input",cell:e=>c.jsx("span",{className:"num",children:ve(Number(e.getValue()))})},{accessorKey:"outputTokens",header:"Output Tokens",cell:e=>c.jsx("span",{className:"num",children:ve(Number(e.getValue()))})},{accessorKey:"reasoningOutput",header:"Reasoning Output",cell:e=>c.jsx("span",{className:"num",children:ve(Number(e.getValue()))})},{accessorKey:"cost",header:"Est. Cost",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"credits",header:"Codex Credits",cell:e=>c.jsx("span",{className:"num",children:ve(Number(e.getValue()))})},{accessorKey:"cachePct",header:"Cache %",cell:e=>c.jsx("span",{className:"cache-pill",children:dt(Number(e.getValue()))})},{accessorKey:"contextPct",header:"Context %",cell:e=>{const t=e.getValue();return c.jsx("span",{className:"num",children:typeof t=="number"?dt(t):"-"})}},{accessorKey:"costPerCall",header:"Cost / Call",cell:e=>c.jsx("span",{className:"num",children:Xt(Number(e.getValue()))})},{accessorKey:"coldResumeRisk",header:"Cold Resume Risk",cell:e=>c.jsx("span",{className:`status-badge ${Ki(String(e.getValue()))}`,children:String(e.getValue())})},{accessorKey:"productivity",header:"Productivity",cell:e=>c.jsx("span",{className:"score",children:Number(e.getValue())})}],Yl=[{id:"name",label:"Thread",locked:!0},{id:"latestActivity",label:"Latest"},{id:"turns",label:"Turns"},{id:"totalDuration",label:"Duration"},{id:"averageGap",label:"Avg Gap"},{id:"initiatorSummary",label:"Initiated"},{id:"modelSummary",label:"Models"},{id:"effortSummary",label:"Effort Mix"},{id:"totalTokens",label:"Total Tokens"},{id:"cachedInput",label:"Cached Input"},{id:"uncachedInput",label:"Uncached Input"},{id:"outputTokens",label:"Output Tokens"},{id:"reasoningOutput",label:"Reasoning Output"},{id:"cost",label:"Est. Cost"},{id:"credits",label:"Codex Credits"},{id:"cachePct",label:"Cache %"},{id:"contextPct",label:"Context %"},{id:"costPerCall",label:"Cost / Call"},{id:"coldResumeRisk",label:"Cold Resume Risk"},{id:"productivity",label:"Productivity"},{id:"investigate",label:"Investigate",locked:!0}];function Ki(e){return e==="High"?"red":e==="Medium"?"orange":e==="Low"?"green":"neutral"}const ht=1,re=0,qt=100,er=1e3,tr=500,nr="codexUsageDashboardLoadSettings",qi={day:1440*60*1e3,week:10080*60*1e3};function ct(e,t=tr){if((e==null?void 0:e.limit_label)==="All"||t===re&&(e==null?void 0:e.limit)==null)return re;const n=Number((e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??t);return Number.isFinite(n)&&n>=0?n:t}function pt(e){return Number.isFinite(e)?e<=re?re:Math.max(ht,Math.round(e)):ht}function je(...e){const t=e.find(n=>typeof n=="number"&&Number.isFinite(n)&&n>0);return t?Math.max(ht,Math.round(t)):ht}function Hi(e,t,n=null,a="rows"){const r=pt(e);return{historyScope:t,loadWindow:a,limit:r===re?null:r,since:n}}function Wi(e){return e.limit??re}function mn(e){return gn(e==null?void 0:e.load_window)?e.load_window:e!=null&&e.since?"week":(e==null?void 0:e.limit_label)==="All"||(e==null?void 0:e.limit)==null?"all":"rows"}function Bi(e){return gn(e==null?void 0:e.default_load_window)?e.default_load_window:mn(e)}function Ht(e,t=new Date){const n=qi[e];if(!n)return null;const a=Math.floor(t.getTime()/6e4)*6e4;return new Date(a-n).toISOString()}function Re(e,t=tr){return e==="day"?"Last 24 hours":e==="week"?"Last 7 days":e==="all"?"All time":`Most recent ${pt(t).toLocaleString()}`}function Qi(e=ar()){if(!e)return null;try{const t=e.getItem(nr);if(!t)return null;const n=JSON.parse(t),a=typeof n.loadLimit=="number"&&Number.isFinite(n.loadLimit)?pt(n.loadLimit):void 0,r=n.historyScope==="active"||n.historyScope==="all"?n.historyScope:void 0,s=gn(n.loadWindow)?n.loadWindow:void 0;return a===void 0&&r===void 0&&s===void 0?null:{loadLimit:a,historyScope:r,loadWindow:s}}catch{return null}}function zi(e,t,n="rows",a=ar()){if(a)try{a.setItem(nr,JSON.stringify({loadLimit:pt(e),historyScope:t,loadWindow:n}))}catch{}}function gn(e){return e==="day"||e==="week"||e==="rows"||e==="all"}function Gi({currentLimit:e,loadedRows:t,pendingLimit:n}){const a=n===re?0:n+qt,s=Math.max(ht,e===re?0:e,a,t);return Math.ceil((s+er)/qt)*qt}function Ji({currentLimit:e,loadedRows:t,pendingLimit:n}){return Math.max(je(e),je(n),je(t))+er}function Zi({loadedRows:e,limit:t,totalRows:n}){return t===re&&e>0?`Loaded all ${e.toLocaleString()}`:n>e?`Loaded ${e.toLocaleString()} of ${n.toLocaleString()}`:`Loaded ${e.toLocaleString()} rows`}function ar(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}async function Xi(e,t,n,a="",r=""){const s=Di();switch(e){case"threads":{const{threadCallsForCurrentUrl:i}=await O(async()=>{const{threadCallsForCurrentUrl:o}=await import("./ThreadsPage.js");return{threadCallsForCurrentUrl:o}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]));return te(`codex-thread-filtered-calls-${s}.csv`,i(t,a),ce,"call rows")}case"cache-context":{const{cacheContextCallsForCurrentUrl:i}=await O(async()=>{const{cacheContextCallsForCurrentUrl:o}=await import("./CacheContextPage.js");return{cacheContextCallsForCurrentUrl:o}},__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12]));return te(`codex-${e}-calls-${s}.csv`,i(t),ce,"call rows")}case"usage-drain":{const{usageDrainCallsForCurrentUrl:i}=await O(async()=>{const{usageDrainCallsForCurrentUrl:o}=await import("./UsageDrainPage.js");return{usageDrainCallsForCurrentUrl:o}},__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39]));return te(`codex-usage-drain-calls-${s}.csv`,i(t),ce,"call rows")}case"diagnostics":{const{diagnosticsCallsForCurrentUrl:i}=await O(async()=>{const{diagnosticsCallsForCurrentUrl:o}=await import("./DiagnosticsPage.js");return{diagnosticsCallsForCurrentUrl:o}},__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12]));return te(`codex-diagnostics-calls-${s}.csv`,i(t),ce,"call rows")}case"reports":{const{reportCallsForCurrentUrl:i}=await O(async()=>{const{reportCallsForCurrentUrl:o}=await import("./ReportsPage.js");return{reportCallsForCurrentUrl:o}},__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43]));return te(`codex-reports-evidence-${s}.csv`,i(t),ce,"call rows")}case"settings":return te(`codex-dashboard-settings-${s}.csv`,eo(t,n),Yi,"settings rows");case"calls":{const{callsForCurrentUrl:i}=await O(async()=>{const{callsForCurrentUrl:o}=await import("./CallsPage.js");return{callsForCurrentUrl:o}},__vite__mapDeps([44,1,2,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48]));return te(`codex-calls-${s}.csv`,i(t.calls,a,r),ce,"call rows")}case"overview":{const{overviewCallsForQuery:i}=await O(async()=>{const{overviewCallsForQuery:o}=await import("./OverviewPage.js");return{overviewCallsForQuery:o}},__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50]));return te(`codex-overview-calls-${s}.csv`,i(t.calls,a),ce,"call rows")}case"investigator":{const{investigatorCallsForCurrentUrl:i}=await O(async()=>{const{investigatorCallsForCurrentUrl:o}=await import("./InvestigatorPage.js");return{investigatorCallsForCurrentUrl:o}},__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52]));return te(`codex-investigator-calls-${s}.csv`,i(t),ce,"call rows")}case"compression-lab":return te(`codex-compression-lab-scope-${s}.csv`,t.calls,ce,"call rows");case"call":return te(`codex-call-calls-${s}.csv`,Pi(t),ce,"call rows")}}function te(e,t,n,a){return{filename:e,csv:Ei(t,n),rowCount:t.length,label:a}}const Yi=[{header:"Field",value:e=>e.field},{header:"Value",value:e=>e.value}];function eo(e,t){return[{field:"live_api",value:t.canUseLiveApi?"available":"static snapshot"},{field:"context_api",value:t.contextRuntime.contextApiEnabled?"enabled":"gated"},{field:"history_scope",value:t.historyScope},{field:"data_window",value:Re(t.loadWindow,t.loadLimit)},{field:"scope_since",value:t.scopeSince??"none"},{field:"row_request",value:t.loadLimit===re?"no cap":String(t.loadLimit)},{field:"loaded_rows",value:String(t.loadedRowCount)},{field:"total_available_rows",value:String(t.totalAvailableRows)},{field:"auto_refresh",value:t.autoRefreshEnabled?"enabled":"paused"},{field:"refresh_state",value:t.refreshState},{field:"visible_calls",value:String(e.calls.length)},{field:"visible_threads",value:String(e.threads.length)}]}function to(e){return e instanceof Error?e.message:String(e)}function Yn(e,t){const n=t==="all"?"all history":"active history",a=e.message||"Refreshing usage index",r=typeof e.percent=="number"?` ${Math.round(e.percent)}%`:"";return`${a}${r} (${n})`}function Wt(e,t="active"){return e?typeof e.include_archived=="boolean"?e.include_archived?"all":"active":e.history_scope==="all-history"||e.history_scope==="all"?"all":e.history_scope==="active"?"active":t:t}function no({historyScope:e,activeRows:t,allRows:n,archivedRows:a}){const r=ao({activeRows:t,allRows:n,archivedRows:a});return e==="all"?r===null?"All history selected":r>0?`All history includes ${r.toLocaleString()} archived calls`:"All history selected; no archived calls are indexed yet":r===null||r<=0?"Active sessions only":`Active sessions only; ${r.toLocaleString()} archived calls hidden`}function ao({activeRows:e,allRows:t,archivedRows:n}){const a=Bt(n);if(a!==null)return a;const r=Bt(e),s=Bt(t);return r!==null&&s!==null?Math.max(s-r,0):null}function Bt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.round(e):null}const rr=["aria-description","aria-label","aria-valuetext","title","placeholder","alt"],ro="data-localization-attributes",so=new Set(["CODE","KBD","PRE","SAMP","SCRIPT","STYLE","TEXTAREA"]),en=new WeakMap,tn=new WeakMap;function io({value:e,children:t}){return c.jsxs(Ys,{value:e,children:[c.jsx(oo,{}),t]})}function oo(){const e=Va();return C.useLayoutEffect(()=>{const t=document.querySelector("[data-dashboard-localization-root]");if(!t)return;if(e.language!=="zh-Hans"){lo(t),document.title="Codex Usage Tracker React Dashboard";return}document.title="Codex Usage Tracker · 用量仪表盘",ea(t,e.translateText);const n=new MutationObserver(a=>{for(const r of a){if(r.type==="characterData"&&r.target instanceof Text){nn(r.target,e.translateText);continue}if(r.type==="attributes"&&r.target instanceof Element){an(r.target,e.translateText);continue}for(const s of r.addedNodes)s instanceof Text?nn(s,e.translateText):s instanceof Element&&ea(s,e.translateText)}});return n.observe(t,{attributes:!0,attributeFilter:[...rr],characterData:!0,childList:!0,subtree:!0}),()=>n.disconnect()},[e]),null}function ea(e,t){if(Rt(e))return;an(e,t);const n=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);let a=n.nextNode();for(;a;){if(a instanceof Element){if(Rt(a)){a=co(n,a,e);continue}an(a,t)}else a instanceof Text&&nn(a,t);a=n.nextNode()}}function co(e,t,n){let a=t;for(;a&&a!==n;){const r=e.nextSibling();if(r)return r;a=a.parentNode,a&&(e.currentNode=a)}return null}function nn(e,t){const n=e.parentElement;if(!n||Rt(n))return;const a=e.nodeValue??"",r=en.get(e),s=r&&(a===r.source||a===r.translated)?r.source:a,i=s.match(/^(\s*)([\s\S]*?)(\s*)$/u);if(!i||!i[2])return;const o=t(i[2]),d=`${i[1]}${o}${i[3]}`;en.set(e,{source:s,translated:d}),d!==a&&(e.nodeValue=d)}function an(e,t){if(Rt(e))return;const n=new Set((e.getAttribute(ro)??"").split(/[\s,]+/u).filter(Boolean));if(!n.size)return;const a=tn.get(e)??new Map;for(const r of rr){if(!n.has(r))continue;const s=e.getAttribute(r);if(!s)continue;const i=a.get(r),o=i&&(s===i.source||s===i.translated)?i.source:s,d=t(o);a.set(r,{source:o,translated:d}),d!==s&&e.setAttribute(r,d)}a.size&&tn.set(e,a)}function lo(e){const t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);ta(e);let n=t.nextNode();for(;n;){if(n instanceof Text){const a=en.get(n);a&&n.nodeValue===a.translated&&(n.nodeValue=a.source)}else n instanceof Element&&ta(n);n=t.nextNode()}}function ta(e){const t=tn.get(e);if(t)for(const[n,a]of t)e.getAttribute(n)===a.translated&&e.setAttribute(n,a.source)}function Rt(e){return so.has(e.tagName)||!!e.closest('[data-localization-skip="true"]')}const Mt=["May 12","May 19","May 26","Jun 02","Jun 09","Jun 16","Jun 23","Jun 30"],it=Mt.slice(2),sr={contextRuntime:{apiToken:"",contextApiEnabled:!1,fileMode:!1},cards:[{label:"Total Tokens",value:"24.83M",detail:"7-day total: 12.56M",trend:"up 18.7% vs prior 7 days",tone:"blue"},{label:"Estimated Cost",value:"$42.67",detail:"7-day total: $24.81",trend:"up 14.2% vs prior 7 days",tone:"green"},{label:"Cache Hit Rate",value:"38.7%",detail:"7-day average: 42.3%",trend:"down 3.6pp vs prior 7 days",tone:"purple"},{label:"Total Calls",value:"1,342",detail:"678 calls in last 7 days",trend:"up 11.3% vs prior 7 days",tone:"blue"},{label:"Usage Remaining",value:"32.4%",detail:"~15.9K credits estimated",trend:"resets in 4d 12h",tone:"green"}],tokenSeries:[W("input","Input","#2563eb",[5.2,6.4,7.5,9.2,6.7,7.5,6.6,9],1e6),W("output","Output","#059669",[2.5,3,3.6,5.1,3.7,5,4,5.4],1e6),W("cached","Cached","#7c3aed",[1.1,1.4,1.7,2.4,1.8,2.3,1.8,2.6],1e6,!0)],costSeries:[W("cost","Estimated Cost","#2563eb",[8.4,10.1,14.3,9.9,11.4,7.8,12.7,16.5])],cacheSeries:[W("cache","Cache Hit Rate","#059669",[58,61,39,45,50,44,48,41])],weeklyCreditSeries:[{id:"pro",label:"Pro observed",color:"#2563eb",points:Mt.map((e,t)=>({label:e,value:[59800,44900,45e3,40500,42800,38900,31400,35900][t]??0,low:[52100,38800,38900,34700,36200,32200,26100,29900][t]??0,high:[67400,51200,51100,46800,49200,45100,37300,41900][t]??0}))},W("pro-trend","Pro trend","#1d4ed8",[54.2,51,47.8,44.6,41.4,38.2,35,31.8],1e3,!0),W("prolite","Prolite observed","#0f766e",[15.9,15.8,15.9,16.1,15.7,15.6,15.9,15.8],1e3)],usageRemainingSeries:[W("remaining","Usage remaining","#059669",[87,71,63,56,56,48,50,54]),W("allowance","Allowance guide","#0f766e",[86,85,84,83,82,81,80,79],1,!0)],actualVsPredictedSeries:[W("observed","Observed drain","#2563eb",[18.7,22.1,45.3,31,34.8],1e3),W("predicted","Predicted baseline","#1d4ed8",[17.9,21.4,41.2,29.6,33.9],1e3,!0)],findings:[{rank:1,title:"Long Thread: data-engine-refactor",severity:"High",credits:12847,share:25.6,summary:"Very long duration with high model effort."},{rank:2,title:"Cache Misses (Large Inputs)",severity:"High",credits:9612,share:19.1,summary:"Large uncached inputs across 214 calls."},{rank:3,title:"High Model Effort",severity:"Medium",credits:7404,share:14.7,summary:"Reasoning and output token volume are concentrated."},{rank:4,title:"Tool Output Volume",severity:"Medium",credits:5231,share:10.4,summary:"Large tool outputs returned to the model."}],calls:[["2026-06-01T10:24:00Z","Jun 1, 10:24 AM","thread-9f3a1c","codex-1","high",128542,45231,62,.42,"18.4s",!1,["review"]],["2026-06-01T10:18:00Z","Jun 1, 10:18 AM","thread-7b2e91","o4-mini","medium",98731,32104,41,.31,"12.7s",!0,["analysis"]],["2026-06-01T10:12:00Z","Jun 1, 10:12 AM","thread-3c8d4e","o3","high",64221,18903,28,.12,"9.3s",!0,["uncached"]],["2026-06-01T10:06:00Z","Jun 1, 10:06 AM","thread-1a2b3c","codex-1","high",245123,98112,71,.87,"27.6s",!1,["large"]],["2026-06-01T10:01:00Z","Jun 1, 10:01 AM","thread-8d7c6b","gpt-4.1","low",12543,4231,12,.03,"3.6s",!0,["quick"]],["2026-06-01T09:55:00Z","Jun 1, 09:55 AM","thread-2f9e7d","o4-mini","medium",76881,28442,39,.24,"11.2s",!1,["subagent"]],["2026-06-01T09:50:00Z","Jun 1, 09:50 AM","thread-6a5b4c","codex-1","high",312654,112991,67,1.12,"31.8s",!1,["file-heavy"]],["2026-06-01T09:47:00Z","Jun 1, 09:47 AM","thread-0f1e2d","o3","low",8221,2903,15,.02,"2.8s",!0,["fast"]]].map(([e,t,n,a,r,s,i,o,d,f,h,v],u)=>{const p=Number(s),g=Number(i),b=Number(o),w=Math.round(p*Math.max(100-b,0)/100);return{id:`fixture-call-${u}`,rawTime:String(e),eventTimestamp:String(e),callStartedAt:String(e),time:String(t),thread:String(n),model:String(a),effort:String(r),input:p,output:g,reasoningOutput:Math.round(g*.2),totalTokens:p+g,cachedInput:Math.round(p*b/100),uncachedInput:w,cachedPct:b,cost:u===4?0:Number(d),standardCost:u===4?0:Number(d),priorityCost:u===4?0:Number(d)*2,pricingServiceTier:"standard",billingBasis:"unknown",costSemantics:"api_token_estimate",credits:(u===4?0:Number(d))*25,duration:String(f),durationSeconds:Number.parseFloat(String(f))||0,previousCallGap:u===0?"-":`${u*7}m 0s`,previousCallEventTimestamp:u===0?"":`2026-06-01T09:${String(40+u).padStart(2,"0")}:00Z`,previousCallGapSeconds:u*420,initiator:u%3===0?"user":u%3===1?"assistant":"tool",initiatorReason:u%3===0?"direct user request":u%3===1?"assistant follow-up":"tool-driven continuation",initiatorConfidence:u%2===0?"exact":"estimated",serviceTier:"",fast:null,serviceTierSource:"",serviceTierConfidence:"",fastProxyCandidate:!!h,standardUsageCredits:(u===4?0:Number(d))*25,fastUsageCredits:(u===4?0:Number(d))*50,usageCreditMultiplier:1,usageCreditMultiplierSource:"tier_unknown",usageCreditMultiplierSourceUrl:"https://example.invalid/fixture-fast",usageCreditMultiplierFetchedAt:"2026-07-16",usageCreditMultiplierConfidence:"exact",usageCreditConfidence:u===7?"user_override":u%4===0?"exact":u%4===1?"estimated":u%4===2?"missing":"fixture",usageCreditModel:u===4?"":`${a}-credits`,usageCreditSource:u===4?"":"fixture-rate-card",usageCreditFetchedAt:u===4?"":"2026-06-01T10:00:00Z",usageCreditTier:u%2===0?"standard":"estimated",usageCreditNote:u===2?"fixture inherited rate card":"",pricingModel:u===4?"":`${a}-pricing`,pricingEstimated:u===1||u===5,signal:w>5e4?"cache-risk":"aggregate",recommendation:w>5e4?"Review uncached aggregate input before continuing this thread.":"",tags:v,sessionId:`fixture-session-${u}`,turnId:`fixture-turn-${u}`,parentSessionId:u%3===0?"fixture-parent-session":"",parentSessionUpdatedAt:u%3===0?"2026-06-01T09:30:00Z":"",parentThread:u%3===0?"parent-thread-analysis":"",threadAttachmentLabel:u%3===0?"spawned child thread":"direct active thread",threadSource:u%3===0?"subagent":"user",subagentType:u%3===0?"analysis":"",agentRole:u%3===0?"reviewer":"",agentNickname:u%3===0?"usage-reviewer":"",project:u%2===0?"codex-usage-tracker":"local-ops",projectRelativeCwd:u%2===0?"frontend/dashboard":".",projectTags:u%2===0?["dashboard","rewrite"]:["local"],cwd:`/fixtures/${u%2===0?"codex-usage-tracker":"local-ops"}`,sourceFile:`fixture-thread-${u}.jsonl`,lineNumber:120+u,gitBranch:"experiment/frontend-rewrite",gitRemoteLabel:"origin",gitRemoteHash:`fixture-${u}`,contextWindowPct:Math.min(18+b,96),modelContextWindow:128e3,cumulativeTotalTokens:p+g+u*1e4,estimatedCacheSavings:Math.round((p-w)*1e-5*100)/100,efficiencyFlags:w>5e4?["cache-risk"]:[]}}),threads:[["thread-9f3a",142,58400,8.76,12,1.38,"High",42],["thread-7c2b",87,31200,4.21,22,1.12,"Medium",55],["thread-1a8c",64,22700,3.02,18,.98,"High",48],["thread-d3e1",53,18100,2.11,41,.81,"Low",72],["thread-b7f0",41,13600,1.65,47,.73,"Low",75],["thread-3c5d",36,9900,1.18,35,.66,"Medium",63],["thread-0e16",28,6400,.72,56,.58,"Low",82]].map(([e,t,n,a,r,s,i,o],d)=>{const f=Number(t),h=Number(n),v=Number(r),u=f*48,p=(d+1)*420;return{name:String(e),latestCallId:`fixture-call-${d}`,latestActivity:`Jun ${d+1}, 10:${String(24-d).padStart(2,"0")} AM`,latestActivityRaw:`2026-06-${String(d+1).padStart(2,"0")}T10:${String(24-d).padStart(2,"0")}:00Z`,turns:f,totalDurationSeconds:u,totalDuration:`${Math.floor(u/60)}m ${u%60}s`,averageGapSeconds:p,averageGap:`${Math.floor(p/60)}m ${p%60}s`,initiatorSummary:d%2===0?"user x4, assistant x2":"assistant x3, tool x1",modelSummary:d%2===0?"codex-1 x5, o4-mini x2":"o4-mini x3, o3 x1",effortSummary:d%2===0?"high x5, medium x2":"medium x3, low x1",totalTokens:h,cachedInput:Math.round(h*v/100),uncachedInput:Math.round(h*Math.max(100-v,0)/100),outputTokens:Math.round(h*.28),reasoningOutput:Math.round(h*.08),cost:Number(a),credits:Number(a)*25,cachePct:v,contextPct:Math.min(96,28+d*7),costPerCall:Number(s),coldResumeRisk:i,productivity:Number(o)}}),weeklyWindows:Mt.map((e,t)=>({week:e,plan:t===0?"Prolite":"Pro",observedPct:[61.4,49.2,47.7,48.3,44.5,37.4,40.1,35.8][t]??0,credits:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,projected:[49812,41275,39887,40563,37284,31420,33842,35900][t]??0,ciLow:[42156,34892,33424,34021,31241,26164,28234,29450][t]??0,ciHigh:[57467,47657,46349,47105,43326,36676,39450,41900][t]??0,confidence:t===0?"Medium":"High",note:["Prolite baseline","Drop in credits","Stable","Slight uptick","Down again","Lowest window","Recovery","Latest"][t]??""})),modelCosts:[{label:"codex-1",value:16.21,color:"#2563eb"},{label:"o3",value:12.43,color:"#1d4ed8"},{label:"o4-mini",value:7.62,color:"#059669"},{label:"gpt-4.1",value:4.91,color:"#f59e0b"},{label:"other",value:1.5,color:"#94a3b8"}],commandActions:[{title:"Show highest uncached calls",status:"Ready",owner:"Calls",description:"214 calls above the uncached threshold."},{title:"Compare Pro weeks",status:"Ready",owner:"Usage Drain",description:"Allowance windows with confidence intervals."},{title:"Find cold resumes",status:"Ready",owner:"Cache",description:"14 threads with long idle gaps."},{title:"Export support bundle",status:"Planned",owner:"Reports",description:"Local aggregate artifacts only."}],cacheSegments:[{label:"Cache read",value:38.7,color:"#2563eb"},{label:"Cache write",value:29.6,color:"#059669"},{label:"Uncached",value:31.7,color:"#7c3aed"}],cacheHeatmap:[{thread:"thread-8c1e",labels:it,values:[62,71,89,82,74,31]},{thread:"thread-2b9d",labels:it,values:[42,58,77,61,51,24]},{thread:"thread-713a",labels:it,values:[78,81,83,66,59,37]},{thread:"thread-4af2",labels:it,values:[24,36,63,54,71,44]},{thread:"thread-f9c3",labels:it,values:[18,25,41,38,52,22]}],diagnostics:[{title:"Usage Drain",status:"Ready",finding:"Projected weekly credits declined from the baseline and partially recovered in the latest window.",confidence:"High",metric:"33,842 credits / week",series:[W("usage-drain","Projected credits","#2563eb",[41.8,46.7,45.9,32.1,33.8],1e3)]},{title:"Cache Behavior",status:"Ready",finding:"Cache hit rate is healthy overall, with spikes aligned to large cache misses and cold resumes.",confidence:"Medium",metric:"41.1% hit rate",series:[W("cache","Cache hit %","#059669",[44,48,38,33,40])]},{title:"Thread Efficiency",status:"Ready",finding:"Long threads account for most estimated cost and are the clearest optimization target.",confidence:"High",metric:"65% cost share",series:[W("threads","Cost share","#1d4ed8",[65,23,8,4])]},{title:"Tool And Command Activity",status:"Stale",finding:"Command volume is stable with a slight upward trend; read and shell commands dominate.",confidence:"Medium",metric:"912 commands",series:[W("commands","Commands","#7c3aed",[542,488,611,883,912])]}],reports:[{title:"Weekly Credits",status:"Ready",owner:"Usage Drain",description:"Plan-specific weekly credits, trend lines, and confidence intervals."},{title:"Usage Remaining",status:"Ready",owner:"Usage Drain",description:"Observed remaining usage over time with reset handling."},{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Cumulative estimated cost by thread and concentration metrics."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Actual-vs-predicted drain and feature group comparisons."},{title:"Fast Mode Proxy",status:"Planned",owner:"Calls",description:"Candidate detection, speedup histogram, and confidence breakdowns."},{title:"Allowance Change",status:"Planned",owner:"Reports",description:"Week-to-week allowance estimate changes with careful language."}]};function W(e,t,n,a,r=1,s=!1){return{id:e,label:t,color:n,dashed:s,points:a.map((i,o)=>({label:Mt[o]??`Point ${o+1}`,value:i*r}))}}function ir(e){if(window.location.protocol==="file:")throw new Error("Live refresh requires the localhost dashboard server.");if(!(e!=null&&e.api_token))throw new Error("Live refresh requires localhost dashboard API token.")}function pn(e){return{Accept:"application/json","X-Codex-Usage-Token":e.api_token||""}}function uo(e,t){return new Promise((n,a)=>{if(t!=null&&t.aborted){a(na(t));return}const r=window.setTimeout(()=>{t==null||t.removeEventListener("abort",s),n()},e);function s(){window.clearTimeout(r),a(na(t))}t==null||t.addEventListener("abort",s,{once:!0})})}function or(e){return(e instanceof DOMException||e instanceof Error)&&e.name==="AbortError"}function na(e){return(e==null?void 0:e.reason)instanceof Error?e.reason:new DOMException("The request was cancelled.","AbortError")}const ho=["#2563eb","#1d4ed8","#059669","#f59e0b","#94a3b8"];function cr(e){const t=new Map;e.forEach(r=>{const s=r.model||"unknown";t.set(s,(t.get(s)??0)+r.cost)});const n=[...t.entries()].sort((r,s)=>s[1]-r[1]||r[0].localeCompare(s[0]));return(n.length>5?[...n.slice(0,4),["other",n.slice(4).reduce((r,s)=>r+s[1],0)]]:n).map(([r,s],i)=>({label:r,value:s,color:ho[i]??"#94a3b8"}))}function lr(e){if(!e.length)return[];const t=Math.max(e.reduce((n,a)=>n+bt(a),0),1);return[fo(e,t),mo(e,t),go(e,t),po(e,t)].filter(n=>!!n).sort((n,a)=>a.credits-n.credits).map((n,a)=>({...n,rank:a+1}))}function ur(e){if(!e.length)return[];const t=[{title:"Cost Curves",status:"Ready",owner:"Threads",description:"Estimated cost concentration by loaded aggregate thread."},{title:"Usage Drain Model",status:"Ready",owner:"Reports",description:"Highest estimated credit-impact calls from loaded aggregate rows."}];return e.some(n=>n.fastProxyCandidate||n.effort.toLowerCase()==="low")&&t.push({title:"Fast Mode Proxy",status:"Ready",owner:"Calls",description:"Low-effort and fast-call candidates inferred from aggregate rows."}),t}function fo(e,t){const n=new Map;e.forEach(i=>n.set(i.thread,[...n.get(i.thread)??[],i]));const[a,r]=[...n.entries()].sort((i,o)=>Ae(o[1],f=>f.totalTokens)-Ae(i[1],f=>f.totalTokens)||o[1].length-i[1].length)[0]??[];if(!a||!(r!=null&&r.length)||r.length<2)return null;const s=Ae(r,bt);return{rank:0,title:`Long Thread: ${a}`,severity:s/t>=.25||r.length>=8?"High":"Medium",credits:Math.round(s),share:s/t*100,summary:`${r.length.toLocaleString()} loaded calls and ${Ae(r,i=>i.totalTokens).toLocaleString()} tokens in this thread.`}}function mo(e,t){const n=e.filter(r=>r.signal==="cache-risk"||r.cachedPct<35||r.uncachedInput>5e4);if(!n.length)return null;const a=Ae(n,bt);return{rank:0,title:"Cache Misses (Large Inputs)",severity:n.some(r=>r.cachedPct<20||r.uncachedInput>5e4)?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls show low cache reuse or large uncached input.`}}function go(e,t){const n=e.filter(r=>r.effort.toLowerCase()==="high"||r.reasoningOutput>0);if(!n.length)return null;const a=Ae(n,bt);return{rank:0,title:"High Model Effort",severity:a/t>=.25?"High":"Medium",credits:Math.round(a),share:a/t*100,summary:`${n.length.toLocaleString()} loaded calls use high effort or report reasoning output.`}}function po(e,t){const n=Math.max(25e3,bo(e.map(s=>s.output),.75)),a=e.filter(s=>s.output>=n||s.tags.some(i=>["file-heavy","subagent","large"].includes(i)));if(!a.length)return null;const r=Ae(a,bt);return{rank:0,title:"Tool Output Volume",severity:a.some(s=>s.output>5e4)?"High":"Medium",credits:Math.round(r),share:r/t*100,summary:`${a.length.toLocaleString()} loaded calls have high output volume or file-heavy/subagent tags.`}}function bt(e){return e.credits>0?e.credits:e.cost*25}function Ae(e,t){return e.reduce((n,a)=>n+t(a),0)}function bo(e,t){const n=e.filter(a=>Number.isFinite(a)).sort((a,r)=>a-r);return n.length?n[Math.min(n.length-1,Math.max(0,Math.floor((n.length-1)*t)))]??0:0}function dr(e){const t=new Map;for(const a of e){if(!Number.isFinite(a.timestamp))continue;const r=hr(a.timestamp),s=t.get(r)??{label:fr(a.timestamp),timestamp:wo(a.timestamp),cached:0,cost:0,input:0,output:0};s.cached+=a.cached,s.cost+=a.cost,s.input+=a.input,s.output+=a.output,t.set(r,s)}const n=vo(t);return n.length?{tokenSeries:[{id:"input",label:"Input",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input}))},{id:"output",label:"Output",color:"#059669",points:n.map(a=>({label:a.label,value:a.output}))},{id:"cached",label:"Cached",color:"#7c3aed",dashed:!0,points:n.map(a=>({label:a.label,value:a.cached}))}],costSeries:[{id:"cost",label:"Estimated Cost",color:"#f59e0b",points:n.map(a=>({label:a.label,value:a.cost}))}],cacheSeries:[{id:"cache",label:"Cache hit %",color:"#2563eb",points:n.map(a=>({label:a.label,value:a.input>0?a.cached/a.input*100:0}))}]}:{tokenSeries:[],costSeries:[],cacheSeries:[]}}function vo(e){const t=[...e.values()].sort((s,i)=>s.timestamp-i.timestamp),n=t.at(0),a=t.at(-1);if(!n||!a)return[];const r=[];for(const s=new Date(n.timestamp);s.getTime()<=a.timestamp;s.setDate(s.getDate()+1)){const i=s.getTime(),o=hr(i);r.push(e.get(o)??{label:fr(i),timestamp:i,cached:0,cost:0,input:0,output:0})}return r}function hr(e){const t=new Date(e),n=String(t.getMonth()+1).padStart(2,"0"),a=String(t.getDate()).padStart(2,"0");return`${t.getFullYear()}-${n}-${a}`}function wo(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()}function fr(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function B(e,t){var a;const n=Number(((a=e.summary)==null?void 0:a[t])??0);return Number.isFinite(n)?n:0}function yo(e){if(!(!e.summary||e.load_window==="rows"))return{visibleCalls:B(e,"visible_calls"),inputTokens:B(e,"input_tokens"),cachedInputTokens:B(e,"cached_input_tokens"),uncachedInputTokens:B(e,"uncached_input_tokens"),outputTokens:B(e,"output_tokens"),reasoningOutputTokens:B(e,"reasoning_output_tokens"),totalTokens:B(e,"total_tokens"),estimatedCostUsd:B(e,"estimated_cost_usd"),usageCredits:B(e,"usage_credits")}}function _o(e){return{cost:Number(e.estimated_cost_usd??0),standardCost:aa(e.standard_cost_usd),priorityCost:aa(e.priority_cost_usd),pricingServiceTier:String(e.pricing_service_tier??""),billingBasis:String(e.billing_basis??"unknown"),costSemantics:String(e.cost_semantics??"api_token_estimate")}}function aa(e){if(e==null||e==="")return null;const t=Number(e);return Number.isFinite(t)?t:null}function So(e,t,n){const a=e.fast,r=a===!0||a===1?!0:a===!1||a===0?!1:null;return{credits:Number(e.usage_credits??0),serviceTier:String(e.service_tier??""),fast:r,serviceTierSource:String(e.service_tier_source??""),serviceTierConfidence:String(e.service_tier_confidence??""),fastProxyCandidate:t>0&&n/Math.max(t,1)>4e3,standardUsageCredits:Number(e.standard_usage_credits??e.usage_credits??0),fastUsageCredits:Co(e.fast_usage_credits),usageCreditMultiplier:Number(e.usage_credit_multiplier??1),usageCreditMultiplierSource:String(e.usage_credit_multiplier_source??""),usageCreditMultiplierSourceUrl:String(e.usage_credit_multiplier_source_url??""),usageCreditMultiplierFetchedAt:String(e.usage_credit_multiplier_fetched_at??""),usageCreditMultiplierConfidence:String(e.usage_credit_multiplier_confidence??"")}}function Co(e){if(e==null||e==="")return null;const t=Number(e);return Number.isFinite(t)?t:null}const xo=1e4,ko=500;async function ra(e,t,n){var s,i;const a=t.limit&&t.limit>0?t.limit:ko,r=await n(e,{...t,limit:a});return(i=t.onProgress)==null||i.call(t,{status:"completed",phase:"loading_rows",message:`Loaded ${t.loadWindow==="all"?"all-history":t.loadWindow} evidence window`,completed:Number(r.loaded_row_count??((s=r.rows)==null?void 0:s.length)??0),total:Number(r.total_available_rows??r.loaded_row_count??0),percent:100}),r}async function sa(e,t,n){var o,d;const a=[];let r=0,s=null,i=Number((e==null?void 0:e.total_available_rows)??0);for(let f=0;f<1e3;f+=1){(o=t.signal)==null||o.throwIfAborted();const h=await n(e,{...t,refresh:f===0?t.refresh:!1,limit:xo,offset:r}),v=h.rows??[];s=h,a.push(...v),i=Number(h.total_available_rows??i??a.length);const u=a.length>=i||!h.has_more;if((d=t.onProgress)==null||d.call(t,{status:u?"completed":"running",phase:"loading_rows",message:"Loading all rows",completed:a.length,total:i,percent:u?100:i>0?Math.min(99,Math.floor(a.length/i*100)):0}),r+=v.length,!h.has_more||v.length===0||a.length>=i)break}return{...s??e??{},rows:a,loaded_row_count:a.length,limit:null,limit_label:"All",has_more:!1,total_available_rows:i||a.length}}function To(){if(window.__CODEX_USAGE_BOOT__)return window.__CODEX_USAGE_BOOT__;const e=document.getElementById("usage-data");if(!(e!=null&&e.textContent))return null;try{return JSON.parse(e.textContent)}catch{return null}}async function Lo(e,t={}){if(t.refresh&&(e!=null&&e.refresh_jobs_available)){const n=await Ro(e,t),a={...t,refresh:!n};return a.loadWindow&&a.loadWindow!=="rows"?ra(e,a,He):a.limit===0?sa(e,a,He):He(e,a)}return t.loadWindow&&t.loadWindow!=="rows"?ra(e,t,He):t.limit===0?sa(e,t,He):He(e,t)}async function Ro(e,t){try{return await Mo(e,t),!0}catch(n){if(or(n)||n instanceof mr)throw n;return!1}}async function He(e,t={}){ir(e);const n=new URLSearchParams({refresh:t.refresh?"1":"0",limit:String(t.limit??(e==null?void 0:e.limit)??(e==null?void 0:e.loaded_row_count)??500),_:String(Date.now())});t.loadWindow&&n.set("load_window",t.loadWindow),t.since&&n.set("since",t.since),t.offset&&t.offset>0&&n.set("offset",String(t.offset)),(t.includeArchived??_r(e))&&n.set("include_archived","1");const r=await fetch(`/api/usage?${n.toString()}`,{headers:pn(e),cache:"no-store",signal:t.signal});return await bn(r,"Usage refresh")}async function Mo(e,t){var o;ir(e);const n=new URLSearchParams({_:String(Date.now())});(t.includeArchived??_r(e))&&n.set("include_archived","1");const r=await fetch(`/api/refresh/start?${n.toString()}`,{headers:pn(e),cache:"no-store",signal:t.signal}),s=await bn(r,"Usage refresh start");(o=t.onProgress)==null||o.call(t,s);const i=typeof s.job_id=="string"?s.job_id:"";if(!i)throw new Error("Usage refresh start did not return a job id.");return Po(e,i,t.onProgress,t.signal)}async function Po(e,t,n,a){for(let r=0;r<600;r+=1){a==null||a.throwIfAborted();const s=new URLSearchParams({job_id:t,_:String(Date.now())}),i=await fetch(`/api/refresh/status?${s.toString()}`,{headers:pn(e),cache:"no-store",signal:a}),o=await bn(i,"Usage refresh status");if(n==null||n(o),o.status==="completed")return o;if(o.status==="failed")throw new mr(o.error||o.message||"Usage refresh failed.");await uo(Math.min(1e3,150+r*50),a)}throw new Error("Usage refresh did not complete before the polling timeout.")}class mr extends Error{}function ia(e){if(!e)return{...sr,contextRuntime:sn(e)};const t=e.rows??[],n=t.map(pr),a=t.length?Te(t,b=>Number(b.total_tokens??0)):B(e,"total_tokens"),r=t.length?Te(t,b=>Number(b.estimated_cost_usd??0)):B(e,"estimated_cost_usd"),s=t.length?Te(t,b=>Number(b.cached_input_tokens??0)):B(e,"cached_input_tokens"),i=t.length?Te(t,b=>Number(b.input_tokens??0)):B(e,"input_tokens"),o=t.length?Te(t,b=>{const w=Number(b.input_tokens??0),T=Number(b.cached_input_tokens??0);return Number(b.uncached_input_tokens??Math.max(w-T,0))}):Math.max(i-s,0),d=t.length?Te(t,b=>Number(b.output_tokens??0)):B(e,"output_tokens"),f=t.length?Te(t,b=>Number(b.reasoning_output_tokens??0)):B(e,"reasoning_output_tokens"),h=i>0?s/i*100:0,v=n.length||Math.max(0,Number(e.loaded_row_count??0)),u=Ao(t),p=No(t),g=$o({cachePct:h,cachedTokens:s,estimatedCost:r,historyScope:e.history_scope??"active",totalCalls:v,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:o,output:d,reasoningOutput:f},usageRemainingCard:Io(e)});return{...jo(e),contextRuntime:sn(e),scopeSummary:yo(e),cards:g,...u,...p,calls:n,threads:Sr(n),findings:lr(n),modelCosts:cr(n),reports:ur(n),cacheSegments:[{label:"Cache read",value:h,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-h,0),color:"#7c3aed"}]}}function jo(e){return{...sr,contextRuntime:sn(e),tokenSeries:[],costSeries:[],cacheSeries:[],weeklyCreditSeries:[],usageRemainingSeries:[],actualVsPredictedSeries:[],calls:[],threads:[],findings:[],weeklyWindows:[],modelCosts:[],commandActions:[],cacheSegments:[],cacheHeatmap:[],diagnostics:[],reports:[]}}function Ao(e){return dr(e.map(t=>({timestamp:wn(t),cached:Number(t.cached_input_tokens??0),cost:Number(t.estimated_cost_usd??0),input:Number(t.input_tokens??0),output:Number(t.output_tokens??0)})))}function No(e){const t=[...e].map(f=>({row:f,timestamp:wn(f)})).filter(f=>Number.isFinite(f.timestamp)).sort((f,h)=>f.timestamp-h.timestamp),n=new Map;for(const{row:f,timestamp:h}of t){const v=rn(h),u=n.get(v)??{timestamp:h,credits:0,weeklyUsedPercent:null};u.credits+=Math.max(0,Number(f.usage_credits??0));const p=Oe(f.rate_limit_secondary_used_percent);p!==null&&(u.weeklyUsedPercent=p),n.set(v,u)}const a=[...n.entries()].map(([f,h])=>({label:f,...h}));let r=0;const s=a.map(f=>(r+=f.credits,{label:f.label,value:r})),i=s.map((f,h)=>{var v;return{label:f.label,value:s.length>1?(((v=s.at(-1))==null?void 0:v.value)??0)*((h+1)/s.length):f.value}}),o=a.filter(f=>f.weeklyUsedPercent!==null).map(f=>({label:f.label,value:Pt(100-(f.weeklyUsedPercent??0))})),d=Eo(e);return{weeklyCreditSeries:Fo(d),usageRemainingSeries:o.length?[{id:"weekly-remaining",label:"Weekly remaining",color:"#059669",points:o}]:[],actualVsPredictedSeries:s.length?[{id:"observed-drain",label:"Observed drain",color:"#2563eb",points:s},{id:"loaded-baseline",label:"Loaded-row baseline",color:"#1d4ed8",dashed:!0,points:i}]:[],weeklyWindows:d}}function Eo(e){const t=new Map;for(const n of e){const a=wn(n);if(!Number.isFinite(a))continue;const r=Do(n,a),s=t.get(r)??{rows:[],latestTimestamp:0,latestUsedPercent:null};s.rows.push(n),a>=s.latestTimestamp&&(s.latestTimestamp=a,s.latestUsedPercent=Oe(n.rate_limit_secondary_used_percent)),t.set(r,s)}return[...t.entries()].map(([n,a])=>{var i;const r=a.rows.reduce((o,d)=>o+Math.max(0,Number(d.usage_credits??0)),0),s=a.latestUsedPercent??0;return{week:n,plan:String(((i=a.rows[0])==null?void 0:i.rate_limit_plan_type)??"unknown"),observedPct:s,credits:r,projected:s>0?r/(s/100):r,ciLow:s>0?r/(s/100)*.85:r,ciHigh:s>0?r/(s/100)*1.15:r,confidence:a.rows.length>=20?"Medium":"Low",note:`Loaded ${vn(a.rows.length)} rows`}}).sort((n,a)=>n.week.localeCompare(a.week))}function Fo(e){return e.length?[{id:"weekly-projected",label:"Projected weekly credits",color:"#2563eb",points:e.map(t=>({label:t.week,value:t.projected,low:t.ciLow,high:t.ciHigh}))},{id:"loaded-credits",label:"Loaded-row credits",color:"#0f766e",dashed:!0,points:e.map(t=>({label:t.week,value:t.credits}))}]:[]}function Do(e,t){const n=Be(e.rate_limit_secondary_resets_at);return n!==null&&n>0?rn(n*1e3):rn(t)}function rn(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric"}).format(new Date(e))}function sn(e){return{apiToken:String((e==null?void 0:e.api_token)??""),contextApiEnabled:!!(e!=null&&e.context_api_enabled),fileMode:window.location.protocol==="file:"}}function $o(e){return[{label:"Total Tokens",value:Me(e.totalTokens),detail:`${e.historyScope} history scope`,trend:"loaded aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:Me(e.tokenBreakdown.cachedInput)},{label:"Uncached",value:Me(e.tokenBreakdown.uncachedInput)},{label:"Output",value:Me(e.tokenBreakdown.output)},{label:"Reasoning",value:Me(e.tokenBreakdown.reasoningOutput)}]},{label:"Estimated Cost",value:Wo(e.estimatedCost),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.cachePct.toFixed(1)}%`,detail:`${Me(e.cachedTokens)} cached input`,trend:e.cachePct>=40?"healthy cache reuse":"cache risk",tone:e.cachePct>=40?"purple":"orange"},{label:"Total Calls",value:vn(e.totalCalls),detail:"loaded calls in this dashboard",trend:"privacy-safe",tone:"blue"},e.usageRemainingCard]}function Io(e){const t=Oo(e.observed_usage);if(t)return t;const n=Uo(e.allowance_windows);return n||{label:"Usage Remaining",value:"Unknown",detail:e.allowance_configured?"allowance configured; no current window":"no observed usage or allowance window",trend:e.allowance_error?`config issue: ${e.allowance_error}`:"not available in payload",tone:e.allowance_error?"red":"orange"}}function Oo(e){const t=Array.isArray(e==null?void 0:e.windows)?e.windows:[];if(!(e!=null&&e.available)||!t.length)return null;const n=gr(t,s=>Oe(s.used_percent)!==null);if(!n)return null;const a=Oe(n.used_percent)??0,r=Pt(100-a);return{label:"Usage Remaining",value:br(r),detail:`${wr(n.label||n.key,"Observed usage")} observed usage`,trend:vr(n.resets_at)||e.source||"observed locally",tone:yr(r)}}function Uo(e){if(!Array.isArray(e)||!e.length)return null;const t=gr(e,o=>{const d=Oe(o.remaining_percent),f=Be(o.remaining_credits),h=Be(o.total_credits);return d!==null||f!==null||h!==null&&h>0});if(!t)return null;const n=Be(t.remaining_credits),a=Be(t.total_credits),r=n!==null&&a!==null&&a>0?n/a*100:null,s=Oe(t.remaining_percent)??r;return{label:"Usage Remaining",value:s!==null?br(Pt(s)):`${oa(n??0)} left`,detail:`${wr(t.label||t.key,"Allowance")} allowance window`,trend:[n===null?"":`${oa(n)} left`,vr(t.reset_at)].filter(Boolean).join(" · ")||"configured allowance",tone:s===null?"green":yr(Pt(s))}}function gr(e,t){const n=e.filter(t);return n.find(Vo)??n[0]??null}function Vo(e){const t=Be(e.window_minutes),n=`${e.key??""} ${e.label??""}`.toLowerCase();return t===10080||/\b(weekly|week|7d|7-day|7 day)\b/.test(n)}function pr(e,t=0){const n=String(e.event_timestamp??e.time??e.turn_timestamp??e.started_at??e.call_started_at??""),a=n,r=String(e.call_started_at??e.started_at??n),s=Number(e.input_tokens??0),i=Number(e.output_tokens??0),o=Number(e.reasoning_output_tokens??0),d=Number(e.cached_input_tokens??0),f=Number(e.cache_hit_ratio??e.cache_ratio??0),h=s>0?d/s*100:f*100,v=Number(e.total_tokens??s+i),u=Number(e.duration_seconds??e.call_duration_seconds??0),p=String(e.previous_call_event_timestamp??""),g=Number(e.previous_call_delta_seconds??0),b=Number(e.uncached_input_tokens??Math.max(s-d,0)),w=String(e.record_id??e.id??`${a||"row"}-${t}`),T=String(e.primary_signal??"").trim(),N=Number(e.line_number),R=Oe(e.context_window_percent),_=Number(e.model_context_window),L=Number(e.cumulative_total_tokens);return{id:w,threadKey:String(e.thread_key??""),rawTime:a,eventTimestamp:n,callStartedAt:r,time:Cr(a),thread:qo(e),model:String(e.model??"unknown"),effort:String(e.effort??"blank"),input:s,output:i,reasoningOutput:o,totalTokens:v,cachedInput:d,uncachedInput:b,cachedPct:h,..._o(e),duration:jt(u),durationSeconds:u,previousCallGap:jt(g),previousCallEventTimestamp:p,previousCallGapSeconds:Number.isFinite(g)?g:0,initiator:String(e.call_initiator??"unknown"),initiatorReason:String(e.call_initiator_reason??""),initiatorConfidence:String(e.call_initiator_confidence??""),...So(e,u,v),usageCreditConfidence:String(e.usage_credit_confidence??"unknown"),usageCreditModel:String(e.usage_credit_model??""),usageCreditSource:String(e.usage_credit_source??""),usageCreditFetchedAt:String(e.usage_credit_fetched_at??""),usageCreditTier:String(e.usage_credit_tier??""),usageCreditNote:String(e.usage_credit_note??""),pricingModel:String(e.pricing_model??""),pricingEstimated:!!e.pricing_estimated,signal:T||(h<25?"cache-risk":"aggregate"),recommendation:String(e.recommended_action??""),tags:h<25?["uncached"]:h>60?["healthy-cache"]:[],sessionId:String(e.session_id??""),turnId:String(e.turn_id??""),parentSessionId:String(e.parent_session_id??""),parentSessionUpdatedAt:String(e.resolved_parent_session_updated_at??e.parent_session_updated_at??""),parentThread:String(e.resolved_parent_thread_name??e.parent_thread_name??""),threadAttachmentLabel:String(e.thread_attachment_label??""),threadSource:String(e.thread_source??""),subagentType:String(e.subagent_type??""),agentRole:String(e.agent_role??""),agentNickname:String(e.agent_nickname??""),project:String(e.project_name??""),projectRelativeCwd:String(e.project_relative_cwd??""),projectTags:Array.isArray(e.project_tags)?e.project_tags.map(y=>String(y)):[],cwd:String(e.cwd??""),sourceFile:String(e.source_file??""),lineNumber:Number.isFinite(N)&&N>0?N:null,gitBranch:String(e.git_branch??""),gitRemoteLabel:String(e.git_remote_label??""),gitRemoteHash:String(e.git_remote_hash??""),contextWindowPct:R,modelContextWindow:Number.isFinite(_)&&_>0?_:null,cumulativeTotalTokens:Number.isFinite(L)&&L>0?L:null,estimatedCacheSavings:Number(e.estimated_cache_savings_usd??0),efficiencyFlags:Array.isArray(e.efficiency_flags)?e.efficiency_flags.map(y=>String(y)):[]}}function Oe(e){const t=Number(e);return Number.isFinite(t)?t<=1?t*100:t:null}function Be(e){const t=Number(e);return Number.isFinite(t)?t:null}function Pt(e){return Math.max(0,Math.min(100,e))}function br(e){const t=Math.abs(e)>=10?0:1;return`${e.toFixed(t)}%`}function oa(e){return`${Me(e)} cr`}function vr(e){if(e==null||e==="")return"";const t=typeof e=="number"?e*1e3:Date.parse(e);return Number.isFinite(t)?`resets ${Ko(t)}`:""}function Ko(e){const t=new Date(e);return Number.isNaN(t.getTime())?String(e):`${t.toISOString().slice(0,16).replace("T"," ")} UTC`}function wr(e,t){return(e==null?void 0:e.trim())||t}function yr(e){return e<20?"red":e<40?"orange":"green"}function _r(e){return typeof e.include_archived=="boolean"?e.include_archived:e.history_scope==="all-history"||e.history_scope==="all"}function qo(e){const t=e.thread_name??e.thread??e.resolved_parent_thread_name??e.parent_thread_name;if(t&&String(t).trim())return String(t);const n=e.project_name??e.project_relative_cwd,a=e.session_id?e.session_id.slice(-6):"";return n&&a?`${n} ${a}`:e.thread_attachment_label?String(e.thread_attachment_label):"Untitled thread"}function Sr(e){const t=new Map;for(const n of e)t.set(n.thread,[...t.get(n.thread)??[],n]);return[...t.entries()].map(([n,a])=>{const r=a.length,i=[...a].sort((y,k)=>ca(k)-ca(y))[0]??null,o=(i==null?void 0:i.rawTime)||(i==null?void 0:i.time)||"",d=a.reduce((y,k)=>y+k.totalTokens,0),f=a.reduce((y,k)=>y+k.cachedInput,0),h=a.reduce((y,k)=>y+k.uncachedInput,0),v=a.reduce((y,k)=>y+k.output,0),u=a.reduce((y,k)=>y+k.reasoningOutput,0),p=a.reduce((y,k)=>y+k.cost,0),g=a.reduce((y,k)=>y+k.credits,0),b=a.reduce((y,k)=>y+k.durationSeconds,0),w=a.filter(y=>y.previousCallGapSeconds>0),T=w.reduce((y,k)=>y+k.previousCallGapSeconds,0)/Math.max(w.length,1),N=f+h,R=N>0?f/N*100:a.reduce((y,k)=>y+k.cachedPct,0)/Math.max(r,1),_=a.map(y=>y.contextWindowPct).filter(y=>typeof y=="number"&&Number.isFinite(y)),L=R<25?"High":R<45?"Medium":"Low";return{name:n,latestCallId:(i==null?void 0:i.id)??"",latestActivity:Cr(o),latestActivityRaw:o,turns:r,totalDurationSeconds:b,totalDuration:jt(b),averageGapSeconds:T,averageGap:jt(T),initiatorSummary:Qt(a.map(y=>y.initiator)),modelSummary:Qt(a.map(y=>y.model)),effortSummary:Qt(a.map(y=>y.effort)),totalTokens:d,cachedInput:f,uncachedInput:h,outputTokens:v,reasoningOutput:u,cost:p,credits:g,cachePct:R,contextPct:_.length?Math.max(..._):null,costPerCall:p/Math.max(r,1),coldResumeRisk:L,productivity:Math.max(20,Math.round(R-p/Math.max(r,1)*4))}}).sort((n,a)=>a.cost-n.cost).slice(0,20)}function ca(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function Qt(e,t=3){const n=new Map;for(const a of e){const r=a.trim()||"unknown";n.set(r,(n.get(r)??0)+1)}return[...n.entries()].sort((a,r)=>r[1]-a[1]||a[0].localeCompare(r[0])).slice(0,t).map(([a,r])=>`${a} x${vn(r)}`).join(", ")||"unknown"}function Te(e,t){return e.reduce((n,a)=>n+t(a),0)}async function bn(e,t){let n;try{n=await e.json()}catch(a){if(e.ok)throw new Error(`${t} response could not be read as JSON: ${Ho(a)}`);n={}}if(!e.ok){const a=typeof n.error=="string"?n.error:`${t} request failed (${e.status})`;throw new Error(a)}return n}function Ho(e){return e instanceof Error?e.message:String(e)}function vn(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function Me(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function Wo(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(e)}function jt(e){if(!Number.isFinite(e)||e<=0)return"-";if(e<60)return`${e.toFixed(0)}s`;const t=Math.floor(e/60),n=Math.round(e%60);return`${t}m ${n}s`}function Cr(e){const t=new Date(e);return Number.isNaN(t.getTime())?e||"-":new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}).format(t)}function wn(e){return Date.parse(String(e.started_at??e.call_started_at??e.time??e.event_timestamp??e.turn_timestamp??""))}const Pe=1440*60*1e3;function Bo(e,t,n=window.location.search){const a=xr(n);if(!a.active)return e;const r=e.calls.filter(s=>Qo(s,a));return r.length===e.calls.length?e:Yo(e,r,`${t} filtered`)}function xr(e){var d,f,h,v,u,p;const t=new URLSearchParams(e),n=((d=t.get("model"))==null?void 0:d.trim())??"",a=((f=t.get("effort"))==null?void 0:f.trim())??"",r=((h=t.get("confidence")||t.get("pricing"))==null?void 0:h.trim())??"",s=((v=t.get("date")||t.get("time"))==null?void 0:v.trim())??"",i=((u=t.get("from"))==null?void 0:u.trim())??"",o=((p=t.get("to"))==null?void 0:p.trim())??"";return{model:n,effort:a,confidence:r,datePreset:s,dateStart:i,dateEnd:o,active:!!(n||a||r||s||i||o)}}function Qo(e,t){return!(t.model&&e.model!==t.model||t.effort&&e.effort!==t.effort||t.confidence&&!zo(e,t.confidence)||!Go(e,t))}function zo(e,t){return t==="official"||t==="cost-exact"?!!(e.pricingModel&&!e.pricingEstimated):t==="estimated"||t==="cost-estimated"?e.pricingEstimated:t==="unpriced"||t==="cost-unpriced"?!e.pricingModel:t==="credit-exact"?e.usageCreditConfidence==="exact":t==="credit-estimated"?e.usageCreditConfidence==="estimated":t==="credit-override"?e.usageCreditConfidence==="user_override":t==="credit-missing"?e.usageCreditConfidence==="missing"||e.usageCreditConfidence==="unknown":!0}function Go(e,t){const n=Jo(t);if(!n.active)return!0;if(n.invalid)return!1;const a=Date.parse(e.rawTime||e.time);return!(!Number.isFinite(a)||n.start!==null&&a=n.endExclusive)}function Jo(e){if(e.datePreset&&e.datePreset!=="all"&&e.datePreset!=="custom"){const a=Zo(e.datePreset);return a?{active:!0,invalid:!1,...a}:{active:!1,invalid:!1,start:null,endExclusive:null}}const t=la(e.dateStart),n=la(e.dateEnd);return t!==null&&n!==null&&t>n?{active:!0,invalid:!0,start:t,endExclusive:n+Pe}:{active:t!==null||n!==null,invalid:!1,start:t,endExclusive:n===null?null:n+Pe}}function Zo(e){const t=Xo(new Date);if(e==="today")return{start:t,endExclusive:t+Pe};if(e==="last-7-days")return{start:t-6*Pe,endExclusive:t+Pe};if(e==="this-week"){const a=new Date(t).getDay(),r=a===0?-6:1-a,s=t+r*Pe;return{start:s,endExclusive:s+7*Pe}}if(e==="this-month"){const n=new Date(t),a=new Date(n.getFullYear(),n.getMonth(),1).getTime(),r=new Date(n.getFullYear(),n.getMonth()+1,1).getTime();return{start:a,endExclusive:r}}return null}function la(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function Xo(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()}function Yo(e,t,n="filtered"){const a=t.reduce((u,p)=>u+p.totalTokens,0),r=t.reduce((u,p)=>u+p.cost,0),s=t.reduce((u,p)=>u+p.cachedInput,0),i=t.reduce((u,p)=>u+p.uncachedInput,0),o=t.reduce((u,p)=>u+p.output,0),d=t.reduce((u,p)=>u+p.reasoningOutput,0),f=t.reduce((u,p)=>u+p.input,0),h=f>0?s/f*100:0,v=e.cards.find(u=>u.label==="Usage Remaining")??{label:"Usage Remaining",value:"Unknown",detail:"not available in filtered view",trend:"not available in payload",tone:"orange"};return{...e,cards:ec({cachePct:h,cachedTokens:s,estimatedCost:r,historyScope:n,totalCalls:t.length,totalTokens:a,tokenBreakdown:{cachedInput:s,uncachedInput:i,output:o,reasoningOutput:d},usageRemainingCard:v}),...tc(t),calls:t,threads:Sr(t),findings:lr(t),modelCosts:cr(t),reports:ur(t),cacheSegments:[{label:"Cache read",value:h,color:"#2563eb"},{label:"Uncached input",value:Math.max(100-h,0),color:"#7c3aed"}]}}function ec({cachePct:e,cachedTokens:t,estimatedCost:n,historyScope:a,totalCalls:r,totalTokens:s,tokenBreakdown:i,usageRemainingCard:o}){return[{label:"Total Tokens",value:We(s),detail:`${a} history scope`,trend:"filtered aggregate rows",tone:"blue",breakdown:[{label:"Cached",value:We(i.cachedInput)},{label:"Uncached",value:We(i.uncachedInput)},{label:"Output",value:We(i.output)},{label:"Reasoning",value:We(i.reasoningOutput)}]},{label:"Estimated Cost",value:ac(n),detail:"local pricing config",trend:"privacy-safe estimate",tone:"green"},{label:"Cache Hit Rate",value:`${e.toFixed(1)}%`,detail:`${We(t)} cached input`,trend:e>=40?"healthy cache reuse":"cache risk",tone:e>=40?"purple":"orange"},{label:"Total Calls",value:nc(r),detail:"loaded calls matching filters",trend:"legacy shell filters",tone:"blue"},o]}function tc(e){return dr(e.map(t=>({timestamp:Date.parse(t.rawTime||t.time),cached:t.cachedInput,cost:t.cost,input:t.input,output:t.output})))}function We(e){return new Intl.NumberFormat("en-US",{notation:"compact",maximumFractionDigits:2}).format(e)}function nc(e){return new Intl.NumberFormat("en-US").format(Math.round(e))}function ac(e){return new Intl.NumberFormat("en-US",{currency:"USD",maximumFractionDigits:2,minimumFractionDigits:2,style:"currency"}).format(e)}const kr=[{id:"overview",label:"Overview",description:"High-level telemetry",icon:$s},{id:"investigator",label:"Investigate",description:"Root-cause evidence",icon:Ds},{id:"compression-lab",label:"Compression Lab",description:"Context savings",icon:Ms},{id:"calls",label:"Calls",description:"Model-call table",icon:Vs},{id:"threads",label:"Threads",description:"Thread efficiency",icon:Hs},{id:"usage-drain",label:"Limits",description:"Allowance intelligence",icon:qs},{id:"cache-context",label:"Cache And Context",description:"Cache and cold resumes",icon:As},{id:"diagnostics",label:"Diagnostics Notebook",description:"Technical report",icon:Ls},{id:"reports",label:"Reports",description:"Generated analyses",icon:Ps},{id:"settings",label:"Settings",description:"Local configuration",icon:Os}],Tr=[{label:"Files",icon:Es,target:"settings"},{label:"Commands",icon:ks,target:"investigator"},{label:"Models",icon:Rs,target:"calls"}];function Lr(e){return _s(e)}const rc=[{value:"day",label:"24 hours",ariaLabel:"Last 24h"},{value:"week",label:"7 days",ariaLabel:"Last 7 days"},{value:"rows",label:"Recent",ariaLabel:"Recent rows"},{value:"all",label:"All time",ariaLabel:"All time"}];function sc(e){const t=e.refreshing||!e.canUseLiveApi,n=e.loadWindow==="rows",a=`${e.loadedRowCount.toLocaleString()} detail row${e.loadedRowCount===1?"":"s"} cached`,r=n?`${e.loadedRowCount.toLocaleString()} loaded / ${e.totalAvailableRows.toLocaleString()} total`:`${e.totalAvailableRows.toLocaleString()} calls analyzed · ${a}`,s=n?`${e.loadedRowCount.toLocaleString()} of ${e.totalAvailableRows.toLocaleString()} evidence rows loaded`:`Focused pages analyze all ${e.totalAvailableRows.toLocaleString()} calls in scope; ${e.loadedRowCount.toLocaleString()} call rows are cached for immediate detail views.`,i=n?e.rowLoadStatus:`${e.rowLoadModeLabel} analysis uses ${e.totalAvailableRows.toLocaleString()} calls; ${a}`;return c.jsxs("section",{className:"data-window-control","aria-label":"Analysis scope",children:[c.jsxs("div",{className:"data-window-summary",children:[c.jsx("span",{children:"Analysis scope"}),c.jsx("strong",{children:e.rowLoadModeLabel}),c.jsx("small",{title:s,children:r})]}),c.jsx("div",{className:"data-window-options",role:"group","aria-label":"Choose loaded call window",children:rc.map(o=>c.jsx("button",{type:"button","aria-label":o.ariaLabel,"aria-pressed":e.loadWindow===o.value,disabled:t,onClick:()=>e.onWindowChange(o.value),children:o.label},o.value))}),e.loadWindow==="rows"?c.jsxs("div",{className:"row-window-editor",children:[c.jsx("input",{"aria-label":"Rows to load slider","aria-valuetext":`${e.finitePendingLoadLimit.toLocaleString()} recent rows`,type:"range",min:1,max:e.rowLimitSliderMax,step:100,value:e.rowLimitSliderValue,onChange:o=>e.onSliderChange(o.target.value),disabled:t}),c.jsx("input",{"aria-label":"Rows to load",type:"number",min:1,step:100,value:e.pendingLoadLimit,onChange:o=>e.onDraftChange(o.target.value),disabled:t}),c.jsx("button",{type:"button","data-primary":"true",onClick:e.onApply,disabled:t||!e.rowLimitChanged,children:e.loadLabel}),c.jsx("button",{type:"button",onClick:e.onLoadMore,disabled:t||!e.hasMoreRows,children:e.loadMoreLabel})]}):null,e.refreshing?c.jsxs("div",{className:"row-load-progress","aria-label":"Row loading progress",children:[c.jsx("div",{className:"row-load-progress-track",role:"progressbar","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":e.refreshProgressPercent??void 0,children:c.jsx("span",{style:{width:`${e.refreshProgressPercent??8}%`}})}),c.jsxs("span",{children:[e.refreshProgressPercent===null?e.refreshProgressText:`${Math.round(e.refreshProgressPercent)}% loaded`,c.jsx("button",{className:"icon-button",type:"button",onClick:()=>void e.onCancel(),"aria-label":"Cancel refresh",title:"Cancel refresh",children:c.jsx(dn,{size:13})})]})]}):null,c.jsx("span",{className:"sr-only",role:"status","aria-live":"polite",children:i})]})}const yn=[{value:"all",label:"All time"},{value:"today",label:"Today"},{value:"this-week",label:"This week"},{value:"last-7-days",label:"Last 7 days"},{value:"this-month",label:"This month"},{value:"custom",label:"Custom"}],Rr=[{value:"all",label:"All confidence"},{value:"cost-exact",label:"Exact cost"},{value:"cost-estimated",label:"Estimated cost"},{value:"cost-unpriced",label:"Unpriced cost"},{value:"credit-exact",label:"Exact credit"},{value:"credit-estimated",label:"Estimated credit"},{value:"credit-override",label:"Credit override"},{value:"credit-missing",label:"Missing credit"}];function ic({activeView:e,locationSearch:t,model:n,onUrlChange:a}){const r=xr(t),s=C.useMemo(()=>ua(n.calls.map(g=>g.model)),[n.calls]),i=C.useMemo(()=>ua(n.calls.map(g=>g.effort)),[n.calls]),o=r.dateStart||r.dateEnd?"custom":oc(r.datePreset),d=lc(r,o);if(e==="calls"||e==="call"||!n.calls.length)return null;function f(g){const b=new URL(window.location.href);g(b),a(b)}function h(g,b){f(w=>{g==="confidence"&&w.searchParams.delete("pricing"),!b||b==="all"?w.searchParams.delete(g):w.searchParams.set(g,b)})}function v(g){f(b=>{if(!g||g==="all"){b.searchParams.delete("date"),b.searchParams.delete("time"),b.searchParams.delete("from"),b.searchParams.delete("to");return}b.searchParams.set("date",g),b.searchParams.set("time",g),g!=="custom"&&(b.searchParams.delete("from"),b.searchParams.delete("to"))})}function u(g,b){f(w=>{b?(w.searchParams.set(g,b),w.searchParams.set("date","custom"),w.searchParams.set("time","custom")):(w.searchParams.delete(g),!w.searchParams.get("from")&&!w.searchParams.get("to")&&(w.searchParams.delete("date"),w.searchParams.delete("time")))})}function p(){f(g=>{for(const b of["model","effort","confidence","pricing","date","time","from","to"])g.searchParams.delete(b)})}return c.jsxs("section",{className:"global-filter-strip span-all","aria-label":"Dashboard filters",children:[c.jsxs("strong",{children:[c.jsx(Fs,{size:15}),"Filters"]}),c.jsxs("label",{children:[c.jsx("span",{children:"Model"}),c.jsxs("select",{"aria-label":"Global model filter",value:r.model||"all",onChange:g=>h("model",g.target.value),children:[c.jsx("option",{value:"all",children:"All models"}),s.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Effort"}),c.jsxs("select",{"aria-label":"Global effort filter",value:r.effort||"all",onChange:g=>h("effort",g.target.value),children:[c.jsx("option",{value:"all",children:"All effort"}),i.map(g=>c.jsx("option",{value:g,children:g},g))]})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Confidence"}),c.jsx("select",{"aria-label":"Global confidence filter",value:cc(r.confidence),onChange:g=>h("confidence",g.target.value),children:Rr.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))})]}),c.jsxs("label",{children:[c.jsx("span",{children:"Time"}),c.jsx("select",{"aria-label":"Global time filter",value:o,onChange:g=>v(g.target.value),children:yn.map(g=>c.jsx("option",{value:g.value,children:g.label},g.value))}),d?c.jsx("span",{className:"filter-status","data-state":d.state,"aria-live":"polite",children:d.label}):null]}),c.jsxs("label",{children:[c.jsx("span",{children:"Start"}),c.jsx("input",{"aria-label":"Global start date",type:"date",value:r.dateStart,onChange:g=>u("from",g.target.value)})]}),c.jsxs("label",{children:[c.jsx("span",{children:"End"}),c.jsx("input",{"aria-label":"Global end date",type:"date",value:r.dateEnd,onChange:g=>u("to",g.target.value)})]}),c.jsxs("button",{className:"toolbar-button",type:"button",disabled:!r.active,onClick:p,children:[c.jsx(dn,{size:15}),"Clear filters"]})]})}function ua(e){return Array.from(new Set(e.map(t=>t.trim()).filter(Boolean))).sort((t,n)=>t.localeCompare(n))}function oc(e){return yn.some(t=>t.value===e)?e:"all"}function cc(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":Rr.some(t=>t.value===e)?e:"all"}function lc(e,t){var r;const n=ha(e.dateStart),a=ha(e.dateEnd);if(n!==null&&a!==null&&n>a)return{label:"Invalid date range",state:"error"};if(t==="custom"&&(e.dateStart||e.dateEnd))return{label:uc(e.dateStart,e.dateEnd),state:"active"};if(t!=="all"){const s=((r=yn.find(o=>o.value===t))==null?void 0:r.label)??t,i=dc(t);return{label:i?`${s}: ${da(i.start)} to ${da(Qe(i.endExclusive,-1))}`:s,state:"active"}}return null}function uc(e,t){return e&&t?`Custom: ${e} to ${t}`:e?`Custom: from ${e}`:t?`Custom: through ${t}`:"Custom range"}function dc(e){const t=hc();if(e==="today")return{start:t,endExclusive:Qe(t,1)};if(e==="this-week"){const n=fc(t);return{start:n,endExclusive:Qe(n,7)}}return e==="last-7-days"?{start:Qe(t,-6),endExclusive:Qe(t,1)}:e==="this-month"?{start:new Date(t.getFullYear(),t.getMonth(),1),endExclusive:new Date(t.getFullYear(),t.getMonth()+1,1)}:null}function hc(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function fc(e){const t=e.getDay();return Qe(e,t===0?-6:1-t)}function Qe(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function da(e){const t=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${e.getFullYear()}-${t}-${n}`}function ha(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[t,n,a]=e.split("-").map(Number),r=new Date(t,n-1,a);return r.getFullYear()!==t||r.getMonth()!==n-1||r.getDate()!==a?null:r.getTime()}function mc(e){return Lr(e)&&e!=="call"}function on(e,t="overview"){return e==="insights"?"overview":Lr(e)?e:t}function fa(e=window.location.search,t="calls"){const n=new URLSearchParams(e).get("return"),a=on(n,t);return mc(a)?a:t}function ma(e=window.location.search){return new URLSearchParams(e).has("return")}function gc(e){var t,n;return((t=kr.find(a=>a.id===e))==null?void 0:t.label)??((n=Tr.find(a=>a.target===e))==null?void 0:n.label)??"Calls"}function ga(e,t=window.location.search){return new URLSearchParams(t).get("history")==="all"?"all":e}function pa(e,t=window.location.href){const n=new URL(t);return e==="all"?n.searchParams.set("history","all"):n.searchParams.delete("history"),n}const pc={investigator:["finding"],threads:["thread","expand","threads","thread_q","risk","thread_call_sort","thread_call_page"],"cache-context":["cache_thread"],reports:["report"],"usage-drain":["usage_plan","usage_effort","usage_subagents","usage_sample","usage_confidence","limit_window","limit_hypothesis"],diagnostics:["diagnostic_source","diagnostic_fact"],calls:["explore","detail","call_q","source","sort","direction","density","page"],call:["record","return","mode","max_entries","max_chars","include_tool_output","include_compaction_history"]};function kt(e,t,n=[]){const a=new Set([t,...Array.isArray(n)?n:[n]]);for(const[r,s]of Object.entries(pc))if(!a.has(r))for(const i of s)e.searchParams.delete(i)}function ba(e){let t=!1;return e.searchParams.get("view")==="insights"&&(e.searchParams.set("view","overview"),t=!0),e.searchParams.get("return")==="insights"&&(e.searchParams.set("return","overview"),t=!0),t}const Mr=[{key:"overview",title:"Overview",path:"/api/diagnostics/overview",refreshPath:"/api/diagnostics/overview/refresh"},{key:"toolOutput",title:"Tool Output",path:"/api/diagnostics/tool-output",refreshPath:"/api/diagnostics/tool-output/refresh"},{key:"commands",title:"Commands",path:"/api/diagnostics/commands",refreshPath:"/api/diagnostics/commands/refresh"},{key:"gitInteractions",title:"Git Interactions",path:"/api/diagnostics/git-interactions",refreshPath:"/api/diagnostics/git-interactions/refresh"},{key:"fileReads",title:"File Reads",path:"/api/diagnostics/file-reads",refreshPath:"/api/diagnostics/file-reads/refresh"},{key:"fileModifications",title:"File Modifications",path:"/api/diagnostics/file-modifications",refreshPath:"/api/diagnostics/file-modifications/refresh"},{key:"readProductivity",title:"Read Productivity",path:"/api/diagnostics/read-productivity",refreshPath:"/api/diagnostics/read-productivity/refresh"},{key:"concentration",title:"Concentration",path:"/api/diagnostics/concentration",refreshPath:"/api/diagnostics/concentration/refresh"},{key:"guidedSummary",title:"What Is Driving Usage?",path:"/api/diagnostics/guided-summary",refreshPath:"/api/diagnostics/guided-summary/refresh"},{key:"usageDrain",title:"Usage Drain",path:"/api/diagnostics/usage-drain",refreshPath:"/api/diagnostics/usage-drain/refresh"}],At=new Map,Ft=new Map;function bc(){At.clear(),Ft.clear()}async function eu(e,t,n={}){Cn(t);const a=Sc(e);return n.signal?Nt(a,t,n.signal):_c(Ft,Sn(e,t,n.cacheKey),()=>Nt(a,t))}async function tu(e,t={}){Cn(e);const n=await fetch(`/api/diagnostics/refresh?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":e.apiToken},cache:"no-store",signal:t.signal}),a=await Dt(n,"Diagnostic snapshot refresh"),r=a.sections??(jr(a)?await vc(e,await Pr(a,e,t),t.signal):{});At.set(_n(e),r);for(const[s,i]of Object.entries(r))Ft.set(Sn(s,e),i);return r}async function nu(e,t,n={}){Cn(t);const a=await fetch(`${e.refreshPath}?_=${Date.now()}`,{method:"POST",headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),r=await Dt(a,e.title),s=jr(r)?await wc(t,e,await Pr(r,t,n),n.signal):r,i=_n(t),o=At.get(i),d=o?await Promise.resolve(o):{};return At.set(i,{...d,[e.key]:s}),Ft.set(Sn(e.key,t),s),s}async function Pr(e,t,n){var r,s,i,o;let a=e;for((r=n.onProgress)==null||r.call(n,a);a.status==="pending"||a.status==="running";){const d=n.pollIntervalMs??((s=a.next)==null?void 0:s.poll_after_ms)??250;await yc(d,n.signal);const f=new URLSearchParams({job_id:a.job_id,_:String(Date.now())}),h=await fetch(`/api/diagnostics/refresh/status?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});a=await Dt(h,"Diagnostic refresh status"),(i=n.onProgress)==null||i.call(n,a)}if(a.status!=="completed")throw new Error(`Diagnostic refresh failed: ${((o=a.error)==null?void 0:o.code)??a.status}`);return a}async function vc(e,t,n){const a=await Promise.all(Mr.map(async r=>[r.key,await Nt(r,e,n)]));return Object.fromEntries(a)}async function wc(e,t,n,a){return Nt(t,e,a)}function jr(e){if(!e||typeof e!="object")return!1;const t=e;return t.schema==="codex-usage-tracker-analysis-job-v1"&&t.job_kind==="diagnostic-refresh"&&typeof t.job_id=="string"}function yc(e,t){return t!=null&&t.aborted?Promise.reject(t.reason??new DOMException("Aborted","AbortError")):e<=0?Promise.resolve():new Promise((n,a)=>{const r=()=>{window.clearTimeout(s),t==null||t.removeEventListener("abort",r),a((t==null?void 0:t.reason)??new DOMException("Aborted","AbortError"))},s=window.setTimeout(()=>{t==null||t.removeEventListener("abort",r),n()},e);t==null||t.addEventListener("abort",r,{once:!0})})}function _c(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function _n(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function Sn(e,t,n=""){return`snapshot:${_n(t)}:${n}:${e}`}function Sc(e){const t=Mr.find(n=>n.key===e);if(!t)throw new Error(`Unknown diagnostic snapshot: ${e}`);return t}async function Nt(e,t,n){const a=await fetch(`${e.path}?_=${Date.now()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n});return await Dt(a,e.title)}function Cn(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Dt(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(typeof n.error=="string"&&n.error)throw new Error(n.error);return n}const va=[{key:"facts",label:"Top Facts",title:"Top Diagnostic Facts",path:"/api/diagnostics/facts",limit:50},{key:"tools",label:"Tools",title:"Tool and Function Activity",path:"/api/diagnostics/tools",limit:25},{key:"compactions",label:"Compactions",title:"Compaction Activity",path:"/api/diagnostics/compactions",limit:25}],Ar=new Map,Nr=new Map;function Cc(){bc(),Ar.clear(),Nr.clear()}async function au(e,t,n={}){$r(t);const a=va.find(f=>f.key===e)??va[0],r=kc(n.sort??"uncached"),s=n.direction??"desc",i=Math.max(1,Math.round(n.limit??a.limit)),o=Math.max(0,Math.round(n.offset??0)),d=async()=>{const f=new URLSearchParams({limit:String(i),offset:String(o),sort:r,direction:s});Dr(f,"include_archived",n.includeArchived);const h=await fetch(`${a.path}?${f.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal});return await Ir(h,a.title)};return n.signal?d():Er(Ar,xc(a.key,t,i,o,r,s,n.cacheKey,n.includeArchived),d)}async function ru(e,t,n={}){$r(t);const a=Math.max(1,Math.round(n.limit??8)),r=Math.max(0,Math.round(n.offset??0)),s=n.sort??"tokens",i=n.direction??"desc",o=async()=>{const d=String(e.fact_type??""),f=String(e.fact_name??"");if(!d||!f)throw new Error("Diagnostic fact type and name are required.");const h=new URLSearchParams({fact_type:d,fact_name:f,limit:String(a),offset:String(r),sort:s,direction:i});Dr(h,"include_archived",n.includeArchived);const v=await fetch(`/api/diagnostics/fact-calls?${h.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":t.apiToken},cache:"no-store",signal:n.signal}),u=await Ir(v,"Diagnostic fact calls");return{calls:(u.rows??[]).map((p,g)=>pr(p,g)),rawPayload:u}};return n.signal?o():Er(Nr,Tc(e,t,a,r,s,i,n.cacheKey,n.includeArchived),o)}function Er(e,t,n){const a=e.get(t);if(a!==void 0)return Promise.resolve(a);const r=n().then(s=>(e.set(t,s),s)).catch(s=>{throw e.delete(t),s});return e.set(t,r),r}function Fr(e){return`${e.fileMode?"file":"live"}:${e.apiToken}`}function xc(e,t,n,a,r,s,i="",o){return["facts",e,Fr(t),i,o??"default",n,a,r,s].join(":")}function kc(e){return e==="total"?"tokens":e==="latest"?"time":e}function Tc(e,t,n,a,r,s,i="",o){return["fact-calls",Fr(t),i,o??"default",String(e.fact_type??""),String(e.fact_name??""),n,a,r,s].join(":")}function Dr(e,t,n){n!==void 0&&e.set(t,String(n))}function $r(e){if(e.fileMode)throw new Error("Diagnostic facts require localhost dashboard server.");if(!e.apiToken)throw new Error("Diagnostic facts require localhost dashboard API token.")}async function Ir(e,t){if(!e.ok)throw new Error(`${t} request failed with HTTP ${e.status}`);const n=await e.json();if(n.error)throw new Error(n.error);return n}const Lc=[{id:"usage-snapshot",endpoint:"/api/usage",dataClass:"snapshot",schema:"codex-usage-tracker-dashboard-v1"},{id:"overview-summary",endpoint:"/api/summary",dataClass:"aggregate",schema:"codex-usage-tracker-summary-v1"},{id:"overview-recommendations",endpoint:"/api/recommendations",dataClass:"aggregate",schema:"codex-usage-tracker-recommendations-v1"},{id:"calls",endpoint:"/api/calls",dataClass:"aggregate",schema:"codex-usage-tracker-calls-v1"},{id:"threads",endpoint:"/api/threads",dataClass:"aggregate",schema:"codex-usage-tracker-threads-v1"},{id:"thread-calls",endpoint:"/api/thread-calls",dataClass:"detail",schema:"codex-usage-tracker-thread-calls-v1"},{id:"investigator-agentic",endpoint:"/api/investigations/agentic",dataClass:"aggregate",schema:"codex-usage-tracker-agentic-investigation-v1"},{id:"investigator-walk",endpoint:"/api/investigations/walk",dataClass:"userAction",schema:"codex-usage-tracker-investigation-walk-v1"},{id:"diagnostics-facts",endpoint:"/api/diagnostics/facts",dataClass:"aggregate",schema:null},{id:"diagnostics-fact-calls",endpoint:"/api/diagnostics/fact-calls",dataClass:"detail",schema:null},{id:"diagnostics-dedupe",endpoint:"/api/diagnostics/dedupe",dataClass:"aggregate",schema:"codex-usage-tracker-dedupe-diagnostics-v1"},{id:"diagnostics-snapshot",endpoint:"/api/diagnostics/{snapshot}",dataClass:"aggregate",schema:null},{id:"compression-profile",endpoint:"/api/compression/profile",dataClass:"aggregate",schema:"codex-usage-tracker-compression-api-v1"},{id:"reports",endpoint:"/api/reports/pack",dataClass:"aggregate",schema:"codex-usage-tracker-reports-pack-v1"}],Rc=Lc,Mc=new Map(Rc.map(e=>[e.id,e])),Pc=15*6e4,jc=3e4,Or={snapshot:ot({persistedCache:"aggregate-only"}),aggregate:ot({persistedCache:"aggregate-only"}),detail:ot(),heavyJob:ot({cancellation:"shared-job",staleTime:1e3}),userAction:ot({retry:0,staleTime:0})};function Ac({sourceKey:e,sourceRevision:t}){return{sourceKey:wa(e,"local-api"),sourceRevision:wa(t,"unversioned")}}function Nc(e,t,n={},...a){return["dashboard",e.id,t.sourceKey,t.sourceRevision,Dc(n),...a]}function Ec(e){return["dashboard",e.id]}function Fc(e){const t=Mc.get(e);if(!t)throw new Error(`Unknown dashboard query definition: ${e}`);return t}function Ur(e){const t=Or[e];return{gcTime:t.gcTime,refetchOnReconnect:t.refetchOnReconnect,refetchOnWindowFocus:t.refetchOnWindowFocus,retry:t.retry,staleTime:t.staleTime}}function su({enabled:e,hasData:t,isError:n,isFetching:a,isPending:r}){return e?t?a?"updating":"ready":n?"error":a||r?"loading":"waiting":"waiting"}function iu(e){const t=e.filter(a=>a==="ready"||a==="updating").length,n=e.length;return{ready:t,total:n,percent:n===0?100:Math.round(t/n*100),loading:e.filter(a=>a==="loading").length,errors:e.filter(a=>a==="error").length}}function Dc(e){return{historyScope:e.historyScope??"active",loadWindow:e.loadWindow??"all",limit:e.limit??null,since:e.since??""}}function wa(e,t){return(e==null?void 0:e.trim())||t}function ot(e={}){return{staleTime:jc,gcTime:Pc,retry:1,refetchOnReconnect:!1,refetchOnWindowFocus:!1,cancellation:"observer",persistedCache:"none",...e}}const $c=new Set(["command_text","content_fragment","content_fragments","excerpt","indexed_content","indexed_fragment","indexed_fragments","prompt","raw_context","raw_output","snippet","tool_output"]),Ic=new Set(["includes_indexed_content","includes_raw_fragment","includes_raw_fragments","indexed_content_included","raw_content_included","raw_context_included"]),Oc=new Set(["codex-usage-tracker-context-v1"]);function ya(e){return cn(e,new WeakSet)}function cn(e,t){if(!e||typeof e!="object")return!0;if(t.has(e))return!1;t.add(e);const n=Array.isArray(e)?e.every(a=>cn(a,t)):Object.entries(e).every(([a,r])=>{const s=a.toLowerCase();return $c.has(s)||Ic.has(s)&&r===!0||s==="schema"&&typeof r=="string"&&Oc.has(r)?!1:cn(r,t)});return t.delete(e),n}const Uc="codexUsageDashboard",Vc=1,Y="usageSnapshots",Kc=6,qc=10080*60*1e3,Hc={async read(e){if(!e.sourceRevision)return null;try{const t=await Sa();if(!t)return null;const n=await Vr(t.transaction(Y,"readonly").objectStore(Y).get(_a(e)));return!n||n.sourceRevision!==e.sourceRevision||Date.now()-n.storedAt>qc?null:ya(n.payload)?n.payload:(await Wc(t,n.cacheKey),null)}catch{return null}},async write(e,t){if(!(!e.sourceRevision||!ya(t)))try{const n=await Sa();if(!n)return;const a=n.transaction(Y,"readwrite");a.objectStore(Y).put({...e,cacheKey:_a(e),payload:t,storedAt:Date.now()}),await xn(a),await Bc(n)}catch{}}};async function Wc(e,t){const n=e.transaction(Y,"readwrite");n.objectStore(Y).delete(t),await xn(n)}function _a(e){const{historyScope:t,loadWindow:n,limit:a,since:r}=e.scope;return JSON.stringify([e.sourceKey,t,n,a,r])}function Sa(){return typeof indexedDB>"u"?Promise.resolve(null):new Promise(e=>{const t=indexedDB.open(Uc,Vc);t.onupgradeneeded=()=>{t.result.objectStoreNames.contains(Y)||t.result.createObjectStore(Y,{keyPath:"cacheKey"})},t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)})}function Vr(e){return new Promise((t,n)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>n(e.error??new Error("IndexedDB request failed"))})}function xn(e){return new Promise((t,n)=>{e.oncomplete=()=>t(),e.onerror=()=>n(e.error??new Error("IndexedDB transaction failed")),e.onabort=()=>n(e.error??new Error("IndexedDB transaction aborted"))})}async function Bc(e){const t=e.transaction(Y,"readonly"),a=(await Vr(t.objectStore(Y).getAll())).sort((i,o)=>o.storedAt-i.storedAt).slice(Kc);if(!a.length)return;const r=e.transaction(Y,"readwrite"),s=r.objectStore(Y);a.forEach(i=>s.delete(i.cacheKey)),await xn(r)}const Qc={kind:"production",load:Lo},zc="codexUsageDashboardRuntimeMetadata",Gc=2048,ln=Fc("usage-snapshot"),Kr={all:Ec(ln),snapshot:(e,t,n)=>Nc(ln,Ac({sourceKey:e,sourceRevision:t}),n)};function Jc(){return new Ri({defaultOptions:{queries:{...Ur("aggregate")}}})}const kn=Jc();async function Zc({currentPayload:e,historyScope:t,loadWindow:n,loadLimit:a,since:r=null,onProgress:s,queryClient:i=kn,refresh:o=!1,snapshotStore:d=Hc,transport:f=Qc}){const h=Hi(a,t,r,n),v=Tn(e),u=Kr.snapshot(v.sourceKey,v.sourceRevision,h);!i.getQueryData(u)&&nl(e,h)&&i.setQueryData(u,e),o&&await i.invalidateQueries({queryKey:u,exact:!0});const p=Ca(e,h),g=await i.fetchQuery({queryKey:u,...Ur(ln.dataClass),queryFn:async({signal:b})=>{var R;const w=!o&&p?await d.read(p):null;if(w)return s==null||s({status:"completed",phase:"loading_rows",message:"Loaded cached dashboard snapshot",completed:Number(w.loaded_row_count??((R=w.rows)==null?void 0:R.length)??0),total:Number(w.total_available_rows??w.loaded_row_count??0),percent:100}),w;const T=await f.load(e,{refresh:o,limit:Wi(h),includeArchived:h.historyScope==="all",loadWindow:n,since:h.since,onProgress:s,signal:b}),N=p?{...p,sourceRevision:String(T.latest_refresh_at??p.sourceRevision)}:Ca(T,h);return N&&await d.write(N,T),T},staleTime:o?0:Or.snapshot.staleTime});return tl(el(g,h)),g}function Ca(e,t){if(!(e!=null&&e.api_token))return null;const n=String(e.latest_refresh_at??"");return n?{sourceKey:qr(e),sourceRevision:n,scope:t}:null}async function Xc(e=kn){await e.cancelQueries({queryKey:Kr.all})}function Yc(e){return yi(e)||or(e)}function el(e,t){return{schema:"codex-usage-dashboard-runtime-v1",...Tn(e),scope:t,updatedAt:Date.now()}}function Tn(e){return{sourceKey:qr(e),sourceRevision:al(e)}}function tl(e,t=rl()){if(t)try{const n=JSON.stringify(e);n.length<=Gc&&t.setItem(zc,n)}catch{}}function nl(e,t){var o;if(!e||!(((o=e.rows)==null?void 0:o.length)??0))return!1;const n=ct(e),a=t.limit===null?n===0:n===t.limit,r=(e.since??null)===t.since,s=mn(e)===t.loadWindow,i=e.include_archived||e.history_scope==="all-history"?"all":"active";return a&&r&&s&&i===t.historyScope}function qr(e){const t=e,n=Number((t==null?void 0:t.payload_cache_version)??0),a=String((t==null?void 0:t.payload_cache_key)??(e!=null&&e.api_token?"live":"static"));return`${n}:${a}`}function al(e){return String((e==null?void 0:e.latest_refresh_at)??"unversioned")}function rl(){try{return typeof window>"u"?null:window.sessionStorage}catch{return null}}const sl=new Set(["duplicate_cumulative_total"]);function il({canUseLiveApi:e,payload:t,shellI18n:n}){const a=ol(t,e,n);return c.jsxs("section",{className:"environment-status","aria-label":n.t("aria.dashboard_status","Dashboard status"),children:[c.jsx("span",{className:"environment-status-title",children:n.t("aria.dashboard_status","Dashboard status")}),c.jsx("div",{className:"environment-status-grid",children:a.map(r=>c.jsx("span",{className:"environment-chip","data-state":r.state,title:r.title,children:r.label},r.label))})]})}function ol(e,t,n){const a=hl(e==null?void 0:e.parser_diagnostics,n);return[{label:n.t("badge.unofficial_project","Unofficial project"),state:"neutral",title:n.t("badge.unofficial_project_title","Codex Usage Tracker is independent and is not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI. OpenAI and Codex are trademarks of OpenAI.")},{label:t?`${n.t("badge.live","Live")} API`:n.t("badge.static","Static"),state:t?"ready":"warn",title:t?"Local API token present for refresh actions.":"Static embedded snapshot; live refresh is unavailable."},ll(e,n),ul(e,n),dl(e,n),cl(e),...a?[a]:[]]}function cl(e){const t=e==null?void 0:e.dedupe,n=Number((t==null?void 0:t.excluded_copied_rows)||0),a=Number((t==null?void 0:t.canonical_rows)||0),r=Number((t==null?void 0:t.physical_rows)||0);return{label:`Deduped · ${n.toLocaleString()} copied excluded`,state:"ready",title:`Billable totals use ${a.toLocaleString()} canonical rows while preserving ${r.toLocaleString()} physical source rows.`}}function ll(e,t){var s;const n=!!(e!=null&&e.pricing_configured),a=((s=e==null?void 0:e.pricing_snapshot_warning)==null?void 0:s.trim())??"",r=Hr(e==null?void 0:e.pricing_source);return{label:n?t.t("badge.costs","Costs"):t.t("badge.no_costs","No costs"),state:n?a?"warn":"ready":"missing",title:n?[r||"Pricing configured",a].filter(Boolean).join(" - "):t.t("pricing.configure_hint","Run codex-usage-tracker update-pricing to configure estimated costs.")}}function ul(e,t){var s,i;const n=((s=e==null?void 0:e.allowance_error)==null?void 0:s.trim())??"",a=((i=e==null?void 0:e.rate_card_error)==null?void 0:i.trim())??"",r=Hr(e==null?void 0:e.allowance_source)||"Codex credit rates";return n?{label:t.t("state.allowance_config_error","Allowance config error"),state:"missing",title:`Config error: ${n}`}:a?{label:"Rate-card error",state:"missing",title:`Rate-card error: ${a}`}:e!=null&&e.allowance_configured?{label:t.t("state.allowance_configured","Allowance configured"),state:"ready",title:r}:e!=null&&e.rate_card_configured?{label:"Credit rates loaded",state:"ready",title:r}:{label:t.t("action.set_limits","Set limits"),state:"warn",title:"No local allowance windows are configured."}}function dl(e,t){const n=e==null?void 0:e.project_metadata_privacy,a=(n==null?void 0:n.mode)||(e==null?void 0:e.privacy_mode)||"normal",r=a==="normal",s=[n!=null&&n.cwd_redacted?"cwd redacted":"",n!=null&&n.project_names_redacted?"project names redacted":"",n!=null&&n.git_remote_label_hidden?"git remote hidden":"",n!=null&&n.relative_cwd_hidden?"relative cwd hidden":"",n!=null&&n.git_branch_hidden?"git branch hidden":"",n!=null&&n.tags_hidden?"tags hidden":""].filter(Boolean);return{label:r?t.t("badge.metadata_normal","Metadata normal"):Wr(t.t("badge.metadata_mode","Metadata {mode}"),{mode:a}),state:r?"ready":"warn",title:r?"Project metadata is shown normally.":[`Metadata mode: ${a}`,...s].join(" - ")}}function hl(e,t){const n=Object.entries(e??{}).filter(([s,i])=>Number(i||0)>0&&!sl.has(s));if(!n.length)return null;const a=n.reduce((s,[,i])=>s+Number(i||0),0),r=n.map(([s,i])=>`${s}=${Number(i||0)}`).join(", ");return{label:t.t("badge.parser_warnings","Parser warnings"),state:"missing",title:Wr(t.t("parser.warnings_title","Latest refresh reported {count} parser diagnostics: {entries}. Run codex-usage-tracker inspect-log to investigate schema drift."),{count:a.toLocaleString(),entries:r})}}function Hr(e){if(!e)return"";if(typeof e=="string")return e;const t=e.label??e.name??e.type??e.path??"";return typeof t=="string"?t:""}function Wr(e,t){return e.replace(/\{([a-zA-Z0-9_]+)\}/g,(n,a)=>t[a]??n)}async function xa(e){var n;if((n=navigator.clipboard)!=null&&n.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly","readonly"),t.style.position="fixed",t.style.left="-9999px",t.style.top="0",document.body.appendChild(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}const fl={"highest-cost":"Highest Cost Threads","context-bloat":"Context Bloat","cache-misses":"Cache Misses","pricing-gaps":"Pricing Gaps","codex-credits":"Codex Credits","reasoning-spike":"Reasoning Spike"};function ou(e,t){return t==="context-bloat"?Number(e.contextWindowPct??0)>=60||e.totalTokens>=2e5:t==="cache-misses"?e.signal==="cache-risk"||e.cachedPct<30||e.uncachedInput>=5e4:t==="pricing-gaps"?e.pricingEstimated||!Number.isFinite(e.cost):t==="codex-credits"?e.credits>0:t==="reasoning-spike"?e.reasoningOutput>0:!0}function ml(e){return fl[e]??e}const gl=se(()=>O(()=>import("./OverviewPage.js"),__vite__mapDeps([49,1,2,34,4,20,21,9,10,31,32,6,16,17,18,45,22,11,12,13,14,35,23,24,25,26,50])),"OverviewPage"),pl=se(()=>O(()=>import("./InvestigatorPage.js"),__vite__mapDeps([51,1,2,34,4,6,41,7,20,21,9,10,16,17,18,45,22,11,12,13,23,24,38,25,26,52])),"InvestigatorPage"),bl=se(()=>O(()=>import("./CompressionLabPage.js"),__vite__mapDeps([53,1,2,34,4,6,9,10,17,25,26,12,54])),"CompressionLabPage"),vl=se(()=>O(()=>import("./ExploreRoutePage.js"),__vite__mapDeps([55,1,2,44,3,4,5,6,7,14,29,33,19,45,22,11,12,13,35,23,24,34,46,47,38,25,26,48,8,9,10,56])),"ExploreRoutePage"),wl=se(()=>O(()=>import("./CallInvestigatorPage.js"),__vite__mapDeps([57,1,2,46,33,19,37,38,47,25,26,12])),"CallInvestigatorPage"),yl=se(()=>O(()=>import("./ThreadsPage.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27])),"ThreadsPage"),_l=se(()=>O(()=>import("./UsageDrainPage.js"),__vite__mapDeps([36,1,2,34,4,20,21,9,10,16,17,18,24,37,38,25,26,12,39])),"UsageDrainPage"),Sl=se(()=>O(()=>import("./CacheContextPage.js"),__vite__mapDeps([28,1,2,29,30,22,31,32,6,33,19,20,21,9,10,23,34,4,3,5,7,15,35,24,25,26,12])),"CacheContextPage"),Cl=se(()=>O(()=>import("./DiagnosticsPage.js"),__vite__mapDeps([40,1,2,29,33,19,20,21,9,10,23,24,41,4,6,7,34,3,25,26,12])),"DiagnosticsPage"),xl=se(()=>O(()=>import("./ReportsPage.js"),__vite__mapDeps([42,1,2,34,4,6,33,19,20,21,9,10,16,17,18,30,22,35,23,24,25,26,12,43])),"ReportsPage"),kl=se(()=>O(()=>import("./SettingsPage.js"),__vite__mapDeps([58,1,2,33,19,32,38,47,17,25,26,12,59])),"SettingsPage");function Tl(e){return c.jsx(C.Suspense,{fallback:c.jsx(Rl,{activeView:e.activeView}),children:Ll(e)})}function Ll(e){const{activePreset:t,activeRecordId:n,activeView:a,autoRefreshEnabled:r,applicationI18n:s,backFromCallInvestigator:i,callBackLabel:o,canLoadAllRows:d,canUseLiveApi:f,contextRuntime:h,copyCallInvestigatorLink:v,dashboardPayload:u,globalFilters:p,globalQuery:g,hasMoreRows:b,historyScope:w,loadWindow:T,loadAllRows:N,loadedRowCount:R,loadLimit:_,loadMoreRows:L,scopeSince:y,model:k,navigateView:j,onRefresh:E,openCallInvestigator:F,refreshing:me,refreshState:vt,setContextApiEnabled:wt,sourceIdentity:I,totalAvailableRows:at}=e;switch(a){case"overview":return c.jsx(gl,{model:k,contextRuntime:h,sourceKey:I.sourceKey,sourceRevision:I.sourceRevision,onRefresh:E,globalQuery:g,runtime:{historyScope:w,loadLimit:_,loadWindow:T,loadedRowCount:R,scopeSince:y,totalAvailableRows:at},refreshing:me,canLoadMoreRows:f&&b,onLoadMoreRows:L,onOpenInvestigator:F,onCopyCallLink:v,onNavigateView:j,globalFilters:p});case"investigator":return c.jsx(pl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceKey:I.sourceKey,sourceRevision:I.sourceRevision,onOpenInvestigator:F,onCopyCallLink:v,onNavigateView:j});case"compression-lab":return c.jsx(bl,{contextRuntime:h,includeArchived:w==="all",since:y,sourceKey:I.sourceKey,sourceRevision:I.sourceRevision});case"calls":return c.jsx(vl,{model:k,globalQuery:g,activePreset:t,onRefresh:E,contextRuntime:h,includeArchived:w==="all",scopeSince:y,sourceKey:I.sourceKey,sourceRevision:I.sourceRevision,onContextApiEnabledChange:wt,onOpenInvestigator:F,onCopyCallLink:v,onNavigateView:j});case"call":return c.jsx(wl,{model:k,recordId:n,contextRuntime:h,onContextApiEnabledChange:wt,onNavigateRecord:F,onCopyCallLink:v,onBackToCalls:i,backLabel:o});case"threads":return c.jsx(yl,{model:k,globalQuery:g,onOpenInvestigator:F,onCopyCallLink:v,globalFilters:p,contextRuntime:h,includeArchived:w==="all",sourceKey:I.sourceKey,sourceRevision:I.sourceRevision,onNavigateView:j});case"usage-drain":return c.jsx(_l,{model:k,contextRuntime:h,includeArchived:w==="all",sourceRevision:I.sourceRevision,onOpenInvestigator:F,onCopyCallLink:v});case"cache-context":return c.jsx(Sl,{model:k,contextRuntime:h,includeArchived:w==="all",scopeSince:y,sourceKey:I.sourceKey,sourceRevision:I.sourceRevision,onOpenInvestigator:F,onCopyCallLink:v});case"diagnostics":return c.jsx(Cl,{model:k,contextRuntime:h,includeArchived:w==="all",sourceKey:I.sourceKey,sourceRevision:I.sourceRevision,rowLoadControls:{loadedRowCount:R,totalAvailableRows:at,canLoadMoreRows:f&&b,canLoadAllRows:d,refreshing:me,onLoadMoreRows:L,onLoadAllRows:N},onOpenInvestigator:F,onCopyCallLink:v,globalFilters:p});case"reports":return c.jsx(xl,{model:k,refreshState:vt,includeArchived:w==="all",loadWindow:T,loadLimit:_,sourceKey:I.sourceKey,sourceRevision:I.sourceRevision,onOpenInvestigator:F,onCopyCallLink:v});case"settings":return c.jsx(kl,{model:k,payload:u,historyScope:w,loadWindow:T,loadLimit:_,scopeSince:y,loadedRowCount:R,totalAvailableRows:at,canUseLiveApi:f,autoRefreshEnabled:r,refreshState:vt,applicationI18n:s})}}function Rl({activeView:e}){return c.jsxs("section",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:["Loading ",e.replace("-"," "),"..."]})}const ka=1e4,Ml={1:"overview",2:"calls",3:"threads",4:"diagnostics"},Pl=new Set(["call","compression-lab","diagnostics","investigator"]);function Br(e){return!Pl.has(e)}function jl(e){return e instanceof Element?!!e.closest('input, select, textarea, button, [contenteditable="true"]'):!1}function Qr(){var Vn;const e=C.useRef(null),t=C.useMemo(()=>To(),[]),[n,a]=C.useState(t),[r,s]=C.useState(()=>ia(t)),[i,o]=C.useState(()=>{const m=new URLSearchParams(window.location.search);return on(m.get("view"))}),[d,f]=C.useState(()=>new URLSearchParams(window.location.search).get("record")??""),[h,v]=C.useState(()=>fa()),[u,p]=C.useState(()=>ma()),[g,b]=C.useState(()=>new URLSearchParams(window.location.search).get("q")??""),[w,T]=C.useState(()=>new URLSearchParams(window.location.search).get("preset")??""),[N,R]=C.useState(()=>window.location.search),[_,L]=C.useState("Stored snapshot loaded just now"),[y,k]=C.useState(null),[j,E]=C.useState(!1),[F,me]=C.useState(!1),[vt,wt]=C.useState(!1),[I,at]=C.useState(()=>Gs(t)),$t=C.useRef(!1),[G,Ln]=C.useState(()=>je(ct(t),500)),[Ue,yt]=C.useState(()=>je(ct(t),500)),[q,Rn]=C.useState(()=>Bi(t)),[J,_t]=C.useState(()=>ga(Wt(t))),[Mn,Pn]=C.useState(r.contextRuntime.contextApiEnabled),H=!!(n!=null&&n.api_token),zr=C.useMemo(()=>Tn(n),[n]),A=C.useMemo(()=>$a(n,I),[n,I]),jn=C.useMemo(()=>({...r.contextRuntime,contextApiEnabled:Mn}),[Mn,r.contextRuntime]),Gr=C.useMemo(()=>Bo(r,J,N),[J,N,r]),An=i==="calls"||i==="call"?r:Gr,rt=Br(i),It=je(Ue,G,500),ge=Math.max(0,Number((n==null?void 0:n.loaded_row_count)??((Vn=n==null?void 0:n.rows)==null?void 0:Vn.length)??r.calls.length??0)),Ve=Math.max(0,Number((n==null?void 0:n.total_available_rows)??ge)),Jr=Ue!==G,Nn=Gi({currentLimit:G,loadedRows:ge,pendingLimit:Ue}),Zr=Math.min(It,Nn),En=!!(n!=null&&n.has_more)||Ve>0&&ge{const m=new URL(window.location.href);ba(m)&&Ke(m)},[]),C.useEffect(()=>{function m(){const S=window.location.search,M=new URLSearchParams(S);o(on(M.get("view"))),f(M.get("record")??""),v(fa(S)),p(ma(S)),b(M.get("q")??""),T(M.get("preset")??""),_t(ga(Wt(n),S)),R(S)}return window.addEventListener("popstate",m),()=>window.removeEventListener("popstate",m)},[n]),C.useEffect(()=>{function m(S){var oe;if(jl(S.target))return;if(S.key==="/"){S.preventDefault(),(oe=e.current)==null||oe.focus();return}const M=Ml[S.key];M&&(S.preventDefault(),st(M))}return window.addEventListener("keydown",m),()=>window.removeEventListener("keydown",m)},[]),C.useEffect(()=>{function m(){wt(window.scrollY>320)}return m(),window.addEventListener("scroll",m,{passive:!0}),()=>window.removeEventListener("scroll",m)},[]);function rs(m){const S=i==="call"?h:i;v(S),p(i==="call"?u:!0),o("call"),f(m);const M=new URL(window.location.href);kt(M,i,i==="call"?h:[]),M.searchParams.set("view","call"),M.searchParams.set("record",m),M.searchParams.set("return",S),$n(M)}function ss(){st(h)}function is(m){b(m),T("");const S=new URL(window.location.href);S.searchParams.delete("preset"),m?S.searchParams.set("q",m):S.searchParams.delete("q"),Ke(S)}async function ie(m={}){var St;if(j)return;$t.current=!0;const S=m.loadLimit??G,M=m.loadWindow??q,oe=Ht(M),pe=m.historyScope??J,ee=m.refresh??!0,Ot=!!(n!=null&&n.refresh_jobs_available);E(!0),k(Ot?{status:"running",phase:ee?"refreshing_index":"loading_rows",message:`${ee?"Refreshing":"Loading"} ${Re(M,S)}`}:null),L(`${ee?"Refreshing index for":"Loading"} ${Re(M,S)}...`);let qe=!1;try{const z=await Zc({currentPayload:n,refresh:ee,loadLimit:S,loadWindow:M,since:oe,historyScope:pe,onProgress:Vt=>{qe||(qe=Vt.message==="Loaded cached dashboard snapshot"),k(Vt),L(Yn(Vt,pe))}});Cc(),a(z),s(ia(z)),Pn(!!z.context_api_enabled);const ke=M==="rows"?je(ct(z,S),S):S;Ln(ke),yt(ke),Rn(M);const Kn=Wt(z,pe);_t(Kn),zi(ke,Kn,M);const Ut=z.loaded_row_count??((St=z.rows)==null?void 0:St.length)??0,qn=z.total_available_rows??Ut;L(M==="rows"?`${qe?"Cache hit; l":ee?"Refreshed index; l":"L"}oaded ${Ut.toLocaleString()} of ${qn.toLocaleString()} calls from ${Re(M,ke)}`:`${qe?"Cache hit; ":ee?"Refreshed index; ":""}${Re(M,ke)} analysis ready across ${qn.toLocaleString()} calls; ${Ut.toLocaleString()} detail rows cached`)}catch(z){if(k(null),Yc(z)){L("Refresh cancelled; stored snapshot remains visible");return}const ke=new Date().toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});L(`${to(z)} Stored snapshot kept at ${ke}`)}finally{k(null),E(!1)}}async function os(){await Xc(),k(null),E(!1),L("Refresh cancelled; stored snapshot remains visible")}C.useEffect(()=>{document.documentElement.lang=A.language,document.documentElement.dir=A.direction},[A.direction,A.language]),C.useEffect(()=>{var z;const m=Number((n==null?void 0:n.total_available_rows)??0),S=Number((n==null?void 0:n.loaded_row_count)??((z=n==null?void 0:n.rows)==null?void 0:z.length)??0),M=Qi(),oe=(M==null?void 0:M.historyScope)??J,pe=(M==null?void 0:M.loadLimit)??G,ee=(M==null?void 0:M.loadWindow)??q,Ot=mn(n),qe=oe!==J||ee!==Ot||ee==="rows"&&pe!==ct(n),St=S>0;!H||!qe&&St||m<=0||j||$t.current||($t.current=!0,qe&&(_t(oe),Ln(pe),yt(pe),Rn(ee),Ke(pa(oe))),ie({refresh:!1,historyScope:oe,loadLimit:pe,loadWindow:ee}))},[H,n,J,G,q,j]),C.useEffect(()=>{!H&&F&&me(!1)},[F,H]),C.useEffect(()=>{if(!F||!H||!rt)return;const m=window.setInterval(()=>{ie()},ka);return()=>window.clearInterval(m)},[F,rt,H,n,J,G,q,j]),C.useEffect(()=>{if(!F||!H||!rt)return;function m(){document.visibilityState==="visible"&&ie()}return document.addEventListener("visibilitychange",m),()=>document.removeEventListener("visibilitychange",m)},[F,rt,H,n,J,G,q,j]);function In(m){const S=m.trim();yt(Math.max(1,pt(S===""?Number.NaN:Number(S))))}function cs(m){In(m)}function ls(){ie({refresh:!1,loadLimit:Ue,loadWindow:"rows"})}function us(){ie({refresh:!1,loadWindow:"all"})}function On(){yt(Fn),ie({refresh:!1,loadLimit:Fn,loadWindow:q})}function ds(m){m!==q&&ie({refresh:!1,loadWindow:m})}function hs(m){const S=m==="all"?"all":"active";_t(S),Ke(pa(S)),ie({refresh:!1,historyScope:S})}function fs(m){if(me(m),m){if(!rt){L("Auto refresh pauses on this evidence-heavy view");return}L(`Auto refresh every ${ka/1e3}s`),ie()}else L("Auto refresh paused")}function ms(m){at(m),Js(m)}async function gs(){try{const m=new URL(window.location.href);if(ba(m),kt(m,i,i==="call"?h:[]),!await xa(m.toString()))throw new Error("Clipboard unavailable");L("Copied current view link")}catch{L("Copy unavailable in browser")}}async function ps(m){try{const S=new URL(window.location.href);kt(S,i,i==="call"?h:[]);const M=i==="call"?h:i;if(S.searchParams.set("view","call"),S.searchParams.set("record",m),S.searchParams.set("return",M),!await xa(S.toString()))throw new Error("Clipboard unavailable");L("Copied call investigator link")}catch{L("Copy unavailable in browser")}}async function bs(){const m=await Xi(i,An,{contextRuntime:jn,historyScope:J,loadWindow:q,loadLimit:G,scopeSince:(n==null?void 0:n.since)??Ht(q),loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:F,refreshState:_},g,w);if(!m.rowCount){L(`No ${m.label} to export`);return}Fi(m.filename,m.csv),L(`Exported ${m.rowCount} ${m.label}`)}function vs(){T("");const m=new URL(window.location.href);m.searchParams.delete("preset"),Ke(m),L("Investigation preset cleared")}function ws(){window.scrollTo({top:0,behavior:"smooth"})}return c.jsx(io,{value:A,children:c.jsxs("div",{className:"app-shell","data-dashboard-localization-root":!0,children:[c.jsxs("aside",{className:"sidebar",children:[c.jsxs("div",{className:"brand",children:[c.jsx("div",{className:"brand-mark",children:c.jsx(Ks,{size:22})}),c.jsxs("div",{children:[c.jsx("strong",{children:"Codex Usage Tracker"}),c.jsx("span",{children:A.t("dashboard.eyebrow","Local telemetry console")})]})]}),c.jsxs("div",{className:"local-pill",children:[c.jsx("span",{"aria-hidden":"true"}),"Local data only"]}),c.jsx(il,{payload:n,canUseLiveApi:H,shellI18n:A}),c.jsx("nav",{className:"primary-nav","aria-label":"Primary",children:kr.map(m=>{const S=m.icon,M=i===m.id||i==="call"&&m.id==="calls";return c.jsxs("button",{type:"button","aria-pressed":M,className:M?"active":"",onClick:()=>st(m.id),children:[c.jsx(S,{size:18}),c.jsx("span",{children:A.navLabel(m.id,m.label)})]},m.id)})}),c.jsxs("div",{className:"secondary-block",role:"group","aria-label":"Quick Links",children:[c.jsx("span",{children:"Quick Links"}),Tr.map(m=>{const S=m.icon;return c.jsxs("button",{type:"button",onClick:()=>st(m.target),children:[c.jsx(S,{size:16}),m.label]},m.label)})]})]}),c.jsxs("main",{className:"workspace",children:[c.jsxs("div",{className:"unofficial-banner",role:"note","aria-label":"Unofficial project notice",children:[c.jsx(Us,{size:16}),c.jsxs("span",{children:[c.jsx("strong",{children:"Unofficial project."})," Not made by, affiliated with, endorsed by, sponsored by, or supported by OpenAI."]})]}),c.jsxs("header",{className:"topbar","aria-label":"Dashboard toolbar",children:[c.jsxs("label",{className:"global-search",children:[c.jsx("span",{className:"sr-only",children:A.t("filter.search","Search dashboard")}),c.jsx("input",{ref:e,"aria-label":A.t("filter.search","Search dashboard"),value:g,onChange:m=>is(m.target.value),placeholder:A.t("filter.search_placeholder","Search calls, threads, models, diagnostics...")})]}),c.jsxs("div",{className:"topbar-actions",children:[c.jsxs("div",{className:"topbar-scope-controls",children:[A.languages.length>1?c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("language.label","Language")}),c.jsx("select",{"data-localization-skip":"true","aria-label":A.t("language.label","Language"),value:A.language,onChange:m=>ms(m.target.value),children:A.languages.map(m=>c.jsx("option",{value:m.code,children:m.native_name||m.english_name||m.code},m.code))})]}):null,c.jsxs("label",{className:"topbar-select",children:[c.jsx("span",{children:A.t("nav.history","History")}),c.jsxs("select",{"aria-label":"History scope",title:Dn,value:J,onChange:m=>hs(m.target.value),disabled:j||!H,children:[c.jsx("option",{value:"active",children:A.t("option.active_sessions_only","Active")}),c.jsx("option",{value:"all",children:A.t("option.all_history","All history")})]}),c.jsx("small",{className:"sr-only",children:Dn})]})]}),c.jsx(sc,{canUseLiveApi:H,finitePendingLoadLimit:It,hasMoreRows:En,loadLabel:A.t("nav.load","Load"),loadMoreLabel:A.t("button.load_more","Load more"),loadWindow:q,loadedRowCount:ge,pendingLoadLimit:Ue,refreshProgressPercent:ts,refreshProgressText:ns,refreshing:j,rowLimitChanged:Jr,rowLimitSliderMax:Nn,rowLimitSliderValue:Zr,rowLoadModeLabel:Yr,rowLoadStatus:Xr,totalAvailableRows:Ve,onApply:ls,onCancel:os,onDraftChange:In,onLoadMore:On,onSliderChange:cs,onWindowChange:ds}),c.jsxs("div",{className:"topbar-meta",children:[c.jsxs("div",{className:"topbar-statuses",children:[w?c.jsxs("button",{className:"toolbar-button",type:"button",onClick:vs,children:[c.jsx(dn,{size:15}),A.t("button.clear","Clear")," ",ml(w)]}):null,c.jsxs("label",{className:"topbar-toggle",children:[c.jsx("input",{"aria-label":"Auto refresh",type:"checkbox",checked:F,onChange:m=>fs(m.target.checked),disabled:j||!H}),c.jsx("span",{children:"Auto"})]})]}),c.jsxs("div",{className:"topbar-icon-actions",children:[c.jsx("button",{className:"icon-button",type:"button",onClick:gs,"aria-label":A.t("button.copy_link","Copy link"),title:A.t("button.copy_link","Copy link"),children:c.jsx(js,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:bs,"aria-label":A.t("button.export_csv","Export CSV"),title:A.t("button.export_csv","Export CSV"),children:c.jsx(Ns,{size:17})}),c.jsx("button",{className:"icon-button",type:"button",onClick:Un,"aria-label":A.t("button.refresh","Refresh"),title:A.t("button.refresh","Refresh"),disabled:j,children:c.jsx(Is,{size:17})})]})]})]})]}),c.jsx("p",{className:"sr-only",role:"status","aria-live":"polite",children:_}),c.jsx(Tl,{activeView:i,model:An,navigateView:st,onRefresh:Un,refreshState:_,globalQuery:g,activePreset:w,activeRecordId:d,contextRuntime:jn,setContextApiEnabled:Pn,openCallInvestigator:rs,copyCallInvestigatorLink:ps,callBackLabel:u?`Back to ${gc(h)}`:A.t("button.back_to_dashboard","Back to dashboard"),backFromCallInvestigator:ss,dashboardPayload:n,sourceIdentity:zr,historyScope:J,loadWindow:q,scopeSince:(n==null?void 0:n.since)??Ht(q),loadLimit:G,loadedRowCount:ge,totalAvailableRows:Ve,canUseLiveApi:H,autoRefreshEnabled:F,applicationI18n:A,refreshing:j,hasMoreRows:En,canLoadAllRows:as,loadMoreRows:On,loadAllRows:us,globalFilters:c.jsx(ic,{activeView:i,locationSearch:N,model:r,onUrlChange:Ke})})]}),vt?c.jsxs("button",{className:"to-top-button",type:"button",onClick:ws,"aria-label":"Back to top",children:[c.jsx(Ts,{size:18}),A.t("button.top","Top")]}):null]})});function Un(){ie()}}function Al(){return c.jsx(Mi,{client:kn,children:c.jsx(Qr,{})})}const cu=Object.freeze(Object.defineProperty({__proto__:null,App:Qr,RoutedApp:Al,shouldAutoRefreshUsageView:Br},Symbol.toStringTag,{value:"Module"}));export{Jl as $,Ts as A,Il as B,Oi as C,Ns as D,Zl as E,Ds as F,ks as G,As as H,ya as I,Et as J,Q as K,Ol as L,qa as M,ne as N,au as O,kc as P,eu as Q,Is as R,Os as S,ru as T,Ps as U,Vs as V,ou as W,xa as X,Ql as Y,Bl as Z,Wl as _,js as a,Fs as a0,dn as a1,ml as a2,Kl as a3,Vl as a4,gi as a5,ci as a6,Gt as a7,Wa as a8,ii as a9,oi as aa,zt as ab,Ka as ac,Ci as ad,di as ae,Ul as af,Hl as ag,Gl as ah,kt as ai,fa as aj,zl as ak,Re as al,cu as am,Xl as b,$ as c,Fi as d,ce as e,ve as f,Di as g,iu as h,su as i,Le as j,dr as k,ql as l,Xt as m,Mr as n,nu as o,dt as p,tu as q,Ei as r,va as s,Yl as t,Va as u,pr as v,Ur as w,Nc as x,Ac as y,Fc as z}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js index e96f8316..a5bfb058 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallInvestigatorPage.js @@ -1,6 +1,6 @@ -import{r as C,j as e}from"./dashboard-react.js";import{c as G,v as R,p as U,j as h,u as A,af as ee,a as te,C as ae,f as F,Y as ne,m as Q,Z as se,ag as le,ah as oe,ai as ie,X as ce,_ as O,aj as re}from"./App.js";import{f as q,t as de,T as ue,v as he,C as xe,u as me,w as pe,x as be,c as ge,d as K,a as B,r as $,l as je,g as ve,y as V,b as fe,e as ye,h as Ce,i as J,j as W,k as we,m as ke,n as _e,o as Ne,p as Ee,q as Se,s as Te}from"./contextEvidenceState.js";import{P as T}from"./Panel.js";import{S as z}from"./StatusBadge.js";import{C as Ie,a as Ae}from"./chevron-right.js";import{S as Le}from"./shield-check.js";import{L as Pe}from"./lock-keyhole.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** +import{r as C,j as e}from"./dashboard-react.js";import{c as G,v as R,p as U,j as h,u as A,ag as ee,a as te,C as ae,f as F,Y as ne,Z as se,m as Q,_ as le,ah as oe,ai as ie,aj as ce,X as re,$ as O,ak as de}from"./App.js";import{f as q,t as ue,T as he,v as xe,C as me,u as pe,w as be,x as ge,c as je,d as K,a as B,r as $,l as ve,g as fe,y as V,b as ye,e as Ce,h as we,i as J,j as W,k as ke,m as _e,n as Ne,o as Ee,p as Se,q as Te,s as Ie}from"./contextEvidenceState.js";import{P as T}from"./Panel.js";import{S as z}from"./StatusBadge.js";import{C as Ae,a as Le}from"./chevron-right.js";import{S as Pe}from"./shield-check.js";import{L as Re}from"./lock-keyhole.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const X=G("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]),D=new Map;function Re(t,n){Me(t,n);const s=`${n.apiToken}:${t}`,i=D.get(s);if(i)return i;const l=ze(t,n).finally(()=>{D.delete(s)});return D.set(s,l),l}async function ze(t,n){var o;const s=new URLSearchParams({record_id:t,_:String(Date.now())}),i=await fetch(`/api/call?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":n.apiToken},cache:"no-store"}),l=await Oe(i,"Call detail");if(!((o=l.record)!=null&&o.record_id))throw new Error("Call detail response did not include the requested aggregate record.");const u=Array.isArray(l.adjacent_records)&&l.adjacent_records.length?l.adjacent_records:[l.previous_record,l.record,l.next_record].filter(p=>!!p);return{record:R(l.record,0),previousRecord:l.previous_record?R(l.previous_record,-1):null,nextRecord:l.next_record?R(l.next_record,1):null,adjacentRecords:u.map((p,c)=>R(p,c)),rawPayload:l}}function Me(t,n){if(!t)throw new Error("record_id is required for call detail loading.");if(n.fileMode)throw new Error("Call detail hydration requires the localhost dashboard server.");if(!n.apiToken)throw new Error("Call detail hydration requires a localhost dashboard API token.")}async function Oe(t,n){let s={};try{s=await t.json()}catch{s={}}if(!t.ok){const i=typeof s.error=="string"?s.error:`${n} request failed (${t.status})`;throw new Error(i)}return s}function $e(t,n){return H(n.t("call.readout.exact_body","{input} input tokens = {cached} cached + {uncached} uncached; {output} output tokens; {cache} cache reuse."),{input:h(t.input),cached:h(t.cachedInput),uncached:h(t.uncachedInput),output:h(t.output),cache:U(t.cachedPct)})}function De(t){return t.t("call.readout.previous_unavailable","No previous call is loaded in resolved thread, call-to-call deltas unavailable.")}function qe(t,n){const s=t.uncachedInput-n.uncachedInput,i=t.cachedInput-n.cachedInput;return s>0&&i<0?`Fresh input rose by ${h(s)} while cached input fell by ${h(Math.abs(i))}; classic cache-drop profile.`:s>0?`Fresh input increased by ${h(s)} from previous call; inspect evidence new files, tool results, or rewritten context.`:s<0&&i>=0?`Fresh input fell by ${h(Math.abs(s))} while cached input increased, so this call reused context more efficiently previous one.`:"Token accounting broadly stable compared previous call in resolved thread."}function Ue(t,n){var s;if(t.status==="loaded"){const i=((s=t.payload.entries)==null?void 0:s.length)??0,l=Number(t.payload.visible_char_count??0),u=Number(t.payload.visible_token_estimate??0),o=Fe(t.payload,n);return H(n.t("call.readout.evidence_analyzed","Evidence analyzed: {totalEntries} selected-turn entries, {visibleChars} visible redacted chars, {visibleTokens} visible tokens.{serializedDetail}"),{totalEntries:h(i),visibleChars:h(l),visibleTokens:h(u),estimator:t.payload.visible_token_estimator??"visible-token estimate",serializedDetail:o,renderedEntries:h(i)})}return t.status==="loading"?n.t("call.readout.evidence_loading",t.message):t.status==="error"?`Evidence request failed: ${t.message}`:"Evidence is not loaded yet. Aggregate token counts are exact, but visible-context attribution needs runtime evidence."}function Fe(t,n){const s=t.serialized_evidence??{};if(s.deferred||s.deferred_buckets)return n.t("call.readout.evidence_serialized_deferred","Fast serialized estimate only; full serialized grouping deferred.");const i=Be(t);return i<=0?"":H(n.t("call.readout.evidence_serialized_bound"," Serialized local upper bound: {tokens} tokens."),{tokens:h(i),chars:h(Number(s.raw_json_char_count??s.total_chars??0))})}function He(t,n){const s=t.input>0?t.cachedInput/t.input:t.cachedPct/100,i=n&&n.input>0?n.cachedInput/n.input:n?n.cachedPct/100:null,l=(n==null?void 0:n.uncachedInput)??0;return n&&i!==null&&i>=.8&&s<=.05&&t.input>=1e3?"Compare previous call, then inspect loaded evidence see fresh context was sent after cache miss.":n&&t.uncachedInput>Math.max(l*2,1e3)?"Inspect most recent evidence entries first; spike is in fresh uncached input, not cached history.":s>=.85?`Cache reuse is healthy; focus on ${h(t.uncachedInput)} uncached tokens were still billed as fresh input.`:n?"Use delta cards to locate whether change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough understand this isolated call."}function Ke(t){return t==="Hydrated from /api/call"?"Position: hydrated live record outside loaded snapshot":`Position: ${t}`}function H(t,n){return t.replace(/\{(\w+)\}/g,(s,i)=>n[i]??s)}function Be(t){const n=t.serialized_evidence??{};return Number(n.raw_json_token_estimate??n.token_estimate??0)}function rt({model:t,recordId:n,contextRuntime:s,onContextApiEnabledChange:i,onNavigateRecord:l,onCopyCallLink:u,onBackToCalls:o,backLabel:p}){const c=A(),[j,b]=C.useState(""),[x,k]=C.useState({status:"idle"}),[d,w]=C.useState({status:"idle"}),[S,L]=C.useState({recordId:"",nonce:0}),I=x.status==="loaded"&&x.recordId===n?x.detail:null,{modelIndex:N,hydratedDetail:E,call:a,previous:r,next:g,threadCalls:m,positionLabel:v}=C.useMemo(()=>ee({calls:t.calls,recordId:n,detail:I}),[I,t.calls,n]),Y=d.status==="loaded"?d.payload:null;if(C.useEffect(()=>{w({status:"idle"})},[n]),C.useEffect(()=>{if(!n||N>=0){k({status:"idle"});return}if(s.fileMode||!s.apiToken){k({status:"error",recordId:n,message:"This call is outside the loaded snapshot. Serve the dashboard with its localhost API token to hydrate it."});return}let _=!1;return k({status:"loading",recordId:n,message:"Loading call detail from localhost..."}),Re(n,s).then(P=>{_||k({status:"loaded",recordId:n,detail:P})}).catch(P=>{_||k({status:"error",recordId:n,message:q(P)})}),()=>{_=!0}},[s,N,n]),!a){const _=x.status==="loading"||x.status==="error"?x.message:n?"Selected call is not present in the loaded dashboard rows.":"No aggregate call rows are loaded.";return e.jsx("div",{className:"page-grid",children:e.jsxs("div",{className:"page-title-row",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsx("p",{children:_})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]})]})})}async function Z(){try{const _=new URL(window.location.href);if(oe(_,"call",ie(_.search)),!await ce(_.toString()))throw new Error("Clipboard unavailable");b("Copied investigator link")}catch{b("Copy unavailable in this browser")}}return e.jsxs("div",{className:"call-investigator-layout",children:[e.jsxs("div",{className:"page-title-row span-all",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsxs("p",{children:[a.thread," / ",a.model]})]}),e.jsxs("div",{className:"toolbar",children:[e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>r&&l(r.id),disabled:!r,children:[e.jsx(Ie,{size:16})," ",c.t("button.previous_call","Previous call")]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>g&&l(g.id),disabled:!g,children:[c.t("button.next_call","Next call")," ",e.jsx(Ae,{size:16})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:Z,"aria-label":c.t("button.copy_investigator_link","Copy investigator link"),children:[e.jsx(te,{size:16})," ",c.t("button.copy_link","Copy link")]})]})]}),e.jsxs(T,{title:c.t("call.readout.title","Investigation Readout"),subtitle:j||v,className:"span-all",action:e.jsx(z,{label:c.t("call.readout.badge","Aggregate + on-demand evidence"),tone:"blue"}),children:[e.jsxs("div",{className:"call-summary",children:[e.jsx(z,{label:"Aggregate only",tone:"green"}),E?e.jsx(z,{label:"Hydrated live",tone:"blue"}):null,e.jsx(ae,{call:a}),e.jsx(z,{label:"Raw context gated",tone:"blue"}),e.jsx("span",{className:"call-id",children:a.id.slice(0,16)})]}),e.jsx(Ve,{call:a,previous:r,evidenceState:d,positionLabel:v}),e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Total tokens",value:h(a.totalTokens),detail:`${F(a.input)} input`}),e.jsx(f,{label:"Uncached input",value:h(a.uncachedInput),detail:"fresh billed input"}),e.jsx(f,{label:"Cache hit rate",value:U(a.cachedPct),detail:ne(a)}),e.jsx(f,{label:"Estimated cost",value:Q(a.cost),detail:a.pricingEstimated?"estimated pricing":"configured pricing"}),e.jsx(f,{label:"Duration",value:a.duration,detail:se(a)}),e.jsx(f,{label:"Usage credits",value:a.credits?a.credits.toFixed(3):"-",detail:a.usageCreditConfidence})]}),e.jsx(de,{call:a})]}),e.jsxs(T,{title:"Token Accounting",subtitle:"Exact aggregate row fields",children:[e.jsx(Ye,{call:a}),e.jsx(ue,{call:a})]}),e.jsx(T,{title:"Cache Accounting",subtitle:"Derived from adjacent aggregate call",children:e.jsx(he,{call:a,calls:m})}),e.jsx(T,{title:"Context Attribution",subtitle:"Estimated from visible log volume",className:"span-all",children:e.jsx(xe,{call:a,payload:Y,onRunFullAnalysis:()=>L(_=>({recordId:a.id,nonce:_.nonce+1})),showHeading:!1})}),e.jsxs(T,{title:"Aggregate Identity",subtitle:"Local metadata only",children:[e.jsxs("dl",{className:"detail-list",children:[e.jsx(y,{label:"Record id",value:a.id}),e.jsx(y,{label:"Time",value:a.time}),e.jsx(y,{label:"Thread",value:a.thread}),e.jsx(y,{label:"Model",value:a.model}),e.jsx(y,{label:"Effort",value:a.effort}),e.jsx(y,{label:"Project",value:a.project||"Unknown"}),e.jsx(y,{label:"Context window",value:le(a)}),e.jsx(y,{label:"Recommendation",value:a.recommendation||"No aggregate recommendation"})]}),e.jsx(me,{call:a}),a.recommendation?e.jsxs("div",{className:"recommendation-box",children:[e.jsx(Le,{size:16}),e.jsx("p",{children:a.recommendation})]}):null]}),e.jsx(T,{title:"Thread Context",subtitle:`${m.length} loaded related calls`,className:"span-all",children:e.jsx(Qe,{call:a,calls:m,onNavigateRecord:l,onCopyCallLink:u})}),e.jsx(T,{title:"Raw Evidence",subtitle:"Explicit localhost request only",className:"span-all",children:e.jsx(Je,{call:a,contextRuntime:s,onContextApiEnabledChange:i,onEvidenceStateChange:w,fullAnalysisRequestNonce:S.recordId===a.id?S.nonce:0},a.id)})]})}function Ve({call:t,previous:n,evidenceState:s,positionLabel:i}){const l=A();return e.jsxs("div",{className:"investigation-readout-grid",children:[e.jsx(M,{label:l.t("call.readout.exact_label","Exact callback accounting"),body:$e(t,l)}),e.jsx(M,{label:l.t("call.readout.previous_label","Compared previous call"),body:n?qe(t,n):De(l)}),e.jsx(M,{label:l.t("call.readout.evidence_label","Evidence state"),body:Ue(s,l)}),e.jsx(M,{label:l.t("call.readout.next_label","Next diagnostic move"),body:He(t,n),detail:Ke(i)})]})}function M({label:t,body:n,detail:s}){return e.jsxs("div",{className:"investigation-readout-card",children:[e.jsx("span",{children:t}),e.jsx("p",{children:n}),s?e.jsx("small",{children:s}):null]})}function Je({call:t,contextRuntime:n,onContextApiEnabledChange:s,onEvidenceStateChange:i,fullAnalysisRequestNonce:l}){const u=A(),[o,p]=C.useState(()=>be(window.location.search,ge(t.id)??K)),[c,j]=C.useState({status:"idle"}),b=!!n.apiToken&&!n.fileMode,x=b&&n.contextApiEnabled;C.useEffect(()=>{const a=B(t.id,o);j(a?{status:"loaded",payload:a}:{status:"idle"})},[t.id,o.includeToolOutput,o.includeCompactionHistory,o.maxChars,o.maxEntries,o.mode]),C.useEffect(()=>{i(c)},[c,i]),C.useEffect(()=>{if(l<=0||!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")},[l]);async function k(){j({status:"loading",message:"Enabling localhost context API..."});try{const a=await ye(n);s(a),j({status:"idle",message:a?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(a){j({status:"error",message:q(a)})}}async function d(a=o,r="Loading selected-turn evidence..."){$(t.id,a);const g=B(t.id,a);if(g){j({status:"loaded",payload:g});return}j({status:"loading",message:r});try{const m=await je(t.id,n,a);ve(t.id,a,m),j({status:"loaded",payload:m})}catch(m){j({status:"error",message:q(m)})}}function w(){if(!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")}function S(a){const r=Ee(a,o);N(r),d(r,"Loading older context...")}function L(){const a={...o,includeToolOutput:!0};N(a),d(a,"Loading omitted tool output...")}function I(){const a={...o,includeCompactionHistory:!0};N(a),d(a,"Loading compacted replacement...")}function N(a){p(a),$(t.id,a);const r=new URL(window.location.href);V(r,a),window.history.replaceState(null,"",r)}function E(a,r){p(g=>{const m={...g,[a]:r};$(t.id,m);const v=new URL(window.location.href);return V(v,m),window.history.replaceState(null,"",v),m})}return e.jsxs("div",{className:"investigator-evidence",children:[e.jsxs("div",{className:"locked-context-card",children:[e.jsx(Pe,{size:20}),e.jsxs("div",{children:[e.jsx("strong",{children:"Raw context is gated"}),e.jsx("p",{children:fe(n)})]})]}),e.jsxs("div",{className:"context-action-grid",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:k,disabled:!b||n.contextApiEnabled||c.status==="loading",children:u.t("button.enable_context_loading","Enable context loading")}),e.jsx("button",{className:"primary-button",type:"button",onClick:()=>d(),disabled:!x||c.status==="loading",children:u.t("button.show_turn_evidence","Show turn log evidence")}),e.jsx("button",{className:"toolbar-button",type:"button",onClick:w,disabled:!x||c.status==="loading",children:u.t("button.full_serialized_analysis","Run full serialized analysis")}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Mode"}),e.jsxs("select",{"aria-label":"Context mode",value:o.mode,disabled:!x||c.status==="loading",onChange:a=>E("mode",a.target.value==="full"?"full":"quick"),children:[e.jsx("option",{value:"quick",children:"Quick"}),e.jsx("option",{value:"full",children:"Full"})]})]}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Entries"}),e.jsxs("select",{"aria-label":"Context entries",value:String(o.maxEntries),disabled:!x||c.status==="loading",onChange:a=>E("maxEntries",Number(a.target.value)),children:[e.jsx("option",{value:"20",children:"20"}),e.jsx("option",{value:"50",children:"50"}),e.jsx("option",{value:"100",children:"100"}),e.jsx("option",{value:"0",children:"All"})]})]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeToolOutput,disabled:!x||c.status==="loading",onChange:a=>E("includeToolOutput",a.target.checked)}),u.t("button.include_tool_output","Include tool output")]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeCompactionHistory,disabled:!x||c.status==="loading",onChange:a=>E("includeCompactionHistory",a.target.checked)}),"Include compaction history"]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.maxChars===0,disabled:!x||c.status==="loading",onChange:a=>E("maxChars",a.target.checked?0:K.maxChars)}),u.t("button.no_char_limit","No char limit")]})]}),c.status==="idle"&&c.message?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="loading"?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="error"?e.jsx("p",{className:"context-state-note error",children:c.message}):null,c.status==="loaded"?e.jsx(We,{payload:c.payload,onLoadOlder:S,onLoadCompactionHistory:I,onLoadToolOutput:L}):null,e.jsx("p",{className:"privacy-note",children:"Raw context is read from the local JSONL source only after this explicit action and is not embedded in static dashboard HTML."})]})}function We({payload:t,onLoadOlder:n,onLoadCompactionHistory:s,onLoadToolOutput:i}){var E,a;const l=A(),u=t.entries??[],o=t.omitted??{},p=Number(o.older_entries??0),c=Ce(t),j=10,b=String(t.record_id??""),[x,k]=C.useState(()=>J(b)),[d,w]=C.useState(()=>W(b,u));C.useEffect(()=>{k(J(b)),w(W(b,u))},[u.length,t.context_mode,t.include_compaction_history,t.include_tool_output,(E=t.omitted)==null?void 0:E.max_chars,(a=t.omitted)==null?void 0:a.max_entries,t.record_id,b]);const S=x?u:u.slice(0,j),L=Math.max(u.length-S.length,0);function I(){k(r=>{const g=!r;return Te(b,g),g})}function N(r,g){Se(b,r,g),w(m=>{const v=new Set(m);return g?v.add(r):v.delete(r),v})}return e.jsxs("div",{className:"context-evidence",children:[e.jsxs("div",{className:"context-evidence-summary",children:[e.jsx(f,{label:"Entries",value:h(u.length),detail:String(t.context_mode??"quick")}),e.jsx(f,{label:"Visible chars",value:h(Number(t.visible_char_count??0)),detail:"redacted local text"}),e.jsx(f,{label:"Visible tokens",value:h(Number(t.visible_token_estimate??0)),detail:"estimator"}),e.jsx(f,{label:"Older omitted",value:h(p),detail:"entry budget"})]}),c.length?e.jsx("p",{className:"context-note",children:c.join(" ")}):null,p>0?e.jsx("div",{className:"context-followup-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>n(t),children:l.t("button.load_older_context","Load older entries")})}):null,e.jsxs("div",{className:"context-entry-list",children:[S.map((r,g)=>{const m=we(r,g);return e.jsxs("details",{className:"context-entry",open:d.has(m),onToggle:v=>N(m,v.currentTarget.open),children:[e.jsx("summary",{className:"context-entry-summary",children:e.jsxs("div",{className:"context-entry-meta",children:[e.jsx("strong",{children:r.label||r.role||r.type||`Entry ${g+1}`}),e.jsx("span",{children:r.line_number?`line ${r.line_number}`:r.timestamp||"local evidence"})]})}),e.jsx(ke,{entry:r}),r.tool_output_omitted?e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:i,children:l.t("button.show_tool_output","Show tool output")})}):null,e.jsx(Xe,{entry:r,onLoadCompactionHistory:s}),e.jsx("pre",{ref:v=>{v&&(v.scrollTop=Ne(b,m))},onScroll:v=>_e(b,m,v.currentTarget.scrollTop),children:r.text||"[no visible text]"})]},m)}),u.length?null:e.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),u.length>j?e.jsxs("div",{className:"context-followup-actions",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:I,children:x?`Show first ${h(j)} entries`:`Show all ${h(u.length)} returned entries`}),x?null:e.jsxs("span",{className:"context-entry-count-note",children:[h(L)," entries hidden in compact view"]})]}):null]})}function Xe({entry:t,onLoadCompactionHistory:n}){const s=A(),i=t.compaction;if(!(i!=null&&i.replacement_history_available))return null;const l=i.replacement_history??[],u=Number(i.replacement_entry_count??l.length);return e.jsxs("div",{className:"context-entry-compaction",children:[e.jsx("strong",{children:"Compaction detected"}),e.jsxs("span",{children:[h(u)," replacement history entries available."]}),l.length?e.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:l.map((o,p)=>e.jsxs("div",{className:"context-replacement-entry",children:[e.jsx("strong",{children:o.label||`Replacement item ${p+1}`}),e.jsx("pre",{children:o.text||"[no visible replacement text]"})]},`${o.label??"replacement"}-${p}`))}):e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}function Qe({call:t,calls:n,onNavigateRecord:s,onCopyCallLink:i}){const u=A().t("button.copy_link","Copy link"),o=n.length?n:[t],p=Math.max(o.findIndex(d=>d.id===t.id),0),c=o.reduce((d,w)=>d+w.totalTokens,0),j=o.reduce((d,w)=>d+w.cost,0),b=o.reduce((d,w)=>d+w.cachedPct,0)/Math.max(o.length,1),x=o.filter(d=>Number(d.contextWindowPct??0)>=60).length,k=o.filter(d=>d.cachedPct<25||d.signal==="cache-risk").length;return e.jsxs("div",{className:"thread-context-module",children:[e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Thread calls",value:h(o.length),detail:`selected ${p+1} of ${o.length}`}),e.jsx(f,{label:"Thread tokens",value:F(c),detail:"loaded aggregate rows"}),e.jsx(f,{label:"Thread cost",value:Q(j),detail:"estimated aggregate"}),e.jsx(f,{label:"Avg cache",value:U(b),detail:O(o.map(d=>d.model))}),e.jsx(f,{label:"Cache risks",value:h(k),detail:"weak reuse or flagged"}),e.jsx(f,{label:"Context pressure",value:h(x),detail:">=60% context window"})]}),e.jsxs("div",{className:"thread-context-grid",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Thread timeline"}),e.jsx(pe,{selectedCall:t,calls:o,onOpenInvestigator:s,onCopyCallLink:i,className:"investigator-thread-timeline",copyAriaContext:"thread context call",copyLabel:u})]}),e.jsxs("dl",{className:"detail-list compact",children:[e.jsx(y,{label:"Project",value:t.project||"Unknown"}),e.jsx(y,{label:"Project path",value:t.projectRelativeCwd||t.cwd||"."}),e.jsx(y,{label:"Source line",value:re(t)}),e.jsx(y,{label:"Session",value:t.sessionId||"Not available"}),e.jsx(y,{label:"Parent thread",value:t.parentThread||"None"}),e.jsx(y,{label:"Models in thread",value:O(o.map(d=>d.model),{limit:3})}),e.jsx(y,{label:"Effort mix",value:O(o.map(d=>d.effort),{limit:3})})]})]})]})}function f({label:t,value:n,detail:s}){return e.jsxs("span",{className:"drilldown-metric",children:[e.jsx("small",{children:t}),e.jsx("strong",{children:n}),e.jsx("em",{children:s})]})}function y({label:t,value:n}){return e.jsxs("div",{children:[e.jsx("dt",{children:t}),e.jsx("dd",{children:n})]})}function Ye({call:t}){const s=[{label:"Cached input",value:Math.max(t.input-t.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:t.uncachedInput,color:"#f59e0b"},{label:"Output",value:t.output,color:"#059669"},{label:"Reasoning",value:t.reasoningOutput,color:"#7c3aed"}].filter(l=>l.value>0),i=Math.max(s.reduce((l,u)=>l+u.value,0),1);return e.jsxs("div",{className:"composition-card",children:[e.jsxs("div",{className:"composition-head",children:[e.jsx("strong",{children:"Token composition"}),e.jsxs("span",{children:[F(i)," visible tokens"]})]}),e.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(l=>e.jsx("i",{style:{width:`${Math.max(l.value/i*100,3)}%`,background:l.color}},l.label))}),e.jsx("div",{className:"composition-legend",children:s.map(l=>e.jsxs("span",{children:[e.jsx("i",{style:{background:l.color}}),l.label]},l.label))})]})}export{rt as CallInvestigatorPage}; + */const X=G("ArrowLeft",[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]]),D=new Map;function ze(t,n){Oe(t,n);const s=`${n.apiToken}:${t}`,i=D.get(s);if(i)return i;const l=Me(t,n).finally(()=>{D.delete(s)});return D.set(s,l),l}async function Me(t,n){var o;const s=new URLSearchParams({record_id:t,_:String(Date.now())}),i=await fetch(`/api/call?${s.toString()}`,{headers:{Accept:"application/json","X-Codex-Usage-Token":n.apiToken},cache:"no-store"}),l=await $e(i,"Call detail");if(!((o=l.record)!=null&&o.record_id))throw new Error("Call detail response did not include the requested aggregate record.");const u=Array.isArray(l.adjacent_records)&&l.adjacent_records.length?l.adjacent_records:[l.previous_record,l.record,l.next_record].filter(p=>!!p);return{record:R(l.record,0),previousRecord:l.previous_record?R(l.previous_record,-1):null,nextRecord:l.next_record?R(l.next_record,1):null,adjacentRecords:u.map((p,c)=>R(p,c)),rawPayload:l}}function Oe(t,n){if(!t)throw new Error("record_id is required for call detail loading.");if(n.fileMode)throw new Error("Call detail hydration requires the localhost dashboard server.");if(!n.apiToken)throw new Error("Call detail hydration requires a localhost dashboard API token.")}async function $e(t,n){let s={};try{s=await t.json()}catch{s={}}if(!t.ok){const i=typeof s.error=="string"?s.error:`${n} request failed (${t.status})`;throw new Error(i)}return s}function De(t,n){return H(n.t("call.readout.exact_body","{input} input tokens = {cached} cached + {uncached} uncached; {output} output tokens; {cache} cache reuse."),{input:h(t.input),cached:h(t.cachedInput),uncached:h(t.uncachedInput),output:h(t.output),cache:U(t.cachedPct)})}function qe(t){return t.t("call.readout.previous_unavailable","No previous call is loaded in resolved thread, call-to-call deltas unavailable.")}function Ue(t,n){const s=t.uncachedInput-n.uncachedInput,i=t.cachedInput-n.cachedInput;return s>0&&i<0?`Fresh input rose by ${h(s)} while cached input fell by ${h(Math.abs(i))}; classic cache-drop profile.`:s>0?`Fresh input increased by ${h(s)} from previous call; inspect evidence new files, tool results, or rewritten context.`:s<0&&i>=0?`Fresh input fell by ${h(Math.abs(s))} while cached input increased, so this call reused context more efficiently previous one.`:"Token accounting broadly stable compared previous call in resolved thread."}function Fe(t,n){var s;if(t.status==="loaded"){const i=((s=t.payload.entries)==null?void 0:s.length)??0,l=Number(t.payload.visible_char_count??0),u=Number(t.payload.visible_token_estimate??0),o=He(t.payload,n);return H(n.t("call.readout.evidence_analyzed","Evidence analyzed: {totalEntries} selected-turn entries, {visibleChars} visible redacted chars, {visibleTokens} visible tokens.{serializedDetail}"),{totalEntries:h(i),visibleChars:h(l),visibleTokens:h(u),estimator:t.payload.visible_token_estimator??"visible-token estimate",serializedDetail:o,renderedEntries:h(i)})}return t.status==="loading"?n.t("call.readout.evidence_loading",t.message):t.status==="error"?`Evidence request failed: ${t.message}`:"Evidence is not loaded yet. Aggregate token counts are exact, but visible-context attribution needs runtime evidence."}function He(t,n){const s=t.serialized_evidence??{};if(s.deferred||s.deferred_buckets)return n.t("call.readout.evidence_serialized_deferred","Fast serialized estimate only; full serialized grouping deferred.");const i=Ve(t);return i<=0?"":H(n.t("call.readout.evidence_serialized_bound"," Serialized local upper bound: {tokens} tokens."),{tokens:h(i),chars:h(Number(s.raw_json_char_count??s.total_chars??0))})}function Ke(t,n){const s=t.input>0?t.cachedInput/t.input:t.cachedPct/100,i=n&&n.input>0?n.cachedInput/n.input:n?n.cachedPct/100:null,l=(n==null?void 0:n.uncachedInput)??0;return n&&i!==null&&i>=.8&&s<=.05&&t.input>=1e3?"Compare previous call, then inspect loaded evidence see fresh context was sent after cache miss.":n&&t.uncachedInput>Math.max(l*2,1e3)?"Inspect most recent evidence entries first; spike is in fresh uncached input, not cached history.":s>=.85?`Cache reuse is healthy; focus on ${h(t.uncachedInput)} uncached tokens were still billed as fresh input.`:n?"Use delta cards to locate whether change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough understand this isolated call."}function Be(t){return t==="Hydrated from /api/call"?"Position: hydrated live record outside loaded snapshot":`Position: ${t}`}function H(t,n){return t.replace(/\{(\w+)\}/g,(s,i)=>n[i]??s)}function Ve(t){const n=t.serialized_evidence??{};return Number(n.raw_json_token_estimate??n.token_estimate??0)}function dt({model:t,recordId:n,contextRuntime:s,onContextApiEnabledChange:i,onNavigateRecord:l,onCopyCallLink:u,onBackToCalls:o,backLabel:p}){const c=A(),[j,b]=C.useState(""),[x,k]=C.useState({status:"idle"}),[d,w]=C.useState({status:"idle"}),[S,L]=C.useState({recordId:"",nonce:0}),I=x.status==="loaded"&&x.recordId===n?x.detail:null,{modelIndex:N,hydratedDetail:E,call:a,previous:r,next:g,threadCalls:m,positionLabel:v}=C.useMemo(()=>ee({calls:t.calls,recordId:n,detail:I}),[I,t.calls,n]),Y=d.status==="loaded"?d.payload:null;if(C.useEffect(()=>{w({status:"idle"})},[n]),C.useEffect(()=>{if(!n||N>=0){k({status:"idle"});return}if(s.fileMode||!s.apiToken){k({status:"error",recordId:n,message:"This call is outside the loaded snapshot. Serve the dashboard with its localhost API token to hydrate it."});return}let _=!1;return k({status:"loading",recordId:n,message:"Loading call detail from localhost..."}),ze(n,s).then(P=>{_||k({status:"loaded",recordId:n,detail:P})}).catch(P=>{_||k({status:"error",recordId:n,message:q(P)})}),()=>{_=!0}},[s,N,n]),!a){const _=x.status==="loading"||x.status==="error"?x.message:n?"Selected call is not present in the loaded dashboard rows.":"No aggregate call rows are loaded.";return e.jsx("div",{className:"page-grid",children:e.jsxs("div",{className:"page-title-row",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsx("p",{children:_})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]})]})})}async function Z(){try{const _=new URL(window.location.href);if(ie(_,"call",ce(_.search)),!await re(_.toString()))throw new Error("Clipboard unavailable");b("Copied investigator link")}catch{b("Copy unavailable in this browser")}}return e.jsxs("div",{className:"call-investigator-layout",children:[e.jsxs("div",{className:"page-title-row span-all",children:[e.jsxs("div",{children:[e.jsx("h1",{children:"Call Investigator"}),e.jsxs("p",{children:[a.thread," / ",a.model]})]}),e.jsxs("div",{className:"toolbar",children:[e.jsxs("button",{className:"toolbar-button",type:"button",onClick:o,children:[e.jsx(X,{size:16})," ",p]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>r&&l(r.id),disabled:!r,children:[e.jsx(Ae,{size:16})," ",c.t("button.previous_call","Previous call")]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>g&&l(g.id),disabled:!g,children:[c.t("button.next_call","Next call")," ",e.jsx(Le,{size:16})]}),e.jsxs("button",{className:"toolbar-button",type:"button",onClick:Z,"aria-label":c.t("button.copy_investigator_link","Copy investigator link"),children:[e.jsx(te,{size:16})," ",c.t("button.copy_link","Copy link")]})]})]}),e.jsxs(T,{title:c.t("call.readout.title","Investigation Readout"),subtitle:j||v,className:"span-all",action:e.jsx(z,{label:c.t("call.readout.badge","Aggregate + on-demand evidence"),tone:"blue"}),children:[e.jsxs("div",{className:"call-summary",children:[e.jsx(z,{label:"Aggregate only",tone:"green"}),E?e.jsx(z,{label:"Hydrated live",tone:"blue"}):null,e.jsx(ae,{call:a}),e.jsx(z,{label:"Raw context gated",tone:"blue"}),e.jsx("span",{className:"call-id",children:a.id.slice(0,16)})]}),e.jsx(Je,{call:a,previous:r,evidenceState:d,positionLabel:v}),e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Total tokens",value:h(a.totalTokens),detail:`${F(a.input)} input`}),e.jsx(f,{label:"Uncached input",value:h(a.uncachedInput),detail:"fresh billed input"}),e.jsx(f,{label:"Cache hit rate",value:U(a.cachedPct),detail:ne(a)}),e.jsx(f,{label:"Estimated cost",value:Q(a.cost),detail:se(a)}),e.jsx(f,{label:"Duration",value:a.duration,detail:le(a)}),e.jsx(f,{label:"Usage credits",value:a.credits?a.credits.toFixed(3):"-",detail:a.usageCreditConfidence})]}),e.jsx(ue,{call:a})]}),e.jsxs(T,{title:"Token Accounting",subtitle:"Exact aggregate row fields",children:[e.jsx(Ze,{call:a}),e.jsx(he,{call:a})]}),e.jsx(T,{title:"Cache Accounting",subtitle:"Derived from adjacent aggregate call",children:e.jsx(xe,{call:a,calls:m})}),e.jsx(T,{title:"Context Attribution",subtitle:"Estimated from visible log volume",className:"span-all",children:e.jsx(me,{call:a,payload:Y,onRunFullAnalysis:()=>L(_=>({recordId:a.id,nonce:_.nonce+1})),showHeading:!1})}),e.jsxs(T,{title:"Aggregate Identity",subtitle:"Local metadata only",children:[e.jsxs("dl",{className:"detail-list",children:[e.jsx(y,{label:"Record id",value:a.id}),e.jsx(y,{label:"Time",value:a.time}),e.jsx(y,{label:"Thread",value:a.thread}),e.jsx(y,{label:"Model",value:a.model}),e.jsx(y,{label:"Effort",value:a.effort}),e.jsx(y,{label:"Project",value:a.project||"Unknown"}),e.jsx(y,{label:"Context window",value:oe(a)}),e.jsx(y,{label:"Recommendation",value:a.recommendation||"No aggregate recommendation"})]}),e.jsx(pe,{call:a}),a.recommendation?e.jsxs("div",{className:"recommendation-box",children:[e.jsx(Pe,{size:16}),e.jsx("p",{children:a.recommendation})]}):null]}),e.jsx(T,{title:"Thread Context",subtitle:`${m.length} loaded related calls`,className:"span-all",children:e.jsx(Ye,{call:a,calls:m,onNavigateRecord:l,onCopyCallLink:u})}),e.jsx(T,{title:"Raw Evidence",subtitle:"Explicit localhost request only",className:"span-all",children:e.jsx(We,{call:a,contextRuntime:s,onContextApiEnabledChange:i,onEvidenceStateChange:w,fullAnalysisRequestNonce:S.recordId===a.id?S.nonce:0},a.id)})]})}function Je({call:t,previous:n,evidenceState:s,positionLabel:i}){const l=A();return e.jsxs("div",{className:"investigation-readout-grid",children:[e.jsx(M,{label:l.t("call.readout.exact_label","Exact callback accounting"),body:De(t,l)}),e.jsx(M,{label:l.t("call.readout.previous_label","Compared previous call"),body:n?Ue(t,n):qe(l)}),e.jsx(M,{label:l.t("call.readout.evidence_label","Evidence state"),body:Fe(s,l)}),e.jsx(M,{label:l.t("call.readout.next_label","Next diagnostic move"),body:Ke(t,n),detail:Be(i)})]})}function M({label:t,body:n,detail:s}){return e.jsxs("div",{className:"investigation-readout-card",children:[e.jsx("span",{children:t}),e.jsx("p",{children:n}),s?e.jsx("small",{children:s}):null]})}function We({call:t,contextRuntime:n,onContextApiEnabledChange:s,onEvidenceStateChange:i,fullAnalysisRequestNonce:l}){const u=A(),[o,p]=C.useState(()=>ge(window.location.search,je(t.id)??K)),[c,j]=C.useState({status:"idle"}),b=!!n.apiToken&&!n.fileMode,x=b&&n.contextApiEnabled;C.useEffect(()=>{const a=B(t.id,o);j(a?{status:"loaded",payload:a}:{status:"idle"})},[t.id,o.includeToolOutput,o.includeCompactionHistory,o.maxChars,o.maxEntries,o.mode]),C.useEffect(()=>{i(c)},[c,i]),C.useEffect(()=>{if(l<=0||!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")},[l]);async function k(){j({status:"loading",message:"Enabling localhost context API..."});try{const a=await Ce(n);s(a),j({status:"idle",message:a?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(a){j({status:"error",message:q(a)})}}async function d(a=o,r="Loading selected-turn evidence..."){$(t.id,a);const g=B(t.id,a);if(g){j({status:"loaded",payload:g});return}j({status:"loading",message:r});try{const m=await ve(t.id,n,a);fe(t.id,a,m),j({status:"loaded",payload:m})}catch(m){j({status:"error",message:q(m)})}}function w(){if(!x||c.status==="loading")return;const a={...o,mode:"full"};N(a),d(a,"Loading full turn analysis...")}function S(a){const r=Se(a,o);N(r),d(r,"Loading older context...")}function L(){const a={...o,includeToolOutput:!0};N(a),d(a,"Loading omitted tool output...")}function I(){const a={...o,includeCompactionHistory:!0};N(a),d(a,"Loading compacted replacement...")}function N(a){p(a),$(t.id,a);const r=new URL(window.location.href);V(r,a),window.history.replaceState(null,"",r)}function E(a,r){p(g=>{const m={...g,[a]:r};$(t.id,m);const v=new URL(window.location.href);return V(v,m),window.history.replaceState(null,"",v),m})}return e.jsxs("div",{className:"investigator-evidence",children:[e.jsxs("div",{className:"locked-context-card",children:[e.jsx(Re,{size:20}),e.jsxs("div",{children:[e.jsx("strong",{children:"Raw context is gated"}),e.jsx("p",{children:ye(n)})]})]}),e.jsxs("div",{className:"context-action-grid",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:k,disabled:!b||n.contextApiEnabled||c.status==="loading",children:u.t("button.enable_context_loading","Enable context loading")}),e.jsx("button",{className:"primary-button",type:"button",onClick:()=>d(),disabled:!x||c.status==="loading",children:u.t("button.show_turn_evidence","Show turn log evidence")}),e.jsx("button",{className:"toolbar-button",type:"button",onClick:w,disabled:!x||c.status==="loading",children:u.t("button.full_serialized_analysis","Run full serialized analysis")}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Mode"}),e.jsxs("select",{"aria-label":"Context mode",value:o.mode,disabled:!x||c.status==="loading",onChange:a=>E("mode",a.target.value==="full"?"full":"quick"),children:[e.jsx("option",{value:"quick",children:"Quick"}),e.jsx("option",{value:"full",children:"Full"})]})]}),e.jsxs("label",{className:"context-field",children:[e.jsx("span",{children:"Entries"}),e.jsxs("select",{"aria-label":"Context entries",value:String(o.maxEntries),disabled:!x||c.status==="loading",onChange:a=>E("maxEntries",Number(a.target.value)),children:[e.jsx("option",{value:"20",children:"20"}),e.jsx("option",{value:"50",children:"50"}),e.jsx("option",{value:"100",children:"100"}),e.jsx("option",{value:"0",children:"All"})]})]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeToolOutput,disabled:!x||c.status==="loading",onChange:a=>E("includeToolOutput",a.target.checked)}),u.t("button.include_tool_output","Include tool output")]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.includeCompactionHistory,disabled:!x||c.status==="loading",onChange:a=>E("includeCompactionHistory",a.target.checked)}),"Include compaction history"]}),e.jsxs("label",{className:"toggle-row",children:[e.jsx("input",{type:"checkbox",checked:o.maxChars===0,disabled:!x||c.status==="loading",onChange:a=>E("maxChars",a.target.checked?0:K.maxChars)}),u.t("button.no_char_limit","No char limit")]})]}),c.status==="idle"&&c.message?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="loading"?e.jsx("p",{className:"context-state-note",children:c.message}):null,c.status==="error"?e.jsx("p",{className:"context-state-note error",children:c.message}):null,c.status==="loaded"?e.jsx(Xe,{payload:c.payload,onLoadOlder:S,onLoadCompactionHistory:I,onLoadToolOutput:L}):null,e.jsx("p",{className:"privacy-note",children:"Raw context is read from the local JSONL source only after this explicit action and is not embedded in static dashboard HTML."})]})}function Xe({payload:t,onLoadOlder:n,onLoadCompactionHistory:s,onLoadToolOutput:i}){var E,a;const l=A(),u=t.entries??[],o=t.omitted??{},p=Number(o.older_entries??0),c=we(t),j=10,b=String(t.record_id??""),[x,k]=C.useState(()=>J(b)),[d,w]=C.useState(()=>W(b,u));C.useEffect(()=>{k(J(b)),w(W(b,u))},[u.length,t.context_mode,t.include_compaction_history,t.include_tool_output,(E=t.omitted)==null?void 0:E.max_chars,(a=t.omitted)==null?void 0:a.max_entries,t.record_id,b]);const S=x?u:u.slice(0,j),L=Math.max(u.length-S.length,0);function I(){k(r=>{const g=!r;return Ie(b,g),g})}function N(r,g){Te(b,r,g),w(m=>{const v=new Set(m);return g?v.add(r):v.delete(r),v})}return e.jsxs("div",{className:"context-evidence",children:[e.jsxs("div",{className:"context-evidence-summary",children:[e.jsx(f,{label:"Entries",value:h(u.length),detail:String(t.context_mode??"quick")}),e.jsx(f,{label:"Visible chars",value:h(Number(t.visible_char_count??0)),detail:"redacted local text"}),e.jsx(f,{label:"Visible tokens",value:h(Number(t.visible_token_estimate??0)),detail:"estimator"}),e.jsx(f,{label:"Older omitted",value:h(p),detail:"entry budget"})]}),c.length?e.jsx("p",{className:"context-note",children:c.join(" ")}):null,p>0?e.jsx("div",{className:"context-followup-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>n(t),children:l.t("button.load_older_context","Load older entries")})}):null,e.jsxs("div",{className:"context-entry-list",children:[S.map((r,g)=>{const m=ke(r,g);return e.jsxs("details",{className:"context-entry",open:d.has(m),onToggle:v=>N(m,v.currentTarget.open),children:[e.jsx("summary",{className:"context-entry-summary",children:e.jsxs("div",{className:"context-entry-meta",children:[e.jsx("strong",{children:r.label||r.role||r.type||`Entry ${g+1}`}),e.jsx("span",{children:r.line_number?`line ${r.line_number}`:r.timestamp||"local evidence"})]})}),e.jsx(_e,{entry:r}),r.tool_output_omitted?e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:i,children:l.t("button.show_tool_output","Show tool output")})}):null,e.jsx(Qe,{entry:r,onLoadCompactionHistory:s}),e.jsx("pre",{ref:v=>{v&&(v.scrollTop=Ee(b,m))},onScroll:v=>Ne(b,m,v.currentTarget.scrollTop),children:r.text||"[no visible text]"})]},m)}),u.length?null:e.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),u.length>j?e.jsxs("div",{className:"context-followup-actions",children:[e.jsx("button",{className:"toolbar-button",type:"button",onClick:I,children:x?`Show first ${h(j)} entries`:`Show all ${h(u.length)} returned entries`}),x?null:e.jsxs("span",{className:"context-entry-count-note",children:[h(L)," entries hidden in compact view"]})]}):null]})}function Qe({entry:t,onLoadCompactionHistory:n}){const s=A(),i=t.compaction;if(!(i!=null&&i.replacement_history_available))return null;const l=i.replacement_history??[],u=Number(i.replacement_entry_count??l.length);return e.jsxs("div",{className:"context-entry-compaction",children:[e.jsx("strong",{children:"Compaction detected"}),e.jsxs("span",{children:[h(u)," replacement history entries available."]}),l.length?e.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:l.map((o,p)=>e.jsxs("div",{className:"context-replacement-entry",children:[e.jsx("strong",{children:o.label||`Replacement item ${p+1}`}),e.jsx("pre",{children:o.text||"[no visible replacement text]"})]},`${o.label??"replacement"}-${p}`))}):e.jsx("div",{className:"context-entry-actions",children:e.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}function Ye({call:t,calls:n,onNavigateRecord:s,onCopyCallLink:i}){const u=A().t("button.copy_link","Copy link"),o=n.length?n:[t],p=Math.max(o.findIndex(d=>d.id===t.id),0),c=o.reduce((d,w)=>d+w.totalTokens,0),j=o.reduce((d,w)=>d+w.cost,0),b=o.reduce((d,w)=>d+w.cachedPct,0)/Math.max(o.length,1),x=o.filter(d=>Number(d.contextWindowPct??0)>=60).length,k=o.filter(d=>d.cachedPct<25||d.signal==="cache-risk").length;return e.jsxs("div",{className:"thread-context-module",children:[e.jsxs("div",{className:"drilldown-metric-grid wide",children:[e.jsx(f,{label:"Thread calls",value:h(o.length),detail:`selected ${p+1} of ${o.length}`}),e.jsx(f,{label:"Thread tokens",value:F(c),detail:"loaded aggregate rows"}),e.jsx(f,{label:"Thread cost",value:Q(j),detail:"estimated aggregate"}),e.jsx(f,{label:"Avg cache",value:U(b),detail:O(o.map(d=>d.model))}),e.jsx(f,{label:"Cache risks",value:h(k),detail:"weak reuse or flagged"}),e.jsx(f,{label:"Context pressure",value:h(x),detail:">=60% context window"})]}),e.jsxs("div",{className:"thread-context-grid",children:[e.jsxs("div",{children:[e.jsx("h3",{children:"Thread timeline"}),e.jsx(be,{selectedCall:t,calls:o,onOpenInvestigator:s,onCopyCallLink:i,className:"investigator-thread-timeline",copyAriaContext:"thread context call",copyLabel:u})]}),e.jsxs("dl",{className:"detail-list compact",children:[e.jsx(y,{label:"Project",value:t.project||"Unknown"}),e.jsx(y,{label:"Project path",value:t.projectRelativeCwd||t.cwd||"."}),e.jsx(y,{label:"Source line",value:de(t)}),e.jsx(y,{label:"Session",value:t.sessionId||"Not available"}),e.jsx(y,{label:"Parent thread",value:t.parentThread||"None"}),e.jsx(y,{label:"Models in thread",value:O(o.map(d=>d.model),{limit:3})}),e.jsx(y,{label:"Effort mix",value:O(o.map(d=>d.effort),{limit:3})})]})]})]})}function f({label:t,value:n,detail:s}){return e.jsxs("span",{className:"drilldown-metric",children:[e.jsx("small",{children:t}),e.jsx("strong",{children:n}),e.jsx("em",{children:s})]})}function y({label:t,value:n}){return e.jsxs("div",{children:[e.jsx("dt",{children:t}),e.jsx("dd",{children:n})]})}function Ze({call:t}){const s=[{label:"Cached input",value:Math.max(t.input-t.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:t.uncachedInput,color:"#f59e0b"},{label:"Output",value:t.output,color:"#059669"},{label:"Reasoning",value:t.reasoningOutput,color:"#7c3aed"}].filter(l=>l.value>0),i=Math.max(s.reduce((l,u)=>l+u.value,0),1);return e.jsxs("div",{className:"composition-card",children:[e.jsxs("div",{className:"composition-head",children:[e.jsx("strong",{children:"Token composition"}),e.jsxs("span",{children:[F(i)," visible tokens"]})]}),e.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(l=>e.jsx("i",{style:{width:`${Math.max(l.value/i*100,3)}%`,background:l.color}},l.label))}),e.jsx("div",{className:"composition-legend",children:s.map(l=>e.jsxs("span",{children:[e.jsx("i",{style:{background:l.color}}),l.label]},l.label))})]})}export{dt as CallInvestigatorPage}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js index 1dc1bd6f..f5e4e4f7 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/CallsPage.js @@ -1,16 +1,16 @@ -import{j as t,r as c}from"./dashboard-react.js";import{u as Lt}from"./useInfiniteQuery.js";import{c as kt,d as It}from"./exploreQueries.js";import{c as Re,W as $t,u as ce,j as O,C as Rt,a as dt,G as At,U as ut,H as Ot,X as ht,f as ee,Y as Ae,p as q,m as Oe,Z as Bt,_ as Vt,$ as Ht,a0 as Kt,D as zt,R as Ut,a1 as mt,E as qt,d as Gt,r as Qt,e as Wt,g as Yt}from"./App.js";import{r as Xt,u as Ze}from"./filtering.js";import{L as et}from"./LineChart.js";import{P as Z}from"./Panel.js";import{S as re}from"./StatusBadge.js";import{E as Jt}from"./EvidenceGrid.js";import{b as Zt,c as en}from"./tableActions.js";import{u as tn}from"./useQuery.js";import{d as tt,c as nn,a as nt,b as sn,e as an,f as st,r as at,l as on,g as rn,h as ln,i as it,j as ot,C as cn,k as dn,m as un,n as hn,o as mn,p as xn,q as pn,s as fn,t as gn,u as jn,T as xt,v as vn,w as bn}from"./contextEvidenceState.js";import{L as pt}from"./lock-keyhole.js";import{S as Cn}from"./search.js";import{S as yn}from"./shield-check.js";import{a as Sn}from"./EvidenceGridControls.js";import"./useBaseQuery.js";import"./queryOptions.js";import"./infiniteQueryOptions.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./index2.js";import"./rowActionEvents.js";/** +import{j as t,r as c}from"./dashboard-react.js";import{u as Lt}from"./useInfiniteQuery.js";import{c as kt,d as It}from"./exploreQueries.js";import{c as Re,W as $t,u as ce,j as O,C as Rt,a as dt,G as At,U as ut,H as Ot,X as ht,f as ee,Y as Ae,p as q,Z as Bt,m as Oe,_ as Vt,$ as Ht,a0 as Kt,a1 as zt,D as Ut,R as qt,a2 as mt,E as Gt,d as Qt,r as Wt,e as Yt,g as Xt}from"./App.js";import{r as Jt,u as Ze}from"./filtering.js";import{L as et}from"./LineChart.js";import{P as Z}from"./Panel.js";import{S as re}from"./StatusBadge.js";import{E as Zt}from"./EvidenceGrid.js";import{b as en,c as tn}from"./tableActions.js";import{u as nn}from"./useQuery.js";import{d as tt,c as sn,a as nt,b as an,e as on,f as st,r as at,l as rn,g as ln,h as cn,i as it,j as ot,C as dn,k as un,m as hn,n as mn,o as xn,p as pn,q as fn,s as gn,t as jn,u as vn,T as xt,v as bn,w as Cn}from"./contextEvidenceState.js";import{L as pt}from"./lock-keyhole.js";import{S as yn}from"./search.js";import{S as Sn}from"./shield-check.js";import{a as wn}from"./EvidenceGridControls.js";import"./useBaseQuery.js";import"./queryOptions.js";import"./infiniteQueryOptions.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";import"./index2.js";import"./rowActionEvents.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const wn=Re("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]);/** + */const Fn=Re("GitBranch",[["line",{x1:"6",x2:"6",y1:"3",y2:"15",key:"17qcm7"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}],["path",{d:"M18 9a9 9 0 0 1-9 9",key:"n2h4wq"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Fn=Re("PanelRightClose",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m8 9 3 3-3 3",key:"12hl5m"}]]);/** + */const Nn=Re("PanelRightClose",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m8 9 3 3-3 3",key:"12hl5m"}]]);/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. * See the LICENSE file in the root directory of this source tree. - */const Nn=Re("PanelRightOpen",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m10 15-3-3 3-3",key:"1pgupc"}]]);function Tn(e){const n=[],s=[e.localQuery.trim(),e.globalQuery.trim()].filter(Boolean);s.length&&n.push(`Search ${s.map(i=>`"${i}"`).join(" + ")}`),e.modelFilter!=="all"&&n.push(`Model ${e.modelFilter}`),e.effortFilter!=="all"&&n.push(`Effort ${e.effortFilter}`),e.confidenceFilter!=="all"&&n.push(`Confidence ${_n(e.confidenceFilter)}`),e.sourceFilter!=="all"&&n.push(`Source ${Ln(e.sourceFilter)}`),e.dateRangeStatus.invalid?n.push("Date range invalid"):(e.dateRangeStatus.active||e.timeFilter!=="all")&&n.push(e.dateRangeStatus.label||kn(e.timeFilter)),e.activePresetLabel&&n.push(`Preset ${e.activePresetLabel}`);const a=`Showing ${e.shownCount.toLocaleString()} of ${e.totalCount.toLocaleString()} aggregate rows`;return n.length?`${a} - Filters: ${n.join("; ")}`:a}function En(e,n){return n==="project"?`${e.project.toLocaleString()} project/cwd rows`:n==="session"?`${e.session.toLocaleString()} session-linked rows`:n==="git"?`${e.git.toLocaleString()} git rows`:n==="source-file"?`${e.sourceFile.toLocaleString()} source-file rows`:n==="missing"?`${e.missing.toLocaleString()} rows missing source`:`${e.project.toLocaleString()} project, ${e.session.toLocaleString()} session, ${e.git.toLocaleString()} git`}function Mn(e,n){return n==="all"?!0:n==="project"?Be(e):n==="session"?Ve(e):n==="git"?He(e):n==="source-file"?Ke(e):!ft(e)}function Dn(e,n){if(n==="all")return!0;if(n==="cost-exact")return!e.pricingEstimated&&Number.isFinite(e.cost)&&e.cost>0;if(n==="cost-estimated")return e.pricingEstimated;if(n==="cost-unpriced")return!e.pricingEstimated&&(!Number.isFinite(e.cost)||e.cost<=0);const s=e.usageCreditConfidence.toLowerCase();return n==="credit-exact"?s.includes("exact"):n==="credit-override"?s.includes("override"):n==="credit-estimated"?s.includes("estimated"):s.includes("missing")||s.includes("unpriced")}function Pn(e){return e.reduce((n,s)=>({project:n.project+(Be(s)?1:0),session:n.session+(Ve(s)?1:0),git:n.git+(He(s)?1:0),sourceFile:n.sourceFile+(Ke(s)?1:0),missing:n.missing+(ft(s)?0:1),total:n.total+1}),{project:0,session:0,git:0,sourceFile:0,missing:0,total:0})}function Be(e){return!!(e.project||e.projectRelativeCwd||e.cwd||e.projectTags.length)}function Ve(e){return!!(e.sessionId||e.turnId||e.parentSessionId)}function He(e){return!!(e.gitBranch||e.gitRemoteLabel||e.gitRemoteHash)}function Ke(e){return!!(e.sourceFile||e.lineNumber!==null)}function ft(e){return Be(e)||Ve(e)||He(e)||Ke(e)}function _n(e){return e==="cost-exact"?"exact cost":e==="cost-estimated"?"estimated cost":e==="cost-unpriced"?"unpriced cost":e==="credit-exact"?"exact credit rate":e==="credit-estimated"?"estimated credit mapping":e==="credit-override"?"user credit override":"missing credit rate"}function Ln(e){return e==="project"?"project/cwd":e==="session"?"session-linked":e==="git"?"git metadata":e==="source-file"?"source file":"missing source"}function kn(e){return e==="today"?"Today":e==="this-week"?"This week":e==="last-7-days"?"Last 7 days":e==="this-month"?"This month":e==="custom"?"Custom date range":"All time"}const oe="__detail_first__",In=new Set(["all","cost-exact","cost-estimated","cost-unpriced","credit-exact","credit-estimated","credit-override","credit-missing"]),$n=new Set(["all","today","this-week","last-7-days","this-month","custom"]),Rn=new Set(["all","project","session","git","source-file","missing"]),An=new Set(["time","duration","gap","attention","thread","initiator","model","effort","total","cached","uncached","output","reasoning","cost","usage","cache","context"]);function T(e,n=window.location.href){var s;return((s=new URL(n).searchParams.get(e))==null?void 0:s.trim())??""}function gt(e=window.location.href){const n=T("confidence",e)||T("pricing",e),s=Kn(n);return In.has(s)?s:"all"}function jt(e=window.location.href){const n=T("source",e);return Rn.has(n)?n:"all"}function vt(e=window.location.href){const n=T("date",e)||T("time",e);return $n.has(n)?n:"all"}function le(e,n=window.location.href){return Le(T(e,n))}function On(e=window.location.href){const n=T("record",e);return n||(T("detail",e)==="first"?oe:null)}function Pe(e=window.location.href){const n=T("sort",e);return bt(n)}function bt(e){return An.has(e)?e:"time"}function Ct(e,n=window.location.href){const s=T("direction",n);return s==="asc"||s==="desc"?s:U(e)}function Bn(e=window.location.href){return T("density",e)==="roomy"?"roomy":"dense"}function Vn(e,n=window.location.href){const s=Number(T("page",n)||1);return Number.isFinite(s)&&s>1?Math.floor(s)*e:e}function _e(e,n=window.location.href){const s=new URL(n);return s.searchParams.set("view","calls"),s.searchParams.delete("detail"),s.searchParams.delete("pricing"),k(s,"record",e.selectedRecordId,""),k(s,"call_q",e.localQuery.trim(),""),k(s,"model",e.modelFilter,"all"),k(s,"effort",e.effortFilter,"all"),k(s,"confidence",e.confidenceFilter,"all"),k(s,"source",e.sourceFilter,"all"),k(s,"time",e.timeFilter,"all"),k(s,"date",e.timeFilter,"all"),k(s,"from",e.timeFilter==="custom"?e.dateStart:"",""),k(s,"to",e.timeFilter==="custom"?e.dateEnd:"",""),k(s,"sort",e.sortKey,"time"),k(s,"direction",e.sortDirection,U(e.sortKey)),k(s,"density",e.density,"dense"),k(s,"page",String(Hn(e.visibleRowCount,e.pageSize)),"1"),s}function U(e){return e==="cache"||e==="effort"||e==="initiator"||e==="model"||e==="thread"?"asc":"desc"}function Le(e){const n=zn(e);return n?Un(n):""}function Hn(e,n){return Math.max(1,Math.ceil(Math.max(e,n)/n))}function k(e,n,s,a){if(!s||s===a){e.searchParams.delete(n);return}e.searchParams.set(n,s)}function Kn(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":e}function zn(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function Un(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(e,n){return e.filter(s=>qn(s,n))}function ke(e,n,s){return[...e].sort((a,i)=>Gn(a,i,n,s))}function ze(e,n,s,a){const i=Yn(a);if(e==="custom"){const o=lt(n),r=lt(s);return o&&r&&o>r?{active:!0,invalid:!0,start:o,endExclusive:K(r,1),label:"Invalid date range"}:{active:!!(o||r),invalid:!1,start:o,endExclusive:r?K(r,1):null,label:J("Custom",o,r)}}if(e==="today")return{active:!0,invalid:!1,start:i,endExclusive:K(i,1),label:J("Today",i,i)};if(e==="this-week"){const o=Xn(i);return{active:!0,invalid:!1,start:o,endExclusive:K(o,7),label:J("This week",o,K(o,6))}}if(e==="last-7-days"){const o=K(i,-6);return{active:!0,invalid:!1,start:o,endExclusive:K(i,1),label:J("Last 7 days",o,i)}}if(e==="this-month"){const o=new Date(i.getFullYear(),i.getMonth(),1),r=new Date(i.getFullYear(),i.getMonth()+1,1);return{active:!0,invalid:!1,start:o,endExclusive:r,label:J("This month",o,K(r,-1))}}return{active:!1,invalid:!1,start:null,endExclusive:null,label:"All time"}}function qn(e,n){if(n.modelFilter!=="all"&&e.model!==n.modelFilter||n.effortFilter!=="all"&&e.effort!==n.effortFilter||!Dn(e,n.confidenceFilter)||!Mn(e,n.sourceFilter)||!Jn(e,n.timeFilter,n.dateStart,n.dateEnd)||n.activePreset&&!$t(e,n.activePreset))return!1;const s=[e.thread,e.cwd,e.project,e.projectRelativeCwd,e.gitBranch,e.gitRemoteLabel,e.sessionId,e.model,e.effort,e.initiator,e.initiatorReason,e.signal,e.recommendation,e.rawTime,e.sourceFile,e.lineNumber,e.tags.join(" ")];return[n.globalQuery,n.localQuery].every(a=>Xt(s,a))}function Gn(e,n,s,a){const i=rt(e,s),o=rt(n,s);if(i===null&&o!==null)return 1;if(o===null&&i!==null)return-1;const r=Wn(i,o);return r!==0?a==="asc"?r:-r:Ie(e,n)||e.id.localeCompare(n.id)}function rt(e,n){return n==="time"?$e(e):n==="duration"?e.durationSeconds:n==="gap"?e.previousCallGapSeconds:n==="attention"?Qn(e):n==="thread"?e.thread.toLowerCase():n==="initiator"?e.initiator.toLowerCase():n==="model"?e.model.toLowerCase():n==="effort"?e.effort.toLowerCase():n==="total"?e.totalTokens:n==="cached"?e.input*(e.cachedPct/100):n==="uncached"?e.uncachedInput:n==="output"?e.output:n==="reasoning"?e.reasoningOutput:n==="cost"?e.cost:n==="usage"?e.credits:n==="cache"?e.cachedPct:e.contextWindowPct}function Qn(e){const n=e.signal&&e.signal!=="aggregate"?1e3:0,s=e.recommendation?750:0,a=e.contextWindowPct??0,i=Math.min(e.uncachedInput/1e3,250),o=Math.min(e.cost*25,200),r=Math.min(e.credits,200),h=Math.min(e.durationSeconds/60,120);return n+s+a+i+o+r+h}function Wn(e,n){return e===null&&n===null?0:e===null?1:n===null?-1:typeof e=="string"||typeof n=="string"?String(e).localeCompare(String(n)):e-n}function Ie(e,n){return $e(n)-$e(e)}function $e(e){const n=Date.parse(e.rawTime);return Number.isFinite(n)?n:0}function lt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function ct(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function J(e,n,s){const a=n?ct(n):"",i=s?ct(s):"";return a&&i&&a===i?`${e}: ${a}`:a&&i?`${e}: ${a} to ${i}`:a?`${e}: from ${a}`:i?`${e}: through ${i}`:e}function Yn(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function K(e,n){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+n)}function Xn(e){const n=e.getDay();return K(e,n===0?-6:1-n)}function Jn(e,n,s="",a="",i=new Date){if(n==="all")return!0;const o=ze(n,s,a,i);if(o.invalid)return!1;if(!o.active)return!0;const r=Date.parse(e.rawTime);return!(!Number.isFinite(r)||o.start&&r=o.endExclusive.getTime())}const Zn={time:"time",duration:"duration",gap:"gap",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"tokens",cached:"cached",uncached:"uncached",output:"output",reasoning:"reasoning",cache:"cache"};function es(e){const n=Zn[e.sortKey],s=ze(e.timeFilter,e.dateStart,e.dateEnd,new Date),a=ts(e,n,s.invalid);return{enabled:!a,reason:a,sort:n??"time",filters:{query:[e.globalQuery.trim(),e.localQuery.trim()].filter(Boolean).join(" "),model:e.modelFilter==="all"?void 0:e.modelFilter,effort:e.effortFilter==="all"?void 0:e.effortFilter,...ns(e.confidenceFilter),...ss(s.start,s.endExclusive,e.scopeSince)}}}function ts(e,n,s){return!e.enabled||e.runtime.fileMode||!e.runtime.apiToken?"Stored snapshot":e.globalQuery.trim()&&e.localQuery.trim()?"Multiple searches use loaded snapshot":e.activePreset?"Preset uses loaded snapshot":e.sourceFilter!=="all"?"Source filter uses loaded snapshot":n?s?"Invalid date range":"":"This sort uses loaded snapshot"}function ns(e){return e==="cost-exact"?{pricingStatus:"priced"}:e==="cost-estimated"?{pricingStatus:"estimated"}:e==="cost-unpriced"?{pricingStatus:"unpriced"}:e==="credit-exact"?{creditConfidence:"exact"}:e==="credit-estimated"?{creditConfidence:"estimated"}:e==="credit-override"?{creditConfidence:"user_override"}:e==="credit-missing"?{creditConfidence:"unpriced"}:{}}function ss(e,n,s){return{since:(e==null?void 0:e.toISOString())??s??void 0,until:n?new Date(n.getTime()-1).toISOString():void 0}}function as({data:e,valueLabel:n=s=>String(s)}){const s=Math.max(...e.map(a=>a.value),1);return t.jsx("div",{className:"bar-list",children:e.map(a=>t.jsxs("div",{className:"bar-row",children:[t.jsx("span",{children:a.label}),t.jsx("div",{className:"bar-track","aria-hidden":"true",children:t.jsx("i",{style:{width:`${a.value/s*100}%`,backgroundColor:a.color??"#2563eb"}})}),t.jsx("strong",{children:n(a.value)})]},a.label))})}function P({label:e,value:n,detail:s}){return t.jsxs("span",{className:"drilldown-metric",children:[t.jsx("small",{children:e}),t.jsx("strong",{children:n}),t.jsx("em",{children:s})]})}function S({label:e,value:n}){return t.jsxs("div",{children:[t.jsx("dt",{children:e}),t.jsx("dd",{children:n})]})}function is({call:e,contextRuntime:n,onContextApiEnabledChange:s}){const a=ce(),[i,o]=c.useState(()=>nn(e.id)??tt),[r,h]=c.useState({status:"idle"}),F=!!n.apiToken&&!n.fileMode,d=F&&n.contextApiEnabled;c.useEffect(()=>{const l=nt(e.id,i);h(l?{status:"loaded",payload:l}:{status:"idle"})},[e.id,i.includeCompactionHistory,i.includeToolOutput,i.maxChars,i.maxEntries,i.mode]);async function b(){h({status:"loading",message:"Enabling localhost context API..."});try{const l=await an(n);s(l),h({status:"idle",message:l?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(l){h({status:"error",message:st(l)})}}async function j(l=i,p="Loading selected-turn evidence..."){at(e.id,l);const w=nt(e.id,l);if(w){h({status:"loaded",payload:w});return}h({status:"loading",message:p});try{const g=await on(e.id,n,l);rn(e.id,l,g),h({status:"loaded",payload:g})}catch(g){h({status:"error",message:st(g)})}}function C(){const l={...i,mode:"full"};o(l),j(l,"Loading full turn analysis...")}function D(l){const p=xn(l,i);o(p),j(p,"Loading older context...")}function N(){const l={...i,includeToolOutput:!0};o(l),j(l,"Loading omitted tool output...")}function y(){const l={...i,includeCompactionHistory:!0};o(l),j(l,"Loading compacted replacement...")}function m(l,p){o(w=>{const g={...w,[l]:p};return at(e.id,g),g})}return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"locked-context-card",children:[t.jsx(pt,{size:20}),t.jsxs("div",{children:[t.jsx("strong",{children:"Raw context is gated"}),t.jsx("p",{children:sn(n)})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Record id",value:e.id}),t.jsx(S,{label:"Time",value:e.time}),t.jsx(S,{label:"Thread",value:e.thread}),t.jsx(S,{label:"Model",value:e.model}),t.jsx(S,{label:"Effort",value:e.effort})]}),t.jsxs("div",{className:"context-action-grid",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:b,disabled:!F||n.contextApiEnabled||r.status==="loading",children:a.t("button.enable_context_loading","Enable context loading")}),t.jsx("button",{className:"primary-button",type:"button",onClick:()=>j(),disabled:!d||r.status==="loading",children:a.t("button.show_turn_evidence","Show turn log evidence")}),t.jsx("button",{className:"toolbar-button",type:"button",onClick:C,disabled:!d||r.status==="loading",children:a.t("button.full_serialized_analysis","Run full serialized analysis")}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Mode"}),t.jsxs("select",{"aria-label":"Side panel context mode",value:i.mode,disabled:!d||r.status==="loading",onChange:l=>m("mode",l.target.value==="full"?"full":"quick"),children:[t.jsx("option",{value:"quick",children:"Quick"}),t.jsx("option",{value:"full",children:"Full"})]})]}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Entries"}),t.jsxs("select",{"aria-label":"Side panel context entries",value:String(i.maxEntries),disabled:!d||r.status==="loading",onChange:l=>m("maxEntries",Number(l.target.value)),children:[t.jsx("option",{value:"20",children:"20"}),t.jsx("option",{value:"50",children:"50"}),t.jsx("option",{value:"100",children:"100"}),t.jsx("option",{value:"0",children:"All"})]})]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeToolOutput,disabled:!d||r.status==="loading",onChange:l=>m("includeToolOutput",l.target.checked)}),a.t("button.include_tool_output","Include tool output")]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeCompactionHistory,disabled:!d||r.status==="loading",onChange:l=>m("includeCompactionHistory",l.target.checked)}),"Include compaction history"]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.maxChars===0,disabled:!d||r.status==="loading",onChange:l=>m("maxChars",l.target.checked?0:tt.maxChars)}),a.t("button.no_char_limit","No char limit")]})]}),r.status==="idle"&&r.message?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="loading"?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="error"?t.jsx("p",{className:"context-state-note error",children:r.message}):null,r.status==="loaded"?t.jsx(os,{call:e,payload:r.payload,onLoadOlder:D,onRunFullAnalysis:C,onLoadCompactionHistory:y,onLoadToolOutput:N}):null,t.jsx("p",{className:"privacy-note",children:"Raw context is never embedded in the dashboard HTML. This view reads the selected local JSONL turn only after an explicit request."})]})}function os({call:e,payload:n,onLoadOlder:s,onRunFullAnalysis:a,onLoadCompactionHistory:i,onLoadToolOutput:o}){var _,E;const r=ce(),h=n.entries??[],F=n.omitted??{},d=Number(F.older_entries??0),b=ln(n),j=8,C=e.id||String(n.record_id??""),[D,N]=c.useState(()=>it(C)),[y,m]=c.useState(()=>ot(C,h));c.useEffect(()=>{N(it(C)),m(ot(C,h))},[h.length,n.context_mode,n.include_compaction_history,n.include_tool_output,(_=n.omitted)==null?void 0:_.max_chars,(E=n.omitted)==null?void 0:E.max_entries,n.record_id,C]);const l=D?h:h.slice(0,j),p=Math.max(h.length-l.length,0);function w(){N(x=>{const L=!x;return fn(C,L),L})}function g(x,L){pn(C,x,L),m(v=>{const u=new Set(v);return L?u.add(x):u.delete(x),u})}return t.jsxs("div",{className:"context-evidence",children:[t.jsxs("div",{className:"context-evidence-summary",children:[t.jsx(P,{label:"Entries",value:O(h.length),detail:String(n.context_mode??"quick")}),t.jsx(P,{label:"Visible chars",value:O(Number(n.visible_char_count??0)),detail:"redacted local text"}),t.jsx(P,{label:"Visible tokens",value:O(Number(n.visible_token_estimate??0)),detail:"estimator"}),t.jsx(P,{label:"Older omitted",value:O(d),detail:"entry budget"})]}),b.length?t.jsx("p",{className:"context-note",children:b.join(" ")}):null,t.jsx(cn,{call:e,payload:n,onRunFullAnalysis:a}),d>0?t.jsx("div",{className:"context-followup-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>s(n),children:r.t("button.load_older_context","Load older entries")})}):null,t.jsxs("div",{className:"context-entry-list",children:[l.map((x,L)=>{const v=dn(x,L);return t.jsxs("details",{className:"context-entry",open:y.has(v),onToggle:u=>g(v,u.currentTarget.open),children:[t.jsx("summary",{className:"context-entry-summary",children:t.jsxs("div",{className:"context-entry-meta",children:[t.jsx("strong",{children:x.label||x.role||x.type||`Entry ${L+1}`}),t.jsx("span",{children:x.line_number?`line ${x.line_number}`:x.timestamp||"local evidence"})]})}),t.jsx(un,{entry:x}),x.tool_output_omitted?t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:o,children:r.t("button.show_tool_output","Show tool output")})}):null,t.jsx(rs,{entry:x,onLoadCompactionHistory:i}),t.jsx("pre",{ref:u=>{u&&(u.scrollTop=mn(C,v))},onScroll:u=>hn(C,v,u.currentTarget.scrollTop),children:x.text||"[no visible text]"})]},v)}),h.length?null:t.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),h.length>j?t.jsxs("div",{className:"context-followup-actions",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:w,children:D?`Show first ${O(j)} entries`:`Show all ${O(h.length)} returned entries`}),D?null:t.jsxs("span",{className:"context-entry-count-note",children:[O(p)," entries hidden in compact view"]})]}):null]})}function rs({entry:e,onLoadCompactionHistory:n}){const s=ce(),a=e.compaction;if(!(a!=null&&a.replacement_history_available))return null;const i=a.replacement_history??[],o=Number(a.replacement_entry_count??i.length);return t.jsxs("div",{className:"context-entry-compaction",children:[t.jsx("strong",{children:"Compaction detected"}),t.jsxs("span",{children:[O(o)," replacement history entries available."]}),i.length?t.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:i.map((r,h)=>t.jsxs("div",{className:"context-replacement-entry",children:[t.jsx("strong",{children:r.label||`Replacement item ${h+1}`}),t.jsx("pre",{children:r.text||"[no visible replacement text]"})]},`${r.label??"replacement"}-${h}`))}):t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}const ls=[{id:"summary",label:"Summary",icon:At},{id:"tokens",label:"Tokens",icon:ut},{id:"cache",label:"Cache",icon:Ot},{id:"thread",label:"Thread",icon:wn},{id:"evidence",label:"Evidence",icon:pt}];function cs({call:e,calls:n,contextRuntime:s,includeArchived:a,sourceRevision:i,hydrateThreadCalls:o,onContextApiEnabledChange:r,onOpenInvestigator:h,onCopyCallLink:F}){const[d,b]=c.useState("summary"),[j,C]=c.useState(""),D=c.useMemo(()=>e?n.filter(m=>m.thread===e.thread).sort(Ie):[],[e,n]),N=tn({...kt({runtime:s,includeArchived:a,sourceRevision:i,threadKey:(e==null?void 0:e.threadKey)||(e==null?void 0:e.thread)||"",selectedRecordId:(e==null?void 0:e.id)??"",selectedEventTimestamp:(e==null?void 0:e.eventTimestamp)??""}),enabled:o&&!s.fileMode&&!!s.apiToken&&!!e,placeholderData:m=>m}),y=c.useMemo(()=>{var l;const m=((l=N.data)==null?void 0:l.rows)??D;return!e||m.some(p=>p.id===e.id)?m:[...m,e].sort(Ie)},[e,D,N.data]);return e?t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsxs(Z,{title:"Call Drill-Down",subtitle:`${e.thread} / ${e.model}`,children:[t.jsxs("div",{className:"call-summary",children:[t.jsx(re,{label:"Aggregate only",tone:"green"}),t.jsx(Rt,{call:e}),t.jsx(re,{label:"Raw context gated",tone:"blue"}),t.jsx("span",{className:"call-id",children:e.id.slice(0,12)})]}),t.jsxs("div",{className:"action-row",children:[t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>h(e.id),children:[t.jsx(Cn,{size:16}),"Open investigator"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>ps(e,C),children:[t.jsx(dt,{size:16}),"Copy link"]})]}),j?t.jsx("p",{className:"context-state-note",children:j}):null,t.jsx("div",{className:"drilldown-tabs",role:"tablist","aria-label":"Call drill-down sections",children:ls.map(m=>{const l=m.icon,p=d===m.id;return t.jsxs("button",{type:"button",role:"tab","aria-selected":p,className:p?"active":"",onClick:()=>b(m.id),children:[t.jsx(l,{size:14}),m.label]},m.id)})}),t.jsxs("div",{className:"drilldown-tab-panel",role:"tabpanel",children:[d==="summary"?t.jsx(ds,{call:e}):null,d==="tokens"?t.jsx(hs,{call:e}):null,d==="cache"?t.jsx(ms,{call:e,calls:y}):null,d==="thread"?t.jsx(xs,{call:e,calls:y,onOpenInvestigator:h,onCopyCallLink:F}):null,d==="evidence"?t.jsx(is,{call:e,contextRuntime:s,onContextApiEnabledChange:r},e.id):null]})]})}):t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsx(Z,{title:"Call Drill-Down",subtitle:"No matching call",children:t.jsx("p",{className:"empty-state",children:"No aggregate row matches the active filters."})})})}function ds({call:e}){return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Total tokens",value:O(e.totalTokens),detail:`${ee(e.input)} input`}),t.jsx(P,{label:"Uncached input",value:O(e.uncachedInput),detail:"fresh billed input"}),t.jsx(P,{label:"Cache hit rate",value:q(e.cachedPct),detail:Ae(e)}),t.jsx(P,{label:"Estimated cost",value:Oe(e.cost),detail:e.pricingEstimated?"estimated pricing":"configured pricing"}),t.jsx(P,{label:"Duration",value:e.duration,detail:Bt(e)}),t.jsx(P,{label:"Usage credits",value:e.credits?e.credits.toFixed(3):"-",detail:e.usageCreditConfidence})]}),t.jsx(gn,{call:e}),t.jsx(jn,{call:e}),t.jsx(us,{call:e}),t.jsx(St,{call:e}),t.jsx(wt,{call:e}),e.recommendation?t.jsxs("div",{className:"recommendation-box",children:[t.jsx(yn,{size:16}),t.jsx("p",{children:e.recommendation})]}):null]})}function us({call:e}){return t.jsxs("div",{className:"composition-card accounting-snapshot-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Accounting Snapshot"}),t.jsx("span",{children:"pricing, credits, and cache savings"})]}),t.jsx(xt,{call:e})]})}function hs({call:e}){return t.jsxs(t.Fragment,{children:[t.jsx(St,{call:e}),t.jsx(xt,{call:e})]})}function ms({call:e,calls:n}){return t.jsxs(t.Fragment,{children:[t.jsx(wt,{call:e}),t.jsx(vn,{call:e,calls:n}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Cache state",value:Ae(e)}),t.jsx(S,{label:"Cache hit rate",value:q(e.cachedPct)}),t.jsx(S,{label:"Fresh share",value:q(Math.max(100-e.cachedPct,0))}),t.jsx(S,{label:"Signal",value:e.signal})]}),t.jsx("p",{className:"privacy-note",children:"Use this readout to decide whether the aggregate call needs deeper raw-context investigation."})]})}function xs({call:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a}){const i=n.reduce((b,j)=>b+j.totalTokens,0),o=n.reduce((b,j)=>b+j.cost,0),r=n.reduce((b,j)=>b+j.cachedPct,0)/Math.max(n.length,1),h=Math.max(n.findIndex(b=>b.id===e.id),0),F=Math.min(Math.max(n.length,1),5),d=e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available";return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Loaded thread calls",value:O(n.length),detail:`selected ${h+1} of ${n.length}`}),t.jsx(P,{label:"Thread tokens",value:ee(i),detail:"loaded aggregate rows"}),t.jsx(P,{label:"Thread cost",value:Oe(o),detail:"estimated aggregate"}),t.jsx(P,{label:"Avg cache",value:q(r),detail:Vt(n.map(b=>b.model),{style:"x",emptyLabel:"no model mix"})}),t.jsx(P,{label:"Context window",value:e.contextWindowPct===null?"-":q(e.contextWindowPct),detail:e.modelContextWindow?`${ee(e.modelContextWindow)} window`:"not reported"}),t.jsx(P,{label:"Parent thread",value:e.parentThread||"-",detail:e.parentSessionId||"no parent session"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Thread timeline"}),t.jsxs("span",{children:[F," nearby loaded calls"]})]}),t.jsx(bn,{selectedCall:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a,copyAriaContext:"side-panel thread call"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Call Narrative"}),t.jsx("span",{children:e.initiatorConfidence||"aggregate inference"})]}),t.jsxs("dl",{className:"detail-list compact",children:[t.jsx(S,{label:"Initiated by",value:e.initiator||"unknown"}),t.jsx(S,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),t.jsx(S,{label:"Parent thread",value:e.parentThread||"None"}),t.jsx(S,{label:"Parent session",value:e.parentSessionId||"None"}),t.jsx(S,{label:"Timestamp",value:e.time}),t.jsx(S,{label:"Duration",value:e.duration}),t.jsx(S,{label:"Previous gap",value:e.previousCallGap})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Project",value:e.project||"Unknown"}),t.jsx(S,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),t.jsx(S,{label:"Source line",value:d}),t.jsx(S,{label:"Session",value:e.sessionId||"Not available"}),t.jsx(S,{label:"Git branch",value:e.gitBranch||"Unknown"}),t.jsx(S,{label:"Remote",value:e.gitRemoteLabel||e.gitRemoteHash||"None"})]})]})}function St({call:e}){const s=[{label:"Cached input",value:Math.max(e.input-e.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:e.uncachedInput,color:"#f59e0b"},{label:"Output",value:e.output,color:"#059669"},{label:"Reasoning",value:e.reasoningOutput,color:"#7c3aed"}].filter(i=>i.value>0),a=Math.max(s.reduce((i,o)=>i+o.value,0),1);return t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Token composition"}),t.jsxs("span",{children:[ee(a)," visible tokens"]})]}),t.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(i=>t.jsx("i",{style:{width:`${Math.max(i.value/a*100,3)}%`,background:i.color}},i.label))}),t.jsx("div",{className:"composition-legend",children:s.map(i=>t.jsxs("span",{children:[t.jsx("i",{style:{background:i.color}}),i.label]},i.label))})]})}function wt({call:e}){const n=[{label:"Cache",value:Math.min(Math.max(e.cachedPct,0),100),color:"#2563eb"},{label:"Fresh",value:Math.min(Math.max(100-e.cachedPct,0),100),color:"#f59e0b"},{label:"Output",value:Math.min(Math.max(e.output/Math.max(e.totalTokens,1)*100,0),100),color:"#059669"}];return t.jsxs("div",{className:"cache-mini-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"Cache delta readout"}),t.jsx("span",{children:Ae(e)})]}),t.jsx("div",{className:"cache-bars","aria-label":"Cache delta readout",children:n.map(s=>t.jsxs("span",{children:[t.jsx("i",{style:{height:`${Math.max(s.value,4)}%`,background:s.color}}),t.jsx("em",{children:s.label})]},s.label))})]})}async function ps(e,n){try{const s=new URL(window.location.href);if(s.searchParams.set("view","call"),s.searchParams.set("record",e.id),s.searchParams.set("return","calls"),!await ht(s.toString()))throw new Error("Clipboard unavailable");n("Copied investigator link")}catch{n("Copy unavailable in this browser")}}const fs="_page_gyxvc_1",gs="_pageHeader_gyxvc_5",js="_tableHeading_gyxvc_13",vs="_eyebrow_gyxvc_22",bs="_headerActions_gyxvc_36",Cs="_tableActions_gyxvc_37",ys="_gridFooter_gyxvc_38",Ss="_queryBar_gyxvc_46",ws="_advancedFilters_gyxvc_80",Fs="_patternsDisclosure_gyxvc_85",Ns="_advancedFilterGrid_gyxvc_107",Ts="_gridColumn_gyxvc_138",$={page:fs,pageHeader:gs,tableHeading:js,eyebrow:vs,headerActions:bs,tableActions:Cs,gridFooter:ys,queryBar:Ss,advancedFilters:ws,patternsDisclosure:Fs,advancedFilterGrid:Ns,gridColumn:Ts};function Es({searchInputRef:e,localQuery:n,modelFilter:s,effortFilter:a,confidenceFilter:i,sourceFilter:o,timeFilter:r,dateStart:h,dateEnd:F,sortKey:d,sortDirection:b,modelOptions:j,effortOptions:C,sourceCoverage:D,dateRangeStatus:N,onLocalQueryChange:y,onModelFilterChange:m,onEffortFilterChange:l,onConfidenceFilterChange:p,onSourceFilterChange:w,onTimeFilterChange:g,onDateStartChange:_,onDateEndChange:E,onSortKeyChange:x,onSortDirectionChange:L,onClear:v}){return t.jsxs("section",{className:$.queryBar,"aria-label":"Call filters",children:[t.jsxs("label",{className:"search-box",children:[t.jsx("span",{className:"sr-only",children:"Search calls"}),t.jsx("input",{ref:e,value:n,onChange:u=>y(u.target.value),placeholder:"Search calls, cwd, projects, models..."})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Model"}),t.jsxs("select",{value:s,onChange:u=>m(u.target.value),children:[t.jsx("option",{value:"all",children:"All models"}),j.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Effort"}),t.jsxs("select",{value:a,onChange:u=>l(u.target.value),children:[t.jsx("option",{value:"all",children:"All effort"}),C.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Confidence"}),t.jsxs("select",{"aria-label":"Confidence filter",value:i,onChange:u=>p(u.target.value),children:[t.jsx("option",{value:"all",children:"All confidence"}),t.jsx("option",{value:"cost-exact",children:"Exact cost"}),t.jsx("option",{value:"cost-estimated",children:"Estimated cost"}),t.jsx("option",{value:"cost-unpriced",children:"Unpriced cost"}),t.jsx("option",{value:"credit-exact",children:"Exact credit rate"}),t.jsx("option",{value:"credit-estimated",children:"Estimated credit mapping"}),t.jsx("option",{value:"credit-override",children:"User credit override"}),t.jsx("option",{value:"credit-missing",children:"Missing credit rate"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Time"}),t.jsxs("select",{"aria-label":"Time filter",value:r,onChange:u=>g(u.target.value),children:[t.jsx("option",{value:"all",children:"All time"}),t.jsx("option",{value:"today",children:"Today"}),t.jsx("option",{value:"this-week",children:"This week"}),t.jsx("option",{value:"last-7-days",children:"Last 7 days"}),t.jsx("option",{value:"this-month",children:"This month"}),t.jsx("option",{value:"custom",children:"Custom range"})]}),N.active||N.invalid?t.jsx("span",{className:"filter-status","data-state":N.invalid?"error":"active","aria-live":"polite",children:N.label}):null]}),t.jsxs("details",{className:$.advancedFilters,children:[t.jsxs("summary",{children:[t.jsx(Ht,{size:16}),"More filters"]}),t.jsxs("div",{className:$.advancedFilterGrid,children:[t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Source"}),t.jsxs("select",{"aria-label":"Source filter",value:o,onChange:u=>w(u.target.value),children:[t.jsx("option",{value:"all",children:"All sources"}),t.jsx("option",{value:"project",children:"Project / cwd"}),t.jsx("option",{value:"session",children:"Session-linked"}),t.jsx("option",{value:"git",children:"Git metadata"}),t.jsx("option",{value:"source-file",children:"Source file"}),t.jsx("option",{value:"missing",children:"Missing source"})]}),t.jsx("span",{className:"filter-status","data-state":o==="all"?"active":"filtered","aria-live":"polite",children:En(D,o)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Start"}),t.jsx("input",{"aria-label":"Start date",type:"date",value:h,onChange:u=>_(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"End"}),t.jsx("input",{"aria-label":"End date",type:"date",value:F,onChange:u=>E(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Sort"}),t.jsxs("select",{"aria-label":"Sort calls",value:d,onChange:u=>x(u.target.value),children:[t.jsx("option",{value:"time",children:"Newest calls"}),t.jsx("option",{value:"duration",children:"Longest duration"}),t.jsx("option",{value:"gap",children:"Longest gap"}),t.jsx("option",{value:"attention",children:"Needs attention"}),t.jsx("option",{value:"thread",children:"Thread name"}),t.jsx("option",{value:"initiator",children:"Initiated"}),t.jsx("option",{value:"model",children:"Model"}),t.jsx("option",{value:"effort",children:"Reasoning"}),t.jsx("option",{value:"total",children:"Most tokens"}),t.jsx("option",{value:"cached",children:"Cached"}),t.jsx("option",{value:"uncached",children:"Uncached"}),t.jsx("option",{value:"output",children:"Output"}),t.jsx("option",{value:"reasoning",children:"Reasoning output"}),t.jsx("option",{value:"cost",children:"Highest estimated cost"}),t.jsx("option",{value:"usage",children:"Highest Codex credits"}),t.jsx("option",{value:"cache",children:"Lowest cache ratio"}),t.jsx("option",{value:"context",children:"Highest context use"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Direction"}),t.jsxs("select",{"aria-label":"Sort direction",value:b,onChange:u=>L(u.target.value),children:[t.jsx("option",{value:"desc",children:"Descending"}),t.jsx("option",{value:"asc",children:"Ascending"})]})]})]})]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:v,children:[t.jsx(Kt,{size:16}),"Clear filters"]})]})}function Ms({workspaceSwitcher:e,canExport:n,onExport:s,onCopyView:a,onRefresh:i}){return t.jsxs("header",{className:$.pageHeader,children:[t.jsxs("div",{children:[t.jsx("p",{className:$.eyebrow,children:"Evidence explorer"}),t.jsx("h1",{children:"Calls"}),t.jsx("p",{children:"Find expensive, cold, or context-heavy calls and move directly into their evidence."})]}),t.jsxs("div",{className:$.headerActions,children:[e,t.jsxs("button",{className:"toolbar-button",type:"button",onClick:s,disabled:!n,children:[t.jsx(zt,{size:16}),"Export"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:a,children:[t.jsx(dt,{size:16}),"Copy view"]}),t.jsxs("button",{className:"primary-button",type:"button",onClick:i,children:[t.jsx(Ut,{size:16}),"Refresh"]})]})]})}const Ft="codexUsageDetailPanel";function Ds(e=!1){var n;try{const s=(n=window.sessionStorage)==null?void 0:n.getItem(Ft);return s?s==="expanded":e}catch{return e}}function Ps(e){var n;try{(n=window.sessionStorage)==null||n.setItem(Ft,e?"expanded":"collapsed")}catch{}}const B=250;function _s(e,n){const s=T("density"),[a,i]=c.useState(()=>T("call_q")),[o,r]=c.useState(()=>T("model")||"all"),[h,F]=c.useState(()=>T("effort")||"all"),[d,b]=c.useState(()=>gt()),[j,C]=c.useState(()=>jt()),[D,N]=c.useState(()=>vt()),[y,m]=c.useState(()=>le("from")),[l,p]=c.useState(()=>le("to")),[w,g]=c.useState(()=>Pe()),[_,E]=c.useState(()=>Ct(Pe())),x=Sn("codexUsageCallsEvidenceGrid",{density:Bn()==="dense"?"compact":"comfortable",columnVisibility:{}},s==="roomy"?"comfortable":s==="dense"?"compact":void 0),L=x.density==="compact"?"dense":"roomy",v=c.useMemo(()=>On(),[]),[u,te]=c.useState(v),[G,R]=c.useState(()=>Vn(B)),[ne,Q]=c.useState(""),[de,ue]=c.useState(""),[W,he]=c.useState(()=>Ds(!!v)),me=c.useRef(null),se=c.useRef(n),xe=c.useMemo(()=>Ze(e.calls.map(f=>f.model)),[e.calls]),pe=c.useMemo(()=>Ze(e.calls.map(f=>f.effort)),[e.calls]),fe=c.useMemo(()=>Pn(e.calls),[e.calls]),Y=c.useMemo(()=>ze(D,y,l,new Date),[l,y,D]);c.useEffect(()=>{se.current!==n&&(se.current=n,R(B))},[n]);function I(){R(B)}function ge(f){i(f),I()}function je(f){r(f),I()}function ve(f){F(f),I()}function be(f){b(f),I()}function Ce(f){C(f),I()}function ye(f){N(f),I()}function Se(f){m(Le(f)),N("custom"),I()}function we(f){p(Le(f)),N("custom"),I()}function Fe(f){const A=bt(f);g(A),E(U(A)),I()}function Ne(f){E(f==="asc"?"asc":"desc"),I()}function Te(){i(""),r("all"),F("all"),b("all"),C("all"),N("all"),m(""),p(""),g("time"),E(U("time")),x.setDensity("compact"),x.setColumnVisibility({}),te(null),R(B),window.history.replaceState(null,"",_e({localQuery:"",modelFilter:"all",effortFilter:"all",confidenceFilter:"all",sourceFilter:"all",timeFilter:"all",dateStart:"",dateEnd:"",sortKey:"time",sortDirection:U("time"),density:"dense",selectedRecordId:"",visibleRowCount:B,pageSize:B})),ue("Calls filters cleared")}function Ee(){he(f=>{const A=!f;return Ps(A),A})}return{localQuery:a,modelFilter:o,effortFilter:h,confidenceFilter:d,sourceFilter:j,timeFilter:D,dateStart:y,dateEnd:l,sortKey:w,setSortKey:g,sortDirection:_,setSortDirection:E,gridPreferences:x,density:L,initialSelectedCallId:v,selectedCallId:u,setSelectedCallId:te,visibleCallRows:G,setVisibleCallRows:R,exportStatus:ne,setExportStatus:Q,filterStatus:de,detailsExpanded:W,searchInputRef:me,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}}function Ls({model:e,header:n,filters:s,table:a,inspector:i}){var F;const o=ce(),r=o.t("dashboard.model_calls","Model Calls"),h=o.t("dashboard.model_calls","Model calls");return t.jsxs("div",{className:`${$.page} page-grid`,children:[t.jsx(Ms,{...n}),t.jsx(Es,{...s}),t.jsxs("div",{className:$.tableHeading,children:[t.jsxs("div",{children:[t.jsx("h2",{children:r}),t.jsx("p",{children:a.exportStatus||a.filterStatus||a.subtitle})]}),t.jsxs("div",{className:$.tableActions,children:[t.jsx(re,{label:ks(a.isFetching,a.focused,a.focusedReason),tone:a.focused?"green":"blue"}),t.jsx(re,{label:a.activePreset?`Preset: ${mt(a.activePreset)}`:"Raw context gated",tone:a.activePreset?"green":"blue"}),t.jsxs("button",{className:"toolbar-button",type:"button","aria-expanded":a.detailsExpanded,onClick:a.onToggleDetails,children:[a.detailsExpanded?t.jsx(Fn,{size:16}):t.jsx(Nn,{size:16}),a.detailsExpanded?o.t("button.hide_details","Hide details"):o.t("dashboard.call_details","Call Details")]})]})]}),t.jsxs("div",{className:a.detailsExpanded?"table-detail-layout":"table-detail-layout detail-collapsed",children:[t.jsxs("div",{className:$.gridColumn,children:[t.jsx(Jt,{ariaLabel:h,columns:a.columns,data:a.calls,identityColumnId:"thread",lockedColumnIds:["investigate"],getRowId:d=>d.id,mobile:{primary:d=>d.thread,secondary:d=>o.translateText(`${d.time} · ${d.model} · ${ee(d.totalTokens)} tokens · ${q(d.cachedPct)} cache`),actionLabel:d=>Zt(d)},sorting:a.sorting,onSortingChange:a.onSortingChange,manualSorting:!0,columnVisibility:a.gridPreferences.columnVisibility,onColumnVisibilityChange:a.gridPreferences.setColumnVisibility,density:a.gridPreferences.density,onDensityChange:a.gridPreferences.setDensity,onRestoreDefaults:a.gridPreferences.restoreDefaults,selectedRowId:(F=a.selectedCall)==null?void 0:F.id,onRowSelect:d=>a.onSelectCall(d.id),onRowActivate:d=>i.onOpenInvestigator(d.id),activateOnClick:!0,selectOnHover:!0,viewportHeight:560,emptyLabel:"No rows match current filters."}),t.jsxs("div",{className:$.gridFooter,"aria-live":"polite",children:[t.jsx("span",{children:o.translateText(`${a.calls.length.toLocaleString()} loaded / ${a.totalMatchedCalls.toLocaleString()} matched`)}),a.focused&&a.hasNextPage?t.jsx("button",{className:"toolbar-button",type:"button",onClick:a.onLoadMore,disabled:a.isFetchingNextPage,children:a.isFetchingNextPage?"Loading more...":`Load ${B.toLocaleString()} more`}):null]})]}),a.detailsExpanded?t.jsx(cs,{call:a.selectedCall,calls:e.calls,...i}):null]}),t.jsxs("details",{className:$.patternsDisclosure,children:[t.jsxs("summary",{children:[t.jsx(ut,{size:17}),"Usage patterns"]}),t.jsxs("div",{className:"dashboard-grid three",children:[t.jsx(Z,{title:"Usage Over Time",subtitle:"Tokens",children:t.jsx(et,{series:e.tokenSeries,yLabel:"Tokens",height:220})}),t.jsx(Z,{title:"Cost by Model",subtitle:"Estimated USD",children:t.jsx(as,{data:e.modelCosts,valueLabel:Oe})}),t.jsx(Z,{title:"Cache Hit Rate Over Time",subtitle:o.translateText("Daily"),children:t.jsx(et,{series:e.cacheSeries,yLabel:"Cache %",height:220,valueFormatter:d=>`${d}%`})})]})]})]})}function ks(e,n,s){return e&&n?"Updating focused rows":e?"Loading focused rows":n?"Focused paged API":s||"Stored snapshot"}function oa(e,n="",s=""){const a=Pe();return ke(yt(e,{globalQuery:n,localQuery:T("call_q"),modelFilter:T("model")||"all",effortFilter:T("effort")||"all",confidenceFilter:gt(),sourceFilter:jt(),timeFilter:vt(),dateStart:le("from"),dateEnd:le("to"),activePreset:s}),a,Ct(a))}const Nt={time:"time",duration:"duration",gap:"previousCallGap",attention:"signal",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"totalTokens",cached:"cachedInput",uncached:"uncachedInput",output:"output",reasoning:"reasoningOutput",cost:"cost",usage:"credits",cache:"cachedPct",context:"contextWindowPct"},Is=Object.fromEntries(Object.entries(Nt).map(([e,n])=>[n,e]));function ra({model:e,globalQuery:n,activePreset:s,onRefresh:a,contextRuntime:i,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h,includeArchived:F=!1,sourceKey:d,sourceRevision:b="",scopeSince:j=null,focusedEndpointsEnabled:C=!0,workspaceSwitcher:D}){var We,Ye;const N=_s(e,n),{localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,setSortKey:L,sortDirection:v,setSortDirection:u,gridPreferences:te,density:G,selectedCallId:R,setSelectedCallId:ne,visibleCallRows:Q,setVisibleCallRows:de,exportStatus:ue,setExportStatus:W,filterStatus:he,detailsExpanded:me,searchInputRef:se,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}=N,f=c.useMemo(()=>[...qt,en({onOpenInvestigator:r,onCopyCallLink:h})],[h,r]),A=c.useMemo(()=>es({runtime:i,enabled:C,activePreset:s,sourceFilter:w,sortKey:x,scopeSince:j,timeFilter:g,dateStart:_,dateEnd:E,confidenceFilter:p,globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l}),[s,p,i,E,_,l,C,n,y,m,x,w,j,g]),V=Lt({...It({runtime:i,includeArchived:F,sourceKey:d,sourceRevision:b,filters:A.filters,sort:A.sort,direction:v,pageSize:B}),enabled:A.enabled,placeholderData:M=>M}),Ue=c.useMemo(()=>yt(e.calls,{globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,activePreset:s}),[s,p,E,_,l,n,y,e.calls,m,w,g]),qe=c.useMemo(()=>ke(Ue,x,v),[Ue,v,x]),Ge=c.useMemo(()=>{var M;return((M=V.data)==null?void 0:M.pages.flatMap(X=>X.rows))??[]},[V.data]),ae=A.enabled&&!!V.data,H=c.useMemo(()=>ae?ke(Ge,x,v):qe,[Ge,qe,v,x,ae]),Me=ae?((Ye=(We=V.data)==null?void 0:We.pages[0])==null?void 0:Ye.totalMatchedRows)??H.length:e.calls.length,Tt=c.useMemo(()=>Tn({shownCount:H.length,totalCount:Me,localQuery:y,globalQuery:n,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateRangeStatus:Y,activePresetLabel:s?mt(s):""}),[s,p,Y,l,n,y,m,H.length,w,g,Me]),Qe=c.useMemo(()=>[{id:Nt[x],desc:v==="desc"}],[v,x]),ie=R===oe?H[0]??null:H.find(M=>M.id===R)??H[0]??null,z=ie&&(ie.id===R||R===oe)?ie.id:"";c.useEffect(()=>{R===oe&&z&&ne(z)},[R,z]),c.useEffect(()=>{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});M.toString()!==window.location.href&&window.history.replaceState(null,"",M)},[p,E,_,G,l,y,m,z,v,x,w,g,Q]);function Et(){Gt(`codex-calls-${Yt()}.csv`,Qt(H,Wt)),W(`Exported ${H.length} calls`)}async function Mt(){try{const M=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});if(!await ht(M.toString()))throw new Error("Clipboard unavailable");W("Copied Calls view link")}catch{W("Copy unavailable in browser")}}function Dt(M){var Xe,Je;const X=typeof M=="function"?M(Qe):M,De=Is[((Xe=X[0])==null?void 0:Xe.id)??""]??"time",_t=De!==x;L(De),u(_t?U(De):(Je=X[0])!=null&&Je.desc?"desc":"asc"),I()}async function Pt(){!V.hasNextPage||V.isFetchingNextPage||(await V.fetchNextPage(),de(M=>M+B))}return t.jsx(Ls,{model:e,header:{workspaceSwitcher:D,canExport:!!H.length,onExport:Et,onCopyView:Mt,onRefresh:a},filters:{searchInputRef:se,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,onLocalQueryChange:ge,onModelFilterChange:je,onEffortFilterChange:ve,onConfidenceFilterChange:be,onSourceFilterChange:Ce,onTimeFilterChange:ye,onDateStartChange:Se,onDateEndChange:we,onSortKeyChange:Fe,onSortDirectionChange:Ne,onClear:Te},table:{activePreset:s,exportStatus:ue,filterStatus:he,subtitle:Tt,focused:ae,focusedReason:A.reason,isFetching:V.isFetching,isFetchingNextPage:V.isFetchingNextPage,hasNextPage:!!V.hasNextPage,detailsExpanded:me,calls:H,totalMatchedCalls:Me,columns:f,sorting:Qe,gridPreferences:te,selectedCall:ie,onSortingChange:Dt,onSelectCall:ne,onLoadMore:Pt,onToggleDetails:Ee},inspector:{contextRuntime:i,includeArchived:F,sourceRevision:b,hydrateThreadCalls:C,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h}})}export{ra as CallsPage,oa as callsForCurrentUrl}; + */const Tn=Re("PanelRightOpen",[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M15 3v18",key:"14nvp0"}],["path",{d:"m10 15-3-3 3-3",key:"1pgupc"}]]);function En(e){const n=[],s=[e.localQuery.trim(),e.globalQuery.trim()].filter(Boolean);s.length&&n.push(`Search ${s.map(i=>`"${i}"`).join(" + ")}`),e.modelFilter!=="all"&&n.push(`Model ${e.modelFilter}`),e.effortFilter!=="all"&&n.push(`Effort ${e.effortFilter}`),e.confidenceFilter!=="all"&&n.push(`Confidence ${Ln(e.confidenceFilter)}`),e.sourceFilter!=="all"&&n.push(`Source ${kn(e.sourceFilter)}`),e.dateRangeStatus.invalid?n.push("Date range invalid"):(e.dateRangeStatus.active||e.timeFilter!=="all")&&n.push(e.dateRangeStatus.label||In(e.timeFilter)),e.activePresetLabel&&n.push(`Preset ${e.activePresetLabel}`);const a=`Showing ${e.shownCount.toLocaleString()} of ${e.totalCount.toLocaleString()} aggregate rows`;return n.length?`${a} - Filters: ${n.join("; ")}`:a}function Dn(e,n){return n==="project"?`${e.project.toLocaleString()} project/cwd rows`:n==="session"?`${e.session.toLocaleString()} session-linked rows`:n==="git"?`${e.git.toLocaleString()} git rows`:n==="source-file"?`${e.sourceFile.toLocaleString()} source-file rows`:n==="missing"?`${e.missing.toLocaleString()} rows missing source`:`${e.project.toLocaleString()} project, ${e.session.toLocaleString()} session, ${e.git.toLocaleString()} git`}function Mn(e,n){return n==="all"?!0:n==="project"?Be(e):n==="session"?Ve(e):n==="git"?He(e):n==="source-file"?Ke(e):!ft(e)}function Pn(e,n){if(n==="all")return!0;if(n==="cost-exact")return!e.pricingEstimated&&Number.isFinite(e.cost)&&e.cost>0;if(n==="cost-estimated")return e.pricingEstimated;if(n==="cost-unpriced")return!e.pricingEstimated&&(!Number.isFinite(e.cost)||e.cost<=0);const s=e.usageCreditConfidence.toLowerCase();return n==="credit-exact"?s.includes("exact"):n==="credit-override"?s.includes("override"):n==="credit-estimated"?s.includes("estimated"):s.includes("missing")||s.includes("unpriced")}function _n(e){return e.reduce((n,s)=>({project:n.project+(Be(s)?1:0),session:n.session+(Ve(s)?1:0),git:n.git+(He(s)?1:0),sourceFile:n.sourceFile+(Ke(s)?1:0),missing:n.missing+(ft(s)?0:1),total:n.total+1}),{project:0,session:0,git:0,sourceFile:0,missing:0,total:0})}function Be(e){return!!(e.project||e.projectRelativeCwd||e.cwd||e.projectTags.length)}function Ve(e){return!!(e.sessionId||e.turnId||e.parentSessionId)}function He(e){return!!(e.gitBranch||e.gitRemoteLabel||e.gitRemoteHash)}function Ke(e){return!!(e.sourceFile||e.lineNumber!==null)}function ft(e){return Be(e)||Ve(e)||He(e)||Ke(e)}function Ln(e){return e==="cost-exact"?"exact cost":e==="cost-estimated"?"estimated cost":e==="cost-unpriced"?"unpriced cost":e==="credit-exact"?"exact credit rate":e==="credit-estimated"?"estimated credit mapping":e==="credit-override"?"user credit override":"missing credit rate"}function kn(e){return e==="project"?"project/cwd":e==="session"?"session-linked":e==="git"?"git metadata":e==="source-file"?"source file":"missing source"}function In(e){return e==="today"?"Today":e==="this-week"?"This week":e==="last-7-days"?"Last 7 days":e==="this-month"?"This month":e==="custom"?"Custom date range":"All time"}const oe="__detail_first__",$n=new Set(["all","cost-exact","cost-estimated","cost-unpriced","credit-exact","credit-estimated","credit-override","credit-missing"]),Rn=new Set(["all","today","this-week","last-7-days","this-month","custom"]),An=new Set(["all","project","session","git","source-file","missing"]),On=new Set(["time","duration","gap","attention","thread","initiator","model","effort","total","cached","uncached","output","reasoning","cost","usage","cache","context"]);function T(e,n=window.location.href){var s;return((s=new URL(n).searchParams.get(e))==null?void 0:s.trim())??""}function gt(e=window.location.href){const n=T("confidence",e)||T("pricing",e),s=zn(n);return $n.has(s)?s:"all"}function jt(e=window.location.href){const n=T("source",e);return An.has(n)?n:"all"}function vt(e=window.location.href){const n=T("date",e)||T("time",e);return Rn.has(n)?n:"all"}function le(e,n=window.location.href){return Le(T(e,n))}function Bn(e=window.location.href){const n=T("record",e);return n||(T("detail",e)==="first"?oe:null)}function Pe(e=window.location.href){const n=T("sort",e);return bt(n)}function bt(e){return On.has(e)?e:"time"}function Ct(e,n=window.location.href){const s=T("direction",n);return s==="asc"||s==="desc"?s:U(e)}function Vn(e=window.location.href){return T("density",e)==="roomy"?"roomy":"dense"}function Hn(e,n=window.location.href){const s=Number(T("page",n)||1);return Number.isFinite(s)&&s>1?Math.floor(s)*e:e}function _e(e,n=window.location.href){const s=new URL(n);return s.searchParams.set("view","calls"),s.searchParams.delete("detail"),s.searchParams.delete("pricing"),k(s,"record",e.selectedRecordId,""),k(s,"call_q",e.localQuery.trim(),""),k(s,"model",e.modelFilter,"all"),k(s,"effort",e.effortFilter,"all"),k(s,"confidence",e.confidenceFilter,"all"),k(s,"source",e.sourceFilter,"all"),k(s,"time",e.timeFilter,"all"),k(s,"date",e.timeFilter,"all"),k(s,"from",e.timeFilter==="custom"?e.dateStart:"",""),k(s,"to",e.timeFilter==="custom"?e.dateEnd:"",""),k(s,"sort",e.sortKey,"time"),k(s,"direction",e.sortDirection,U(e.sortKey)),k(s,"density",e.density,"dense"),k(s,"page",String(Kn(e.visibleRowCount,e.pageSize)),"1"),s}function U(e){return e==="cache"||e==="effort"||e==="initiator"||e==="model"||e==="thread"?"asc":"desc"}function Le(e){const n=Un(e);return n?qn(n):""}function Kn(e,n){return Math.max(1,Math.ceil(Math.max(e,n)/n))}function k(e,n,s,a){if(!s||s===a){e.searchParams.delete(n);return}e.searchParams.set(n,s)}function zn(e){return e==="official"?"cost-exact":e==="estimated"?"cost-estimated":e==="unpriced"?"cost-unpriced":e}function Un(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function qn(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function yt(e,n){return e.filter(s=>Gn(s,n))}function ke(e,n,s){return[...e].sort((a,i)=>Qn(a,i,n,s))}function ze(e,n,s,a){const i=Xn(a);if(e==="custom"){const o=lt(n),r=lt(s);return o&&r&&o>r?{active:!0,invalid:!0,start:o,endExclusive:K(r,1),label:"Invalid date range"}:{active:!!(o||r),invalid:!1,start:o,endExclusive:r?K(r,1):null,label:J("Custom",o,r)}}if(e==="today")return{active:!0,invalid:!1,start:i,endExclusive:K(i,1),label:J("Today",i,i)};if(e==="this-week"){const o=Jn(i);return{active:!0,invalid:!1,start:o,endExclusive:K(o,7),label:J("This week",o,K(o,6))}}if(e==="last-7-days"){const o=K(i,-6);return{active:!0,invalid:!1,start:o,endExclusive:K(i,1),label:J("Last 7 days",o,i)}}if(e==="this-month"){const o=new Date(i.getFullYear(),i.getMonth(),1),r=new Date(i.getFullYear(),i.getMonth()+1,1);return{active:!0,invalid:!1,start:o,endExclusive:r,label:J("This month",o,K(r,-1))}}return{active:!1,invalid:!1,start:null,endExclusive:null,label:"All time"}}function Gn(e,n){if(n.modelFilter!=="all"&&e.model!==n.modelFilter||n.effortFilter!=="all"&&e.effort!==n.effortFilter||!Pn(e,n.confidenceFilter)||!Mn(e,n.sourceFilter)||!Zn(e,n.timeFilter,n.dateStart,n.dateEnd)||n.activePreset&&!$t(e,n.activePreset))return!1;const s=[e.thread,e.cwd,e.project,e.projectRelativeCwd,e.gitBranch,e.gitRemoteLabel,e.sessionId,e.model,e.effort,e.initiator,e.initiatorReason,e.signal,e.recommendation,e.rawTime,e.sourceFile,e.lineNumber,e.tags.join(" ")];return[n.globalQuery,n.localQuery].every(a=>Jt(s,a))}function Qn(e,n,s,a){const i=rt(e,s),o=rt(n,s);if(i===null&&o!==null)return 1;if(o===null&&i!==null)return-1;const r=Yn(i,o);return r!==0?a==="asc"?r:-r:Ie(e,n)||e.id.localeCompare(n.id)}function rt(e,n){return n==="time"?$e(e):n==="duration"?e.durationSeconds:n==="gap"?e.previousCallGapSeconds:n==="attention"?Wn(e):n==="thread"?e.thread.toLowerCase():n==="initiator"?e.initiator.toLowerCase():n==="model"?e.model.toLowerCase():n==="effort"?e.effort.toLowerCase():n==="total"?e.totalTokens:n==="cached"?e.input*(e.cachedPct/100):n==="uncached"?e.uncachedInput:n==="output"?e.output:n==="reasoning"?e.reasoningOutput:n==="cost"?e.cost:n==="usage"?e.credits:n==="cache"?e.cachedPct:e.contextWindowPct}function Wn(e){const n=e.signal&&e.signal!=="aggregate"?1e3:0,s=e.recommendation?750:0,a=e.contextWindowPct??0,i=Math.min(e.uncachedInput/1e3,250),o=Math.min(e.cost*25,200),r=Math.min(e.credits,200),h=Math.min(e.durationSeconds/60,120);return n+s+a+i+o+r+h}function Yn(e,n){return e===null&&n===null?0:e===null?1:n===null?-1:typeof e=="string"||typeof n=="string"?String(e).localeCompare(String(n)):e-n}function Ie(e,n){return $e(n)-$e(e)}function $e(e){const n=Date.parse(e.rawTime);return Number.isFinite(n)?n:0}function lt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return null;const[n,s,a]=e.split("-").map(Number),i=new Date(n,s-1,a);return i.getFullYear()===n&&i.getMonth()===s-1&&i.getDate()===a?i:null}function ct(e){return`${e.getFullYear()}-${String(e.getMonth()+1).padStart(2,"0")}-${String(e.getDate()).padStart(2,"0")}`}function J(e,n,s){const a=n?ct(n):"",i=s?ct(s):"";return a&&i&&a===i?`${e}: ${a}`:a&&i?`${e}: ${a} to ${i}`:a?`${e}: from ${a}`:i?`${e}: through ${i}`:e}function Xn(e=new Date){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function K(e,n){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+n)}function Jn(e){const n=e.getDay();return K(e,n===0?-6:1-n)}function Zn(e,n,s="",a="",i=new Date){if(n==="all")return!0;const o=ze(n,s,a,i);if(o.invalid)return!1;if(!o.active)return!0;const r=Date.parse(e.rawTime);return!(!Number.isFinite(r)||o.start&&r=o.endExclusive.getTime())}const es={time:"time",duration:"duration",gap:"gap",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"tokens",cached:"cached",uncached:"uncached",output:"output",reasoning:"reasoning",cache:"cache"};function ts(e){const n=es[e.sortKey],s=ze(e.timeFilter,e.dateStart,e.dateEnd,new Date),a=ns(e,n,s.invalid);return{enabled:!a,reason:a,sort:n??"time",filters:{query:[e.globalQuery.trim(),e.localQuery.trim()].filter(Boolean).join(" "),model:e.modelFilter==="all"?void 0:e.modelFilter,effort:e.effortFilter==="all"?void 0:e.effortFilter,...ss(e.confidenceFilter),...as(s.start,s.endExclusive,e.scopeSince)}}}function ns(e,n,s){return!e.enabled||e.runtime.fileMode||!e.runtime.apiToken?"Stored snapshot":e.globalQuery.trim()&&e.localQuery.trim()?"Multiple searches use loaded snapshot":e.activePreset?"Preset uses loaded snapshot":e.sourceFilter!=="all"?"Source filter uses loaded snapshot":n?s?"Invalid date range":"":"This sort uses loaded snapshot"}function ss(e){return e==="cost-exact"?{pricingStatus:"priced"}:e==="cost-estimated"?{pricingStatus:"estimated"}:e==="cost-unpriced"?{pricingStatus:"unpriced"}:e==="credit-exact"?{creditConfidence:"exact"}:e==="credit-estimated"?{creditConfidence:"estimated"}:e==="credit-override"?{creditConfidence:"user_override"}:e==="credit-missing"?{creditConfidence:"unpriced"}:{}}function as(e,n,s){return{since:(e==null?void 0:e.toISOString())??s??void 0,until:n?new Date(n.getTime()-1).toISOString():void 0}}function is({data:e,valueLabel:n=s=>String(s)}){const s=Math.max(...e.map(a=>a.value),1);return t.jsx("div",{className:"bar-list",children:e.map(a=>t.jsxs("div",{className:"bar-row",children:[t.jsx("span",{children:a.label}),t.jsx("div",{className:"bar-track","aria-hidden":"true",children:t.jsx("i",{style:{width:`${a.value/s*100}%`,backgroundColor:a.color??"#2563eb"}})}),t.jsx("strong",{children:n(a.value)})]},a.label))})}function P({label:e,value:n,detail:s}){return t.jsxs("span",{className:"drilldown-metric",children:[t.jsx("small",{children:e}),t.jsx("strong",{children:n}),t.jsx("em",{children:s})]})}function S({label:e,value:n}){return t.jsxs("div",{children:[t.jsx("dt",{children:e}),t.jsx("dd",{children:n})]})}function os({call:e,contextRuntime:n,onContextApiEnabledChange:s}){const a=ce(),[i,o]=c.useState(()=>sn(e.id)??tt),[r,h]=c.useState({status:"idle"}),F=!!n.apiToken&&!n.fileMode,d=F&&n.contextApiEnabled;c.useEffect(()=>{const l=nt(e.id,i);h(l?{status:"loaded",payload:l}:{status:"idle"})},[e.id,i.includeCompactionHistory,i.includeToolOutput,i.maxChars,i.maxEntries,i.mode]);async function b(){h({status:"loading",message:"Enabling localhost context API..."});try{const l=await on(n);s(l),h({status:"idle",message:l?"Context API enabled. Load this call when ready.":"Context API did not enable."})}catch(l){h({status:"error",message:st(l)})}}async function j(l=i,p="Loading selected-turn evidence..."){at(e.id,l);const w=nt(e.id,l);if(w){h({status:"loaded",payload:w});return}h({status:"loading",message:p});try{const g=await rn(e.id,n,l);ln(e.id,l,g),h({status:"loaded",payload:g})}catch(g){h({status:"error",message:st(g)})}}function C(){const l={...i,mode:"full"};o(l),j(l,"Loading full turn analysis...")}function M(l){const p=pn(l,i);o(p),j(p,"Loading older context...")}function N(){const l={...i,includeToolOutput:!0};o(l),j(l,"Loading omitted tool output...")}function y(){const l={...i,includeCompactionHistory:!0};o(l),j(l,"Loading compacted replacement...")}function m(l,p){o(w=>{const g={...w,[l]:p};return at(e.id,g),g})}return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"locked-context-card",children:[t.jsx(pt,{size:20}),t.jsxs("div",{children:[t.jsx("strong",{children:"Raw context is gated"}),t.jsx("p",{children:an(n)})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Record id",value:e.id}),t.jsx(S,{label:"Time",value:e.time}),t.jsx(S,{label:"Thread",value:e.thread}),t.jsx(S,{label:"Model",value:e.model}),t.jsx(S,{label:"Effort",value:e.effort})]}),t.jsxs("div",{className:"context-action-grid",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:b,disabled:!F||n.contextApiEnabled||r.status==="loading",children:a.t("button.enable_context_loading","Enable context loading")}),t.jsx("button",{className:"primary-button",type:"button",onClick:()=>j(),disabled:!d||r.status==="loading",children:a.t("button.show_turn_evidence","Show turn log evidence")}),t.jsx("button",{className:"toolbar-button",type:"button",onClick:C,disabled:!d||r.status==="loading",children:a.t("button.full_serialized_analysis","Run full serialized analysis")}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Mode"}),t.jsxs("select",{"aria-label":"Side panel context mode",value:i.mode,disabled:!d||r.status==="loading",onChange:l=>m("mode",l.target.value==="full"?"full":"quick"),children:[t.jsx("option",{value:"quick",children:"Quick"}),t.jsx("option",{value:"full",children:"Full"})]})]}),t.jsxs("label",{className:"context-field",children:[t.jsx("span",{children:"Entries"}),t.jsxs("select",{"aria-label":"Side panel context entries",value:String(i.maxEntries),disabled:!d||r.status==="loading",onChange:l=>m("maxEntries",Number(l.target.value)),children:[t.jsx("option",{value:"20",children:"20"}),t.jsx("option",{value:"50",children:"50"}),t.jsx("option",{value:"100",children:"100"}),t.jsx("option",{value:"0",children:"All"})]})]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeToolOutput,disabled:!d||r.status==="loading",onChange:l=>m("includeToolOutput",l.target.checked)}),a.t("button.include_tool_output","Include tool output")]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.includeCompactionHistory,disabled:!d||r.status==="loading",onChange:l=>m("includeCompactionHistory",l.target.checked)}),"Include compaction history"]}),t.jsxs("label",{className:"toggle-row",children:[t.jsx("input",{type:"checkbox",checked:i.maxChars===0,disabled:!d||r.status==="loading",onChange:l=>m("maxChars",l.target.checked?0:tt.maxChars)}),a.t("button.no_char_limit","No char limit")]})]}),r.status==="idle"&&r.message?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="loading"?t.jsx("p",{className:"context-state-note",children:r.message}):null,r.status==="error"?t.jsx("p",{className:"context-state-note error",children:r.message}):null,r.status==="loaded"?t.jsx(rs,{call:e,payload:r.payload,onLoadOlder:M,onRunFullAnalysis:C,onLoadCompactionHistory:y,onLoadToolOutput:N}):null,t.jsx("p",{className:"privacy-note",children:"Raw context is never embedded in the dashboard HTML. This view reads the selected local JSONL turn only after an explicit request."})]})}function rs({call:e,payload:n,onLoadOlder:s,onRunFullAnalysis:a,onLoadCompactionHistory:i,onLoadToolOutput:o}){var _,E;const r=ce(),h=n.entries??[],F=n.omitted??{},d=Number(F.older_entries??0),b=cn(n),j=8,C=e.id||String(n.record_id??""),[M,N]=c.useState(()=>it(C)),[y,m]=c.useState(()=>ot(C,h));c.useEffect(()=>{N(it(C)),m(ot(C,h))},[h.length,n.context_mode,n.include_compaction_history,n.include_tool_output,(_=n.omitted)==null?void 0:_.max_chars,(E=n.omitted)==null?void 0:E.max_entries,n.record_id,C]);const l=M?h:h.slice(0,j),p=Math.max(h.length-l.length,0);function w(){N(x=>{const L=!x;return gn(C,L),L})}function g(x,L){fn(C,x,L),m(v=>{const u=new Set(v);return L?u.add(x):u.delete(x),u})}return t.jsxs("div",{className:"context-evidence",children:[t.jsxs("div",{className:"context-evidence-summary",children:[t.jsx(P,{label:"Entries",value:O(h.length),detail:String(n.context_mode??"quick")}),t.jsx(P,{label:"Visible chars",value:O(Number(n.visible_char_count??0)),detail:"redacted local text"}),t.jsx(P,{label:"Visible tokens",value:O(Number(n.visible_token_estimate??0)),detail:"estimator"}),t.jsx(P,{label:"Older omitted",value:O(d),detail:"entry budget"})]}),b.length?t.jsx("p",{className:"context-note",children:b.join(" ")}):null,t.jsx(dn,{call:e,payload:n,onRunFullAnalysis:a}),d>0?t.jsx("div",{className:"context-followup-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:()=>s(n),children:r.t("button.load_older_context","Load older entries")})}):null,t.jsxs("div",{className:"context-entry-list",children:[l.map((x,L)=>{const v=un(x,L);return t.jsxs("details",{className:"context-entry",open:y.has(v),onToggle:u=>g(v,u.currentTarget.open),children:[t.jsx("summary",{className:"context-entry-summary",children:t.jsxs("div",{className:"context-entry-meta",children:[t.jsx("strong",{children:x.label||x.role||x.type||`Entry ${L+1}`}),t.jsx("span",{children:x.line_number?`line ${x.line_number}`:x.timestamp||"local evidence"})]})}),t.jsx(hn,{entry:x}),x.tool_output_omitted?t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:o,children:r.t("button.show_tool_output","Show tool output")})}):null,t.jsx(ls,{entry:x,onLoadCompactionHistory:i}),t.jsx("pre",{ref:u=>{u&&(u.scrollTop=xn(C,v))},onScroll:u=>mn(C,v,u.currentTarget.scrollTop),children:x.text||"[no visible text]"})]},v)}),h.length?null:t.jsx("p",{className:"empty-state",children:"No visible evidence entries returned for this call."})]}),h.length>j?t.jsxs("div",{className:"context-followup-actions",children:[t.jsx("button",{className:"toolbar-button",type:"button",onClick:w,children:M?`Show first ${O(j)} entries`:`Show all ${O(h.length)} returned entries`}),M?null:t.jsxs("span",{className:"context-entry-count-note",children:[O(p)," entries hidden in compact view"]})]}):null]})}function ls({entry:e,onLoadCompactionHistory:n}){const s=ce(),a=e.compaction;if(!(a!=null&&a.replacement_history_available))return null;const i=a.replacement_history??[],o=Number(a.replacement_entry_count??i.length);return t.jsxs("div",{className:"context-entry-compaction",children:[t.jsx("strong",{children:"Compaction detected"}),t.jsxs("span",{children:[O(o)," replacement history entries available."]}),i.length?t.jsx("div",{className:"context-replacement-history","aria-label":"Compacted replacement context",children:i.map((r,h)=>t.jsxs("div",{className:"context-replacement-entry",children:[t.jsx("strong",{children:r.label||`Replacement item ${h+1}`}),t.jsx("pre",{children:r.text||"[no visible replacement text]"})]},`${r.label??"replacement"}-${h}`))}):t.jsx("div",{className:"context-entry-actions",children:t.jsx("button",{className:"toolbar-button",type:"button",onClick:n,children:s.t("button.show_compaction_history","Show compacted replacement")})})]})}const cs=[{id:"summary",label:"Summary",icon:At},{id:"tokens",label:"Tokens",icon:ut},{id:"cache",label:"Cache",icon:Ot},{id:"thread",label:"Thread",icon:Fn},{id:"evidence",label:"Evidence",icon:pt}];function ds({call:e,calls:n,contextRuntime:s,includeArchived:a,sourceRevision:i,hydrateThreadCalls:o,onContextApiEnabledChange:r,onOpenInvestigator:h,onCopyCallLink:F}){const[d,b]=c.useState("summary"),[j,C]=c.useState(""),M=c.useMemo(()=>e?n.filter(m=>m.thread===e.thread).sort(Ie):[],[e,n]),N=nn({...kt({runtime:s,includeArchived:a,sourceRevision:i,threadKey:(e==null?void 0:e.threadKey)||(e==null?void 0:e.thread)||"",selectedRecordId:(e==null?void 0:e.id)??"",selectedEventTimestamp:(e==null?void 0:e.eventTimestamp)??""}),enabled:o&&!s.fileMode&&!!s.apiToken&&!!e,placeholderData:m=>m}),y=c.useMemo(()=>{var l;const m=((l=N.data)==null?void 0:l.rows)??M;return!e||m.some(p=>p.id===e.id)?m:[...m,e].sort(Ie)},[e,M,N.data]);return e?t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsxs(Z,{title:"Call Drill-Down",subtitle:`${e.thread} / ${e.model}`,children:[t.jsxs("div",{className:"call-summary",children:[t.jsx(re,{label:"Aggregate only",tone:"green"}),t.jsx(Rt,{call:e}),t.jsx(re,{label:"Raw context gated",tone:"blue"}),t.jsx("span",{className:"call-id",children:e.id.slice(0,12)})]}),t.jsxs("div",{className:"action-row",children:[t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>h(e.id),children:[t.jsx(yn,{size:16}),"Open investigator"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:()=>fs(e,C),children:[t.jsx(dt,{size:16}),"Copy link"]})]}),j?t.jsx("p",{className:"context-state-note",children:j}):null,t.jsx("div",{className:"drilldown-tabs",role:"tablist","aria-label":"Call drill-down sections",children:cs.map(m=>{const l=m.icon,p=d===m.id;return t.jsxs("button",{type:"button",role:"tab","aria-selected":p,className:p?"active":"",onClick:()=>b(m.id),children:[t.jsx(l,{size:14}),m.label]},m.id)})}),t.jsxs("div",{className:"drilldown-tab-panel",role:"tabpanel",children:[d==="summary"?t.jsx(us,{call:e}):null,d==="tokens"?t.jsx(ms,{call:e}):null,d==="cache"?t.jsx(xs,{call:e,calls:y}):null,d==="thread"?t.jsx(ps,{call:e,calls:y,onOpenInvestigator:h,onCopyCallLink:F}):null,d==="evidence"?t.jsx(os,{call:e,contextRuntime:s,onContextApiEnabledChange:r},e.id):null]})]})}):t.jsx("aside",{className:"side-panel drilldown-panel",children:t.jsx(Z,{title:"Call Drill-Down",subtitle:"No matching call",children:t.jsx("p",{className:"empty-state",children:"No aggregate row matches the active filters."})})})}function us({call:e}){return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Total tokens",value:O(e.totalTokens),detail:`${ee(e.input)} input`}),t.jsx(P,{label:"Uncached input",value:O(e.uncachedInput),detail:"fresh billed input"}),t.jsx(P,{label:"Cache hit rate",value:q(e.cachedPct),detail:Ae(e)}),t.jsx(P,{label:"Estimated cost",value:Oe(e.cost),detail:Bt(e)}),t.jsx(P,{label:"Duration",value:e.duration,detail:Vt(e)}),t.jsx(P,{label:"Usage credits",value:e.credits?e.credits.toFixed(3):"-",detail:e.usageCreditConfidence})]}),t.jsx(jn,{call:e}),t.jsx(vn,{call:e}),t.jsx(hs,{call:e}),t.jsx(St,{call:e}),t.jsx(wt,{call:e}),e.recommendation?t.jsxs("div",{className:"recommendation-box",children:[t.jsx(Sn,{size:16}),t.jsx("p",{children:e.recommendation})]}):null]})}function hs({call:e}){return t.jsxs("div",{className:"composition-card accounting-snapshot-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Accounting Snapshot"}),t.jsx("span",{children:"pricing, credits, and cache savings"})]}),t.jsx(xt,{call:e})]})}function ms({call:e}){return t.jsxs(t.Fragment,{children:[t.jsx(St,{call:e}),t.jsx(xt,{call:e})]})}function xs({call:e,calls:n}){return t.jsxs(t.Fragment,{children:[t.jsx(wt,{call:e}),t.jsx(bn,{call:e,calls:n}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Cache state",value:Ae(e)}),t.jsx(S,{label:"Cache hit rate",value:q(e.cachedPct)}),t.jsx(S,{label:"Fresh share",value:q(Math.max(100-e.cachedPct,0))}),t.jsx(S,{label:"Signal",value:e.signal})]}),t.jsx("p",{className:"privacy-note",children:"Use this readout to decide whether the aggregate call needs deeper raw-context investigation."})]})}function ps({call:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a}){const i=n.reduce((b,j)=>b+j.totalTokens,0),o=n.reduce((b,j)=>b+j.cost,0),r=n.reduce((b,j)=>b+j.cachedPct,0)/Math.max(n.length,1),h=Math.max(n.findIndex(b=>b.id===e.id),0),F=Math.min(Math.max(n.length,1),5),d=e.sourceFile?`${e.sourceFile}${e.lineNumber?`:${e.lineNumber}`:""}`:"Not available";return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"drilldown-metric-grid",children:[t.jsx(P,{label:"Loaded thread calls",value:O(n.length),detail:`selected ${h+1} of ${n.length}`}),t.jsx(P,{label:"Thread tokens",value:ee(i),detail:"loaded aggregate rows"}),t.jsx(P,{label:"Thread cost",value:Oe(o),detail:"estimated aggregate"}),t.jsx(P,{label:"Avg cache",value:q(r),detail:Ht(n.map(b=>b.model),{style:"x",emptyLabel:"no model mix"})}),t.jsx(P,{label:"Context window",value:e.contextWindowPct===null?"-":q(e.contextWindowPct),detail:e.modelContextWindow?`${ee(e.modelContextWindow)} window`:"not reported"}),t.jsx(P,{label:"Parent thread",value:e.parentThread||"-",detail:e.parentSessionId||"no parent session"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Thread timeline"}),t.jsxs("span",{children:[F," nearby loaded calls"]})]}),t.jsx(Cn,{selectedCall:e,calls:n,onOpenInvestigator:s,onCopyCallLink:a,copyAriaContext:"side-panel thread call"})]}),t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Call Narrative"}),t.jsx("span",{children:e.initiatorConfidence||"aggregate inference"})]}),t.jsxs("dl",{className:"detail-list compact",children:[t.jsx(S,{label:"Initiated by",value:e.initiator||"unknown"}),t.jsx(S,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),t.jsx(S,{label:"Parent thread",value:e.parentThread||"None"}),t.jsx(S,{label:"Parent session",value:e.parentSessionId||"None"}),t.jsx(S,{label:"Timestamp",value:e.time}),t.jsx(S,{label:"Duration",value:e.duration}),t.jsx(S,{label:"Previous gap",value:e.previousCallGap})]})]}),t.jsxs("dl",{className:"detail-list",children:[t.jsx(S,{label:"Project",value:e.project||"Unknown"}),t.jsx(S,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),t.jsx(S,{label:"Source line",value:d}),t.jsx(S,{label:"Session",value:e.sessionId||"Not available"}),t.jsx(S,{label:"Git branch",value:e.gitBranch||"Unknown"}),t.jsx(S,{label:"Remote",value:e.gitRemoteLabel||e.gitRemoteHash||"None"})]})]})}function St({call:e}){const s=[{label:"Cached input",value:Math.max(e.input-e.uncachedInput,0),color:"#2563eb"},{label:"Uncached input",value:e.uncachedInput,color:"#f59e0b"},{label:"Output",value:e.output,color:"#059669"},{label:"Reasoning",value:e.reasoningOutput,color:"#7c3aed"}].filter(i=>i.value>0),a=Math.max(s.reduce((i,o)=>i+o.value,0),1);return t.jsxs("div",{className:"composition-card",children:[t.jsxs("div",{className:"composition-head",children:[t.jsx("strong",{children:"Token composition"}),t.jsxs("span",{children:[ee(a)," visible tokens"]})]}),t.jsx("div",{className:"composition-bar",role:"img","aria-label":"Token composition",children:s.map(i=>t.jsx("i",{style:{width:`${Math.max(i.value/a*100,3)}%`,background:i.color}},i.label))}),t.jsx("div",{className:"composition-legend",children:s.map(i=>t.jsxs("span",{children:[t.jsx("i",{style:{background:i.color}}),i.label]},i.label))})]})}function wt({call:e}){const n=[{label:"Cache",value:Math.min(Math.max(e.cachedPct,0),100),color:"#2563eb"},{label:"Fresh",value:Math.min(Math.max(100-e.cachedPct,0),100),color:"#f59e0b"},{label:"Output",value:Math.min(Math.max(e.output/Math.max(e.totalTokens,1)*100,0),100),color:"#059669"}];return t.jsxs("div",{className:"cache-mini-card",children:[t.jsxs("div",{children:[t.jsx("strong",{children:"Cache delta readout"}),t.jsx("span",{children:Ae(e)})]}),t.jsx("div",{className:"cache-bars","aria-label":"Cache delta readout",children:n.map(s=>t.jsxs("span",{children:[t.jsx("i",{style:{height:`${Math.max(s.value,4)}%`,background:s.color}}),t.jsx("em",{children:s.label})]},s.label))})]})}async function fs(e,n){try{const s=new URL(window.location.href);if(s.searchParams.set("view","call"),s.searchParams.set("record",e.id),s.searchParams.set("return","calls"),!await ht(s.toString()))throw new Error("Clipboard unavailable");n("Copied investigator link")}catch{n("Copy unavailable in this browser")}}const gs="_page_gyxvc_1",js="_pageHeader_gyxvc_5",vs="_tableHeading_gyxvc_13",bs="_eyebrow_gyxvc_22",Cs="_headerActions_gyxvc_36",ys="_tableActions_gyxvc_37",Ss="_gridFooter_gyxvc_38",ws="_queryBar_gyxvc_46",Fs="_advancedFilters_gyxvc_80",Ns="_patternsDisclosure_gyxvc_85",Ts="_advancedFilterGrid_gyxvc_107",Es="_gridColumn_gyxvc_138",$={page:gs,pageHeader:js,tableHeading:vs,eyebrow:bs,headerActions:Cs,tableActions:ys,gridFooter:Ss,queryBar:ws,advancedFilters:Fs,patternsDisclosure:Ns,advancedFilterGrid:Ts,gridColumn:Es};function Ds({searchInputRef:e,localQuery:n,modelFilter:s,effortFilter:a,confidenceFilter:i,sourceFilter:o,timeFilter:r,dateStart:h,dateEnd:F,sortKey:d,sortDirection:b,modelOptions:j,effortOptions:C,sourceCoverage:M,dateRangeStatus:N,onLocalQueryChange:y,onModelFilterChange:m,onEffortFilterChange:l,onConfidenceFilterChange:p,onSourceFilterChange:w,onTimeFilterChange:g,onDateStartChange:_,onDateEndChange:E,onSortKeyChange:x,onSortDirectionChange:L,onClear:v}){return t.jsxs("section",{className:$.queryBar,"aria-label":"Call filters",children:[t.jsxs("label",{className:"search-box",children:[t.jsx("span",{className:"sr-only",children:"Search calls"}),t.jsx("input",{ref:e,value:n,onChange:u=>y(u.target.value),placeholder:"Search calls, cwd, projects, models..."})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Model"}),t.jsxs("select",{value:s,onChange:u=>m(u.target.value),children:[t.jsx("option",{value:"all",children:"All models"}),j.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Effort"}),t.jsxs("select",{value:a,onChange:u=>l(u.target.value),children:[t.jsx("option",{value:"all",children:"All effort"}),C.map(u=>t.jsx("option",{value:u,children:u},u))]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Confidence"}),t.jsxs("select",{"aria-label":"Confidence filter",value:i,onChange:u=>p(u.target.value),children:[t.jsx("option",{value:"all",children:"All confidence"}),t.jsx("option",{value:"cost-exact",children:"Exact cost"}),t.jsx("option",{value:"cost-estimated",children:"Estimated cost"}),t.jsx("option",{value:"cost-unpriced",children:"Unpriced cost"}),t.jsx("option",{value:"credit-exact",children:"Exact credit rate"}),t.jsx("option",{value:"credit-estimated",children:"Estimated credit mapping"}),t.jsx("option",{value:"credit-override",children:"User credit override"}),t.jsx("option",{value:"credit-missing",children:"Missing credit rate"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Time"}),t.jsxs("select",{"aria-label":"Time filter",value:r,onChange:u=>g(u.target.value),children:[t.jsx("option",{value:"all",children:"All time"}),t.jsx("option",{value:"today",children:"Today"}),t.jsx("option",{value:"this-week",children:"This week"}),t.jsx("option",{value:"last-7-days",children:"Last 7 days"}),t.jsx("option",{value:"this-month",children:"This month"}),t.jsx("option",{value:"custom",children:"Custom range"})]}),N.active||N.invalid?t.jsx("span",{className:"filter-status","data-state":N.invalid?"error":"active","aria-live":"polite",children:N.label}):null]}),t.jsxs("details",{className:$.advancedFilters,children:[t.jsxs("summary",{children:[t.jsx(Kt,{size:16}),"More filters"]}),t.jsxs("div",{className:$.advancedFilterGrid,children:[t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Source"}),t.jsxs("select",{"aria-label":"Source filter",value:o,onChange:u=>w(u.target.value),children:[t.jsx("option",{value:"all",children:"All sources"}),t.jsx("option",{value:"project",children:"Project / cwd"}),t.jsx("option",{value:"session",children:"Session-linked"}),t.jsx("option",{value:"git",children:"Git metadata"}),t.jsx("option",{value:"source-file",children:"Source file"}),t.jsx("option",{value:"missing",children:"Missing source"})]}),t.jsx("span",{className:"filter-status","data-state":o==="all"?"active":"filtered","aria-live":"polite",children:Dn(M,o)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Start"}),t.jsx("input",{"aria-label":"Start date",type:"date",value:h,onChange:u=>_(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"End"}),t.jsx("input",{"aria-label":"End date",type:"date",value:F,onChange:u=>E(u.target.value)})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Sort"}),t.jsxs("select",{"aria-label":"Sort calls",value:d,onChange:u=>x(u.target.value),children:[t.jsx("option",{value:"time",children:"Newest calls"}),t.jsx("option",{value:"duration",children:"Longest duration"}),t.jsx("option",{value:"gap",children:"Longest gap"}),t.jsx("option",{value:"attention",children:"Needs attention"}),t.jsx("option",{value:"thread",children:"Thread name"}),t.jsx("option",{value:"initiator",children:"Initiated"}),t.jsx("option",{value:"model",children:"Model"}),t.jsx("option",{value:"effort",children:"Reasoning"}),t.jsx("option",{value:"total",children:"Most tokens"}),t.jsx("option",{value:"cached",children:"Cached"}),t.jsx("option",{value:"uncached",children:"Uncached"}),t.jsx("option",{value:"output",children:"Output"}),t.jsx("option",{value:"reasoning",children:"Reasoning output"}),t.jsx("option",{value:"cost",children:"Highest estimated cost"}),t.jsx("option",{value:"usage",children:"Highest Codex credits"}),t.jsx("option",{value:"cache",children:"Lowest cache ratio"}),t.jsx("option",{value:"context",children:"Highest context use"})]})]}),t.jsxs("label",{className:"filter-field",children:[t.jsx("span",{children:"Direction"}),t.jsxs("select",{"aria-label":"Sort direction",value:b,onChange:u=>L(u.target.value),children:[t.jsx("option",{value:"desc",children:"Descending"}),t.jsx("option",{value:"asc",children:"Ascending"})]})]})]})]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:v,children:[t.jsx(zt,{size:16}),"Clear filters"]})]})}function Ms({workspaceSwitcher:e,canExport:n,onExport:s,onCopyView:a,onRefresh:i}){return t.jsxs("header",{className:$.pageHeader,children:[t.jsxs("div",{children:[t.jsx("p",{className:$.eyebrow,children:"Evidence explorer"}),t.jsx("h1",{children:"Calls"}),t.jsx("p",{children:"Find expensive, cold, or context-heavy calls and move directly into their evidence."})]}),t.jsxs("div",{className:$.headerActions,children:[e,t.jsxs("button",{className:"toolbar-button",type:"button",onClick:s,disabled:!n,children:[t.jsx(Ut,{size:16}),"Export"]}),t.jsxs("button",{className:"toolbar-button",type:"button",onClick:a,children:[t.jsx(dt,{size:16}),"Copy view"]}),t.jsxs("button",{className:"primary-button",type:"button",onClick:i,children:[t.jsx(qt,{size:16}),"Refresh"]})]})]})}const Ft="codexUsageDetailPanel";function Ps(e=!1){var n;try{const s=(n=window.sessionStorage)==null?void 0:n.getItem(Ft);return s?s==="expanded":e}catch{return e}}function _s(e){var n;try{(n=window.sessionStorage)==null||n.setItem(Ft,e?"expanded":"collapsed")}catch{}}const B=250;function Ls(e,n){const s=T("density"),[a,i]=c.useState(()=>T("call_q")),[o,r]=c.useState(()=>T("model")||"all"),[h,F]=c.useState(()=>T("effort")||"all"),[d,b]=c.useState(()=>gt()),[j,C]=c.useState(()=>jt()),[M,N]=c.useState(()=>vt()),[y,m]=c.useState(()=>le("from")),[l,p]=c.useState(()=>le("to")),[w,g]=c.useState(()=>Pe()),[_,E]=c.useState(()=>Ct(Pe())),x=wn("codexUsageCallsEvidenceGrid",{density:Vn()==="dense"?"compact":"comfortable",columnVisibility:{}},s==="roomy"?"comfortable":s==="dense"?"compact":void 0),L=x.density==="compact"?"dense":"roomy",v=c.useMemo(()=>Bn(),[]),[u,te]=c.useState(v),[G,R]=c.useState(()=>Hn(B)),[ne,Q]=c.useState(""),[de,ue]=c.useState(""),[W,he]=c.useState(()=>Ps(!!v)),me=c.useRef(null),se=c.useRef(n),xe=c.useMemo(()=>Ze(e.calls.map(f=>f.model)),[e.calls]),pe=c.useMemo(()=>Ze(e.calls.map(f=>f.effort)),[e.calls]),fe=c.useMemo(()=>_n(e.calls),[e.calls]),Y=c.useMemo(()=>ze(M,y,l,new Date),[l,y,M]);c.useEffect(()=>{se.current!==n&&(se.current=n,R(B))},[n]);function I(){R(B)}function ge(f){i(f),I()}function je(f){r(f),I()}function ve(f){F(f),I()}function be(f){b(f),I()}function Ce(f){C(f),I()}function ye(f){N(f),I()}function Se(f){m(Le(f)),N("custom"),I()}function we(f){p(Le(f)),N("custom"),I()}function Fe(f){const A=bt(f);g(A),E(U(A)),I()}function Ne(f){E(f==="asc"?"asc":"desc"),I()}function Te(){i(""),r("all"),F("all"),b("all"),C("all"),N("all"),m(""),p(""),g("time"),E(U("time")),x.setDensity("compact"),x.setColumnVisibility({}),te(null),R(B),window.history.replaceState(null,"",_e({localQuery:"",modelFilter:"all",effortFilter:"all",confidenceFilter:"all",sourceFilter:"all",timeFilter:"all",dateStart:"",dateEnd:"",sortKey:"time",sortDirection:U("time"),density:"dense",selectedRecordId:"",visibleRowCount:B,pageSize:B})),ue("Calls filters cleared")}function Ee(){he(f=>{const A=!f;return _s(A),A})}return{localQuery:a,modelFilter:o,effortFilter:h,confidenceFilter:d,sourceFilter:j,timeFilter:M,dateStart:y,dateEnd:l,sortKey:w,setSortKey:g,sortDirection:_,setSortDirection:E,gridPreferences:x,density:L,initialSelectedCallId:v,selectedCallId:u,setSelectedCallId:te,visibleCallRows:G,setVisibleCallRows:R,exportStatus:ne,setExportStatus:Q,filterStatus:de,detailsExpanded:W,searchInputRef:me,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}}function ks({model:e,header:n,filters:s,table:a,inspector:i}){var F;const o=ce(),r=o.t("dashboard.model_calls","Model Calls"),h=o.t("dashboard.model_calls","Model calls");return t.jsxs("div",{className:`${$.page} page-grid`,children:[t.jsx(Ms,{...n}),t.jsx(Ds,{...s}),t.jsxs("div",{className:$.tableHeading,children:[t.jsxs("div",{children:[t.jsx("h2",{children:r}),t.jsx("p",{children:a.exportStatus||a.filterStatus||a.subtitle})]}),t.jsxs("div",{className:$.tableActions,children:[t.jsx(re,{label:Is(a.isFetching,a.focused,a.focusedReason),tone:a.focused?"green":"blue"}),t.jsx(re,{label:a.activePreset?`Preset: ${mt(a.activePreset)}`:"Raw context gated",tone:a.activePreset?"green":"blue"}),t.jsxs("button",{className:"toolbar-button",type:"button","aria-expanded":a.detailsExpanded,onClick:a.onToggleDetails,children:[a.detailsExpanded?t.jsx(Nn,{size:16}):t.jsx(Tn,{size:16}),a.detailsExpanded?o.t("button.hide_details","Hide details"):o.t("dashboard.call_details","Call Details")]})]})]}),t.jsxs("div",{className:a.detailsExpanded?"table-detail-layout":"table-detail-layout detail-collapsed",children:[t.jsxs("div",{className:$.gridColumn,children:[t.jsx(Zt,{ariaLabel:h,columns:a.columns,data:a.calls,identityColumnId:"thread",lockedColumnIds:["investigate"],getRowId:d=>d.id,mobile:{primary:d=>d.thread,secondary:d=>o.translateText(`${d.time} · ${d.model} · ${ee(d.totalTokens)} tokens · ${q(d.cachedPct)} cache`),actionLabel:d=>en(d)},sorting:a.sorting,onSortingChange:a.onSortingChange,manualSorting:!0,columnVisibility:a.gridPreferences.columnVisibility,onColumnVisibilityChange:a.gridPreferences.setColumnVisibility,density:a.gridPreferences.density,onDensityChange:a.gridPreferences.setDensity,onRestoreDefaults:a.gridPreferences.restoreDefaults,selectedRowId:(F=a.selectedCall)==null?void 0:F.id,onRowSelect:d=>a.onSelectCall(d.id),onRowActivate:d=>i.onOpenInvestigator(d.id),activateOnClick:!0,selectOnHover:!0,viewportHeight:560,emptyLabel:"No rows match current filters."}),t.jsxs("div",{className:$.gridFooter,"aria-live":"polite",children:[t.jsx("span",{children:o.translateText(`${a.calls.length.toLocaleString()} loaded / ${a.totalMatchedCalls.toLocaleString()} matched`)}),a.focused&&a.hasNextPage?t.jsx("button",{className:"toolbar-button",type:"button",onClick:a.onLoadMore,disabled:a.isFetchingNextPage,children:a.isFetchingNextPage?"Loading more...":`Load ${B.toLocaleString()} more`}):null]})]}),a.detailsExpanded?t.jsx(ds,{call:a.selectedCall,calls:e.calls,...i}):null]}),t.jsxs("details",{className:$.patternsDisclosure,children:[t.jsxs("summary",{children:[t.jsx(ut,{size:17}),"Usage patterns"]}),t.jsxs("div",{className:"dashboard-grid three",children:[t.jsx(Z,{title:"Usage Over Time",subtitle:"Tokens",children:t.jsx(et,{series:e.tokenSeries,yLabel:"Tokens",height:220})}),t.jsx(Z,{title:"Cost by Model",subtitle:"Estimated USD",children:t.jsx(is,{data:e.modelCosts,valueLabel:Oe})}),t.jsx(Z,{title:"Cache Hit Rate Over Time",subtitle:o.translateText("Daily"),children:t.jsx(et,{series:e.cacheSeries,yLabel:"Cache %",height:220,valueFormatter:d=>`${d}%`})})]})]})]})}function Is(e,n,s){return e&&n?"Updating focused rows":e?"Loading focused rows":n?"Focused paged API":s||"Stored snapshot"}function ra(e,n="",s=""){const a=Pe();return ke(yt(e,{globalQuery:n,localQuery:T("call_q"),modelFilter:T("model")||"all",effortFilter:T("effort")||"all",confidenceFilter:gt(),sourceFilter:jt(),timeFilter:vt(),dateStart:le("from"),dateEnd:le("to"),activePreset:s}),a,Ct(a))}const Nt={time:"time",duration:"duration",gap:"previousCallGap",attention:"signal",thread:"thread",initiator:"initiator",model:"model",effort:"effort",total:"totalTokens",cached:"cachedInput",uncached:"uncachedInput",output:"output",reasoning:"reasoningOutput",cost:"cost",usage:"credits",cache:"cachedPct",context:"contextWindowPct"},$s=Object.fromEntries(Object.entries(Nt).map(([e,n])=>[n,e]));function la({model:e,globalQuery:n,activePreset:s,onRefresh:a,contextRuntime:i,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h,includeArchived:F=!1,sourceKey:d,sourceRevision:b="",scopeSince:j=null,focusedEndpointsEnabled:C=!0,workspaceSwitcher:M}){var We,Ye;const N=Ls(e,n),{localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,setSortKey:L,sortDirection:v,setSortDirection:u,gridPreferences:te,density:G,selectedCallId:R,setSelectedCallId:ne,visibleCallRows:Q,setVisibleCallRows:de,exportStatus:ue,setExportStatus:W,filterStatus:he,detailsExpanded:me,searchInputRef:se,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,resetCallTablePage:I,updateLocalQuery:ge,updateModelFilter:je,updateEffortFilter:ve,updateConfidenceFilter:be,updateSourceFilter:Ce,updateTimeFilter:ye,updateDateStart:Se,updateDateEnd:we,updateSortKey:Fe,updateSortDirection:Ne,clearCallFilters:Te,toggleCallDetails:Ee}=N,f=c.useMemo(()=>[...Gt,tn({onOpenInvestigator:r,onCopyCallLink:h})],[h,r]),A=c.useMemo(()=>ts({runtime:i,enabled:C,activePreset:s,sourceFilter:w,sortKey:x,scopeSince:j,timeFilter:g,dateStart:_,dateEnd:E,confidenceFilter:p,globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l}),[s,p,i,E,_,l,C,n,y,m,x,w,j,g]),V=Lt({...It({runtime:i,includeArchived:F,sourceKey:d,sourceRevision:b,filters:A.filters,sort:A.sort,direction:v,pageSize:B}),enabled:A.enabled,placeholderData:D=>D}),Ue=c.useMemo(()=>yt(e.calls,{globalQuery:n,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,activePreset:s}),[s,p,E,_,l,n,y,e.calls,m,w,g]),qe=c.useMemo(()=>ke(Ue,x,v),[Ue,v,x]),Ge=c.useMemo(()=>{var D;return((D=V.data)==null?void 0:D.pages.flatMap(X=>X.rows))??[]},[V.data]),ae=A.enabled&&!!V.data,H=c.useMemo(()=>ae?ke(Ge,x,v):qe,[Ge,qe,v,x,ae]),De=ae?((Ye=(We=V.data)==null?void 0:We.pages[0])==null?void 0:Ye.totalMatchedRows)??H.length:e.calls.length,Tt=c.useMemo(()=>En({shownCount:H.length,totalCount:De,localQuery:y,globalQuery:n,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateRangeStatus:Y,activePresetLabel:s?mt(s):""}),[s,p,Y,l,n,y,m,H.length,w,g,De]),Qe=c.useMemo(()=>[{id:Nt[x],desc:v==="desc"}],[v,x]),ie=R===oe?H[0]??null:H.find(D=>D.id===R)??H[0]??null,z=ie&&(ie.id===R||R===oe)?ie.id:"";c.useEffect(()=>{R===oe&&z&&ne(z)},[R,z]),c.useEffect(()=>{const D=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});D.toString()!==window.location.href&&window.history.replaceState(null,"",D)},[p,E,_,G,l,y,m,z,v,x,w,g,Q]);function Et(){Qt(`codex-calls-${Xt()}.csv`,Wt(H,Yt)),W(`Exported ${H.length} calls`)}async function Dt(){try{const D=_e({localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,density:G,selectedRecordId:z,visibleRowCount:Q,pageSize:B});if(!await ht(D.toString()))throw new Error("Clipboard unavailable");W("Copied Calls view link")}catch{W("Copy unavailable in browser")}}function Mt(D){var Xe,Je;const X=typeof D=="function"?D(Qe):D,Me=$s[((Xe=X[0])==null?void 0:Xe.id)??""]??"time",_t=Me!==x;L(Me),u(_t?U(Me):(Je=X[0])!=null&&Je.desc?"desc":"asc"),I()}async function Pt(){!V.hasNextPage||V.isFetchingNextPage||(await V.fetchNextPage(),de(D=>D+B))}return t.jsx(ks,{model:e,header:{workspaceSwitcher:M,canExport:!!H.length,onExport:Et,onCopyView:Dt,onRefresh:a},filters:{searchInputRef:se,localQuery:y,modelFilter:m,effortFilter:l,confidenceFilter:p,sourceFilter:w,timeFilter:g,dateStart:_,dateEnd:E,sortKey:x,sortDirection:v,modelOptions:xe,effortOptions:pe,sourceCoverage:fe,dateRangeStatus:Y,onLocalQueryChange:ge,onModelFilterChange:je,onEffortFilterChange:ve,onConfidenceFilterChange:be,onSourceFilterChange:Ce,onTimeFilterChange:ye,onDateStartChange:Se,onDateEndChange:we,onSortKeyChange:Fe,onSortDirectionChange:Ne,onClear:Te},table:{activePreset:s,exportStatus:ue,filterStatus:he,subtitle:Tt,focused:ae,focusedReason:A.reason,isFetching:V.isFetching,isFetchingNextPage:V.isFetchingNextPage,hasNextPage:!!V.hasNextPage,detailsExpanded:me,calls:H,totalMatchedCalls:De,columns:f,sorting:Qe,gridPreferences:te,selectedCall:ie,onSortingChange:Mt,onSelectCall:ne,onLoadMore:Pt,onToggleDetails:Ee},inspector:{contextRuntime:i,includeArchived:F,sourceRevision:b,hydrateThreadCalls:C,onContextApiEnabledChange:o,onOpenInvestigator:r,onCopyCallLink:h}})}export{la as CallsPage,ra as callsForCurrentUrl}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js index 0fdff1d6..c1245fa2 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/SettingsPage.js @@ -1,4 +1,4 @@ -import{r as j,j as t}from"./dashboard-react.js";import{P as A}from"./Panel.js";import{S as v}from"./StatusBadge.js";import{c as W,H as h,G as B,ak as M,R as $}from"./App.js";import{G as f}from"./gauge.js";import{S as _}from"./shield-check.js";import{L as T}from"./lock-keyhole.js";import{T as H}from"./triangle-alert.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** +import{r as j,j as t}from"./dashboard-react.js";import{P as A}from"./Panel.js";import{S as v}from"./StatusBadge.js";import{c as W,H as h,G as B,al as M,R as $}from"./App.js";import{G as f}from"./gauge.js";import{S as _}from"./shield-check.js";import{L as T}from"./lock-keyhole.js";import{T as H}from"./triangle-alert.js";import"./locale-zh-Hans.js";import"./dashboardRouter.js";import"./router.js";/** * @license lucide-react v0.468.0 - ISC * * This source code is licensed under the ISC license. diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js index 9cd414f5..7472afcf 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/contextEvidenceState.js @@ -1 +1 @@ -import{j as n}from"./dashboard-react.js";import{j as o,p as x,u as G,f as w,aj as $,m as q,a as J}from"./App.js";function ye({call:e,calls:t}){const i=[...t,e].filter((h,m,b)=>b.findIndex(c=>c.id===h.id)===m).sort(te),a=i.findIndex(h=>h.id===e.id),r=a>0?i[a-1]:null,s=r?Z(e,r):null,l=V(e,r);return n.jsxs("div",{className:"call-cache-delta-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Cache Accounting Delta"}),n.jsx("span",{children:r?`Call ${a+1} of ${i.length}`:"No previous call"})]}),n.jsx(K,{call:e,delta:s,diagnostic:l,previous:r,selectedIndex:a,totalCalls:i.length}),r&&s?n.jsxs(n.Fragment,{children:[n.jsx("p",{className:"diagnostic-interpretation",children:ee(s)}),n.jsxs("div",{className:"cache-delta-grid",children:[n.jsx(f,{label:"Last call input",value:p(s.input),detail:`${o(r.input)} -> ${o(e.input)}`}),n.jsx(f,{label:"Cached input",value:p(s.cached),detail:`${o(r.cachedInput)} -> ${o(e.cachedInput)}`}),n.jsx(f,{label:"Uncached input",value:p(s.uncached),detail:`${o(r.uncachedInput)} -> ${o(e.uncachedInput)}`}),n.jsx(f,{label:"Output",value:p(s.output),detail:`${o(r.output)} -> ${o(e.output)}`}),n.jsx(f,{label:"Reasoning output",value:p(s.reasoning),detail:`${o(r.reasoningOutput)} -> ${o(e.reasoningOutput)}`}),n.jsx(f,{label:"Cache ratio",value:M(s.cacheRatio),detail:`${x(r.cachedPct)} -> ${x(e.cachedPct)}`})]})]}):n.jsx("p",{className:"empty-state",children:"No previous aggregate call available for cache delta accounting."})]})}function K({call:e,delta:t,diagnostic:i,previous:a,selectedIndex:r,totalCalls:s}){return n.jsxs("div",{className:`cache-verdict-card cache-verdict-${i.key}`,children:[n.jsxs("div",{className:"cache-verdict-main",children:[n.jsx("span",{className:"cache-diagnostic-pill",children:i.label}),n.jsx("p",{children:i.body})]}),n.jsxs("div",{className:"cache-verdict-meta",children:[n.jsxs("span",{children:["Cache ratio: ",x(e.cachedPct)]}),n.jsx("span",{children:t?Q(t):"No previous call loaded for delta comparison."}),n.jsxs("span",{children:["Position: ",r+1," of ",s]}),n.jsxs("span",{children:["Next: ",Y(e,i,a)]})]})]})}function V(e,t){const i=X(e,t);return i==="spike"?{key:"spike",label:"Uncached spike",body:"Fresh input rose sharply compared with the previous call in this resolved thread."}:i==="warm"?{key:"warm",label:"Warm cache reuse",body:"Most input tokens reused prompt cache. The uncached portion is the most likely investigation target."}:i==="partial"?{key:"partial",label:"Partial cache miss",body:"Some prefix reused cache, but a meaningful share of input was fresh or reserialized."}:{key:"cold",label:"Cold resume / stale cache",body:"Conversation-specific cache likely expired or missed; remaining cache is probably stable Codex scaffolding or tool schema prefix."}}function X(e,t){const i=S(e),a=t?S(t):null,r=(t==null?void 0:t.uncachedInput)??0,s=.05,l=.85,h=.8,m=1e3;return t&&a!==null&&a>=h&&i<=s&&e.input>=m?"cold":t&&e.uncachedInput>Math.max(r*2,m)?"spike":i>=l?"warm":i>s?"partial":"cold"}function S(e){return Number.isFinite(e.cachedPct)?e.cachedPct/100:0}function Q(e){return`Uncached input: ${p(e.uncached)}. Cached input: ${p(e.cached)}. Cache ratio: ${M(e.cacheRatio)}.`}function Y(e,t,i){return t.key==="cold"?"Compare the previous call, then inspect loaded evidence to see what fresh context was sent after the cache miss.":t.key==="spike"?"Inspect the most recent evidence entries first; the spike is in fresh uncached input, not cached history.":t.key==="warm"?`Cache reuse is healthy; focus on ${o(e.uncachedInput)} uncached tokens that were still billed as fresh input.`:i?"Use delta cards to locate whether the change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough to understand this isolated call."}function Z(e,t){return{input:e.input-t.input,cached:e.cachedInput-t.cachedInput,uncached:e.uncachedInput-t.uncachedInput,output:e.output-t.output,reasoning:e.reasoningOutput-t.reasoningOutput,cacheRatio:e.cachedPct-t.cachedPct}}function ee(e){return e.uncached>0&&e.cached<0?`Uncached input rose by ${o(e.uncached)} while cached input fell by ${o(Math.abs(e.cached))}.`:e.uncached>0?`Uncached input increased by ${o(e.uncached)} versus the previous aggregate call.`:e.uncached<0&&e.cached>=0?`Uncached input decreased by ${o(Math.abs(e.uncached))} while cached input increased.`:"Cache accounting is stable versus the previous aggregate call."}function f({label:e,value:t,detail:i}){return n.jsxs("span",{className:"cache-delta-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function p(e){return e===0?"0":`${e>0?"+":"-"}${o(Math.abs(e))}`}function M(e){return e===0?"0.0pp":`${e>0?"+":"-"}${Math.abs(e).toFixed(1)}pp`}function te(e,t){return T(e)-T(t)}function T(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function _e({call:e}){const t=G(),i=ne(e);return n.jsxs("div",{className:"call-decision-card",children:[n.jsxs("div",{className:"section-heading compact",children:[n.jsx("h3",{children:"Call Decision"}),n.jsx("span",{children:i.nextAction})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsxs("div",{children:[n.jsx("dt",{children:"Pricing status"}),n.jsx("dd",{children:i.pricingStatus})]}),n.jsxs("div",{children:[n.jsx("dt",{children:t.t("detail.next_action","Next action")}),n.jsx("dd",{children:i.nextAction})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Why flagged"}),n.jsx("dd",{children:i.whyFlagged})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Allowance impact"}),n.jsx("dd",{children:i.allowanceImpact})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Context use"}),n.jsx("dd",{children:i.contextUse})]})]})]})}function ne(e){return{allowanceImpact:`${se(e.credits)} counted`,contextUse:e.contextWindowPct==null?"Not reported":x(e.contextWindowPct),nextAction:re(e),pricingStatus:ie(e),whyFlagged:ae(e)}}function ie(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function re(e){return e.recommendation?e.recommendation:e.cost<=0?"Configure pricing":e.cachedPct<30&&e.input>0?"Compare fresh input":(e.contextWindowPct??0)>=60?"Inspect thread timeline":e.reasoningOutput>e.output?"Review reasoning effort":"Use aggregate first"}function ae(e){return e.recommendation?e.recommendation:e.signal&&e.signal!=="aggregate"?`${e.signal} aggregate signal`:(e.contextWindowPct??0)>=60?"High reported context use.":e.cachedPct<30&&e.input>0?`${w(e.uncachedInput)} uncached input with weak cache reuse.`:e.reasoningOutput>e.output?"Reasoning output exceeds visible output.":e.cost>0||e.credits>0?"Review cost and credit impact before loading raw context.":"No aggregate efficiency flag on this row."}function se(e){return`${new Intl.NumberFormat("en-US",{maximumFractionDigits:2}).format(e)} credits`}function we({call:e}){return n.jsxs("div",{className:"call-source-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Call Source"}),n.jsx("span",{children:$(e)})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsx(d,{label:"Project",value:e.project||"Unknown"}),n.jsx(d,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),n.jsx(d,{label:"Project tags",value:e.projectTags.length?e.projectTags.join(", "):"None"}),n.jsx(d,{label:"Thread attachment",value:e.threadAttachmentLabel||"Direct thread"}),n.jsx(d,{label:"Thread source",value:e.threadSource||"user"}),n.jsx(d,{label:"Subagent type",value:e.subagentType||"None"}),n.jsx(d,{label:"Agent role",value:e.agentRole||"None"}),n.jsx(d,{label:"Agent nickname",value:e.agentNickname||"None"}),n.jsx(d,{label:"Source line",value:$(e)}),n.jsx(d,{label:"Initiated by",value:e.initiator||"unknown"}),n.jsx(d,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),n.jsx(d,{label:"Session",value:e.sessionId||"Not available"}),n.jsx(d,{label:"Turn",value:e.turnId||"None"}),n.jsx(d,{label:"Parent thread",value:e.parentThread||"None"}),n.jsx(d,{label:"Parent session",value:e.parentSessionId||"None"}),n.jsx(d,{label:"Parent updated",value:oe(e.parentSessionUpdatedAt)}),n.jsx(d,{label:"Working directory",value:e.cwd||"Not available"}),n.jsx(d,{label:"Git branch",value:e.gitBranch||"Not available"}),n.jsx(d,{label:"Git remote",value:e.gitRemoteLabel||"Not available"}),n.jsx(d,{label:"Git hash",value:e.gitRemoteHash||"Not available"}),n.jsx(d,{label:"Credit note",value:e.usageCreditNote||"None"})]})]})}function oe(e){if(!e)return"None";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function d({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function ke({call:e}){return n.jsxs("dl",{className:"detail-list",children:[n.jsx(u,{label:"Last call total",value:o(e.totalTokens)}),n.jsx(u,{label:"Last call input",value:o(e.input)}),n.jsx(u,{label:"Cached input",value:o(e.cachedInput)}),n.jsx(u,{label:"Output tokens",value:o(e.output)}),n.jsx(u,{label:"Reasoning output",value:o(e.reasoningOutput)}),n.jsx(u,{label:"Session cumulative",value:e.cumulativeTotalTokens?o(e.cumulativeTotalTokens):"Not reported"}),n.jsx(u,{label:"Pricing model",value:ce(e)}),n.jsx(u,{label:"Credit model",value:e.usageCreditModel||"No mapped rate"}),n.jsx(u,{label:"Credit confidence",value:e.usageCreditConfidence||"unknown"}),n.jsx(u,{label:"Credit source",value:e.usageCreditSource||"None"}),n.jsx(u,{label:"Credit source fetched",value:e.usageCreditFetchedAt||"Unknown"}),n.jsx(u,{label:"Credit tier",value:e.usageCreditTier||"Unknown"}),n.jsx(u,{label:"Cache savings",value:q(e.estimatedCacheSavings)}),n.jsx(u,{label:"Efficiency signals",value:de(e)})]})}function u({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function ce(e){return e.pricingModel?e.pricingModel:e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function de(e){return e.efficiencyFlags.length?e.efficiencyFlags.join(", "):e.signal&&e.signal!=="aggregate"?e.signal:e.recommendation?"recommendation":"None"}function $e({selectedCall:e,calls:t,onOpenInvestigator:i,onCopyCallLink:a,className:r,copyAriaContext:s,copyLabel:l="Copy link"}){const h=t.length?t:[e],m=le(h,e.id),b=["thread-mini-timeline",r].filter(Boolean).join(" ");return n.jsx("ol",{className:b,children:m.map(c=>n.jsxs("li",{className:c.id===e.id?"active":"",children:[n.jsx("span",{children:c.time}),n.jsxs("strong",{children:[c.model," / ",c.effort]}),n.jsxs("em",{children:[w(c.totalTokens)," tokens - ",x(c.cachedPct)," cache"]}),n.jsxs("div",{className:"thread-call-meta",children:[n.jsx("span",{children:c.initiator||"unknown"}),n.jsx("span",{children:c.duration}),n.jsxs("span",{children:["prev ",c.previousCallGap]})]}),n.jsxs("div",{className:"thread-call-flags",children:[n.jsxs("span",{children:["Context ",ue(c)]}),n.jsx("span",{children:me(c)})]}),c.recommendation?n.jsx("p",{className:"thread-call-recommendation",children:c.recommendation}):null,n.jsx("div",{className:"thread-context-bar",title:`Context window ${he(c)}`,children:n.jsx("span",{className:pe(c.contextWindowPct),style:{width:xe(c.contextWindowPct)}})}),n.jsxs("div",{className:"thread-call-actions table-action-group",children:[n.jsx("button",{className:"table-action-button",type:"button",onClick:()=>i(c.id),disabled:c.id===e.id,children:"Open"}),n.jsxs("button",{className:"table-action-button",type:"button","aria-label":`${l} for ${s} ${c.thread} ${c.model}`,onClick:()=>a(c.id),children:[n.jsx(J,{size:14})," ",l]})]})]},c.id))})}function le(e,t){if(e.length<=5)return e;const i=e.findIndex(r=>r.id===t);if(i<0)return e.slice(0,5);const a=Math.max(0,Math.min(i-2,e.length-5));return e.slice(a,a+5)}function ue(e){return e.contextWindowPct===null?"Not reported":x(e.contextWindowPct)}function he(e){if(e.contextWindowPct===null)return"Not reported";const t=e.modelContextWindow?` of ${w(e.modelContextWindow)}`:"";return`${x(e.contextWindowPct)}${t}`}function me(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function pe(e){const t=Number(e??0);return t>=75?"high":t>=50?"medium":"low"}function xe(e){const t=Number(e??0),i=Math.max(0,Math.min(100,Number.isFinite(t)?t:0));return`${Math.round(i)}%`}async function Se(e){I(e);const t=new URLSearchParams({enabled:"1",_:String(Date.now())}),i=await fetch(`/api/context-settings?${t.toString()}`,{headers:A(e),cache:"no-store"});return!!(await O(i,"Context settings")).context_api_enabled}async function Te(e,t,i){if(I(t),!t.contextApiEnabled)throw new Error("Context API is not enabled.");const a=new URLSearchParams({record_id:e,mode:i.mode,include_tool_output:i.includeToolOutput?"1":"0",include_compaction_history:i.includeCompactionHistory?"1":"0",max_chars:String(i.maxChars),max_entries:String(i.maxEntries),_:String(Date.now())});return await fetch(`/api/context?${a.toString()}`,{headers:A(t),cache:"no-store"}).then(s=>O(s,"Context"))}function I(e){if(e.fileMode)throw new Error("Context loading requires the localhost dashboard server.");if(!e.apiToken)throw new Error("Context loading requires a localhost dashboard API token.")}function A(e){return{Accept:"application/json","X-Codex-Usage-Token":e.apiToken}}async function O(e,t){let i={};try{i=await e.json()}catch{i={}}if(!e.ok){const a=typeof i.error=="string"?i.error:`${t} API returned HTTP ${e.status}.`;throw new Error(a)}if(typeof i.error=="string")throw new Error(i.error);return i}function ze({call:e,payload:t,onRunFullAnalysis:i,showHeading:a=!0}){const r=be(e,t);return n.jsxs("div",{className:"context-attribution-module",children:[a?n.jsxs("div",{className:"serialized-breakdown-heading context-attribution-heading",children:[n.jsx("strong",{children:"Context Attribution"}),n.jsx("span",{children:"Estimated from visible log volume"})]}):null,n.jsxs("div",{className:"drilldown-metric-grid wide context-attribution-grid",children:[n.jsx(g,{label:"Uncached input",value:o(e.uncachedInput),detail:"exact aggregate row"}),n.jsx(g,{label:"Visible new context estimate",value:r?`~${o(r.visibleTokenEstimate)}`:"Not loaded yet",detail:r?`${o(r.visibleChars)} analyzed chars`:"Runtime evidence"}),n.jsx(g,{label:"Serialized local upper bound",value:r!=null&&r.serializedTokens?`~${o(r.serializedBound)}`:"Not loaded yet",detail:r!=null&&r.serializedTokens?ge(r):"Runtime evidence"}),n.jsx(g,{label:"Unexplained hidden/serialized input estimate",value:r?`~${o(r.visibleGap)}`:"Not loaded yet",detail:r?"uncached input minus visible estimate":"Runtime evidence"}),n.jsx(g,{label:"Possible serialized overhead",value:r?`~${o(r.serializedCandidate)}`:"Not loaded yet",detail:r?"serialized upper bound minus visible estimate":"Runtime evidence"}),n.jsx(g,{label:"Remaining after serialized bound",value:r?`~${o(r.remainingAfterSerialized)}`:"Not loaded yet",detail:r?"not covered by serialized upper bound":"Runtime evidence"})]}),n.jsx(fe,{stats:r,onRunFullAnalysis:(t==null?void 0:t.context_mode)==="full"?void 0:i}),n.jsx("p",{className:"privacy-note",children:"Compare exact uncached input with tokenizer-counted visible log evidence. Treat the gap as hidden scaffolding, serialization, or tokenizer estimate error."})]})}function g({label:e,value:t,detail:i}){return n.jsxs("span",{className:"drilldown-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function fe({stats:e,onRunFullAnalysis:t}){if(!(e!=null&&e.serializedTokens))return null;if(e.serializedDeferred)return n.jsxs("div",{className:"serialized-breakdown deferred",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Fast estimate loaded; full serialized grouping is deferred."})]}),t?n.jsx("div",{className:"context-followup-actions",children:n.jsx("button",{className:"toolbar-button serialized-action",type:"button",onClick:t,children:"Run full serialized analysis"})}):null]});const i=e.serializedBuckets.slice(0,6);return n.jsxs("div",{className:"serialized-breakdown",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Upper-bound local JSONL structure; not exact prompt text."})]}),n.jsx("div",{className:"serialized-bucket-grid",children:i.length?i.map(a=>n.jsxs("div",{className:"serialized-bucket",children:[n.jsx("span",{children:a.label||a.key||"Unknown"}),n.jsx("strong",{children:o(Number(a.token_estimate??0))}),n.jsxs("small",{children:[o(Number(a.count??0))," fields · ",o(Number(a.char_count??0))," chars"]}),a.note?n.jsx("small",{children:a.note}):null]},a.key??a.label??String(a.token_estimate??0))):n.jsx("p",{className:"empty-state",children:"No serialized evidence groups returned."})})]})}function ge(e){const t=[`${o(e.serializedChars)} raw JSON chars`,e.serializedEstimator];return e.serializedDeferred&&t.push("fast estimate"),e.serializedLineCount&&t.push(`${o(e.serializedLineCount)} raw lines`),t.join(" · ")}function be(e,t){if(!t)return null;const i=t.entries??[],a=Number(t.visible_char_count??i.reduce((B,H)=>B+String(H.text??"").length,0)),r=Number(t.visible_token_estimate??Math.ceil(a/4)),s=t.serialized_evidence??{},l=Number(s.raw_json_token_estimate??s.token_estimate??0),h=Number(s.raw_json_char_count??s.total_chars??0),m=Number(s.raw_line_count??0),b=s.token_estimator||t.visible_token_estimator||"chars_per_4_fallback",c=Array.isArray(s.buckets)?s.buckets:[],v=l>0?Math.min(l,e.uncachedInput):0,k=Math.max(e.uncachedInput-r,0),F=v>r?v-r:0,W=l>0?Math.max(e.uncachedInput-Math.max(r,v),0):k;return{visibleChars:a,visibleTokenEstimate:r,serializedTokens:l,serializedChars:h,serializedLineCount:m,serializedEstimator:b,serializedBound:v,visibleGap:k,serializedCandidate:F,remainingAfterSerialized:W,serializedDeferred:!!(s.deferred||s.deferred_buckets),serializedBuckets:c}}function Pe({entry:e}){const t=je(e);return t.length?n.jsx("div",{className:"context-entry-chips","aria-label":"Evidence entry metadata",children:t.map(i=>n.jsxs("span",{title:i.title,children:[i.label,": ",i.value]},`${i.label}-${i.value}`))}):null}function je(e){var s,l,h,m;const t=[],i=e.action_timing;(i==null?void 0:i.since_turn_start_ms)!==void 0&&t.push({label:"T+",value:N(i.since_turn_start_ms),title:"Elapsed since selected turn start"}),(i==null?void 0:i.since_previous_entry_ms)!==void 0&&t.push({label:"Gap",value:N(i.since_previous_entry_ms),title:"Gap since previous evidence entry"}),(i==null?void 0:i.reported_duration_ms)!==void 0&&t.push({label:"Duration",value:N(i.reported_duration_ms),title:i.duration_source||"Duration reported by this event"});const a=(s=e.token_usage)==null?void 0:s.last_token_usage;a&&t.push({label:"Entry tokens",value:z(a),title:"Token usage reported for this evidence entry"});const r=(l=e.token_usage)==null?void 0:l.total_token_usage;return r&&t.push({label:"Session tokens",value:z(r),title:"Cumulative token usage reported by this evidence entry"}),(h=e.compaction)!=null&&h.replacement_history_available&&t.push({label:"Compaction",value:`${o(((m=e.compaction.replacement_history)==null?void 0:m.length)??0)} replacement entries`,title:"Compaction replacement history is available for this entry"}),e.tool_output_omitted&&t.push({label:"Tool output",value:"omitted",title:"Tool output omitted until explicitly requested"}),t}function z(e){const t=Number((e==null?void 0:e.input_tokens)??0),i=Number((e==null?void 0:e.cached_input_tokens)??0),a=Number((e==null?void 0:e.uncached_input_tokens)??Math.max(t-i,0)),r=Number((e==null?void 0:e.output_tokens)??0),s=Number((e==null?void 0:e.total_tokens)??t+r);return`${o(s)} total · ${o(a)} uncached`}function N(e){if(!Number.isFinite(e))return"0ms";if(e<1e3)return`${Math.round(e)}ms`;const t=e/1e3;return t>=10?`${t.toFixed(0)}s`:`${t.toFixed(1)}s`}const R=new Map,U=new Map,y=new Map,_=new Map,D=new Map;function Ee(e,t){return R.get(L(e,t))??null}function Me(e,t,i){R.set(L(e,t),i)}function Ie(e){const t=U.get(e);return t?{...t}:null}function Ae(e,t){U.set(e,{...t})}function ve(e,t){return`${e.type??"entry"}-${e.line_number??e.timestamp??t}`}function Oe(e,t){const i=y.get(e);return i?new Set(i):t.length?new Set([ve(t[0],0)]):new Set}function Re(e,t,i){const a=y.get(e)??new Set;i?a.add(t):a.delete(t),y.set(e,a)}function Ue(e,t){var i;return((i=_.get(e))==null?void 0:i.get(t))??0}function De(e,t,i){const a=_.get(e)??new Map;i>0?a.set(t,i):a.delete(t),_.set(e,a)}function Le(e){return D.get(e)??!1}function Fe(e,t){D.set(e,t)}function L(e,t){return[e,t.mode,t.includeToolOutput?"tool-output":"no-tool-output",t.includeCompactionHistory?"compaction-history":"no-compaction-history",String(t.maxChars),String(t.maxEntries)].join("|")}const C={includeToolOutput:!1,includeCompactionHistory:!1,maxChars:8e3,maxEntries:20,mode:"quick"};function We(e=window.location.search,t=C){const i=new URLSearchParams(e);return{includeToolOutput:P(i.get("include_tool_output"),t.includeToolOutput),includeCompactionHistory:P(i.get("include_compaction_history"),t.includeCompactionHistory),maxChars:E(i.get("max_chars"),t.maxChars),maxEntries:E(i.get("max_entries"),t.maxEntries),mode:i.get("mode")==="full"?"full":t.mode}}function Be(e,t,i=C){j(e,"mode",t.mode,i.mode),j(e,"max_entries",String(t.maxEntries),String(i.maxEntries)),j(e,"max_chars",String(t.maxChars),String(i.maxChars)),j(e,"include_tool_output",t.includeToolOutput?"1":"0",i.includeToolOutput?"1":"0"),j(e,"include_compaction_history",t.includeCompactionHistory?"1":"0",i.includeCompactionHistory?"1":"0")}function He(e){return e.fileMode?"Static file mode cannot read local JSONL context. Use serve-dashboard with the context API enabled.":e.apiToken?e.contextApiEnabled?"Context API is enabled. Load selected-turn evidence from the local JSONL source only when needed.":"Context API is available but off. Enable it here before loading selected-turn evidence.":"Context loading requires the localhost dashboard server API token."}function P(e,t){return e==="1"||e==="true"?!0:e==="0"||e==="false"?!1:t}function E(e,t){if(e===null||e.trim()==="")return t;const i=Number(e);return Number.isFinite(i)&&i>=0?Math.floor(i):t}function j(e,t,i,a){i===a?e.searchParams.delete(t):e.searchParams.set(t,i)}function Ge(e){return e instanceof Error?e.message:String(e)}function qe(e,t){var s;const i=Number(((s=e.omitted)==null?void 0:s.max_entries)??t.maxEntries??C.maxEntries),a=C.maxEntries||20,r=i>0?Math.max(i+a,i*2):0;return{...t,maxEntries:r}}function Je(e){const t=e.omitted??{},i=e.source??{},a=["Local JSONL context loaded on demand.",e.include_tool_output?"Tool output included with redaction and size limits.":"Tool output hidden for this view."];i.file&&a.push(`Source: ${i.file}${i.line_number?`:${i.line_number}`:""}.`);const r=Number(t.older_entries??0);r>0&&a.push(`${o(r)} older entries omitted.`);const s=Number(t.over_budget_chars??0);return s>0&&a.push(`${o(s)} chars over budget omitted.`),Number(t.max_chars??NaN)===0&&a.push("No character limit applied."),a}export{ze as C,ke as T,Ee as a,He as b,Ie as c,C as d,Se as e,Ge as f,Me as g,Je as h,Le as i,Oe as j,ve as k,Te as l,Pe as m,De as n,Ue as o,qe as p,Re as q,Ae as r,Fe as s,_e as t,we as u,ye as v,$e as w,We as x,Be as y}; +import{j as n}from"./dashboard-react.js";import{j as o,p as x,u as G,f as w,ak as $,m as q,a as J}from"./App.js";function ye({call:e,calls:t}){const i=[...t,e].filter((h,m,b)=>b.findIndex(c=>c.id===h.id)===m).sort(te),a=i.findIndex(h=>h.id===e.id),r=a>0?i[a-1]:null,s=r?Z(e,r):null,l=V(e,r);return n.jsxs("div",{className:"call-cache-delta-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Cache Accounting Delta"}),n.jsx("span",{children:r?`Call ${a+1} of ${i.length}`:"No previous call"})]}),n.jsx(K,{call:e,delta:s,diagnostic:l,previous:r,selectedIndex:a,totalCalls:i.length}),r&&s?n.jsxs(n.Fragment,{children:[n.jsx("p",{className:"diagnostic-interpretation",children:ee(s)}),n.jsxs("div",{className:"cache-delta-grid",children:[n.jsx(f,{label:"Last call input",value:p(s.input),detail:`${o(r.input)} -> ${o(e.input)}`}),n.jsx(f,{label:"Cached input",value:p(s.cached),detail:`${o(r.cachedInput)} -> ${o(e.cachedInput)}`}),n.jsx(f,{label:"Uncached input",value:p(s.uncached),detail:`${o(r.uncachedInput)} -> ${o(e.uncachedInput)}`}),n.jsx(f,{label:"Output",value:p(s.output),detail:`${o(r.output)} -> ${o(e.output)}`}),n.jsx(f,{label:"Reasoning output",value:p(s.reasoning),detail:`${o(r.reasoningOutput)} -> ${o(e.reasoningOutput)}`}),n.jsx(f,{label:"Cache ratio",value:M(s.cacheRatio),detail:`${x(r.cachedPct)} -> ${x(e.cachedPct)}`})]})]}):n.jsx("p",{className:"empty-state",children:"No previous aggregate call available for cache delta accounting."})]})}function K({call:e,delta:t,diagnostic:i,previous:a,selectedIndex:r,totalCalls:s}){return n.jsxs("div",{className:`cache-verdict-card cache-verdict-${i.key}`,children:[n.jsxs("div",{className:"cache-verdict-main",children:[n.jsx("span",{className:"cache-diagnostic-pill",children:i.label}),n.jsx("p",{children:i.body})]}),n.jsxs("div",{className:"cache-verdict-meta",children:[n.jsxs("span",{children:["Cache ratio: ",x(e.cachedPct)]}),n.jsx("span",{children:t?Q(t):"No previous call loaded for delta comparison."}),n.jsxs("span",{children:["Position: ",r+1," of ",s]}),n.jsxs("span",{children:["Next: ",Y(e,i,a)]})]})]})}function V(e,t){const i=X(e,t);return i==="spike"?{key:"spike",label:"Uncached spike",body:"Fresh input rose sharply compared with the previous call in this resolved thread."}:i==="warm"?{key:"warm",label:"Warm cache reuse",body:"Most input tokens reused prompt cache. The uncached portion is the most likely investigation target."}:i==="partial"?{key:"partial",label:"Partial cache miss",body:"Some prefix reused cache, but a meaningful share of input was fresh or reserialized."}:{key:"cold",label:"Cold resume / stale cache",body:"Conversation-specific cache likely expired or missed; remaining cache is probably stable Codex scaffolding or tool schema prefix."}}function X(e,t){const i=S(e),a=t?S(t):null,r=(t==null?void 0:t.uncachedInput)??0,s=.05,l=.85,h=.8,m=1e3;return t&&a!==null&&a>=h&&i<=s&&e.input>=m?"cold":t&&e.uncachedInput>Math.max(r*2,m)?"spike":i>=l?"warm":i>s?"partial":"cold"}function S(e){return Number.isFinite(e.cachedPct)?e.cachedPct/100:0}function Q(e){return`Uncached input: ${p(e.uncached)}. Cached input: ${p(e.cached)}. Cache ratio: ${M(e.cacheRatio)}.`}function Y(e,t,i){return t.key==="cold"?"Compare the previous call, then inspect loaded evidence to see what fresh context was sent after the cache miss.":t.key==="spike"?"Inspect the most recent evidence entries first; the spike is in fresh uncached input, not cached history.":t.key==="warm"?`Cache reuse is healthy; focus on ${o(e.uncachedInput)} uncached tokens that were still billed as fresh input.`:i?"Use delta cards to locate whether the change came from cached input, uncached input, or output/reasoning.":"Use loaded evidence if aggregate totals are not enough to understand this isolated call."}function Z(e,t){return{input:e.input-t.input,cached:e.cachedInput-t.cachedInput,uncached:e.uncachedInput-t.uncachedInput,output:e.output-t.output,reasoning:e.reasoningOutput-t.reasoningOutput,cacheRatio:e.cachedPct-t.cachedPct}}function ee(e){return e.uncached>0&&e.cached<0?`Uncached input rose by ${o(e.uncached)} while cached input fell by ${o(Math.abs(e.cached))}.`:e.uncached>0?`Uncached input increased by ${o(e.uncached)} versus the previous aggregate call.`:e.uncached<0&&e.cached>=0?`Uncached input decreased by ${o(Math.abs(e.uncached))} while cached input increased.`:"Cache accounting is stable versus the previous aggregate call."}function f({label:e,value:t,detail:i}){return n.jsxs("span",{className:"cache-delta-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function p(e){return e===0?"0":`${e>0?"+":"-"}${o(Math.abs(e))}`}function M(e){return e===0?"0.0pp":`${e>0?"+":"-"}${Math.abs(e).toFixed(1)}pp`}function te(e,t){return T(e)-T(t)}function T(e){const t=Date.parse(e.rawTime||e.time);return Number.isFinite(t)?t:0}function _e({call:e}){const t=G(),i=ne(e);return n.jsxs("div",{className:"call-decision-card",children:[n.jsxs("div",{className:"section-heading compact",children:[n.jsx("h3",{children:"Call Decision"}),n.jsx("span",{children:i.nextAction})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsxs("div",{children:[n.jsx("dt",{children:"Pricing status"}),n.jsx("dd",{children:i.pricingStatus})]}),n.jsxs("div",{children:[n.jsx("dt",{children:t.t("detail.next_action","Next action")}),n.jsx("dd",{children:i.nextAction})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Why flagged"}),n.jsx("dd",{children:i.whyFlagged})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Allowance impact"}),n.jsx("dd",{children:i.allowanceImpact})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Context use"}),n.jsx("dd",{children:i.contextUse})]})]})]})}function ne(e){return{allowanceImpact:`${se(e.credits)} counted`,contextUse:e.contextWindowPct==null?"Not reported":x(e.contextWindowPct),nextAction:re(e),pricingStatus:ie(e),whyFlagged:ae(e)}}function ie(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function re(e){return e.recommendation?e.recommendation:e.cost<=0?"Configure pricing":e.cachedPct<30&&e.input>0?"Compare fresh input":(e.contextWindowPct??0)>=60?"Inspect thread timeline":e.reasoningOutput>e.output?"Review reasoning effort":"Use aggregate first"}function ae(e){return e.recommendation?e.recommendation:e.signal&&e.signal!=="aggregate"?`${e.signal} aggregate signal`:(e.contextWindowPct??0)>=60?"High reported context use.":e.cachedPct<30&&e.input>0?`${w(e.uncachedInput)} uncached input with weak cache reuse.`:e.reasoningOutput>e.output?"Reasoning output exceeds visible output.":e.cost>0||e.credits>0?"Review cost and credit impact before loading raw context.":"No aggregate efficiency flag on this row."}function se(e){return`${new Intl.NumberFormat("en-US",{maximumFractionDigits:2}).format(e)} credits`}function we({call:e}){return n.jsxs("div",{className:"call-source-card composition-card",children:[n.jsxs("div",{className:"composition-head",children:[n.jsx("strong",{children:"Call Source"}),n.jsx("span",{children:$(e)})]}),n.jsxs("dl",{className:"detail-list compact",children:[n.jsx(d,{label:"Project",value:e.project||"Unknown"}),n.jsx(d,{label:"Project path",value:e.projectRelativeCwd||e.cwd||"."}),n.jsx(d,{label:"Project tags",value:e.projectTags.length?e.projectTags.join(", "):"None"}),n.jsx(d,{label:"Thread attachment",value:e.threadAttachmentLabel||"Direct thread"}),n.jsx(d,{label:"Thread source",value:e.threadSource||"user"}),n.jsx(d,{label:"Subagent type",value:e.subagentType||"None"}),n.jsx(d,{label:"Agent role",value:e.agentRole||"None"}),n.jsx(d,{label:"Agent nickname",value:e.agentNickname||"None"}),n.jsx(d,{label:"Source line",value:$(e)}),n.jsx(d,{label:"Initiated by",value:e.initiator||"unknown"}),n.jsx(d,{label:"Initiator reason",value:e.initiatorReason||"Not reported"}),n.jsx(d,{label:"Session",value:e.sessionId||"Not available"}),n.jsx(d,{label:"Turn",value:e.turnId||"None"}),n.jsx(d,{label:"Parent thread",value:e.parentThread||"None"}),n.jsx(d,{label:"Parent session",value:e.parentSessionId||"None"}),n.jsx(d,{label:"Parent updated",value:oe(e.parentSessionUpdatedAt)}),n.jsx(d,{label:"Working directory",value:e.cwd||"Not available"}),n.jsx(d,{label:"Git branch",value:e.gitBranch||"Not available"}),n.jsx(d,{label:"Git remote",value:e.gitRemoteLabel||"Not available"}),n.jsx(d,{label:"Git hash",value:e.gitRemoteHash||"Not available"}),n.jsx(d,{label:"Credit note",value:e.usageCreditNote||"None"})]})]})}function oe(e){if(!e)return"None";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString([],{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function d({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function ke({call:e}){return n.jsxs("dl",{className:"detail-list",children:[n.jsx(u,{label:"Last call total",value:o(e.totalTokens)}),n.jsx(u,{label:"Last call input",value:o(e.input)}),n.jsx(u,{label:"Cached input",value:o(e.cachedInput)}),n.jsx(u,{label:"Output tokens",value:o(e.output)}),n.jsx(u,{label:"Reasoning output",value:o(e.reasoningOutput)}),n.jsx(u,{label:"Session cumulative",value:e.cumulativeTotalTokens?o(e.cumulativeTotalTokens):"Not reported"}),n.jsx(u,{label:"Pricing model",value:ce(e)}),n.jsx(u,{label:"Credit model",value:e.usageCreditModel||"No mapped rate"}),n.jsx(u,{label:"Credit confidence",value:e.usageCreditConfidence||"unknown"}),n.jsx(u,{label:"Credit source",value:e.usageCreditSource||"None"}),n.jsx(u,{label:"Credit source fetched",value:e.usageCreditFetchedAt||"Unknown"}),n.jsx(u,{label:"Credit tier",value:e.usageCreditTier||"Unknown"}),n.jsx(u,{label:"Cache savings",value:q(e.estimatedCacheSavings)}),n.jsx(u,{label:"Efficiency signals",value:de(e)})]})}function u({label:e,value:t}){return n.jsxs("div",{children:[n.jsx("dt",{children:e}),n.jsx("dd",{children:t})]})}function ce(e){return e.pricingModel?e.pricingModel:e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function de(e){return e.efficiencyFlags.length?e.efficiencyFlags.join(", "):e.signal&&e.signal!=="aggregate"?e.signal:e.recommendation?"recommendation":"None"}function $e({selectedCall:e,calls:t,onOpenInvestigator:i,onCopyCallLink:a,className:r,copyAriaContext:s,copyLabel:l="Copy link"}){const h=t.length?t:[e],m=le(h,e.id),b=["thread-mini-timeline",r].filter(Boolean).join(" ");return n.jsx("ol",{className:b,children:m.map(c=>n.jsxs("li",{className:c.id===e.id?"active":"",children:[n.jsx("span",{children:c.time}),n.jsxs("strong",{children:[c.model," / ",c.effort]}),n.jsxs("em",{children:[w(c.totalTokens)," tokens - ",x(c.cachedPct)," cache"]}),n.jsxs("div",{className:"thread-call-meta",children:[n.jsx("span",{children:c.initiator||"unknown"}),n.jsx("span",{children:c.duration}),n.jsxs("span",{children:["prev ",c.previousCallGap]})]}),n.jsxs("div",{className:"thread-call-flags",children:[n.jsxs("span",{children:["Context ",ue(c)]}),n.jsx("span",{children:me(c)})]}),c.recommendation?n.jsx("p",{className:"thread-call-recommendation",children:c.recommendation}):null,n.jsx("div",{className:"thread-context-bar",title:`Context window ${he(c)}`,children:n.jsx("span",{className:pe(c.contextWindowPct),style:{width:xe(c.contextWindowPct)}})}),n.jsxs("div",{className:"thread-call-actions table-action-group",children:[n.jsx("button",{className:"table-action-button",type:"button",onClick:()=>i(c.id),disabled:c.id===e.id,children:"Open"}),n.jsxs("button",{className:"table-action-button",type:"button","aria-label":`${l} for ${s} ${c.thread} ${c.model}`,onClick:()=>a(c.id),children:[n.jsx(J,{size:14})," ",l]})]})]},c.id))})}function le(e,t){if(e.length<=5)return e;const i=e.findIndex(r=>r.id===t);if(i<0)return e.slice(0,5);const a=Math.max(0,Math.min(i-2,e.length-5));return e.slice(a,a+5)}function ue(e){return e.contextWindowPct===null?"Not reported":x(e.contextWindowPct)}function he(e){if(e.contextWindowPct===null)return"Not reported";const t=e.modelContextWindow?` of ${w(e.modelContextWindow)}`:"";return`${x(e.contextWindowPct)}${t}`}function me(e){return e.cost<=0?"No configured price":e.pricingEstimated?"Best-guess estimate":"Configured price"}function pe(e){const t=Number(e??0);return t>=75?"high":t>=50?"medium":"low"}function xe(e){const t=Number(e??0),i=Math.max(0,Math.min(100,Number.isFinite(t)?t:0));return`${Math.round(i)}%`}async function Se(e){I(e);const t=new URLSearchParams({enabled:"1",_:String(Date.now())}),i=await fetch(`/api/context-settings?${t.toString()}`,{headers:A(e),cache:"no-store"});return!!(await O(i,"Context settings")).context_api_enabled}async function Te(e,t,i){if(I(t),!t.contextApiEnabled)throw new Error("Context API is not enabled.");const a=new URLSearchParams({record_id:e,mode:i.mode,include_tool_output:i.includeToolOutput?"1":"0",include_compaction_history:i.includeCompactionHistory?"1":"0",max_chars:String(i.maxChars),max_entries:String(i.maxEntries),_:String(Date.now())});return await fetch(`/api/context?${a.toString()}`,{headers:A(t),cache:"no-store"}).then(s=>O(s,"Context"))}function I(e){if(e.fileMode)throw new Error("Context loading requires the localhost dashboard server.");if(!e.apiToken)throw new Error("Context loading requires a localhost dashboard API token.")}function A(e){return{Accept:"application/json","X-Codex-Usage-Token":e.apiToken}}async function O(e,t){let i={};try{i=await e.json()}catch{i={}}if(!e.ok){const a=typeof i.error=="string"?i.error:`${t} API returned HTTP ${e.status}.`;throw new Error(a)}if(typeof i.error=="string")throw new Error(i.error);return i}function ze({call:e,payload:t,onRunFullAnalysis:i,showHeading:a=!0}){const r=be(e,t);return n.jsxs("div",{className:"context-attribution-module",children:[a?n.jsxs("div",{className:"serialized-breakdown-heading context-attribution-heading",children:[n.jsx("strong",{children:"Context Attribution"}),n.jsx("span",{children:"Estimated from visible log volume"})]}):null,n.jsxs("div",{className:"drilldown-metric-grid wide context-attribution-grid",children:[n.jsx(g,{label:"Uncached input",value:o(e.uncachedInput),detail:"exact aggregate row"}),n.jsx(g,{label:"Visible new context estimate",value:r?`~${o(r.visibleTokenEstimate)}`:"Not loaded yet",detail:r?`${o(r.visibleChars)} analyzed chars`:"Runtime evidence"}),n.jsx(g,{label:"Serialized local upper bound",value:r!=null&&r.serializedTokens?`~${o(r.serializedBound)}`:"Not loaded yet",detail:r!=null&&r.serializedTokens?ge(r):"Runtime evidence"}),n.jsx(g,{label:"Unexplained hidden/serialized input estimate",value:r?`~${o(r.visibleGap)}`:"Not loaded yet",detail:r?"uncached input minus visible estimate":"Runtime evidence"}),n.jsx(g,{label:"Possible serialized overhead",value:r?`~${o(r.serializedCandidate)}`:"Not loaded yet",detail:r?"serialized upper bound minus visible estimate":"Runtime evidence"}),n.jsx(g,{label:"Remaining after serialized bound",value:r?`~${o(r.remainingAfterSerialized)}`:"Not loaded yet",detail:r?"not covered by serialized upper bound":"Runtime evidence"})]}),n.jsx(fe,{stats:r,onRunFullAnalysis:(t==null?void 0:t.context_mode)==="full"?void 0:i}),n.jsx("p",{className:"privacy-note",children:"Compare exact uncached input with tokenizer-counted visible log evidence. Treat the gap as hidden scaffolding, serialization, or tokenizer estimate error."})]})}function g({label:e,value:t,detail:i}){return n.jsxs("span",{className:"drilldown-metric",children:[n.jsx("small",{children:e}),n.jsx("strong",{children:t}),n.jsx("em",{children:i})]})}function fe({stats:e,onRunFullAnalysis:t}){if(!(e!=null&&e.serializedTokens))return null;if(e.serializedDeferred)return n.jsxs("div",{className:"serialized-breakdown deferred",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Fast estimate loaded; full serialized grouping is deferred."})]}),t?n.jsx("div",{className:"context-followup-actions",children:n.jsx("button",{className:"toolbar-button serialized-action",type:"button",onClick:t,children:"Run full serialized analysis"})}):null]});const i=e.serializedBuckets.slice(0,6);return n.jsxs("div",{className:"serialized-breakdown",children:[n.jsxs("div",{className:"serialized-breakdown-heading",children:[n.jsx("strong",{children:"Serialized evidence groups"}),n.jsx("span",{children:"Upper-bound local JSONL structure; not exact prompt text."})]}),n.jsx("div",{className:"serialized-bucket-grid",children:i.length?i.map(a=>n.jsxs("div",{className:"serialized-bucket",children:[n.jsx("span",{children:a.label||a.key||"Unknown"}),n.jsx("strong",{children:o(Number(a.token_estimate??0))}),n.jsxs("small",{children:[o(Number(a.count??0))," fields · ",o(Number(a.char_count??0))," chars"]}),a.note?n.jsx("small",{children:a.note}):null]},a.key??a.label??String(a.token_estimate??0))):n.jsx("p",{className:"empty-state",children:"No serialized evidence groups returned."})})]})}function ge(e){const t=[`${o(e.serializedChars)} raw JSON chars`,e.serializedEstimator];return e.serializedDeferred&&t.push("fast estimate"),e.serializedLineCount&&t.push(`${o(e.serializedLineCount)} raw lines`),t.join(" · ")}function be(e,t){if(!t)return null;const i=t.entries??[],a=Number(t.visible_char_count??i.reduce((B,H)=>B+String(H.text??"").length,0)),r=Number(t.visible_token_estimate??Math.ceil(a/4)),s=t.serialized_evidence??{},l=Number(s.raw_json_token_estimate??s.token_estimate??0),h=Number(s.raw_json_char_count??s.total_chars??0),m=Number(s.raw_line_count??0),b=s.token_estimator||t.visible_token_estimator||"chars_per_4_fallback",c=Array.isArray(s.buckets)?s.buckets:[],v=l>0?Math.min(l,e.uncachedInput):0,k=Math.max(e.uncachedInput-r,0),F=v>r?v-r:0,W=l>0?Math.max(e.uncachedInput-Math.max(r,v),0):k;return{visibleChars:a,visibleTokenEstimate:r,serializedTokens:l,serializedChars:h,serializedLineCount:m,serializedEstimator:b,serializedBound:v,visibleGap:k,serializedCandidate:F,remainingAfterSerialized:W,serializedDeferred:!!(s.deferred||s.deferred_buckets),serializedBuckets:c}}function Pe({entry:e}){const t=je(e);return t.length?n.jsx("div",{className:"context-entry-chips","aria-label":"Evidence entry metadata",children:t.map(i=>n.jsxs("span",{title:i.title,children:[i.label,": ",i.value]},`${i.label}-${i.value}`))}):null}function je(e){var s,l,h,m;const t=[],i=e.action_timing;(i==null?void 0:i.since_turn_start_ms)!==void 0&&t.push({label:"T+",value:N(i.since_turn_start_ms),title:"Elapsed since selected turn start"}),(i==null?void 0:i.since_previous_entry_ms)!==void 0&&t.push({label:"Gap",value:N(i.since_previous_entry_ms),title:"Gap since previous evidence entry"}),(i==null?void 0:i.reported_duration_ms)!==void 0&&t.push({label:"Duration",value:N(i.reported_duration_ms),title:i.duration_source||"Duration reported by this event"});const a=(s=e.token_usage)==null?void 0:s.last_token_usage;a&&t.push({label:"Entry tokens",value:z(a),title:"Token usage reported for this evidence entry"});const r=(l=e.token_usage)==null?void 0:l.total_token_usage;return r&&t.push({label:"Session tokens",value:z(r),title:"Cumulative token usage reported by this evidence entry"}),(h=e.compaction)!=null&&h.replacement_history_available&&t.push({label:"Compaction",value:`${o(((m=e.compaction.replacement_history)==null?void 0:m.length)??0)} replacement entries`,title:"Compaction replacement history is available for this entry"}),e.tool_output_omitted&&t.push({label:"Tool output",value:"omitted",title:"Tool output omitted until explicitly requested"}),t}function z(e){const t=Number((e==null?void 0:e.input_tokens)??0),i=Number((e==null?void 0:e.cached_input_tokens)??0),a=Number((e==null?void 0:e.uncached_input_tokens)??Math.max(t-i,0)),r=Number((e==null?void 0:e.output_tokens)??0),s=Number((e==null?void 0:e.total_tokens)??t+r);return`${o(s)} total · ${o(a)} uncached`}function N(e){if(!Number.isFinite(e))return"0ms";if(e<1e3)return`${Math.round(e)}ms`;const t=e/1e3;return t>=10?`${t.toFixed(0)}s`:`${t.toFixed(1)}s`}const R=new Map,U=new Map,y=new Map,_=new Map,D=new Map;function Ee(e,t){return R.get(L(e,t))??null}function Me(e,t,i){R.set(L(e,t),i)}function Ie(e){const t=U.get(e);return t?{...t}:null}function Ae(e,t){U.set(e,{...t})}function ve(e,t){return`${e.type??"entry"}-${e.line_number??e.timestamp??t}`}function Oe(e,t){const i=y.get(e);return i?new Set(i):t.length?new Set([ve(t[0],0)]):new Set}function Re(e,t,i){const a=y.get(e)??new Set;i?a.add(t):a.delete(t),y.set(e,a)}function Ue(e,t){var i;return((i=_.get(e))==null?void 0:i.get(t))??0}function De(e,t,i){const a=_.get(e)??new Map;i>0?a.set(t,i):a.delete(t),_.set(e,a)}function Le(e){return D.get(e)??!1}function Fe(e,t){D.set(e,t)}function L(e,t){return[e,t.mode,t.includeToolOutput?"tool-output":"no-tool-output",t.includeCompactionHistory?"compaction-history":"no-compaction-history",String(t.maxChars),String(t.maxEntries)].join("|")}const C={includeToolOutput:!1,includeCompactionHistory:!1,maxChars:8e3,maxEntries:20,mode:"quick"};function We(e=window.location.search,t=C){const i=new URLSearchParams(e);return{includeToolOutput:P(i.get("include_tool_output"),t.includeToolOutput),includeCompactionHistory:P(i.get("include_compaction_history"),t.includeCompactionHistory),maxChars:E(i.get("max_chars"),t.maxChars),maxEntries:E(i.get("max_entries"),t.maxEntries),mode:i.get("mode")==="full"?"full":t.mode}}function Be(e,t,i=C){j(e,"mode",t.mode,i.mode),j(e,"max_entries",String(t.maxEntries),String(i.maxEntries)),j(e,"max_chars",String(t.maxChars),String(i.maxChars)),j(e,"include_tool_output",t.includeToolOutput?"1":"0",i.includeToolOutput?"1":"0"),j(e,"include_compaction_history",t.includeCompactionHistory?"1":"0",i.includeCompactionHistory?"1":"0")}function He(e){return e.fileMode?"Static file mode cannot read local JSONL context. Use serve-dashboard with the context API enabled.":e.apiToken?e.contextApiEnabled?"Context API is enabled. Load selected-turn evidence from the local JSONL source only when needed.":"Context API is available but off. Enable it here before loading selected-turn evidence.":"Context loading requires the localhost dashboard server API token."}function P(e,t){return e==="1"||e==="true"?!0:e==="0"||e==="false"?!1:t}function E(e,t){if(e===null||e.trim()==="")return t;const i=Number(e);return Number.isFinite(i)&&i>=0?Math.floor(i):t}function j(e,t,i,a){i===a?e.searchParams.delete(t):e.searchParams.set(t,i)}function Ge(e){return e instanceof Error?e.message:String(e)}function qe(e,t){var s;const i=Number(((s=e.omitted)==null?void 0:s.max_entries)??t.maxEntries??C.maxEntries),a=C.maxEntries||20,r=i>0?Math.max(i+a,i*2):0;return{...t,maxEntries:r}}function Je(e){const t=e.omitted??{},i=e.source??{},a=["Local JSONL context loaded on demand.",e.include_tool_output?"Tool output included with redaction and size limits.":"Tool output hidden for this view."];i.file&&a.push(`Source: ${i.file}${i.line_number?`:${i.line_number}`:""}.`);const r=Number(t.older_entries??0);r>0&&a.push(`${o(r)} older entries omitted.`);const s=Number(t.over_budget_chars??0);return s>0&&a.push(`${o(s)} chars over budget omitted.`),Number(t.max_chars??NaN)===0&&a.push("No character limit applied."),a}export{ze as C,ke as T,Ee as a,He as b,Ie as c,C as d,Se as e,Ge as f,Me as g,Je as h,Le as i,Oe as j,ve as k,Te as l,Pe as m,De as n,Ue as o,qe as p,Re as q,Ae as r,Fe as s,_e as t,we as u,ye as v,$e as w,We as x,Be as y}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js index dbabdee0..1d729ec3 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/dashboardRouter.js @@ -1,2 +1,2 @@ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/App.js","assets/dashboard-react.js","assets/index.css","assets/locale-zh-Hans.js","assets/router.js"])))=>i.map(i=>d[i]); -import{j as o,_ as u}from"./dashboard-react.js";import{Y as h,$ as f,T as g,a9 as b}from"./router.js";const p=["overview","investigator","compression-lab","calls","call","threads","usage-drain","cache-context","diagnostics","reports","settings"],m=new Set(p);function y(e){return typeof e=="string"&&m.has(e)}function d(e,r="overview"){const t=s(e);return t==="insights"?"overview":y(t)?t:r}function R(e){const r={...e,view:d(e.view)};i(r,"record",e.record),i(r,"q",e.q),i(r,"preset",e.preset);const t=d(e.return,"calls");s(e.return)&&t!=="call"?r.return=t:delete r.return;const n=s(e.history);n==="active"||n==="all"?r.history=n:delete r.history;const a=w(e.finding);return a!==null&&a>0?r.finding=a:delete r.finding,r}function i(e,r,t){const n=s(t);n?e[r]=n:delete e[r]}function s(e){return Array.isArray(e)?s(e[0]):typeof e=="string"?e.trim():""}function w(e){const r=Array.isArray(e)?e[0]:e,t=typeof r=="number"?r:Number.parseInt(s(r),10);return Number.isFinite(t)?Math.trunc(t):null}const _=b(()=>u(()=>import("./App.js").then(e=>e.al),__vite__mapDeps([0,1,2,3,4])),"RoutedApp");function c(e={}){const r=h({validateSearch:R,component:_,pendingComponent:x,errorComponent:v});return f({routeTree:r,history:e.history??g(),basepath:e.basepath??l(),defaultPreload:"intent",defaultPendingMs:120,defaultPendingMinMs:180,scrollRestoration:!0,search:{strict:!1}})}const j=c();function l(){return"/"}function x(){return o.jsxs("main",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:[o.jsx("strong",{children:"Loading dashboard"}),o.jsx("span",{children:"Restoring the local usage workspace..."})]})}function v({error:e,reset:r}){return o.jsxs("main",{className:"route-state",role:"alert",children:[o.jsx("strong",{children:"Dashboard route could not load"}),o.jsx("span",{children:e instanceof Error?e.message:String(e)}),o.jsx("button",{type:"button",onClick:r,children:"Retry"})]})}const A=Object.freeze(Object.defineProperty({__proto__:null,createDashboardRouter:c,dashboardBasepath:l,dashboardRouter:j},Symbol.toStringTag,{value:"Module"}));export{A as d,y as i}; +import{j as o,_ as u}from"./dashboard-react.js";import{Y as h,$ as f,T as g,a9 as b}from"./router.js";const m=["overview","investigator","compression-lab","calls","call","threads","usage-drain","cache-context","diagnostics","reports","settings"],p=new Set(m);function y(e){return typeof e=="string"&&p.has(e)}function d(e,r="overview"){const t=s(e);return t==="insights"?"overview":y(t)?t:r}function R(e){const r={...e,view:d(e.view)};i(r,"record",e.record),i(r,"q",e.q),i(r,"preset",e.preset);const t=d(e.return,"calls");s(e.return)&&t!=="call"?r.return=t:delete r.return;const n=s(e.history);n==="active"||n==="all"?r.history=n:delete r.history;const a=w(e.finding);return a!==null&&a>0?r.finding=a:delete r.finding,r}function i(e,r,t){const n=s(t);n?e[r]=n:delete e[r]}function s(e){return Array.isArray(e)?s(e[0]):typeof e=="string"?e.trim():""}function w(e){const r=Array.isArray(e)?e[0]:e,t=typeof r=="number"?r:Number.parseInt(s(r),10);return Number.isFinite(t)?Math.trunc(t):null}const _=b(()=>u(()=>import("./App.js").then(e=>e.am),__vite__mapDeps([0,1,2,3,4])),"RoutedApp");function c(e={}){const r=h({validateSearch:R,component:_,pendingComponent:x,errorComponent:v});return f({routeTree:r,history:e.history??g(),basepath:e.basepath??l(),defaultPreload:"intent",defaultPendingMs:120,defaultPendingMinMs:180,scrollRestoration:!0,search:{strict:!1}})}const j=c();function l(){return"/"}function x(){return o.jsxs("main",{"aria-busy":"true","aria-live":"polite",className:"route-state",role:"status",children:[o.jsx("strong",{children:"Loading dashboard"}),o.jsx("span",{children:"Restoring the local usage workspace..."})]})}function v({error:e,reset:r}){return o.jsxs("main",{className:"route-state",role:"alert",children:[o.jsx("strong",{children:"Dashboard route could not load"}),o.jsx("span",{children:e instanceof Error?e.message:String(e)}),o.jsx("button",{type:"button",onClick:r,children:"Retry"})]})}const A=Object.freeze(Object.defineProperty({__proto__:null,createDashboardRouter:c,dashboardBasepath:l,dashboardRouter:j},Symbol.toStringTag,{value:"Module"}));export{A as d,y as i}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js index b482baa7..901b4dc6 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useBaseQuery.js @@ -1 +1 @@ -var bt=s=>{throw TypeError(s)};var $=(s,t,e)=>t.has(s)||bt("Cannot "+e);var i=(s,t,e)=>($(s,t,"read from private field"),e?e.call(s):t.get(s)),p=(s,t,e)=>t.has(s)?bt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),l=(s,t,e,r)=>($(s,t,"write to private field"),r?r.call(s,e):t.set(s,e),e),d=(s,t,e)=>($(s,t,"access private method"),e);import{J as Tt,a4 as gt,a5 as R,L as q,a6 as W,N as tt,a7 as et,a8 as mt,a9 as Mt,aa as X,ab as Qt,ac as xt,ad as vt,K as Ct,ae as Ot,l as _t}from"./App.js";import{r as C}from"./dashboard-react.js";var m,a,z,g,x,U,E,w,V,D,P,_,F,T,L,n,H,st,it,rt,at,nt,ht,ot,It,Et,Gt=(Et=class extends Tt{constructor(t,e){super();p(this,n);p(this,m);p(this,a);p(this,z);p(this,g);p(this,x);p(this,U);p(this,E);p(this,w);p(this,V);p(this,D);p(this,P);p(this,_);p(this,F);p(this,T);p(this,L,new Set);this.options=e,l(this,m,t),l(this,w,null),l(this,E,gt()),this.bindMethods(),this.setOptions(e)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(i(this,a).addObserver(this),Rt(i(this,a),this.options)?d(this,n,H).call(this):this.updateResult(),d(this,n,at).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return ct(i(this,a),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return ct(i(this,a),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,d(this,n,nt).call(this),d(this,n,ht).call(this),i(this,a).removeObserver(this)}setOptions(t){const e=this.options,r=i(this,a);if(this.options=i(this,m).defaultQueryOptions(t),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof R(this.options.enabled,i(this,a))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");d(this,n,ot).call(this),i(this,a).setOptions(this.options),e._defaulted&&!q(this.options,e)&&i(this,m).getQueryCache().notify({type:"observerOptionsUpdated",query:i(this,a),observer:this});const h=this.hasListeners();h&&St(i(this,a),r,this.options,e)&&d(this,n,H).call(this),this.updateResult(),h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||W(this.options.staleTime,i(this,a))!==W(e.staleTime,i(this,a)))&&d(this,n,st).call(this);const o=d(this,n,it).call(this);h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||o!==i(this,T))&&d(this,n,rt).call(this,o)}getOptimisticResult(t){const e=i(this,m).getQueryCache().build(i(this,m),t),r=this.createResult(e,t);return Ut(this,r)&&(l(this,g,r),l(this,U,this.options),l(this,x,i(this,a).state)),r}getCurrentResult(){return i(this,g)}trackResult(t,e){return new Proxy(t,{get:(r,h)=>(this.trackProp(h),e==null||e(h),h==="promise"&&(this.trackProp("data"),!this.options.experimental_prefetchInRender&&i(this,E).status==="pending"&&i(this,E).reject(new Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(r,h))})}trackProp(t){i(this,L).add(t)}getCurrentQuery(){return i(this,a)}refetch({...t}={}){return this.fetch({...t})}fetchOptimistic(t){const e=i(this,m).defaultQueryOptions(t),r=i(this,m).getQueryCache().build(i(this,m),e);return r.fetch().then(()=>this.createResult(r,e))}fetch(t){return d(this,n,H).call(this,{...t,cancelRefetch:t.cancelRefetch??!0}).then(()=>(this.updateResult(),i(this,g)))}createResult(t,e){var ft;const r=i(this,a),h=this.options,o=i(this,g),c=i(this,x),S=i(this,U),N=t!==r?t.state:i(this,z),{state:b}=t;let u={...b},B=!1,f;if(e._optimisticResults){const v=this.hasListeners(),j=!v&&Rt(t,e),K=v&&St(t,r,e,h);(j||K)&&(u={...u,...xt(b.data,t.options)}),e._optimisticResults==="isRestoring"&&(u.fetchStatus="idle")}let{error:k,errorUpdatedAt:Q,status:y}=u;f=u.data;let O=!1;if(e.placeholderData!==void 0&&f===void 0&&y==="pending"){let v;o!=null&&o.isPlaceholderData&&e.placeholderData===(S==null?void 0:S.placeholderData)?(v=o.data,O=!0):v=typeof e.placeholderData=="function"?e.placeholderData((ft=i(this,P))==null?void 0:ft.state.data,i(this,P)):e.placeholderData,v!==void 0&&(y="success",f=vt(o==null?void 0:o.data,v,e),B=!0)}if(e.select&&f!==void 0&&!O)if(o&&f===(c==null?void 0:c.data)&&e.select===i(this,V))f=i(this,D);else try{l(this,V,e.select),f=e.select(f),f=vt(o==null?void 0:o.data,f,e),l(this,D,f),l(this,w,null)}catch(v){l(this,w,v)}i(this,w)&&(k=i(this,w),f=i(this,D),Q=Date.now(),y="error");const A=u.fetchStatus==="fetching",Y=y==="pending",Z=y==="error",ut=Y&&A,dt=f!==void 0,I={status:y,fetchStatus:u.fetchStatus,isPending:Y,isSuccess:y==="success",isError:Z,isInitialLoading:ut,isLoading:ut,data:f,dataUpdatedAt:u.dataUpdatedAt,error:k,errorUpdatedAt:Q,failureCount:u.fetchFailureCount,failureReason:u.fetchFailureReason,errorUpdateCount:u.errorUpdateCount,isFetched:t.isFetched(),isFetchedAfterMount:u.dataUpdateCount>N.dataUpdateCount||u.errorUpdateCount>N.errorUpdateCount,isFetching:A,isRefetching:A&&!Y,isLoadingError:Z&&!dt,isPaused:u.fetchStatus==="paused",isPlaceholderData:B,isRefetchError:Z&&dt,isStale:lt(t,e),refetch:this.refetch,promise:i(this,E),isEnabled:R(e.enabled,t)!==!1};if(this.options.experimental_prefetchInRender){const v=I.data!==void 0,j=I.status==="error"&&!v,K=G=>{j?G.reject(I.error):v&&G.resolve(I.data)},pt=()=>{const G=l(this,E,I.promise=gt());K(G)},J=i(this,E);switch(J.status){case"pending":t.queryHash===r.queryHash&&K(J);break;case"fulfilled":(j||I.data!==J.value)&&pt();break;case"rejected":(!j||I.error!==J.reason)&&pt();break}}return I}updateResult(){const t=i(this,g),e=this.createResult(i(this,a),this.options);if(l(this,x,i(this,a).state),l(this,U,this.options),i(this,x).data!==void 0&&l(this,P,i(this,a)),q(e,t))return;l(this,g,e);const r=()=>{if(!t)return!0;const{notifyOnChangeProps:h}=this.options,o=typeof h=="function"?h():h;if(o==="all"||!o&&!i(this,L).size)return!0;const c=new Set(o??i(this,L));return this.options.throwOnError&&c.add("error"),Object.keys(i(this,g)).some(S=>{const M=S;return i(this,g)[M]!==t[M]&&c.has(M)})};d(this,n,It).call(this,{listeners:r()})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&d(this,n,at).call(this)}},m=new WeakMap,a=new WeakMap,z=new WeakMap,g=new WeakMap,x=new WeakMap,U=new WeakMap,E=new WeakMap,w=new WeakMap,V=new WeakMap,D=new WeakMap,P=new WeakMap,_=new WeakMap,F=new WeakMap,T=new WeakMap,L=new WeakMap,n=new WeakSet,H=function(t){d(this,n,ot).call(this);let e=i(this,a).fetch(this.options,t);return t!=null&&t.throwOnError||(e=e.catch(tt)),e},st=function(){d(this,n,nt).call(this);const t=W(this.options.staleTime,i(this,a));if(et.isServer()||i(this,g).isStale||!mt(t))return;const r=Mt(i(this,g).dataUpdatedAt,t)+1;l(this,_,X.setTimeout(()=>{i(this,g).isStale||this.updateResult()},r))},it=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(i(this,a)):this.options.refetchInterval)??!1},rt=function(t){d(this,n,ht).call(this),l(this,T,t),!(et.isServer()||R(this.options.enabled,i(this,a))===!1||!mt(i(this,T))||i(this,T)===0)&&l(this,F,X.setInterval(()=>{(this.options.refetchIntervalInBackground||Qt.isFocused())&&d(this,n,H).call(this)},i(this,T)))},at=function(){d(this,n,st).call(this),d(this,n,rt).call(this,d(this,n,it).call(this))},nt=function(){i(this,_)!==void 0&&(X.clearTimeout(i(this,_)),l(this,_,void 0))},ht=function(){i(this,F)!==void 0&&(X.clearInterval(i(this,F)),l(this,F,void 0))},ot=function(){const t=i(this,m).getQueryCache().build(i(this,m),this.options);if(t===i(this,a))return;const e=i(this,a);l(this,a,t),l(this,z,t.state),this.hasListeners()&&(e==null||e.removeObserver(this),t.addObserver(this))},It=function(t){Ct.batch(()=>{t.listeners&&this.listeners.forEach(e=>{e(i(this,g))}),i(this,m).getQueryCache().notify({query:i(this,a),type:"observerResultsUpdated"})})},Et);function Ft(s,t){return R(t.enabled,s)!==!1&&s.state.data===void 0&&!(s.state.status==="error"&&R(t.retryOnMount,s)===!1)}function Rt(s,t){return Ft(s,t)||s.state.data!==void 0&&ct(s,t,t.refetchOnMount)}function ct(s,t,e){if(R(t.enabled,s)!==!1&&W(t.staleTime,s)!=="static"){const r=typeof e=="function"?e(s):e;return r==="always"||r!==!1&<(s,t)}return!1}function St(s,t,e,r){return(s!==t||R(r.enabled,s)===!1)&&(!e.suspense||s.state.status!=="error")&<(s,e)}function lt(s,t){return R(t.enabled,s)!==!1&&s.isStaleByTime(W(t.staleTime,s))}function Ut(s,t){return!q(s.getCurrentResult(),t)}var wt=C.createContext(!1),Dt=()=>C.useContext(wt);wt.Provider;function Pt(){let s=!1;return{clearReset:()=>{s=!1},reset:()=>{s=!0},isReset:()=>s}}var Lt=C.createContext(Pt()),Nt=()=>C.useContext(Lt),Bt=(s,t,e)=>{const r=e!=null&&e.state.error&&typeof s.throwOnError=="function"?Ot(s.throwOnError,[e.state.error,e]):s.throwOnError;(s.suspense||s.experimental_prefetchInRender||r)&&(t.isReset()||(s.retryOnMount=!1))},kt=s=>{C.useEffect(()=>{s.clearReset()},[s])},At=({result:s,errorResetBoundary:t,throwOnError:e,query:r,suspense:h})=>s.isError&&!t.isReset()&&!s.isFetching&&r&&(h&&s.data===void 0||Ot(e,[s.error,r])),jt=s=>{if(s.suspense){const e=h=>h==="static"?h:Math.max(h??1e3,1e3),r=s.staleTime;s.staleTime=typeof r=="function"?(...h)=>e(r(...h)):e(r),typeof s.gcTime=="number"&&(s.gcTime=Math.max(s.gcTime,1e3))}},Ht=(s,t)=>s.isLoading&&s.isFetching&&!t,Wt=(s,t)=>(s==null?void 0:s.suspense)&&t.isPending,yt=(s,t,e)=>t.fetchOptimistic(s).catch(()=>{e.clearReset()});function Xt(s,t,e){var f,k,Q,y;const r=Dt(),h=Nt(),o=_t(),c=o.defaultQueryOptions(s);(k=(f=o.getDefaultOptions().queries)==null?void 0:f._experimental_beforeQuery)==null||k.call(f,c);const S=o.getQueryCache().get(c.queryHash),M=s.subscribed!==!1;c._optimisticResults=r?"isRestoring":M?"optimistic":void 0,jt(c),Bt(c,h,S),kt(h);const N=!o.getQueryCache().get(c.queryHash),[b]=C.useState(()=>new t(o,c)),u=b.getOptimisticResult(c),B=!r&&M;if(C.useSyncExternalStore(C.useCallback(O=>{const A=B?b.subscribe(Ct.batchCalls(O)):tt;return b.updateResult(),A},[b,B]),()=>b.getCurrentResult(),()=>b.getCurrentResult()),C.useEffect(()=>{b.setOptions(c)},[c,b]),Wt(c,u))throw yt(c,b,h);if(At({result:u,errorResetBoundary:h,throwOnError:c.throwOnError,query:S,suspense:c.suspense}))throw u.error;if((y=(Q=o.getDefaultOptions().queries)==null?void 0:Q._experimental_afterQuery)==null||y.call(Q,c,u),c.experimental_prefetchInRender&&!et.isServer()&&Ht(u,r)){const O=N?yt(c,b,h):S==null?void 0:S.promise;O==null||O.catch(tt).finally(()=>{b.updateResult()})}return c.notifyOnChangeProps?u:b.trackResult(u)}export{Gt as Q,Nt as a,Bt as b,kt as c,Xt as d,jt as e,yt as f,At as g,Wt as s,Dt as u}; +var bt=s=>{throw TypeError(s)};var $=(s,t,e)=>t.has(s)||bt("Cannot "+e);var i=(s,t,e)=>($(s,t,"read from private field"),e?e.call(s):t.get(s)),p=(s,t,e)=>t.has(s)?bt("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(s):t.set(s,e),l=(s,t,e,r)=>($(s,t,"write to private field"),r?r.call(s,e):t.set(s,e),e),d=(s,t,e)=>($(s,t,"access private method"),e);import{J as Tt,a5 as gt,a6 as R,L as q,a7 as W,N as tt,a8 as et,a9 as mt,aa as Mt,ab as X,ac as Qt,ad as xt,ae as vt,K as Ct,af as Ot,l as _t}from"./App.js";import{r as C}from"./dashboard-react.js";var m,a,z,g,x,U,E,w,V,D,P,_,F,T,L,n,H,st,it,rt,at,nt,ht,ot,It,Et,Gt=(Et=class extends Tt{constructor(t,e){super();p(this,n);p(this,m);p(this,a);p(this,z);p(this,g);p(this,x);p(this,U);p(this,E);p(this,w);p(this,V);p(this,D);p(this,P);p(this,_);p(this,F);p(this,T);p(this,L,new Set);this.options=e,l(this,m,t),l(this,w,null),l(this,E,gt()),this.bindMethods(),this.setOptions(e)}bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(i(this,a).addObserver(this),Rt(i(this,a),this.options)?d(this,n,H).call(this):this.updateResult(),d(this,n,at).call(this))}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return ct(i(this,a),this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return ct(i(this,a),this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,d(this,n,nt).call(this),d(this,n,ht).call(this),i(this,a).removeObserver(this)}setOptions(t){const e=this.options,r=i(this,a);if(this.options=i(this,m).defaultQueryOptions(t),this.options.enabled!==void 0&&typeof this.options.enabled!="boolean"&&typeof this.options.enabled!="function"&&typeof R(this.options.enabled,i(this,a))!="boolean")throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");d(this,n,ot).call(this),i(this,a).setOptions(this.options),e._defaulted&&!q(this.options,e)&&i(this,m).getQueryCache().notify({type:"observerOptionsUpdated",query:i(this,a),observer:this});const h=this.hasListeners();h&&St(i(this,a),r,this.options,e)&&d(this,n,H).call(this),this.updateResult(),h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||W(this.options.staleTime,i(this,a))!==W(e.staleTime,i(this,a)))&&d(this,n,st).call(this);const o=d(this,n,it).call(this);h&&(i(this,a)!==r||R(this.options.enabled,i(this,a))!==R(e.enabled,i(this,a))||o!==i(this,T))&&d(this,n,rt).call(this,o)}getOptimisticResult(t){const e=i(this,m).getQueryCache().build(i(this,m),t),r=this.createResult(e,t);return Ut(this,r)&&(l(this,g,r),l(this,U,this.options),l(this,x,i(this,a).state)),r}getCurrentResult(){return i(this,g)}trackResult(t,e){return new Proxy(t,{get:(r,h)=>(this.trackProp(h),e==null||e(h),h==="promise"&&(this.trackProp("data"),!this.options.experimental_prefetchInRender&&i(this,E).status==="pending"&&i(this,E).reject(new Error("experimental_prefetchInRender feature flag is not enabled"))),Reflect.get(r,h))})}trackProp(t){i(this,L).add(t)}getCurrentQuery(){return i(this,a)}refetch({...t}={}){return this.fetch({...t})}fetchOptimistic(t){const e=i(this,m).defaultQueryOptions(t),r=i(this,m).getQueryCache().build(i(this,m),e);return r.fetch().then(()=>this.createResult(r,e))}fetch(t){return d(this,n,H).call(this,{...t,cancelRefetch:t.cancelRefetch??!0}).then(()=>(this.updateResult(),i(this,g)))}createResult(t,e){var ft;const r=i(this,a),h=this.options,o=i(this,g),c=i(this,x),S=i(this,U),N=t!==r?t.state:i(this,z),{state:b}=t;let u={...b},B=!1,f;if(e._optimisticResults){const v=this.hasListeners(),j=!v&&Rt(t,e),K=v&&St(t,r,e,h);(j||K)&&(u={...u,...xt(b.data,t.options)}),e._optimisticResults==="isRestoring"&&(u.fetchStatus="idle")}let{error:k,errorUpdatedAt:Q,status:y}=u;f=u.data;let O=!1;if(e.placeholderData!==void 0&&f===void 0&&y==="pending"){let v;o!=null&&o.isPlaceholderData&&e.placeholderData===(S==null?void 0:S.placeholderData)?(v=o.data,O=!0):v=typeof e.placeholderData=="function"?e.placeholderData((ft=i(this,P))==null?void 0:ft.state.data,i(this,P)):e.placeholderData,v!==void 0&&(y="success",f=vt(o==null?void 0:o.data,v,e),B=!0)}if(e.select&&f!==void 0&&!O)if(o&&f===(c==null?void 0:c.data)&&e.select===i(this,V))f=i(this,D);else try{l(this,V,e.select),f=e.select(f),f=vt(o==null?void 0:o.data,f,e),l(this,D,f),l(this,w,null)}catch(v){l(this,w,v)}i(this,w)&&(k=i(this,w),f=i(this,D),Q=Date.now(),y="error");const A=u.fetchStatus==="fetching",Y=y==="pending",Z=y==="error",ut=Y&&A,dt=f!==void 0,I={status:y,fetchStatus:u.fetchStatus,isPending:Y,isSuccess:y==="success",isError:Z,isInitialLoading:ut,isLoading:ut,data:f,dataUpdatedAt:u.dataUpdatedAt,error:k,errorUpdatedAt:Q,failureCount:u.fetchFailureCount,failureReason:u.fetchFailureReason,errorUpdateCount:u.errorUpdateCount,isFetched:t.isFetched(),isFetchedAfterMount:u.dataUpdateCount>N.dataUpdateCount||u.errorUpdateCount>N.errorUpdateCount,isFetching:A,isRefetching:A&&!Y,isLoadingError:Z&&!dt,isPaused:u.fetchStatus==="paused",isPlaceholderData:B,isRefetchError:Z&&dt,isStale:lt(t,e),refetch:this.refetch,promise:i(this,E),isEnabled:R(e.enabled,t)!==!1};if(this.options.experimental_prefetchInRender){const v=I.data!==void 0,j=I.status==="error"&&!v,K=G=>{j?G.reject(I.error):v&&G.resolve(I.data)},pt=()=>{const G=l(this,E,I.promise=gt());K(G)},J=i(this,E);switch(J.status){case"pending":t.queryHash===r.queryHash&&K(J);break;case"fulfilled":(j||I.data!==J.value)&&pt();break;case"rejected":(!j||I.error!==J.reason)&&pt();break}}return I}updateResult(){const t=i(this,g),e=this.createResult(i(this,a),this.options);if(l(this,x,i(this,a).state),l(this,U,this.options),i(this,x).data!==void 0&&l(this,P,i(this,a)),q(e,t))return;l(this,g,e);const r=()=>{if(!t)return!0;const{notifyOnChangeProps:h}=this.options,o=typeof h=="function"?h():h;if(o==="all"||!o&&!i(this,L).size)return!0;const c=new Set(o??i(this,L));return this.options.throwOnError&&c.add("error"),Object.keys(i(this,g)).some(S=>{const M=S;return i(this,g)[M]!==t[M]&&c.has(M)})};d(this,n,It).call(this,{listeners:r()})}onQueryUpdate(){this.updateResult(),this.hasListeners()&&d(this,n,at).call(this)}},m=new WeakMap,a=new WeakMap,z=new WeakMap,g=new WeakMap,x=new WeakMap,U=new WeakMap,E=new WeakMap,w=new WeakMap,V=new WeakMap,D=new WeakMap,P=new WeakMap,_=new WeakMap,F=new WeakMap,T=new WeakMap,L=new WeakMap,n=new WeakSet,H=function(t){d(this,n,ot).call(this);let e=i(this,a).fetch(this.options,t);return t!=null&&t.throwOnError||(e=e.catch(tt)),e},st=function(){d(this,n,nt).call(this);const t=W(this.options.staleTime,i(this,a));if(et.isServer()||i(this,g).isStale||!mt(t))return;const r=Mt(i(this,g).dataUpdatedAt,t)+1;l(this,_,X.setTimeout(()=>{i(this,g).isStale||this.updateResult()},r))},it=function(){return(typeof this.options.refetchInterval=="function"?this.options.refetchInterval(i(this,a)):this.options.refetchInterval)??!1},rt=function(t){d(this,n,ht).call(this),l(this,T,t),!(et.isServer()||R(this.options.enabled,i(this,a))===!1||!mt(i(this,T))||i(this,T)===0)&&l(this,F,X.setInterval(()=>{(this.options.refetchIntervalInBackground||Qt.isFocused())&&d(this,n,H).call(this)},i(this,T)))},at=function(){d(this,n,st).call(this),d(this,n,rt).call(this,d(this,n,it).call(this))},nt=function(){i(this,_)!==void 0&&(X.clearTimeout(i(this,_)),l(this,_,void 0))},ht=function(){i(this,F)!==void 0&&(X.clearInterval(i(this,F)),l(this,F,void 0))},ot=function(){const t=i(this,m).getQueryCache().build(i(this,m),this.options);if(t===i(this,a))return;const e=i(this,a);l(this,a,t),l(this,z,t.state),this.hasListeners()&&(e==null||e.removeObserver(this),t.addObserver(this))},It=function(t){Ct.batch(()=>{t.listeners&&this.listeners.forEach(e=>{e(i(this,g))}),i(this,m).getQueryCache().notify({query:i(this,a),type:"observerResultsUpdated"})})},Et);function Ft(s,t){return R(t.enabled,s)!==!1&&s.state.data===void 0&&!(s.state.status==="error"&&R(t.retryOnMount,s)===!1)}function Rt(s,t){return Ft(s,t)||s.state.data!==void 0&&ct(s,t,t.refetchOnMount)}function ct(s,t,e){if(R(t.enabled,s)!==!1&&W(t.staleTime,s)!=="static"){const r=typeof e=="function"?e(s):e;return r==="always"||r!==!1&<(s,t)}return!1}function St(s,t,e,r){return(s!==t||R(r.enabled,s)===!1)&&(!e.suspense||s.state.status!=="error")&<(s,e)}function lt(s,t){return R(t.enabled,s)!==!1&&s.isStaleByTime(W(t.staleTime,s))}function Ut(s,t){return!q(s.getCurrentResult(),t)}var wt=C.createContext(!1),Dt=()=>C.useContext(wt);wt.Provider;function Pt(){let s=!1;return{clearReset:()=>{s=!1},reset:()=>{s=!0},isReset:()=>s}}var Lt=C.createContext(Pt()),Nt=()=>C.useContext(Lt),Bt=(s,t,e)=>{const r=e!=null&&e.state.error&&typeof s.throwOnError=="function"?Ot(s.throwOnError,[e.state.error,e]):s.throwOnError;(s.suspense||s.experimental_prefetchInRender||r)&&(t.isReset()||(s.retryOnMount=!1))},kt=s=>{C.useEffect(()=>{s.clearReset()},[s])},At=({result:s,errorResetBoundary:t,throwOnError:e,query:r,suspense:h})=>s.isError&&!t.isReset()&&!s.isFetching&&r&&(h&&s.data===void 0||Ot(e,[s.error,r])),jt=s=>{if(s.suspense){const e=h=>h==="static"?h:Math.max(h??1e3,1e3),r=s.staleTime;s.staleTime=typeof r=="function"?(...h)=>e(r(...h)):e(r),typeof s.gcTime=="number"&&(s.gcTime=Math.max(s.gcTime,1e3))}},Ht=(s,t)=>s.isLoading&&s.isFetching&&!t,Wt=(s,t)=>(s==null?void 0:s.suspense)&&t.isPending,yt=(s,t,e)=>t.fetchOptimistic(s).catch(()=>{e.clearReset()});function Xt(s,t,e){var f,k,Q,y;const r=Dt(),h=Nt(),o=_t(),c=o.defaultQueryOptions(s);(k=(f=o.getDefaultOptions().queries)==null?void 0:f._experimental_beforeQuery)==null||k.call(f,c);const S=o.getQueryCache().get(c.queryHash),M=s.subscribed!==!1;c._optimisticResults=r?"isRestoring":M?"optimistic":void 0,jt(c),Bt(c,h,S),kt(h);const N=!o.getQueryCache().get(c.queryHash),[b]=C.useState(()=>new t(o,c)),u=b.getOptimisticResult(c),B=!r&&M;if(C.useSyncExternalStore(C.useCallback(O=>{const A=B?b.subscribe(Ct.batchCalls(O)):tt;return b.updateResult(),A},[b,B]),()=>b.getCurrentResult(),()=>b.getCurrentResult()),C.useEffect(()=>{b.setOptions(c)},[c,b]),Wt(c,u))throw yt(c,b,h);if(At({result:u,errorResetBoundary:h,throwOnError:c.throwOnError,query:S,suspense:c.suspense}))throw u.error;if((y=(Q=o.getDefaultOptions().queries)==null?void 0:Q._experimental_afterQuery)==null||y.call(Q,c,u),c.experimental_prefetchInRender&&!et.isServer()&&Ht(u,r)){const O=N?yt(c,b,h):S==null?void 0:S.promise;O==null||O.catch(tt).finally(()=>{b.updateResult()})}return c.notifyOnChangeProps?u:b.trackResult(u)}export{Gt as Q,Nt as a,Bt as b,kt as c,Xt as d,jt as e,yt as f,At as g,Wt as s,Dt as u}; diff --git a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js index 1b42253f..f8eab391 100644 --- a/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js +++ b/src/codex_usage_tracker/plugin_data/dashboard/react/assets/useInfiniteQuery.js @@ -1 +1 @@ -import{Q as v,d as p}from"./useBaseQuery.js";import{a2 as x,a3 as b}from"./App.js";var l=class extends v{constructor(e,t){super(e,t)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){e._type="infinite",super.setOptions(e)}getOptimisticResult(e){return e._type="infinite",super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"backward"}}})}createResult(e,t){var f,P;const{state:s}=e,i=super.createResult(e,t),{isFetching:a,isRefetching:g,isError:c,isRefetchError:d}=i,r=(P=(f=s.fetchMeta)==null?void 0:f.fetchMore)==null?void 0:P.direction,h=c&&r==="forward",n=a&&r==="forward",o=c&&r==="backward",u=a&&r==="backward";return{...i,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:b(t,s.data),hasPreviousPage:x(t,s.data),isFetchNextPageError:h,isFetchingNextPage:n,isFetchPreviousPageError:o,isFetchingPreviousPage:u,isRefetchError:d&&!h&&!o,isRefetching:g&&!n&&!u}}};function w(e,t){return p(e,l)}export{w as u}; +import{Q as v,d as p}from"./useBaseQuery.js";import{a3 as x,a4 as b}from"./App.js";var l=class extends v{constructor(e,t){super(e,t)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){e._type="infinite",super.setOptions(e)}getOptimisticResult(e){return e._type="infinite",super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"forward"}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:"backward"}}})}createResult(e,t){var f,P;const{state:s}=e,i=super.createResult(e,t),{isFetching:a,isRefetching:g,isError:c,isRefetchError:d}=i,r=(P=(f=s.fetchMeta)==null?void 0:f.fetchMore)==null?void 0:P.direction,h=c&&r==="forward",n=a&&r==="forward",o=c&&r==="backward",u=a&&r==="backward";return{...i,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:b(t,s.data),hasPreviousPage:x(t,s.data),isFetchNextPageError:h,isFetchingNextPage:n,isFetchPreviousPageError:o,isFetchingPreviousPage:u,isRefetchError:d&&!h&&!o,isRefetching:g&&!n&&!u}}};function w(e,t){return p(e,l)}export{w as u}; diff --git a/src/codex_usage_tracker/reports/support.py b/src/codex_usage_tracker/reports/support.py index eb66339f..9525594a 100644 --- a/src/codex_usage_tracker/reports/support.py +++ b/src/codex_usage_tracker/reports/support.py @@ -212,6 +212,8 @@ def support_bundle_payload( "loaded": pricing.loaded, "error": pricing.error, "model_count": len(pricing.models), + "api_service_tier_count": len(pricing.api_service_tiers or {}), + "billing_basis": pricing.billing_basis, "source": pricing.source, }, "allowance": { @@ -223,6 +225,7 @@ def support_bundle_payload( "rate_card_error": allowance.rate_card_error, "credit_rate_count": len(allowance.credit_rates), "alias_count": len(allowance.aliases), + "fast_multiplier_count": len(allowance.fast_multipliers), }, "thresholds": { "loaded": thresholds.loaded, diff --git a/tests/dashboard/test_dashboard_payload.py b/tests/dashboard/test_dashboard_payload.py index fba0b2d1..1ae5d656 100644 --- a/tests/dashboard/test_dashboard_payload.py +++ b/tests/dashboard/test_dashboard_payload.py @@ -665,7 +665,11 @@ def test_dashboard_payload_keeps_tier_fields_aggregate_only(tmp_path: Path) -> N upsert_usage_events( [ synthetic_usage_event( - "record-a", "conversation-a", (100, 40, 30, 10), fast=1 + "record-a", + "conversation-a", + (100, 40, 30, 10), + service_tier="priority", + fast=1, ) ], db_path=db_path, @@ -673,7 +677,7 @@ def test_dashboard_payload_keeps_tier_fields_aggregate_only(tmp_path: Path) -> N row = dashboard_payload(db_path=db_path)["rows"][0] - assert row["service_tier"] == "fast" + assert row["service_tier"] == "priority" assert row["fast"] == 1 assert "otel_source_path" not in row @@ -721,6 +725,15 @@ def test_dashboard_payload_contract_includes_analysis_metadata(tmp_path: Path) - "project_name", "project_key", "thread_attachment_label", + "standard_cost_usd", + "priority_cost_usd", + "pricing_service_tier", + "billing_basis", + "cost_semantics", + "fast_usage_credits", + "usage_credit_multiplier_source_url", + "usage_credit_multiplier_fetched_at", + "usage_credit_multiplier_confidence", } <= set(row) diff --git a/tests/reports/test_support.py b/tests/reports/test_support.py index 023d919f..b7fcea96 100644 --- a/tests/reports/test_support.py +++ b/tests/reports/test_support.py @@ -57,7 +57,10 @@ def test_support_bundle_default_mode_contract_and_secret_safety(tmp_path: Path) assert bundle["database"]["exists"] is True assert bundle["refresh"]["parsed_events"] == "1" assert bundle["pricing"]["loaded"] is True + assert bundle["pricing"]["billing_basis"] == "unknown" + assert bundle["pricing"]["api_service_tier_count"] == 0 assert bundle["allowance"]["window_count"] == 0 + assert bundle["allowance"]["fast_multiplier_count"] == 3 assert "low_cache_ratio" in bundle["thresholds"]["keys"] assert bundle["projects"]["tag_group_count"] == 1 assert bundle["doctor"]["schema"] == "codex-usage-tracker-doctor-v1" From d4dba01eb2b6faa54cce884380a55d86ff42181f Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 17:42:37 -0400 Subject: [PATCH 23/24] fix: harden tier-aware pricing selection --- src/codex_usage_tracker/parser/otel.py | 5 +++- .../pricing/allowance_rate_card.py | 2 ++ src/codex_usage_tracker/pricing/config.py | 12 ++++++--- tests/pricing/test_pricing.py | 25 +++++++++++++++++++ tests/pricing/test_rate_card.py | 18 +++++++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/codex_usage_tracker/parser/otel.py b/src/codex_usage_tracker/parser/otel.py index 1e9af711..9c099e13 100644 --- a/src/codex_usage_tracker/parser/otel.py +++ b/src/codex_usage_tracker/parser/otel.py @@ -219,7 +219,7 @@ def _completion_from_attributes( match_status = "invalid" diagnostics["otel_invalid_record"] += 1 - normalized = { + normalized: dict[str, object] = { "conversation_id": conversation_id, "event_timestamp": event_timestamp, "input_tokens": input_tokens, @@ -271,6 +271,9 @@ def _integer( if isinstance(value, bool) or value is None: diagnostics["otel_invalid_integer"] += 1 return None + if not isinstance(value, str | int | float): + diagnostics["otel_invalid_integer"] += 1 + return None try: parsed = int(value) except (TypeError, ValueError, OverflowError): diff --git a/src/codex_usage_tracker/pricing/allowance_rate_card.py b/src/codex_usage_tracker/pricing/allowance_rate_card.py index 4bdccf33..e83afd6d 100644 --- a/src/codex_usage_tracker/pricing/allowance_rate_card.py +++ b/src/codex_usage_tracker/pricing/allowance_rate_card.py @@ -165,6 +165,8 @@ def parse_fast_multipliers( def _fast_multiplier_number(value: object) -> float | None: + if isinstance(value, bool): + return None try: multiplier = number_value(value) except (TypeError, ValueError): diff --git a/src/codex_usage_tracker/pricing/config.py b/src/codex_usage_tracker/pricing/config.py index 12904c20..6c482734 100644 --- a/src/codex_usage_tracker/pricing/config.py +++ b/src/codex_usage_tracker/pricing/config.py @@ -59,15 +59,19 @@ def rates_for( self, model: object, *, service_tier: object | None = None ) -> dict[str, float] | None: normalized_tier = normalize_api_service_tier(service_tier) - tier_models = (self.api_service_tiers or {}).get(normalized_tier or "") - if tier_models is not None: + tier_tables = self.api_service_tiers or {} + if normalized_tier and tier_tables: + tier_models = tier_tables.get(normalized_tier) + if tier_models is None: + return None return _rates_for_models(tier_models, self.aliases, model) return _rates_for_models(self.models, self.aliases, model) def pricing_tier_for(self, service_tier: object | None) -> str | None: normalized = normalize_api_service_tier(service_tier) - if normalized and normalized in (self.api_service_tiers or {}): - return normalized + tier_tables = self.api_service_tiers or {} + if normalized and tier_tables: + return normalized if normalized in tier_tables else None source_tier = normalize_api_service_tier((self.source or {}).get("tier")) return source_tier if source_tier else None diff --git a/tests/pricing/test_pricing.py b/tests/pricing/test_pricing.py index ea441304..9ea32633 100644 --- a/tests/pricing/test_pricing.py +++ b/tests/pricing/test_pricing.py @@ -119,6 +119,31 @@ def test_pricing_v2_selects_rates_by_service_tier(tmp_path: Path) -> None: assert config.rates_for("gpt-5.6", service_tier="default") == standard +def test_tiered_pricing_does_not_fallback_for_an_unconfigured_tier( + tmp_path: Path, +) -> None: + selected = { + "input_per_million": 5.0, + "cached_input_per_million": 0.5, + "output_per_million": 20.0, + } + pricing_path = tmp_path / "pricing.json" + pricing_path.write_text( + json.dumps( + { + "models": {"gpt-5.6": selected}, + "api_service_tiers": {"standard": {"gpt-5.6": selected}}, + } + ), + encoding="utf-8", + ) + + config = load_pricing_config(pricing_path) + + assert config.rates_for("gpt-5.6", service_tier="flex") is None + assert config.pricing_tier_for("flex") is None + + def test_pricing_v1_keeps_selected_projection_for_every_row_tier(tmp_path: Path) -> None: pricing_path = tmp_path / "pricing.json" selected = { diff --git a/tests/pricing/test_rate_card.py b/tests/pricing/test_rate_card.py index f55692b9..e12333d3 100644 --- a/tests/pricing/test_rate_card.py +++ b/tests/pricing/test_rate_card.py @@ -54,6 +54,24 @@ def test_malformed_local_multiplier_retains_valid_bundled_rate(tmp_path: Path) - assert config.fast_multipliers["gpt-5.6"].confidence == "exact" +def test_boolean_local_multiplier_retains_valid_bundled_rate(tmp_path: Path) -> None: + path = tmp_path / "allowance.json" + path.write_text( + json.dumps( + {"fast_multipliers": {"gpt-5.6": {"multiplier": True}}} + ), + encoding="utf-8", + ) + + config = load_allowance_config( + path, rate_card_path=tmp_path / "missing-rate-card.json" + ) + + assert config.loaded is True + assert config.fast_multipliers["gpt-5.6"].multiplier == 2.5 + assert config.fast_multipliers["gpt-5.6"].confidence == "exact" + + def test_legacy_local_rate_card_inherits_bundled_fast_multipliers( tmp_path: Path, ) -> None: From ac0a367b9e9d48db83b123750f3b554e05a965b9 Mon Sep 17 00:00:00 2001 From: Monsky Date: Thu, 16 Jul 2026 22:27:12 -0400 Subject: [PATCH 24/24] fix: verify OTel cursor continuity --- CHANGELOG.md | 3 +- docs/database-schema.md | 19 ++++--- src/codex_usage_tracker/pricing/fast_tier.py | 2 - src/codex_usage_tracker/store/otel_ingest.py | 54 +++++++++++++++----- src/codex_usage_tracker/store/otel_schema.py | 19 +++++-- src/codex_usage_tracker/store/schema.py | 3 +- tests/store/test_otel_ingest.py | 44 ++++++++++++++++ tests/store/test_otel_schema.py | 43 +++++++++++++++- tests/store/test_store_dashboard_mcp.py | 12 ++--- tests/store/test_store_migrations.py | 26 +++++----- 10 files changed, 178 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a9a719..d481cbf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ USD estimates. - Preserve exact response tiers in dashboard labels and CSV contracts, clear OTel staging on confirmed database reset, and make incremental source cursors - descriptor-safe across concurrent file rotation. + descriptor-safe across concurrent file rotation. Verify a bounded content + anchor before resuming so same-inode rewrites cannot silently skip telemetry. ## 0.20.0 - 2026-07-16 diff --git a/docs/database-schema.md b/docs/database-schema.md index 2715a932..3f84a784 100644 --- a/docs/database-schema.md +++ b/docs/database-schema.md @@ -32,17 +32,18 @@ identity, parser coverage, replacement, and refresh revision. Changing or removi a source causes its owned physical rows/materializations to be replaced in a transaction rather than accumulated blindly. -## OTel Service-Tier Enrichment (Schema 30) +## OTel Service-Tier Enrichment (Schemas 30–31) Schema 30 adds nullable `service_tier`, `fast`, `service_tier_source`, and `service_tier_confidence` columns to `usage_events`. Null means the tracker does not have exact tier evidence; it is not interpreted as Standard. `otel_completion_sources` records device/inode identity, size, the last complete -byte and line cursor, and an update timestamp for each local -`codex-completions*.jsonl` file. The default directory is the `otel` sibling of -the selected database (`~/.codex-usage-tracker/otel` for the default database), -so alternate databases do not ingest another tracker instance's telemetry. +byte and line cursor, a bounded SHA-256 resume anchor, and an update timestamp +for each local `codex-completions*.jsonl` file. The default directory is the +`otel` sibling of the selected database (`~/.codex-usage-tracker/otel` for the +default database), so alternate databases do not ingest another tracker +instance's telemetry. `otel_completion_events` stores one semantic fingerprint plus aggregate matching fields, the exact normalized response tier, derived Fast classification, tier provenance, a @@ -50,9 +51,11 @@ bounded match status (`pending`, `matched`, `ambiguous`, `conflict`, or `invalid`), and the matched aggregate record id when available. Append refresh resumes after the last complete JSONL line, retries a partial -trailing line, and restarts a cursor after rotation or truncation. Cursor -identity, size, and offsets come from the open descriptor so a path rotation -cannot persist an offset from one inode against another. Rebuild keeps +trailing line, and restarts a cursor after rotation, truncation, or a mismatched +resume anchor. Schema 31 adds the anchor; a legacy cursor without one is safely +reread once and then anchored. Cursor identity, size, offsets, and anchor bytes +come from the open descriptor so a path rotation or same-inode replacement +cannot persist an offset against different content. Rebuild keeps the aggregate OTel staging rows, resets their match pointers, and reconciles them against the rebuilt canonical calls. A match requires conversation id plus input, cached-input, output, and reasoning-output counters to resolve to exactly diff --git a/src/codex_usage_tracker/pricing/fast_tier.py b/src/codex_usage_tracker/pricing/fast_tier.py index 7fb02f82..d3194b31 100644 --- a/src/codex_usage_tracker/pricing/fast_tier.py +++ b/src/codex_usage_tracker/pricing/fast_tier.py @@ -19,7 +19,6 @@ class FastMultiplierMatch: """A model-family multiplier match with independent numeric provenance.""" multiplier: float - model_family: str source_name: str source_url: str | None fetched_at: str | None @@ -53,7 +52,6 @@ def match_fast_credit_multiplier( rate = configured[family] return FastMultiplierMatch( multiplier=rate.multiplier, - model_family=family, source_name=rate.source_name, source_url=rate.source_url, fetched_at=rate.fetched_at, diff --git a/src/codex_usage_tracker/store/otel_ingest.py b/src/codex_usage_tracker/store/otel_ingest.py index 424d81de..467ff661 100644 --- a/src/codex_usage_tracker/store/otel_ingest.py +++ b/src/codex_usage_tracker/store/otel_ingest.py @@ -2,15 +2,20 @@ from __future__ import annotations +import hashlib +import hmac import os import sqlite3 from collections import Counter from dataclasses import dataclass, field from datetime import datetime, timezone from pathlib import Path +from typing import BinaryIO from codex_usage_tracker.parser.otel import OtelCompletion, parse_otlp_json_line +_CURSOR_ANCHOR_BYTES = 4096 + @dataclass(frozen=True) class OtelIngestResult: @@ -43,6 +48,7 @@ class _SourceState: size: int parsed_offset: int parsed_line: int + resume_anchor: str | None def discover_otel_sources(directory: Path) -> list[Path]: @@ -67,7 +73,7 @@ def ingest_otel_completion_files( source_path = str(path.resolve()) try: state = _source_state(conn, source_path) - final_stat, next_offset, next_line = _ingest_complete_lines( + final_stat, next_offset, next_line, resume_anchor = _ingest_complete_lines( conn, path, source_path, @@ -82,6 +88,7 @@ def ingest_otel_completion_files( final_stat, next_offset, next_line, + resume_anchor, ) totals.files_scanned += 1 return totals.freeze() @@ -90,7 +97,7 @@ def ingest_otel_completion_files( def _source_state(conn: sqlite3.Connection, source_path: str) -> _SourceState | None: row = conn.execute( """ - SELECT device, inode, size, parsed_offset, parsed_line + SELECT device, inode, size, parsed_offset, parsed_line, resume_anchor FROM otel_completion_sources WHERE source_path = ? """, @@ -104,17 +111,24 @@ def _source_state(conn: sqlite3.Connection, source_path: str) -> _SourceState | size=int(row["size"]), parsed_offset=int(row["parsed_offset"]), parsed_line=int(row["parsed_line"]), + resume_anchor=str(row["resume_anchor"]) if row["resume_anchor"] else None, ) def _resume_position( - state: _SourceState | None, stat: os.stat_result + state: _SourceState | None, + stat: os.stat_result, + handle: BinaryIO, ) -> tuple[int, int]: if state is None: return 0, 0 unchanged_file = state.device == stat.st_dev and state.inode == stat.st_ino has_not_shrunk = stat.st_size >= state.size and stat.st_size >= state.parsed_offset - if unchanged_file and has_not_shrunk: + anchor_matches = state.resume_anchor is not None and hmac.compare_digest( + state.resume_anchor, + _cursor_anchor(handle, state.parsed_offset), + ) + if unchanged_file and has_not_shrunk and anchor_matches: return state.parsed_offset, state.parsed_line return 0, 0 @@ -125,7 +139,7 @@ def _ingest_complete_lines( source_path: str, state: _SourceState | None, totals: _MutableIngestTotals, -) -> tuple[os.stat_result, int, int]: +) -> tuple[os.stat_result, int, int, str]: for attempt in range(2): result = _read_source_descriptor( conn, @@ -134,12 +148,12 @@ def _ingest_complete_lines( state if attempt == 0 else None, totals, ) - initial_stat, final_stat, next_offset, next_line = result + initial_stat, final_stat, next_offset, next_line, resume_anchor = result if ( initial_stat.st_dev == final_stat.st_dev and initial_stat.st_ino == final_stat.st_ino ): - return final_stat, next_offset, next_line + return final_stat, next_offset, next_line, resume_anchor raise FileNotFoundError("OTel source descriptor identity changed during retry") @@ -149,10 +163,10 @@ def _read_source_descriptor( source_path: str, state: _SourceState | None, totals: _MutableIngestTotals, -) -> tuple[os.stat_result, os.stat_result, int, int]: +) -> tuple[os.stat_result, os.stat_result, int, int, str]: with path.open("rb") as handle: initial_stat = os.fstat(handle.fileno()) - offset, line_number = _resume_position(state, initial_stat) + offset, line_number = _resume_position(state, initial_stat, handle) next_offset = offset next_line = line_number handle.seek(offset) @@ -174,7 +188,19 @@ def _read_source_descriptor( else: totals.duplicates += 1 final_stat = os.fstat(handle.fileno()) - return initial_stat, final_stat, next_offset, next_line + resume_anchor = _cursor_anchor(handle, next_offset) + return initial_stat, final_stat, next_offset, next_line, resume_anchor + + +def _cursor_anchor(handle: BinaryIO, parsed_offset: int) -> str: + """Hash a bounded suffix of committed bytes without changing the read position.""" + + anchor_start = max(parsed_offset - _CURSOR_ANCHOR_BYTES, 0) + original_position = handle.tell() + handle.seek(anchor_start) + payload = handle.read(parsed_offset - anchor_start) + handle.seek(original_position) + return hashlib.sha256(payload).hexdigest() def _insert_completion( @@ -235,18 +261,21 @@ def _upsert_source_cursor( stat: os.stat_result, parsed_offset: int, parsed_line: int, + resume_anchor: str, ) -> None: conn.execute( """ INSERT INTO otel_completion_sources ( - source_path, device, inode, size, parsed_offset, parsed_line, updated_at - ) VALUES (?, ?, ?, ?, ?, ?, ?) + source_path, device, inode, size, parsed_offset, parsed_line, + resume_anchor, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(source_path) DO UPDATE SET device = excluded.device, inode = excluded.inode, size = excluded.size, parsed_offset = excluded.parsed_offset, parsed_line = excluded.parsed_line, + resume_anchor = excluded.resume_anchor, updated_at = excluded.updated_at """, ( @@ -256,6 +285,7 @@ def _upsert_source_cursor( stat.st_size, parsed_offset, parsed_line, + resume_anchor, datetime.now(timezone.utc).isoformat(), ), ) diff --git a/src/codex_usage_tracker/store/otel_schema.py b/src/codex_usage_tracker/store/otel_schema.py index 4092cdc3..0af8932a 100644 --- a/src/codex_usage_tracker/store/otel_schema.py +++ b/src/codex_usage_tracker/store/otel_schema.py @@ -4,9 +4,10 @@ import sqlite3 -MIGRATION_NAMES = {30: "persist OTel completion tier enrichment"} - -OTEL_MATCH_STATUSES = ("pending", "matched", "ambiguous", "conflict", "invalid") +MIGRATION_NAMES = { + 30: "persist OTel completion tier enrichment", + 31: "persist OTel cursor continuity anchors", +} _USAGE_EVENT_TIER_COLUMNS = { "service_tier": "TEXT", @@ -36,6 +37,7 @@ def migrate_otel_completion_tiers(conn: sqlite3.Connection) -> None: size INTEGER NOT NULL, parsed_offset INTEGER NOT NULL, parsed_line INTEGER NOT NULL, + resume_anchor TEXT, updated_at TEXT NOT NULL ); @@ -74,3 +76,14 @@ def migrate_otel_completion_tiers(conn: sqlite3.Connection) -> None: ); """ ) + + +def add_otel_cursor_resume_anchor(conn: sqlite3.Connection) -> None: + """Add a bounded-content continuity marker to existing OTel source cursors.""" + + source_columns = { + str(row[1]) + for row in conn.execute("PRAGMA table_info(otel_completion_sources)").fetchall() + } + if "resume_anchor" not in source_columns: + conn.execute("ALTER TABLE otel_completion_sources ADD COLUMN resume_anchor TEXT") diff --git a/src/codex_usage_tracker/store/schema.py b/src/codex_usage_tracker/store/schema.py index 2c4ab7b5..bff7d7ab 100644 --- a/src/codex_usage_tracker/store/schema.py +++ b/src/codex_usage_tracker/store/schema.py @@ -19,7 +19,7 @@ USAGE_EVENT_SCHEMA_CHECKSUM, ) -SCHEMA_VERSION = 30 +SCHEMA_VERSION = 31 MIGRATION_NAMES = { 1: "create usage_events aggregate fact table", 2: "track schema migration checksum metadata", @@ -119,6 +119,7 @@ def _schema_migrations() -> tuple[tuple[int, Callable[[sqlite3.Connection], None (28, allowance_schema.migrate_allowance_query_indexes_v3), (29, allowance_schema.add_allowance_plan_provenance), (30, otel_schema.migrate_otel_completion_tiers), + (31, otel_schema.add_otel_cursor_resume_anchor), ) diff --git a/tests/store/test_otel_ingest.py b/tests/store/test_otel_ingest.py index 67f10885..2b5a2736 100644 --- a/tests/store/test_otel_ingest.py +++ b/tests/store/test_otel_ingest.py @@ -45,6 +45,7 @@ def test_incremental_ingest_reads_each_complete_line_once(tmp_path: Path) -> Non assert first.imported == 1 assert second.imported == 1 + assert second.duplicates == 0 assert len(rows) == 2 @@ -102,6 +103,49 @@ def test_truncation_or_inode_replacement_resets_cursor_safely(tmp_path: Path) -> assert ingest_otel_completion_files(conn, directory).imported == 1 +def test_same_inode_same_size_rewrite_resets_cursor_safely(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + first_line = synthetic_otlp_line( + attributes=completion_attributes(conversation_id="synthetic-a") + ) + replacement_line = synthetic_otlp_line( + attributes=completion_attributes(conversation_id="synthetic-b") + ) + assert len(first_line) == len(replacement_line) + source.parent.mkdir(parents=True) + source.write_text(first_line + "\n", encoding="utf-8") + + with initialized_connection(tmp_path) as conn: + ingest_otel_completion_files(conn, directory) + first_stat = source.stat() + source.write_text(replacement_line + "\n", encoding="utf-8") + replacement_stat = source.stat() + result = ingest_otel_completion_files(conn, directory) + + assert first_stat.st_ino == replacement_stat.st_ino + assert first_stat.st_size == replacement_stat.st_size + assert result.imported == 1 + + +def test_legacy_cursor_without_anchor_is_reread_once(tmp_path: Path) -> None: + directory = tmp_path / "otel" + source = directory / "codex-completions.jsonl" + write_lines(source, [synthetic_otlp_line(attributes=completion_attributes())]) + + with initialized_connection(tmp_path) as conn: + assert ingest_otel_completion_files(conn, directory).imported == 1 + conn.execute("UPDATE otel_completion_sources SET resume_anchor = NULL") + + legacy_resume = ingest_otel_completion_files(conn, directory) + anchored_resume = ingest_otel_completion_files(conn, directory) + + assert legacy_resume.imported == 0 + assert legacy_resume.duplicates == 1 + assert anchored_resume.imported == 0 + assert anchored_resume.duplicates == 0 + + def test_rotation_between_discovery_and_open_reads_replacement_from_zero( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, diff --git a/tests/store/test_otel_schema.py b/tests/store/test_otel_schema.py index 864146d8..a74f0fd6 100644 --- a/tests/store/test_otel_schema.py +++ b/tests/store/test_otel_schema.py @@ -3,6 +3,7 @@ from pathlib import Path from codex_usage_tracker.store.connection import connect +from codex_usage_tracker.store.otel_schema import add_otel_cursor_resume_anchor from codex_usage_tracker.store.schema import SCHEMA_VERSION, init_db @@ -18,7 +19,7 @@ def test_schema_migration_creates_otel_sidecar_tables(tmp_path: Path) -> None: for row in conn.execute("PRAGMA table_info(otel_completion_events)") } - assert SCHEMA_VERSION == 30 + assert SCHEMA_VERSION == 31 assert { "source_path", "device", @@ -26,6 +27,7 @@ def test_schema_migration_creates_otel_sidecar_tables(tmp_path: Path) -> None: "size", "parsed_offset", "parsed_line", + "resume_anchor", "updated_at", } <= source_columns assert { @@ -36,3 +38,42 @@ def test_schema_migration_creates_otel_sidecar_tables(tmp_path: Path) -> None: "match_status", "matched_record_id", } <= event_columns + + +def test_cursor_anchor_migration_preserves_existing_source_state(tmp_path: Path) -> None: + with connect(tmp_path / "usage.sqlite3") as conn: + conn.execute( + """ + CREATE TABLE otel_completion_sources ( + source_path TEXT PRIMARY KEY, + device INTEGER NOT NULL, + inode INTEGER NOT NULL, + size INTEGER NOT NULL, + parsed_offset INTEGER NOT NULL, + parsed_line INTEGER NOT NULL, + updated_at TEXT NOT NULL + ) + """ + ) + conn.execute( + """ + INSERT INTO otel_completion_sources ( + source_path, device, inode, size, parsed_offset, parsed_line, updated_at + ) VALUES ('/tmp/synthetic-otel.jsonl', 1, 2, 100, 100, 1, '2026-07-16') + """ + ) + + add_otel_cursor_resume_anchor(conn) + + row = conn.execute( + """ + SELECT parsed_offset, parsed_line, resume_anchor + FROM otel_completion_sources + WHERE source_path = '/tmp/synthetic-otel.jsonl' + """ + ).fetchone() + + assert row is not None + assert row["parsed_offset"] == 100 + assert row["parsed_line"] == 1 + assert row["resume_anchor"] is None diff --git a/tests/store/test_store_dashboard_mcp.py b/tests/store/test_store_dashboard_mcp.py index 142b1eb1..ce6a14c8 100644 --- a/tests/store/test_store_dashboard_mcp.py +++ b/tests/store/test_store_dashboard_mcp.py @@ -79,12 +79,12 @@ def test_refresh_is_idempotent_and_summary_works(tmp_path: Path) -> None: assert meta["parsed_source_files"] == "0" assert meta["skipped_source_files"] == "3" assert meta["parser_adapter"] == "codex-jsonl-v2" - assert meta["schema_version"] == "30" + assert meta["schema_version"] == "31" assert meta["parser_skipped_events"] == "0" state = schema_state(db_path) - assert state["schema_version"] == 30 + assert state["schema_version"] == 31 assert state["checksum_matches"] is True - assert [row["version"] for row in state["migrations"]] == list(range(1, 31)) + assert [row["version"] for row in state["migrations"]] == list(range(1, 32)) with connect(db_path) as conn: init_db(conn) source_rows = [ @@ -711,7 +711,7 @@ def test_connect_sets_sqlite_concurrency_pragmas(tmp_path: Path) -> None: assert busy_timeout == 5000 assert str(journal_mode).lower() == "wal" - assert user_version == 30 + assert user_version == 31 def test_current_schema_reads_succeed_while_writer_is_active(tmp_path: Path) -> None: @@ -809,8 +809,8 @@ def test_init_db_repairs_version_zero_schema(tmp_path: Path) -> None: assert "used_percent" in allowance_columns assert "window_kind" in allowance_columns assert "idx_allowance_observations_window_time" in allowance_indexes - assert user_version == 30 - assert [row["version"] for row in migrations] == list(range(1, 31)) + assert user_version == 31 + assert [row["version"] for row in migrations] == list(range(1, 32)) assert "idx_usage_source_file_line" in indexes diff --git a/tests/store/test_store_migrations.py b/tests/store/test_store_migrations.py index 991be64a..559b69f2 100644 --- a/tests/store/test_store_migrations.py +++ b/tests/store/test_store_migrations.py @@ -70,9 +70,9 @@ def test_init_db_migrates_legacy_aggregate_table_without_data_loss(tmp_path: Pat assert len(str(source_rows[0]["source_record_hash"])) == 64 assert metadata["parsed_events"] == "legacy" assert metadata["parser_invalid_integer"] == "2" - assert state["schema_version"] == 30 + assert state["schema_version"] == 31 assert state["checksum_matches"] is True - assert [row["version"] for row in state["migrations"]] == list(range(1, 31)) + assert [row["version"] for row in state["migrations"]] == list(range(1, 32)) with connect(db_path) as conn: init_db(conn) facts = conn.execute("SELECT COUNT(*) AS count FROM call_diagnostic_facts").fetchone() @@ -108,7 +108,7 @@ def test_refresh_is_idempotent_after_legacy_migration(tmp_path: Path) -> None: assert second_count == 2 assert legacy_rows[0]["record_id"] == "legacy-record" assert new_rows[0]["thread_name"] == "Synthetic migration thread" - assert metadata["schema_version"] == "30" + assert metadata["schema_version"] == "31" assert metadata["parsed_events"] == "0" assert metadata["inserted_or_updated_events"] == "0" assert metadata["parsed_source_files"] == "0" @@ -258,8 +258,8 @@ def test_init_db_records_all_schema_migrations_for_new_database(tmp_path: Path) ).fetchall() ] - assert versions == list(range(1, 31)) - assert user_version == 30 + assert versions == list(range(1, 32)) + assert user_version == 31 assert "idx_usage_source_file_line" in usage_indexes assert { "idx_recommendation_facts_rank_active", @@ -462,7 +462,7 @@ def test_init_db_upgrades_v25_database_without_changing_physical_rows(tmp_path: conn.execute("DROP TABLE allowance_source_state") conn.execute("DROP INDEX idx_allowance_observations_active_newest") conn.execute("DROP INDEX idx_allowance_observations_active_window_newest") - conn.execute("DELETE FROM schema_migrations WHERE version IN (26, 27, 28, 29, 30)") + conn.execute("DELETE FROM schema_migrations WHERE version IN (26, 27, 28, 29, 30, 31)") conn.execute("PRAGMA user_version = 25") versions_before = [ row[0] @@ -484,7 +484,7 @@ def test_init_db_upgrades_v25_database_without_changing_physical_rows(tmp_path: user_version = conn.execute("PRAGMA user_version").fetchone()[0] assert versions_before == list(range(1, 26)) - assert user_version == 30 + assert user_version == 31 assert { "allowance_source_state", "allowance_cycles", @@ -503,7 +503,7 @@ def test_init_db_upgrades_v27_allowance_indexes_to_v28(tmp_path: Path) -> None: """ DROP INDEX idx_allowance_intervals_evidence_cohort; DROP INDEX idx_allowance_intervals_evidence_global; - DELETE FROM schema_migrations WHERE version IN (28, 29, 30); + DELETE FROM schema_migrations WHERE version IN (28, 29, 30, 31); PRAGMA user_version = 27; """ ) @@ -518,8 +518,8 @@ def test_init_db_upgrades_v27_allowance_indexes_to_v28(tmp_path: Path) -> None: ] user_version = conn.execute("PRAGMA user_version").fetchone()[0] - assert user_version == 30 - assert versions == list(range(1, 31)) + assert user_version == 31 + assert versions == list(range(1, 32)) assert { "idx_allowance_intervals_evidence_cohort", "idx_allowance_intervals_evidence_global", @@ -533,7 +533,7 @@ def test_init_db_upgrades_v28_with_allowance_plan_provenance(tmp_path: Path) -> conn.executescript( """ ALTER TABLE allowance_cycles DROP COLUMN plan_type; - DELETE FROM schema_migrations WHERE version IN (29, 30); + DELETE FROM schema_migrations WHERE version IN (29, 30, 31); PRAGMA user_version = 28; """ ) @@ -549,8 +549,8 @@ def test_init_db_upgrades_v28_with_allowance_plan_provenance(tmp_path: Path) -> ] user_version = conn.execute("PRAGMA user_version").fetchone()[0] - assert user_version == 30 - assert versions == list(range(1, 31)) + assert user_version == 31 + assert versions == list(range(1, 32)) assert "plan_type" in columns