From f176d5e579b8f3496e5c0dd90efb4c7b828da593 Mon Sep 17 00:00:00 2001 From: merefield Date: Fri, 18 Sep 2026 17:12:32 +0100 Subject: [PATCH] FEAT: persist and reconcile usage history --- README.md | 84 +++-- internal/codex/account_usage.go | 72 +++- internal/codex/account_usage_test.go | 20 ++ internal/codex/client.go | 10 +- internal/codex/filelock_other.go | 11 +- internal/codex/filelock_unix.go | 28 ++ internal/codex/filelock_windows.go | 42 +++ internal/codex/history_store.go | 375 +++++++++++++++++++++ internal/codex/history_store_test.go | 125 +++++++ internal/codex/live_usage.go | 152 +++++++++ internal/codex/live_usage_test.go | 21 ++ internal/i18n/locales/da.json | 3 + internal/i18n/locales/de.json | 3 + internal/i18n/locales/en-GB.json | 3 + internal/i18n/locales/es.json | 3 + internal/i18n/locales/et.json | 3 + internal/i18n/locales/fi.json | 3 + internal/i18n/locales/fr.json | 3 + internal/i18n/locales/it.json | 3 + internal/i18n/locales/ja.json | 3 + internal/i18n/locales/nb.json | 3 + internal/i18n/locales/nl.json | 3 + internal/i18n/locales/pt-BR.json | 3 + internal/i18n/locales/pt-PT.json | 3 + internal/i18n/locales/ru.json | 3 + internal/i18n/locales/sv.json | 3 + internal/i18n/locales/tr.json | 3 + internal/i18n/locales/zh-Hans.json | 3 + internal/ui/english_snapshot_test.go | 6 +- internal/ui/usage.go | 30 +- internal/web/dist/assets/index-CKsvYdC2.js | 27 ++ internal/web/dist/assets/index-S94ToOzX.js | 26 -- internal/web/dist/index.html | 2 +- intro-post.md | 2 +- main.go | 18 +- web/src/Usage.svelte | 85 ++++- web/src/state.svelte.ts | 25 +- web/tests/browser.spec.ts | 34 +- 38 files changed, 1163 insertions(+), 83 deletions(-) create mode 100644 internal/codex/history_store.go create mode 100644 internal/codex/history_store_test.go create mode 100644 internal/web/dist/assets/index-CKsvYdC2.js delete mode 100644 internal/web/dist/assets/index-S94ToOzX.js diff --git a/README.md b/README.md index d10663f..86d6d26 100644 --- a/README.md +++ b/README.md @@ -796,17 +796,21 @@ estimate can still vary with reasoning effort, model mix, caching, prompt shape, and backend quota weighting, so compare ranges and sample counts rather than treating the midpoint as a fixed entitlement. -Samples remain process-local and are never written to the preferences file, so -evidence cannot leak from one login into another on a later run. During a run, -Codexometer requests the current account email from the same local app-server, -immediately reduces it to an in-memory one-way fingerprint, and uses that only -to separate account observations. The email and fingerprint are not persisted. +Estimator samples remain process-local and are never written to the preferences +or usage-history files, so learned price evidence cannot leak from one login +into another on a later run. Codexometer requests the current account email from +the same local app-server and immediately reduces it to a one-way fingerprint. +The email is never persisted; the fingerprint is stored only in the separate +numeric usage ledger so histories remain isolated across restarts. Cached data +is not selected until the current invocation verifies that same fingerprint. If an older app-server cannot provide an account identity, the estimate fails closed as `ACCOUNT ATTRIBUTION UNKNOWN` rather than mixing indistinguishable accounts. -The privacy trade-off is that quitting Codexometer discards every learned -sample and quota anchor. On restart it can reconstruct cumulative priced usage +The estimator trade-off is that quitting Codexometer discards every learned +sample and its in-memory learning anchor. The separate ledger retains content-free +quota observations for future history views, but does not silently treat them as +complete price evidence. On restart it can reconstruct cumulative priced usage from local rollout telemetry, but the current quota percentage and cost become a new baseline: the display returns to `LEARNING` and needs another five clean percentage points of movement before producing an estimate. Medium confidence @@ -945,21 +949,30 @@ As in Codex's chart, the available display range is 52 Sunday-based weeks ending in the current UTC week. Missing dates in a supplied history count as zero; invalid dates, negative values, future dates, and dates outside that range are ignored. Duplicate dates are summed. The compact summary shows the server's -separately reported lifetime tokens, peak daily tokens, and current streak when -available (`—` otherwise). +separately reported lifetime tokens, peak daily tokens, current and longest +streaks, and longest running turn when available (`—` otherwise). History refreshes when you enter Usage, on the normal refresh interval while -Usage is selected, or with `r` / the Refresh button. These are server-side account -statistics, **not live Sessions telemetry**: updates may lag ongoing work. -Older CLI versions or unsupported accounts can return an unavailable/error state; -missing history is never silently presented as zero. A failed refresh labels -previously fetched data **STALE**, and a detected account change discards it. +Usage is selected, or with `r` / the Refresh button. OpenAI's account-wide daily +totals are authoritative and can fill days when Codexometer was not running. +Codexometer also rescans retained local Codex rollouts for content-free token +counts, including input, cached input, output and reasoning-token detail. Local +counts are shown as attribution against the OpenAI total and are never added to +it. A compact provenance line reports **OPENAI**, **RECOVERED**, or **PARTIAL** +and the percentage of the OpenAI total attributable to retained local history. + +Older CLI versions or unsupported accounts can return an unavailable/error +state; unavailable history is never silently presented as an empty account. A +failed refresh uses the last verified persisted result and labels it **STALE**. +Account fingerprints keep histories isolated, and a newly verified account is +never shown another account's cached Usage data. The endpoint currently exposes daily **total tokens**, not historical per-model, -input/output/cache splits, quota percentages, or dollar spend. Consequently this -tab does not infer historical API-equivalent cost or combine these totals with -the Sessions tab's local counters. History is held in memory only; restarting fetches it -again from Codex. `--demo` includes sample history for previewing the charts. +input/output/cache splits, quota percentages, or dollar spend. The finer token +breakdown is therefore local recovery and can be partial; activity from another +device, cloud task, or deleted rollout remains only in the OpenAI total. The tab +does not infer historical API-equivalent cost. `--demo` includes sample history +for previewing the charts. ### Other top-level views @@ -1519,11 +1532,10 @@ any command; restart the demo to reset its approval. ### Saved presentation preferences -Codexometer stores only the selected theme, main tab, Quota view, benchmark filter, -benchmark ranking weight, and the Sessions context hide/show preference. -No quota estimate or snapshot, raw session telemetry, -benchmark result, message content, credential, session ID, email, account -fingerprint, or account ID is written. The small JSON file uses the +Codexometer's presentation preferences store only the selected theme, main tab, +Quota view, benchmark filter, benchmark ranking weight, and the Sessions context +hide/show preference. No benchmark result, message content, credential, session +ID, email, or account ID is written to that file. The small JSON file uses the platform-standard user configuration directory: - Linux: `$XDG_CONFIG_HOME/codexometer/preferences.json`, normally @@ -1537,6 +1549,32 @@ tab and remembers your Quota view separately. First launch defaults to Quota → Bars; older preferences without a main tab reopen the saved Quota view. Restoring a tab does not resume a benchmark run or reopen an approval dialog. +### Persistent usage history + +Usage history is stored separately as `usage-history.json` in the same +platform-standard `codexometer` directory. This versioned ledger contains only: + +- OpenAI daily account token totals and optional account summary metrics; +- locally recovered daily numeric token aggregates; +- current quota percentage observations, reset boundaries and window lengths; +- a one-way account fingerprint used to prevent histories from being mixed. + +It never stores prompts, replies, commands, source content, working-directory +paths, session IDs, email addresses, credentials, or authentication tokens. +History is retained for approximately 400 days. Writes use a private temporary +file, an atomic replacement, and a cross-process lock so terminal and web +Codexometer instances cannot partially overwrite one another. A damaged or +unwritable ledger does not prevent current OpenAI data from being displayed; +it only disables persistence until the file is repaired or removed. + +On startup Codexometer reconciles three layers: persisted history, retained +local rollout token events, and the newest OpenAI daily buckets. Repeated scans +replace the bounded local aggregate rather than incrementing it, so restarts and +concurrent invocations do not double-count usage. If Codexometer was closed, +OpenAI can backfill account totals and retained rollouts can restore local detail. +If neither source contains a missed period, Codexometer does not invent a +per-session, per-model, quota-percentage, or cost breakdown for it. + ### Benchmark authentication and usage boundary > [!IMPORTANT] diff --git a/internal/codex/account_usage.go b/internal/codex/account_usage.go index d0a1f36..dcd7e78 100644 --- a/internal/codex/account_usage.go +++ b/internal/codex/account_usage.go @@ -9,10 +9,16 @@ import ( // local session telemetry. Nil buckets mean unavailable; an empty list means // the server returned no activity. Summary fields are independently optional. type AccountUsage struct { - Summary AccountUsageSummary `json:"summary"` - DailyUsageBuckets []AccountUsageDay `json:"dailyUsageBuckets"` - AccountFingerprint string `json:"-"` - FetchedAt time.Time `json:"-"` + Summary AccountUsageSummary `json:"summary"` + DailyUsageBuckets []AccountUsageDay `json:"dailyUsageBuckets"` + Coverage AccountUsageCoverage `json:"coverage"` + AccountFingerprint string `json:"-"` + FetchedAt time.Time `json:"-"` + // Persisted means the result has been reconciled with Codexometer's local + // history. Stale means the live refresh failed and this is the most recent + // verified account cache rather than a fresh OpenAI response. + Persisted bool `json:"persisted"` + Stale bool `json:"stale"` } type AccountUsageSummary struct { @@ -24,12 +30,64 @@ type AccountUsageSummary struct { } type AccountUsageDay struct { - StartDate string `json:"startDate"` - Tokens int64 `json:"tokens"` + StartDate string `json:"startDate"` + Tokens int64 `json:"tokens"` + LocalTokens int64 `json:"localTokens,omitempty"` + InputTokens int64 `json:"inputTokens,omitempty"` + CachedInputTokens int64 `json:"cachedInputTokens,omitempty"` + OutputTokens int64 `json:"outputTokens,omitempty"` + ReasoningTokens int64 `json:"reasoningTokens,omitempty"` + Provenance string `json:"provenance,omitempty"` +} + +// AccountUsageCoverage explains how much of the account-wide OpenAI total can +// also be attributed to retained local Codex rollouts. LocalTokens is never +// added to OpenAITokens: it is a subset/comparison, not another usage source. +type AccountUsageCoverage struct { + Status string `json:"status,omitempty"` + OpenAITokens int64 `json:"openaiTokens,omitempty"` + LocalTokens int64 `json:"localTokens,omitempty"` + AttributedPct int `json:"attributedPercent,omitempty"` + OpenAIDays int `json:"openaiDays,omitempty"` + RecoveredDays int `json:"recoveredDays,omitempty"` +} + +// RecoveredUsageDay is reconstructed from content-free token_count events in +// retained local Codex rollouts. Cached input is part of input, not additional +// usage, and TotalTokens remains the comparison value used against OpenAI. +type RecoveredUsageDay struct { + StartDate string `json:"startDate"` + TotalTokens int64 `json:"totalTokens"` + InputTokens int64 `json:"inputTokens,omitempty"` + CachedInputTokens int64 `json:"cachedInputTokens,omitempty"` + OutputTokens int64 `json:"outputTokens,omitempty"` + ReasoningTokens int64 `json:"reasoningTokens,omitempty"` } func (c Client) FetchAccountUsage(ctx context.Context) (AccountUsage, error) { var history AccountUsage _, err := c.fetch(ctx, nil, &history) - return history, err + if err != nil { + if c.History != nil { + if cached, cacheErr := c.History.Latest(); cacheErr == nil && cached.AccountFingerprint != "" { + cached.Stale = true + return cached, nil + } + } + return history, err + } + if c.History == nil { + return history, nil + } + var recovered []RecoveredUsageDay + if c.LiveUsage != nil { + recovered, _ = c.LiveUsage.RecoverDailyUsage(ctx, time.Now().UTC().AddDate(0, 0, -historyRetentionDays)) + } + reconciled, reconcileErr := c.History.Reconcile(history, recovered) + if reconcileErr != nil { + // A local cache failure must not turn a valid OpenAI response into an + // unavailable Usage screen. + return history, nil + } + return reconciled, nil } diff --git a/internal/codex/account_usage_test.go b/internal/codex/account_usage_test.go index 54cb588..61b4d4c 100644 --- a/internal/codex/account_usage_test.go +++ b/internal/codex/account_usage_test.go @@ -3,6 +3,7 @@ package codex import ( "context" "os" + "path/filepath" "strings" "testing" ) @@ -45,6 +46,25 @@ func TestFetchAccountUsage(t *testing.T) { } } +func TestFetchAccountUsageFallsBackToVerifiedPersistedHistory(t *testing.T) { + t.Setenv("CODEXOMETER_FAKE_APP_SERVER", "1") + exe, err := os.Executable() + if err != nil { + t.Fatal(err) + } + store := &HistoryStore{Path: filepath.Join(t.TempDir(), "usage.json")} + client := Client{Binary: exe, History: store} + fresh, err := client.FetchAccountUsage(context.Background()) + if err != nil || !fresh.Persisted || fresh.Stale { + t.Fatalf("fresh history = %+v, %v", fresh, err) + } + t.Setenv("CODEXOMETER_FAKE_USAGE_ERROR", "1") + cached, err := client.FetchAccountUsage(context.Background()) + if err != nil || !cached.Persisted || !cached.Stale || cached.AccountFingerprint != fresh.AccountFingerprint || len(cached.DailyUsageBuckets) != 1 { + t.Fatalf("cached history = %+v, %v", cached, err) + } +} + func TestAccountUsageRequiresVerifiedAccount(t *testing.T) { t.Setenv("CODEXOMETER_FAKE_APP_SERVER", "1") t.Setenv("CODEXOMETER_FAKE_ACCOUNT_ERROR", "1") diff --git a/internal/codex/client.go b/internal/codex/client.go index 93de21f..0bbcd8f 100644 --- a/internal/codex/client.go +++ b/internal/codex/client.go @@ -21,6 +21,9 @@ const requestTimeout = 15 * time.Second type Client struct { Binary string LiveUsage *LiveUsageReader + // History persists content-free account totals and quota observations so + // both terminal and web presentations survive process restarts. + History *HistoryStore // QuotaSteps is an opt-in launch-time policy for lowering the model profile // of loaded sessions as quota consumption crosses configured thresholds. QuotaSteps []QuotaStep @@ -66,7 +69,12 @@ type rpcResponse struct { // Fetch starts a short-lived app-server, performs the initialization handshake, // reads the authenticated account limits, and shuts the server down again. func (c Client) Fetch(ctx context.Context) (Snapshot, error) { - return c.fetch(ctx, nil, nil) + snapshot, err := c.fetch(ctx, nil, nil) + if err == nil && c.History != nil { + // Persistence failure must not hide current authoritative quota data. + _ = c.History.RecordQuota(snapshot) + } + return snapshot, err } type resetAttempt struct { diff --git a/internal/codex/filelock_other.go b/internal/codex/filelock_other.go index 1e57f20..81d712f 100644 --- a/internal/codex/filelock_other.go +++ b/internal/codex/filelock_other.go @@ -2,10 +2,19 @@ package codex -import "errors" +import ( + "errors" + "os" +) const fileLockSupported = false func fileLockHeld(string) (bool, error) { return false, errors.ErrUnsupported } + +func withHistoryFileLock(_ string, action func() error) error { return action() } + +func replaceHistoryFile(from, to string) error { return os.Rename(from, to) } + +func syncHistoryDirectory(string) error { return nil } diff --git a/internal/codex/filelock_unix.go b/internal/codex/filelock_unix.go index e67fef9..420d307 100644 --- a/internal/codex/filelock_unix.go +++ b/internal/codex/filelock_unix.go @@ -5,6 +5,7 @@ package codex import ( "errors" "os" + "path/filepath" "golang.org/x/sys/unix" ) @@ -28,3 +29,30 @@ func fileLockHeld(path string) (bool, error) { } return false, nil } + +func withHistoryFileLock(path string, action func() error) error { + if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil { + return err + } + file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600) + if err != nil { + return err + } + defer file.Close() + if err := unix.Flock(int(file.Fd()), unix.LOCK_EX); err != nil { + return err + } + defer unix.Flock(int(file.Fd()), unix.LOCK_UN) //nolint:errcheck -- best-effort after action + return action() +} + +func replaceHistoryFile(from, to string) error { return os.Rename(from, to) } + +func syncHistoryDirectory(path string) error { + directory, err := os.Open(path) + if err != nil { + return err + } + defer directory.Close() + return directory.Sync() +} diff --git a/internal/codex/filelock_windows.go b/internal/codex/filelock_windows.go index 78be635..d513b74 100644 --- a/internal/codex/filelock_windows.go +++ b/internal/codex/filelock_windows.go @@ -5,6 +5,8 @@ package codex import ( "errors" "os" + "path/filepath" + "time" "golang.org/x/sys/windows" ) @@ -37,3 +39,43 @@ func fileLockHeld(path string) (bool, error) { } return false, nil } + +func withHistoryFileLock(path string, action func() error) error { + if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil { + return err + } + file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0o600) + if err != nil { + return err + } + defer file.Close() + overlapped := new(windows.Overlapped) + deadline := time.Now().Add(5 * time.Second) + for { + err = windows.LockFileEx(windows.Handle(file.Fd()), windows.LOCKFILE_EXCLUSIVE_LOCK|windows.LOCKFILE_FAIL_IMMEDIATELY, 0, 1, 0, overlapped) + if err == nil { + break + } + if !errors.Is(err, windows.ERROR_LOCK_VIOLATION) || time.Now().After(deadline) { + return err + } + time.Sleep(10 * time.Millisecond) + } + defer windows.UnlockFileEx(windows.Handle(file.Fd()), 0, 1, 0, overlapped) //nolint:errcheck -- best-effort after action + return action() +} + +func replaceHistoryFile(from, to string) error { + fromPath, err := windows.UTF16PtrFromString(from) + if err != nil { + return err + } + toPath, err := windows.UTF16PtrFromString(to) + if err != nil { + return err + } + return windows.MoveFileEx(fromPath, toPath, windows.MOVEFILE_REPLACE_EXISTING|windows.MOVEFILE_WRITE_THROUGH) +} + +// MOVEFILE_WRITE_THROUGH flushes the replacement before returning. +func syncHistoryDirectory(string) error { return nil } diff --git a/internal/codex/history_store.go b/internal/codex/history_store.go new file mode 100644 index 0000000..c55fbb0 --- /dev/null +++ b/internal/codex/history_store.go @@ -0,0 +1,375 @@ +package codex + +import ( + "encoding/json" + "errors" + "fmt" + "math" + "os" + "path/filepath" + "sort" + "sync" + "time" +) + +const ( + historySchemaVersion = 1 + historyRetentionDays = 400 + maxQuotaObservations = 12_000 +) + +// HistoryStore is a versioned, content-free local ledger. It stores numeric +// account usage and quota observations, never prompts, replies, commands, +// paths, email addresses, or authentication material. +type HistoryStore struct { + Path string + mu sync.Mutex + activeAccount string // process-local: a persisted cache never selects identity +} + +type historyFile struct { + Version int `json:"version"` + Accounts map[string]*historyAccount `json:"accounts"` +} + +type historyAccount struct { + Summary AccountUsageSummary `json:"summary"` + FetchedAt time.Time `json:"fetchedAt"` + BucketsKnown bool `json:"bucketsKnown,omitempty"` + Days map[string]historyDay `json:"days"` + Quota []historyQuotaObservation `json:"quota,omitempty"` +} + +type historyDay struct { + OpenAITokens *int64 `json:"openaiTokens,omitempty"` + Local RecoveredUsageDay `json:"local,omitempty"` +} + +type historyQuotaObservation struct { + At time.Time `json:"at"` + LimitID string `json:"limitId"` + Window int `json:"window"` + Used int `json:"used"` + Duration *int64 `json:"duration,omitempty"` + Reset *int64 `json:"reset,omitempty"` +} + +// NewDefaultHistoryStore follows the same cross-platform application-data +// convention as presentation preferences while keeping history in its own +// independently migratable file. +func NewDefaultHistoryStore() (*HistoryStore, error) { + directory, err := os.UserConfigDir() + if err != nil { + return nil, err + } + return &HistoryStore{Path: filepath.Join(directory, "codexometer", "usage-history.json")}, nil +} + +func (s *HistoryStore) Reconcile(remote AccountUsage, recovered []RecoveredUsageDay) (AccountUsage, error) { + if s == nil || remote.AccountFingerprint == "" { + return remote, nil + } + s.mu.Lock() + defer s.mu.Unlock() + var result AccountUsage + err := withHistoryFileLock(s.Path+".lock", func() error { + file, err := s.load() + if err != nil { + return err + } + account := file.account(remote.AccountFingerprint) + mergeSummary(&account.Summary, remote.Summary) + if !remote.FetchedAt.IsZero() { + account.FetchedAt = remote.FetchedAt + } + if remote.DailyUsageBuckets != nil { + account.BucketsKnown = true + } + for _, day := range remote.DailyUsageBuckets { + if !validUsageDate(day.StartDate) || day.Tokens < 0 { + continue + } + value := day.Tokens + stored := account.Days[day.StartDate] + stored.OpenAITokens = &value + account.Days[day.StartDate] = stored + } + // Recovery is a complete bounded rescan, so replace local aggregates in + // that range instead of incrementing them and risking duplicate imports. + if recovered != nil { + if len(recovered) > 0 { + account.BucketsKnown = true + } + for date, day := range account.Days { + day.Local = RecoveredUsageDay{} + account.Days[date] = day + } + for _, day := range recovered { + if !validUsageDate(day.StartDate) || day.TotalTokens < 0 { + continue + } + stored := account.Days[day.StartDate] + stored.Local = day + account.Days[day.StartDate] = stored + } + } + pruneHistory(account, time.Now().UTC()) + if err := s.save(file); err != nil { + return err + } + result = renderAccountUsage(remote.AccountFingerprint, account, false) + s.activeAccount = remote.AccountFingerprint + return nil + }) + if err != nil { + return remote, fmt.Errorf("persist usage history: %w", err) + } + return result, nil +} + +// RecordQuota stores current snapshots for later quota-history visualisations. +// Consecutive identical observations are collapsed. +func (s *HistoryStore) RecordQuota(snapshot Snapshot) error { + if s == nil || snapshot.AccountFingerprint == "" { + return nil + } + s.mu.Lock() + defer s.mu.Unlock() + return withHistoryFileLock(s.Path+".lock", func() error { + file, err := s.load() + if err != nil { + return err + } + account := file.account(snapshot.AccountFingerprint) + at := snapshot.FetchedAt + if at.IsZero() { + at = time.Now() + } + windows := map[string]int{} + for _, meter := range snapshot.Meters() { + if meter.Kind != MeterQuotaWindow { + continue + } + window := windows[meter.LimitID] + bucket := snapshot.RateLimits + if len(snapshot.RateLimitsByLimitID) > 0 { + bucket = snapshot.RateLimitsByLimitID[meter.LimitID] + } + if bucket.Primary == nil { + window++ + } + windows[meter.LimitID]++ + observation := historyQuotaObservation{At: at.UTC(), LimitID: meter.LimitID, Window: window, Used: meter.Window.UsedPercent, Duration: meter.Window.WindowDurationMins, Reset: meter.Window.ResetsAt} + latest := -1 + for i := len(account.Quota) - 1; i >= 0; i-- { + if account.Quota[i].LimitID == observation.LimitID && account.Quota[i].Window == observation.Window { + latest = i + break + } + } + if latest >= 0 && sameQuotaObservation(account.Quota[latest], observation) { + account.Quota[latest].At = observation.At + } else { + account.Quota = append(account.Quota, observation) + } + } + if len(account.Quota) > maxQuotaObservations { + account.Quota = append([]historyQuotaObservation(nil), account.Quota[len(account.Quota)-maxQuotaObservations:]...) + } + if err := s.save(file); err != nil { + return err + } + s.activeAccount = snapshot.AccountFingerprint + return nil + }) +} + +func (s *HistoryStore) Latest() (AccountUsage, error) { + if s == nil { + return AccountUsage{}, os.ErrNotExist + } + s.mu.Lock() + defer s.mu.Unlock() + var result AccountUsage + err := withHistoryFileLock(s.Path+".lock", func() error { + if s.activeAccount == "" { + return os.ErrNotExist + } + file, err := s.load() + if err != nil { + return err + } + account := file.Accounts[s.activeAccount] + if account == nil { + return os.ErrNotExist + } + result = renderAccountUsage(s.activeAccount, account, true) + return nil + }) + return result, err +} + +func (f *historyFile) account(id string) *historyAccount { + if f.Accounts == nil { + f.Accounts = map[string]*historyAccount{} + } + account := f.Accounts[id] + if account == nil { + account = &historyAccount{Days: map[string]historyDay{}} + f.Accounts[id] = account + } + if account.Days == nil { + account.Days = map[string]historyDay{} + } + return account +} + +func (s *HistoryStore) load() (*historyFile, error) { + data, err := os.ReadFile(s.Path) + if errors.Is(err, os.ErrNotExist) { + return &historyFile{Version: historySchemaVersion, Accounts: map[string]*historyAccount{}}, nil + } + if err != nil { + return nil, err + } + var file historyFile + if err := json.Unmarshal(data, &file); err != nil { + return nil, err + } + if file.Version != historySchemaVersion { + return nil, fmt.Errorf("unsupported usage history schema %d", file.Version) + } + if file.Accounts == nil { + file.Accounts = map[string]*historyAccount{} + } + return &file, nil +} + +func (s *HistoryStore) save(file *historyFile) error { + data, err := json.MarshalIndent(file, "", " ") + if err != nil { + return err + } + directory := filepath.Dir(s.Path) + if err := os.MkdirAll(directory, 0o700); err != nil { + return err + } + temporary, err := os.CreateTemp(directory, ".usage-history-*") + if err != nil { + return err + } + name := temporary.Name() + defer os.Remove(name) + if err := temporary.Chmod(0o600); err != nil { + temporary.Close() + return err + } + if _, err := temporary.Write(append(data, '\n')); err != nil { + temporary.Close() + return err + } + if err := temporary.Sync(); err != nil { + temporary.Close() + return err + } + if err := temporary.Close(); err != nil { + return err + } + if err := replaceHistoryFile(name, s.Path); err != nil { + return err + } + return syncHistoryDirectory(directory) +} + +func renderAccountUsage(id string, account *historyAccount, stale bool) AccountUsage { + dates := make([]string, 0, len(account.Days)) + for date, day := range account.Days { + if day.OpenAITokens != nil || day.Local.TotalTokens > 0 { + dates = append(dates, date) + } + } + sort.Strings(dates) + result := AccountUsage{Summary: account.Summary, AccountFingerprint: id, FetchedAt: account.FetchedAt, Persisted: true, Stale: stale, DailyUsageBuckets: []AccountUsageDay{}} + if !account.BucketsKnown { + result.DailyUsageBuckets = nil + } + var matchedLocal int64 + for _, date := range dates { + stored := account.Days[date] + day := AccountUsageDay{StartDate: date, LocalTokens: stored.Local.TotalTokens, InputTokens: stored.Local.InputTokens, CachedInputTokens: stored.Local.CachedInputTokens, OutputTokens: stored.Local.OutputTokens, ReasoningTokens: stored.Local.ReasoningTokens} + if stored.OpenAITokens != nil { + day.Tokens = *stored.OpenAITokens + day.Provenance = "OPENAI" + result.Coverage.OpenAITokens = saturatingAdd(result.Coverage.OpenAITokens, day.Tokens) + result.Coverage.OpenAIDays++ + matchedLocal = saturatingAdd(matchedLocal, day.LocalTokens) + } else { + day.Tokens = stored.Local.TotalTokens + day.Provenance = "RECOVERED" + result.Coverage.RecoveredDays++ + } + result.Coverage.LocalTokens = saturatingAdd(result.Coverage.LocalTokens, day.LocalTokens) + result.DailyUsageBuckets = append(result.DailyUsageBuckets, day) + } + switch { + case result.Coverage.OpenAIDays > 0 && result.Coverage.RecoveredDays > 0: + result.Coverage.Status = "PARTIAL" + case result.Coverage.OpenAIDays > 0: + result.Coverage.Status = "OPENAI" + case result.Coverage.LocalTokens > 0: + result.Coverage.Status = "RECOVERED" + default: + result.Coverage.Status = "EMPTY" + } + if result.Coverage.OpenAITokens > 0 { + result.Coverage.AttributedPct = min(100, int(math.Round(100*float64(matchedLocal)/float64(result.Coverage.OpenAITokens)))) + } + return result +} + +func mergeSummary(current *AccountUsageSummary, incoming AccountUsageSummary) { + if incoming.LifetimeTokens != nil { + current.LifetimeTokens = incoming.LifetimeTokens + } + if incoming.PeakDailyTokens != nil { + current.PeakDailyTokens = incoming.PeakDailyTokens + } + if incoming.LongestRunningTurnSec != nil { + current.LongestRunningTurnSec = incoming.LongestRunningTurnSec + } + if incoming.CurrentStreakDays != nil { + current.CurrentStreakDays = incoming.CurrentStreakDays + } + if incoming.LongestStreakDays != nil { + current.LongestStreakDays = incoming.LongestStreakDays + } +} + +func validUsageDate(value string) bool { + _, err := time.Parse("2006-01-02", value) + return err == nil +} + +func pruneHistory(account *historyAccount, now time.Time) { + cutoff := now.AddDate(0, 0, -historyRetentionDays).Format("2006-01-02") + for date := range account.Days { + if date < cutoff { + delete(account.Days, date) + } + } +} + +func sameQuotaObservation(a, b historyQuotaObservation) bool { + return a.LimitID == b.LimitID && a.Window == b.Window && a.Used == b.Used && equalInt64Ptr(a.Duration, b.Duration) && equalInt64Ptr(a.Reset, b.Reset) +} + +func equalInt64Ptr(a, b *int64) bool { + return a == nil && b == nil || a != nil && b != nil && *a == *b +} + +func saturatingAdd(a, b int64) int64 { + if b > 0 && a > math.MaxInt64-b { + return math.MaxInt64 + } + return a + b +} diff --git a/internal/codex/history_store_test.go b/internal/codex/history_store_test.go new file mode 100644 index 0000000..e557617 --- /dev/null +++ b/internal/codex/history_store_test.go @@ -0,0 +1,125 @@ +package codex + +import ( + "errors" + "os" + "path/filepath" + "testing" + "time" +) + +func TestHistoryStoreReconcilesPersistsAndIsolatesAccounts(t *testing.T) { + path := filepath.Join(t.TempDir(), "nested", "usage-history.json") + store := &HistoryStore{Path: path} + now := time.Date(2026, time.September, 18, 12, 0, 0, 0, time.UTC) + lifetime, peak, turn, current, longest := int64(1_000), int64(100), int64(45), int64(2), int64(9) + remote := AccountUsage{ + AccountFingerprint: "account-a", FetchedAt: now, + Summary: AccountUsageSummary{LifetimeTokens: &lifetime, PeakDailyTokens: &peak, LongestRunningTurnSec: &turn, CurrentStreakDays: ¤t, LongestStreakDays: &longest}, + DailyUsageBuckets: []AccountUsageDay{{StartDate: "2026-09-17", Tokens: 100}}, + } + recovered := []RecoveredUsageDay{ + {StartDate: "2026-09-16", TotalTokens: 5, InputTokens: 4, OutputTokens: 1}, + {StartDate: "2026-09-17", TotalTokens: 70, InputTokens: 60, CachedInputTokens: 30, OutputTokens: 10}, + } + got, err := store.Reconcile(remote, recovered) + if err != nil { + t.Fatal(err) + } + if !got.Persisted || got.Stale || got.Coverage.Status != "PARTIAL" || got.Coverage.AttributedPct != 70 || got.Coverage.RecoveredDays != 1 || len(got.DailyUsageBuckets) != 2 { + t.Fatalf("reconciled usage = %+v", got) + } + if got.DailyUsageBuckets[0].Provenance != "RECOVERED" || got.DailyUsageBuckets[1].Tokens != 100 || got.DailyUsageBuckets[1].LocalTokens != 70 { + t.Fatalf("daily provenance = %+v", got.DailyUsageBuckets) + } + + reopened := &HistoryStore{Path: path} + verified := DemoSnapshot() + verified.AccountFingerprint = "account-a" + verified.FetchedAt = now.Add(time.Minute) + if err := reopened.RecordQuota(verified); err != nil { + t.Fatal(err) + } + cached, err := reopened.Latest() + if err != nil || !cached.Stale || cached.AccountFingerprint != "account-a" || cached.Summary.LongestStreakDays == nil || *cached.Summary.LongestStreakDays != 9 { + t.Fatalf("reopened cache = %+v, %v", cached, err) + } + other := remote + other.AccountFingerprint = "account-b" + other.DailyUsageBuckets = []AccountUsageDay{{StartDate: "2026-09-18", Tokens: 3}} + if _, err := reopened.Reconcile(other, []RecoveredUsageDay{}); err != nil { + t.Fatal(err) + } + latest, _ := reopened.Latest() + if latest.AccountFingerprint != "account-b" || len(latest.DailyUsageBuckets) != 1 { + t.Fatalf("latest account was mixed: %+v", latest) + } + data, err := os.ReadFile(path) + if err != nil || os.FileMode(0o077)&fileMode(t, path) != 0 { + t.Fatalf("history permissions/read = %v, %v", fileMode(t, path), err) + } + if len(data) == 0 { + t.Fatal("empty history file") + } + if _, err := (&HistoryStore{Path: path}).Latest(); !errors.Is(err, os.ErrNotExist) { + t.Fatalf("unverified restart selected a cached account: %v", err) + } +} + +func TestHistoryStoreDistinguishesUnavailableAndEmptyBuckets(t *testing.T) { + store := &HistoryStore{Path: filepath.Join(t.TempDir(), "history.json")} + missing, err := store.Reconcile(AccountUsage{AccountFingerprint: "missing", FetchedAt: time.Now()}, nil) + if err != nil || missing.DailyUsageBuckets != nil { + t.Fatalf("missing buckets became available: %+v, %v", missing, err) + } + empty, err := store.Reconcile(AccountUsage{AccountFingerprint: "empty", FetchedAt: time.Now(), DailyUsageBuckets: []AccountUsageDay{}}, []RecoveredUsageDay{}) + if err != nil || empty.DailyUsageBuckets == nil || len(empty.DailyUsageBuckets) != 0 { + t.Fatalf("empty buckets became unavailable: %+v, %v", empty, err) + } +} + +func TestHistoryStoreQuotaObservationsCollapsePerWindow(t *testing.T) { + store := &HistoryStore{Path: filepath.Join(t.TempDir(), "history.json")} + snapshot := DemoSnapshot() + snapshot.AccountFingerprint = "account" + snapshot.FetchedAt = time.Now() + if err := store.RecordQuota(snapshot); err != nil { + t.Fatal(err) + } + snapshot.FetchedAt = snapshot.FetchedAt.Add(time.Minute) + if err := store.RecordQuota(snapshot); err != nil { + t.Fatal(err) + } + file, err := store.load() + if err != nil { + t.Fatal(err) + } + if got := len(file.Accounts["account"].Quota); got != 2 { + t.Fatalf("identical two-window snapshot produced %d observations", got) + } + snapshot.RateLimits.Primary.UsedPercent++ + if err := store.RecordQuota(snapshot); err != nil { + t.Fatal(err) + } + file, _ = store.load() + if got := len(file.Accounts["account"].Quota); got != 3 { + t.Fatalf("changed window was not appended: %d", got) + } + snapshot.RateLimits.Primary = nil + if err := store.RecordQuota(snapshot); err != nil { + t.Fatal(err) + } + file, _ = store.load() + if got := len(file.Accounts["account"].Quota); got != 3 { + t.Fatalf("secondary window changed identity when primary disappeared: %d", got) + } +} + +func fileMode(t *testing.T, path string) os.FileMode { + t.Helper() + info, err := os.Stat(path) + if err != nil { + t.Fatal(err) + } + return info.Mode().Perm() +} diff --git a/internal/codex/live_usage.go b/internal/codex/live_usage.go index e9202f1..9902259 100644 --- a/internal/codex/live_usage.go +++ b/internal/codex/live_usage.go @@ -114,6 +114,11 @@ type LiveUsageReader struct { statusProvider sessionStatusProvider mu sync.Mutex + recoveryMu sync.Mutex + recoveryAt time.Time + recoverySince time.Time + recoveredDays []RecoveredUsageDay + recoveryFiles map[string]recoveredRollout initialized bool startedAt time.Time lastDiscovery time.Time @@ -133,6 +138,153 @@ type LiveUsageReader struct { daemonSubscribedThreads map[string]struct{} } +type recoveredRollout struct { + size int64 + modified time.Time + days []RecoveredUsageDay +} + +// RecoverDailyUsage performs a bounded, content-free rescan of retained +// rollouts. It deliberately derives totals from token_count events only; no +// prompts, replies, commands, or paths leave this reader. A short cache keeps +// the web poller from repeatedly walking an unchanged year of history. +func (r *LiveUsageReader) RecoverDailyUsage(ctx context.Context, since time.Time) ([]RecoveredUsageDay, error) { + r.recoveryMu.Lock() + defer r.recoveryMu.Unlock() + since = time.Date(since.UTC().Year(), since.UTC().Month(), since.UTC().Day(), 0, 0, 0, 0, time.UTC) + if !r.recoveryAt.IsZero() && time.Since(r.recoveryAt) < 4*time.Minute && r.recoverySince.Equal(since) { + return append([]RecoveredUsageDay(nil), r.recoveredDays...), nil + } + if !r.recoverySince.Equal(since) || r.recoveryFiles == nil { + r.recoveryFiles = map[string]recoveredRollout{} + } + seen := map[string]bool{} + err := filepath.WalkDir(r.SessionsRoot, func(path string, entry os.DirEntry, walkErr error) error { + if walkErr != nil { + if errors.Is(walkErr, os.ErrNotExist) { + return nil + } + return walkErr + } + if err := contextErr(ctx); err != nil { + return err + } + if entry.IsDir() || entry.Type()&os.ModeSymlink != 0 || !isRolloutFile(entry.Name()) { + return nil + } + info, err := entry.Info() + if err != nil { + return nil + } + seen[path] = true + if cached, ok := r.recoveryFiles[path]; ok && cached.size == info.Size() && cached.modified.Equal(info.ModTime()) { + return nil + } + metadata, err := readRolloutMetadata(path) + if err != nil { + return nil // one damaged rollout must not hide all recoverable history + } + fileDays := map[string]RecoveredUsageDay{} + if err := recoverRolloutDaily(path, metadata, since, fileDays); err != nil { + return nil + } + dates := make([]string, 0, len(fileDays)) + for date := range fileDays { + dates = append(dates, date) + } + sort.Strings(dates) + rollout := recoveredRollout{size: info.Size(), modified: info.ModTime(), days: make([]RecoveredUsageDay, 0, len(dates))} + for _, date := range dates { + rollout.days = append(rollout.days, fileDays[date]) + } + r.recoveryFiles[path] = rollout + return nil + }) + if errors.Is(err, os.ErrNotExist) { + err = nil + } + if err != nil { + return nil, fmt.Errorf("recover local Codex usage: %w", err) + } + for path := range r.recoveryFiles { + if !seen[path] { + delete(r.recoveryFiles, path) + } + } + days := map[string]RecoveredUsageDay{} + for _, rollout := range r.recoveryFiles { + for _, recovered := range rollout.days { + day := days[recovered.StartDate] + day.StartDate = recovered.StartDate + day.TotalTokens = saturatingAdd(day.TotalTokens, recovered.TotalTokens) + day.InputTokens = saturatingAdd(day.InputTokens, recovered.InputTokens) + day.CachedInputTokens = saturatingAdd(day.CachedInputTokens, recovered.CachedInputTokens) + day.OutputTokens = saturatingAdd(day.OutputTokens, recovered.OutputTokens) + day.ReasoningTokens = saturatingAdd(day.ReasoningTokens, recovered.ReasoningTokens) + days[recovered.StartDate] = day + } + } + dates := make([]string, 0, len(days)) + for date := range days { + dates = append(dates, date) + } + sort.Strings(dates) + result := make([]RecoveredUsageDay, 0, len(dates)) + for _, date := range dates { + result = append(result, days[date]) + } + r.recoveryAt, r.recoverySince = time.Now(), since + r.recoveredDays = append(r.recoveredDays[:0], result...) + return append([]RecoveredUsageDay(nil), result...), nil +} + +func recoverRolloutDaily(path string, metadata rolloutMetadata, since time.Time, days map[string]RecoveredUsageDay) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + reader := bufio.NewReader(file) + var previous int64 + for { + line, readErr := reader.ReadBytes('\n') + if len(line) > 0 && line[len(line)-1] == '\n' { + record, ok := tokenUsageRecord(line) + if ok { + owned := tokenRecordIsOwned(record.ordinal, metadata.SubagentHistoryStartOrdinal, record.at, metadata.NonRoot, metadata.StartedAt) + if !owned { + previous = record.total + } else { + delta := record.total + if record.total >= previous { + delta = record.total - previous + } + previous = record.total + if delta > 0 && !record.at.IsZero() && !record.at.UTC().Before(since) { + date := record.at.UTC().Format("2006-01-02") + day := days[date] + day.StartDate = date + day.TotalTokens = saturatingAdd(day.TotalTokens, delta) + if record.usage.TotalTokens == delta { + day.InputTokens = saturatingAdd(day.InputTokens, record.usage.InputTokens) + day.CachedInputTokens = saturatingAdd(day.CachedInputTokens, record.usage.CachedInputTokens) + day.OutputTokens = saturatingAdd(day.OutputTokens, record.usage.OutputTokens) + day.ReasoningTokens = saturatingAdd(day.ReasoningTokens, record.usage.ReasoningOutputTokens) + } + days[date] = day + } + } + } + } + if readErr != nil { + if errors.Is(readErr, io.EOF) { + return nil + } + return readErr + } + } +} + type rolloutCursor struct { preview SessionContext offset int64 diff --git a/internal/codex/live_usage_test.go b/internal/codex/live_usage_test.go index b2f5cb6..0130a2b 100644 --- a/internal/codex/live_usage_test.go +++ b/internal/codex/live_usage_test.go @@ -60,6 +60,27 @@ func TestLiveUsageReaderBaselinesAndConsumesAppendedTelemetry(t *testing.T) { } } +func TestRecoverDailyUsageRescansWithoutDoubleCounting(t *testing.T) { + home := t.TempDir() + now := time.Date(2026, time.September, 18, 12, 0, 0, 0, time.UTC) + path := testRolloutPath(t, home, now.Add(-24*time.Hour), "history") + writeRollout(t, path, sessionMetaLineAt("root", `"cli"`, "/private/path", nil, now.Add(-24*time.Hour))+"\n"+ + richTokenCountLine(now.Add(-24*time.Hour), 100, 80, 40, 0, 20)+"\n"+ + richTokenCountLine(now, 150, 40, 10, 0, 10)+"\n") + reader, err := NewLiveUsageReader(home) + if err != nil { + t.Fatal(err) + } + first, err := reader.RecoverDailyUsage(context.Background(), now.Add(-48*time.Hour)) + if err != nil || len(first) != 2 || first[0].TotalTokens != 100 || first[0].CachedInputTokens != 40 || first[1].TotalTokens != 50 || first[1].InputTokens != 40 { + t.Fatalf("recovered days = %+v, %v", first, err) + } + second, err := reader.RecoverDailyUsage(context.Background(), now.Add(-48*time.Hour)) + if err != nil || len(second) != 2 || second[1].TotalTokens != 50 { + t.Fatalf("cached recovery doubled usage: %+v, %v", second, err) + } +} + func TestAppendBoundedRetainsNewestValuesWithoutCopyingOnOverflow(t *testing.T) { history := make([]int, 3, 4) copy(history, []int{1, 2, 3}) diff --git a/internal/i18n/locales/da.json b/internal/i18n/locales/da.json index 47e2a2b..0009b2a 100644 --- a/internal/i18n/locales/da.json +++ b/internal/i18n/locales/da.json @@ -208,6 +208,9 @@ "LAST OUT ": "SENESTE OUTPUT ", "LESS ": "MINDRE ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "SAMLET // %s TOKENS TOPDAG // %s STIME // %s DAGE", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "LÆNGSTE KØRSEL // %s LÆNGSTE STIME // %s DAGE", + "LOCAL %d%% ATTRIBUTED": "LOKALT %d%% TILSKREVET", + "%d RECOVERED DAYS": "%d GENDANNEDE DAGE", "LIMIT NEAR": "TÆT PÅ GRÆNSEN", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINEÆR PROGNOSE // GRÆNSE OM ~%s // %s FOR TIDLIGT", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINEÆR PROGNOSE // SIKKER TIL NULSTILLING // ~%d%% TILBAGE", diff --git a/internal/i18n/locales/de.json b/internal/i18n/locales/de.json index 5a33086..ede507c 100644 --- a/internal/i18n/locales/de.json +++ b/internal/i18n/locales/de.json @@ -208,6 +208,9 @@ "LAST OUT ": "LETZTE AUSGABE ", "LESS ": "WENIGER ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "GESAMT // %s TOKEN TAGESREKORD // %s SERIE // %s TAGE", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "LÄNGSTER DURCHLAUF // %s LÄNGSTE SERIE // %s TAGE", + "LOCAL %d%% ATTRIBUTED": "LOKAL %d%% ZUGEORDNET", + "%d RECOVERED DAYS": "%d WIEDERHERGESTELLTE TAGE", "LIMIT NEAR": "LIMIT NAHE", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINEARE PROGNOSE // LIMIT IN ~%s // %s ZU FRÜH", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINEARE PROGNOSE // REICHT BIS ZUM RESET // ~%d%% ÜBRIG", diff --git a/internal/i18n/locales/en-GB.json b/internal/i18n/locales/en-GB.json index 6f5be87..dec5337 100644 --- a/internal/i18n/locales/en-GB.json +++ b/internal/i18n/locales/en-GB.json @@ -208,6 +208,9 @@ "LAST OUT ": "LAST OUT ", "LESS ": "LESS ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "LONGEST TURN // %s LONGEST STREAK // %s DAYS", + "LOCAL %d%% ATTRIBUTED": "LOCAL %d%% ATTRIBUTED", + "%d RECOVERED DAYS": "%d RECOVERED DAYS", "LIMIT NEAR": "LIMIT NEAR", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT", diff --git a/internal/i18n/locales/es.json b/internal/i18n/locales/es.json index 8bf9670..7a5b323 100644 --- a/internal/i18n/locales/es.json +++ b/internal/i18n/locales/es.json @@ -208,6 +208,9 @@ "LAST OUT ": "ÚLTIMA SALIDA ", "LESS ": "MENOS ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTAL HISTÓRICO // %s TOKENS PICO DIARIO // %s RACHA // %s DÍAS", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "TURNO MÁS LARGO // %s RACHA MÁS LARGA // %s DÍAS", + "LOCAL %d%% ATTRIBUTED": "LOCAL %d%% ATRIBUIDO", + "%d RECOVERED DAYS": "%d DÍAS RECUPERADOS", "LIMIT NEAR": "LÍMITE CERCA", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "PROYECCIÓN LINEAL // LÍMITE EN ~%s // %s ANTES", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "PROYECCIÓN LINEAL // SUFICIENTE HASTA RESTABLECER // ~%d%% RESTANTE", diff --git a/internal/i18n/locales/et.json b/internal/i18n/locales/et.json index f7c8357..188edcc 100644 --- a/internal/i18n/locales/et.json +++ b/internal/i18n/locales/et.json @@ -208,6 +208,9 @@ "LAST OUT ": "VIIMANE VÄLJUND ", "LESS ": "VÄHEM ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "KOGUAEG // %s TOKENIT TIPPPÄEV // %s JADA // %s PÄEVA", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "PIKIM TÖÖ // %s PIKIM JADA // %s PÄEVA", + "LOCAL %d%% ATTRIBUTED": "KOHALIKULT %d%% OMISTATUD", + "%d RECOVERED DAYS": "%d TAASTATUD PÄEVA", "LIMIT NEAR": "PIIR LÄHEDAL", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINEAARNE PROGNOOS // PIIRINI ~%s // %s VAREM", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINEAARNE PROGNOOS // JÄTKUB LÄHTESTUSENI // ~%d%% ALLES", diff --git a/internal/i18n/locales/fi.json b/internal/i18n/locales/fi.json index a041a12..622804c 100644 --- a/internal/i18n/locales/fi.json +++ b/internal/i18n/locales/fi.json @@ -208,6 +208,9 @@ "LAST OUT ": "VIIMEISIN TULOSTE ", "LESS ": "VÄHEMMÄN ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "KOKONAISAIKA // %s TOKENIA HUIPPUPÄIVÄ // %s PUTKI // %s PÄIVÄÄ", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "PISIN KIERROS // %s PISIN PUTKI // %s PÄIVÄÄ", + "LOCAL %d%% ATTRIBUTED": "PAIKALLISESTI %d%% KOHDENNETTU", + "%d RECOVERED DAYS": "%d PALAUTETTUA PÄIVÄÄ", "LIMIT NEAR": "RAJA LÄHELLÄ", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINEAARINEN ENNUSTE // RAJA ~%s KULUTTUA // %s ETUAJASSA", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINEAARINEN ENNUSTE // RIITTÄÄ NOLLAUKSEEN // ~%d%% JÄLJELLÄ", diff --git a/internal/i18n/locales/fr.json b/internal/i18n/locales/fr.json index da9e0f9..a3b3a50 100644 --- a/internal/i18n/locales/fr.json +++ b/internal/i18n/locales/fr.json @@ -208,6 +208,9 @@ "LAST OUT ": "DERNIÈRE SORTIE ", "LESS ": "MOINS ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTAL HISTORIQUE // %s TOKENS PIC JOURNALIER // %s SÉRIE // %s JOURS", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "TOUR LE PLUS LONG // %s SÉRIE LA PLUS LONGUE // %s JOURS", + "LOCAL %d%% ATTRIBUTED": "LOCAL ATTRIBUÉ À %d%%", + "%d RECOVERED DAYS": "%d JOURS RÉCUPÉRÉS", "LIMIT NEAR": "LIMITE PROCHE", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "PROJECTION LINÉAIRE // LIMITE DANS ~%s // %s TROP TÔT", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "PROJECTION LINÉAIRE // SUFFISANT JUSQU’AU RESET // ~%d%% RESTANT", diff --git a/internal/i18n/locales/it.json b/internal/i18n/locales/it.json index 6b67433..aa3f0a3 100644 --- a/internal/i18n/locales/it.json +++ b/internal/i18n/locales/it.json @@ -208,6 +208,9 @@ "LAST OUT ": "ULTIMO OUTPUT ", "LESS ": "MENO ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTALE STORICO // %s TOKEN PICCO GIORNALIERO // %s SERIE // %s GIORNI", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "TURNO PIÙ LUNGO // %s SERIE PIÙ LUNGA // %s GIORNI", + "LOCAL %d%% ATTRIBUTED": "LOCALE %d%% ATTRIBUITO", + "%d RECOVERED DAYS": "%d GIORNI RECUPERATI", "LIMIT NEAR": "LIMITE VICINO", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "PROIEZIONE LINEARE // LIMITE TRA ~%s // %s IN ANTICIPO", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "PROIEZIONE LINEARE // SUFFICIENTE FINO AL RESET // ~%d%% RESIDUO", diff --git a/internal/i18n/locales/ja.json b/internal/i18n/locales/ja.json index 8bb811f..cd135ce 100644 --- a/internal/i18n/locales/ja.json +++ b/internal/i18n/locales/ja.json @@ -208,6 +208,9 @@ "LAST OUT ": "直近の出力 ", "LESS ": "少 ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "全期間 // %s トークン 最多日 // %s 連続日数 // %s 日", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "最長ターン // %s 最長連続 // %s 日", + "LOCAL %d%% ATTRIBUTED": "ローカル帰属 %d%%", + "%d RECOVERED DAYS": "%d 日を復元", "LIMIT NEAR": "上限間近", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "線形予測 // 上限まで ~%s // %s 早く到達", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "線形予測 // リセットまで余裕 // ~%d%% 残り", diff --git a/internal/i18n/locales/nb.json b/internal/i18n/locales/nb.json index 2f2330b..222cf0a 100644 --- a/internal/i18n/locales/nb.json +++ b/internal/i18n/locales/nb.json @@ -208,6 +208,9 @@ "LAST OUT ": "SISTE UTDATA ", "LESS ": "MINDRE ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTALT // %s TOKEN TOPPDAG // %s REKKE // %s DAGER", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "LENGSTE KJØRING // %s LENGSTE REKKE // %s DAGER", + "LOCAL %d%% ATTRIBUTED": "LOKALT %d%% TILSKREVET", + "%d RECOVERED DAYS": "%d GJENOPPRETTEDE DAGER", "LIMIT NEAR": "NÆR GRENSEN", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINEÆR PROGNOSE // GRENSE OM ~%s // %s FOR TIDLIG", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINEÆR PROGNOSE // HOLDER TIL TILBAKESTILLING // ~%d%% IGJEN", diff --git a/internal/i18n/locales/nl.json b/internal/i18n/locales/nl.json index b989ddb..2699855 100644 --- a/internal/i18n/locales/nl.json +++ b/internal/i18n/locales/nl.json @@ -208,6 +208,9 @@ "LAST OUT ": "LAATSTE UITVOER ", "LESS ": "MINDER ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTAAL // %s TOKENS DAGPIEK // %s REEKS // %s DAGEN", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "LANGSTE BEURT // %s LANGSTE REEKS // %s DAGEN", + "LOCAL %d%% ATTRIBUTED": "LOKAAL %d%% TOEGEWEZEN", + "%d RECOVERED DAYS": "%d HERSTELDE DAGEN", "LIMIT NEAR": "LIMIET NABIJ", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINEAIRE SCHATTING // LIMIET OVER ~%s // %s TE VROEG", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINEAIRE SCHATTING // VEILIG TOT RESET // ~%d%% OVER", diff --git a/internal/i18n/locales/pt-BR.json b/internal/i18n/locales/pt-BR.json index 0fd5a06..7bbdaed 100644 --- a/internal/i18n/locales/pt-BR.json +++ b/internal/i18n/locales/pt-BR.json @@ -208,6 +208,9 @@ "LAST OUT ": "ÚLTIMA SAÍDA ", "LESS ": "MENOS ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTAL HISTÓRICO // %s TOKENS DIA DE PICO // %s SEQUÊNCIA // %s DIAS", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "TURNO MAIS LONGO // %s MAIOR SEQUÊNCIA // %s DIAS", + "LOCAL %d%% ATTRIBUTED": "LOCAL %d%% ATRIBUÍDO", + "%d RECOVERED DAYS": "%d DIAS RECUPERADOS", "LIMIT NEAR": "LIMITE PRÓXIMO", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "PROJEÇÃO LINEAR // LIMITE EM ~%s // %s ANTES", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "PROJEÇÃO LINEAR // SEGURO ATÉ REDEFINIÇÃO // ~%d%% RESTANTE", diff --git a/internal/i18n/locales/pt-PT.json b/internal/i18n/locales/pt-PT.json index 9c4bcf9..153241d 100644 --- a/internal/i18n/locales/pt-PT.json +++ b/internal/i18n/locales/pt-PT.json @@ -208,6 +208,9 @@ "LAST OUT ": "ÚLTIMA SAÍDA ", "LESS ": "MENOS ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTAL HISTÓRICO // %s TOKENS DIA DE PICO // %s SEQUÊNCIA // %s DIAS", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "TURNO MAIS LONGO // %s MAIOR SEQUÊNCIA // %s DIAS", + "LOCAL %d%% ATTRIBUTED": "LOCAL %d%% ATRIBUÍDO", + "%d RECOVERED DAYS": "%d DIAS RECUPERADOS", "LIMIT NEAR": "LIMITE PRÓXIMO", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "PROJEÇÃO LINEAR // LIMITE EM ~%s // %s ANTES", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "PROJEÇÃO LINEAR // SEGURO ATÉ REPOSIÇÃO // ~%d%% RESTANTE", diff --git a/internal/i18n/locales/ru.json b/internal/i18n/locales/ru.json index c6b196f..332169e 100644 --- a/internal/i18n/locales/ru.json +++ b/internal/i18n/locales/ru.json @@ -208,6 +208,9 @@ "LAST OUT ": "ПОСЛЕДНИЙ ВЫВОД ", "LESS ": "МЕНЬШЕ ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "ЗА ВСЁ ВРЕМЯ // %s ТОКЕНЫ ПИК ЗА ДЕНЬ // %s СЕРИЯ // %s ДНЕЙ", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "САМЫЙ ДОЛГИЙ ХОД // %s САМАЯ ДОЛГАЯ СЕРИЯ // %s ДНЕЙ", + "LOCAL %d%% ATTRIBUTED": "ЛОКАЛЬНО ОПРЕДЕЛЕНО %d%%", + "%d RECOVERED DAYS": "%d ВОССТАНОВЛЕННЫХ ДНЕЙ", "LIMIT NEAR": "ЛИМИТ БЛИЗКО", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "ЛИНЕЙНЫЙ ПРОГНОЗ // ЛИМИТ ЧЕРЕЗ ~%s // %s РАНЬШЕ", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "ЛИНЕЙНЫЙ ПРОГНОЗ // ХВАТИТ ДО СБРОСА // ~%d%% ОСТАЛОСЬ", diff --git a/internal/i18n/locales/sv.json b/internal/i18n/locales/sv.json index 6f1c498..ef7a4eb 100644 --- a/internal/i18n/locales/sv.json +++ b/internal/i18n/locales/sv.json @@ -208,6 +208,9 @@ "LAST OUT ": "SENASTE UTDATA ", "LESS ": "MINDRE ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TOTALT // %s TOKEN TOPPDAG // %s SVIT // %s DAGAR", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "LÄNGSTA KÖRNING // %s LÄNGSTA SVIT // %s DAGAR", + "LOCAL %d%% ATTRIBUTED": "LOKALT %d%% TILLSKRIVET", + "%d RECOVERED DAYS": "%d ÅTERSTÄLLDA DAGAR", "LIMIT NEAR": "NÄRA GRÄNSEN", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "LINJÄR PROGNOS // GRÄNS OM ~%s // %s FÖR TIDIGT", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "LINJÄR PROGNOS // RÄCKER TILL ÅTERSTÄLLNING // ~%d%% KVAR", diff --git a/internal/i18n/locales/tr.json b/internal/i18n/locales/tr.json index 900b107..1aaf951 100644 --- a/internal/i18n/locales/tr.json +++ b/internal/i18n/locales/tr.json @@ -208,6 +208,9 @@ "LAST OUT ": "SON ÇIKTI ", "LESS ": "DAHA AZ ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "TÜM ZAMANLAR // %s TOKEN ZİRVE GÜN // %s SERİ // %s GÜN", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "EN UZUN TUR // %s EN UZUN SERİ // %s GÜN", + "LOCAL %d%% ATTRIBUTED": "YEREL %d%% İLİŞKİLENDİRİLDİ", + "%d RECOVERED DAYS": "%d KURTARILAN GÜN", "LIMIT NEAR": "SINIRA YAKIN", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "DOĞRUSAL TAHMİN // SINIRA ~%s // %s ERKEN", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "DOĞRUSAL TAHMİN // SIFIRLAMAYA KADAR YETERLİ // ~%d%% KALIR", diff --git a/internal/i18n/locales/zh-Hans.json b/internal/i18n/locales/zh-Hans.json index 13f866c..c9be139 100644 --- a/internal/i18n/locales/zh-Hans.json +++ b/internal/i18n/locales/zh-Hans.json @@ -208,6 +208,9 @@ "LAST OUT ": "最近输出 ", "LESS ": "少 ", "LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS": "历史总计 // %s 令牌 单日峰值 // %s 连续天数 // %s 天", + "LONGEST TURN // %s LONGEST STREAK // %s DAYS": "最长回合 // %s 最长连续 // %s 天", + "LOCAL %d%% ATTRIBUTED": "本地归因 %d%%", + "%d RECOVERED DAYS": "已恢复 %d 天", "LIMIT NEAR": "接近上限", "LINEAR PROJECTION // LIMIT IN ~%s // %s EARLY": "线性预测 // 距上限 ~%s // %s 提前", "LINEAR PROJECTION // SAFE THROUGH RESET // ~%d%% LEFT": "线性预测 // 可用至重置 // ~%d%% 剩余", diff --git a/internal/ui/english_snapshot_test.go b/internal/ui/english_snapshot_test.go index 74c277a..baa99ed 100644 --- a/internal/ui/english_snapshot_test.go +++ b/internal/ui/english_snapshot_test.go @@ -31,9 +31,9 @@ func TestEnglishPresentationSnapshot(t *testing.T) { } } got := fmt.Sprintf("%x", hash.Sum(nil)) - // Baseline intentionally updated for the compact [ (C)OPY ] label; - // all themes, views and three terminal sizes are covered. - const want = "49ac2efe33d6574b4f491d0c0165c72c98a2542670979a43f1bd659295936038" + // Baseline includes persistent Usage provenance and the two additional + // OpenAI account summary metrics; every theme, view and size is covered. + const want = "ec5498dccc07e2d2531d3ef645ccd819fcaea9f45b1f69aa206197f877178321" if got != want { t.Fatalf("English presentation changed: got %s, want %s", got, want) } diff --git a/internal/ui/usage.go b/internal/ui/usage.go index 0eb8260..4a1b375 100644 --- a/internal/ui/usage.go +++ b/internal/ui/usage.go @@ -228,6 +228,13 @@ func optionalUsage(n *int64) string { return usageNumber(*n) } +func optionalUsageDuration(seconds *int64) string { + if seconds == nil || *seconds < 0 { + return "—" + } + return (time.Duration(*seconds) * time.Second).Round(time.Second).String() +} + func (m Model) renderHistory(width, height int, colors palette) string { lines := []string{} buttons := "" @@ -245,9 +252,15 @@ func (m Model) renderHistory(width, height int, colors palette) string { lines = append(lines, buttons) data := m.history.data lines = append(lines, colors.label().Render(i18n.Format("LIFETIME // %s TOKENS PEAK DAY // %s STREAK // %s DAYS", optionalUsage(data.Summary.LifetimeTokens), optionalUsage(data.Summary.PeakDailyTokens), optionalUsage(data.Summary.CurrentStreakDays)))) + if height >= 8 { + lines = append(lines, colors.label().Render(i18n.Format("LONGEST TURN // %s LONGEST STREAK // %s DAYS", optionalUsageDuration(data.Summary.LongestRunningTurnSec), optionalUsage(data.Summary.LongestStreakDays)))) + } status := i18n.Format("ACCOUNT HISTORY // UTC // %d WEEKS // R REFRESH", m.history.weeks()) if !data.FetchedAt.IsZero() { - status = i18n.Text("ACCOUNT HISTORY // UTC // UPDATED ") + data.FetchedAt.Local().Format("15:04:05") + i18n.Text(" // R REFRESH") + status = i18n.Text("ACCOUNT HISTORY // UTC // UPDATED ") + data.FetchedAt.Local().Format("15:04:05") + " // " + usageCoverageLabel(data) + i18n.Text(" // R REFRESH") + } + if data.Stale { + status = i18n.Text("STALE") + " // " + usageCoverageLabel(data) + " // " + data.FetchedAt.Local().Format("02 JAN 15:04") + i18n.Text(" // R RETRY") } if m.history.loading { status = i18n.Text("FETCHING ACCOUNT HISTORY…") @@ -316,6 +329,21 @@ func (m Model) renderHistory(width, height int, colors palette) string { return strings.Join(lines, "\n") } +func usageCoverageLabel(data codex.AccountUsage) string { + status := strings.TrimSpace(data.Coverage.Status) + if status == "" { + status = "OPENAI" + } + parts := []string{status} + if data.Coverage.OpenAITokens > 0 && data.Coverage.LocalTokens > 0 { + parts = append(parts, i18n.Format("LOCAL %d%% ATTRIBUTED", data.Coverage.AttributedPct)) + } + if data.Coverage.RecoveredDays > 0 { + parts = append(parts, i18n.Format("%d RECOVERED DAYS", data.Coverage.RecoveredDays)) + } + return strings.Join(parts, " // ") +} + type historyCalendarLayout struct { cellWidth, cellHeight, gap, columns int } diff --git a/internal/web/dist/assets/index-CKsvYdC2.js b/internal/web/dist/assets/index-CKsvYdC2.js new file mode 100644 index 0000000..49c1292 --- /dev/null +++ b/internal/web/dist/assets/index-CKsvYdC2.js @@ -0,0 +1,27 @@ +(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible;function d(e){return typeof e==`function`}var f=()=>{};function p(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}function h(e,t,n=!1){return e===void 0?n?t():t:e}function g(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);let n=[];for(let r of e)if(n.push(r),n.length===t)break;return n}var _=1024,v=2048,y=4096,b=8192,x=16384,S=32768,C=1<<25,w=65536,T=1<<19,E=1<<20,ee=1<<25,D=65536,te=1<<21,ne=1<<22,re=1<<23,ie=Symbol(`$state`),ae=Symbol(`component`),oe=Symbol(`legacy props`),se=Symbol(``),ce=Symbol(`attributes`),le=Symbol(`class`),ue=Symbol(`style`),de=Symbol(`text`),fe=Symbol(`form reset`),pe=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},me=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),he={},ge=Symbol(`uninitialized`),_e=`http://www.w3.org/1999/xhtml`;function ve(){console.warn(`https://svelte.dev/e/derived_inert`)}function ye(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function be(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function xe(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var O=!1;function Se(e){O=e}var k;function Ce(e){if(e===null)throw ye(),he;return k=e}function we(){return Ce(ln(k))}function A(e){if(O){if(ln(k)!==null)throw ye(),he;k=e}}function Te(e=1){if(O){for(var t=e,n=k;t--;)n=ln(n);k=n}}function Ee(e=!0){for(var t=0,n=k;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=ln(n);e&&n.remove(),n=i}}function De(e){if(!e||e.nodeType!==8)throw ye(),he;return e.data}function Oe(e){return e===this.v}function ke(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function Ae(e){return!ke(e,this.v)}function je(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function Me(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function Ne(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function Pe(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function Fe(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Ie(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function Le(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Re(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function ze(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Be(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Ve(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function He(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var Ue=!1;function We(){Ue=!0}var j=null;function Ge(e){j=e}function Ke(e,t=!1,n){j={p:j,i:!1,c:null,e:null,s:e,x:null,r:U,l:Ue&&!t?{s:null,u:null,$:[]}:null}}function qe(e){var t=j,n=t.e;if(n!==null){t.e=null;for(var r of n)Sn(r)}return e!==void 0&&(t.x=e),t.i=!0,j=t.p,Je(e)}function Je(e={}){return i(e,ae,{value:!0}),e}function Ye(){return!Ue||j!==null&&j.l===null}var Xe=[];function Ze(){var e=Xe;Xe=[],p(e)}function Qe(e){if(Xe.length===0&&!Ot){var t=Xe;queueMicrotask(()=>{t===Xe&&Ze()})}Xe.push(e)}function $e(){for(;Xe.length>0;)Ze()}var et=~(v|y|_);function M(e,t){e.f=e.f&et|t}function tt(e){e.f&512||e.deps===null?M(e,_):M(e,y)}function nt(e){if(e!==null)for(let t of e)t.f&2&&t.f&65536&&(t.f^=D,nt(t.deps))}function rt(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),nt(e.deps),M(e,_)}var it=!1;function at(e){var t=it;try{return it=!1,[e(),it]}finally{it=t}}function ot(e){O&&cn(e)!==null&&un(e)}var st=!1;function ct(){st||(st=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[fe]?.()})},{capture:!0}))}function lt(e){var t=H,n=U;Gn(null),Kn(null);try{return e()}finally{Gn(t),Kn(n)}}function ut(e,t,n,r=n){e.addEventListener(t,()=>lt(n));let i=e[fe];e[fe]=i?()=>{i(),r(!0)}:()=>r(!0),ct()}function dt(e,t,n,r){let i=Ye()?ht:vt;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=U,c=ft(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){hn(e,s)}pt()}}var d=mt();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>_t(e))).then(u).catch(e=>hn(e,s)).finally(d)}l?l.then(()=>{c(),f(),pt()}):f()}function ft(){var e=U,t=H,n=j,r=P;return function(i=!0){Kn(e),Gn(t),Ge(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function pt(e=!0){Kn(null),Gn(null),Ge(null),e&&P?.deactivate()}function mt(){var e=U,t=e.b,n=P,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function ht(e){var t=2|v;return U!==null&&(U.f|=T),{ctx:j,deps:null,effects:null,equals:Oe,f:t,fn:e,reactions:null,rv:0,v:ge,wv:0,parent:U,ac:null}}var gt=Symbol(`obsolete`);function _t(e,t,n){let r=U;r===null&&Me();var i=void 0,a=Gt(ge),o=!H,s=new Set;return Tn(()=>{var t=U,n=m();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==pe&&n.reject(e)}).finally(pt)}catch(e){n.reject(e),pt()}var c=P;if(o){if(t.f&32768)var l=mt();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(gt);else for(let e of s.values())e.reject(gt);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==gt&&(c.activate(),t?(a.f|=re,qt(a,t)):(a.f&8388608&&(a.f^=re),qt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),bn(()=>{for(let e of s)e.reject(gt)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function N(e){let t=ht(e);return Jn(t),t}function vt(e){let t=ht(e);return t.equals=Ae,t}function yt(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(pe),t.ac=null}),t.fn!==null&&(t.teardown=f),lr(t,0),An(t))}function Ct(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&ur(t)}var wt=null,P=null,Tt=null,Et=null,Dt=null,Ot=!1,kt=!1,At=null,jt=null,Mt=0,Nt=1,Pt=class e{id=Nt++;#e=!1;linked=!0;#t=null;#n=null;async_deriveds=new Map;current=new Map;previous=new Map;#r=new Set;#i=new Set;#a=0;#o=new Map;#s=null;#c=[];#l=[];#u=new Set;#d=new Set;#f=new Map;#p=new Set;is_fork=!1;#m=!1;constructor(){wt===null?wt=this:(wt.#n=this,this.#t=wt),wt=this}#h(){if(this.is_fork)return!0;for(let n of this.#o.keys()){for(var e=n,t=!1;e.parent!==null;){if(this.#f.has(e)){t=!0;break}e=e.parent}if(!t)return!0}return!1}skip_effect(e){this.#f.has(e)||this.#f.set(e,{d:[],m:[]}),this.#p.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#f.get(e);if(n){this.#f.delete(e);for(var r of n.d)M(r,v),t(r);for(r of n.m)M(r,y),t(r)}this.#p.add(e)}#g(){this.#e=!0,Mt++>1e3&&(this.#x(),It());for(let e of this.#u)this.#d.delete(e),M(e,v),this.schedule(e);for(let e of this.#d)M(e,y),this.schedule(e);let t=this.#c;this.#c=[],this.apply();var n=At=[],r=[],i=jt=[];for(let e of t)try{this.#_(e,n,r)}catch(t){throw Vt(e),this.#h()||this.discard(),t}if(P=null,i.length>0){var a=e.ensure();for(let e of i)a.schedule(e)}if(At=null,jt=null,this.#h()){this.#b(r),this.#b(n);for(let[e,t]of this.#f)Bt(e,t);i.length>0&&P.#g();return}let o=this.#v();if(o){this.#b(r),this.#b(n),o.#y(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),Tt=this,Rt(r),Rt(n),Tt=null,this.#s?.resolve();var s=P;if(this.#a===0&&(this.#c.length===0||s!==null)&&this.#x(),this.#c.length>0){if(s!==null){let e=s;e.#c.push(...this.#c.filter(t=>!e.#c.includes(t)))}else s=this}s!==null&&(Ut.clear(),s.#g())}#_(e,t,n){e.f^=_;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#f.has(r))&&r.fn!==null){a?r.f^=_:i&4?t.push(r):ir(r)&&(i&16&&this.#d.add(r),ur(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#v(){for(var e=this.#t;e!==null;){if(!e.is_fork){for(let[t,[,n]]of this.current)if(e.current.has(t)&&!n)return e}e=e.#t}return null}#y(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_effects(e.#u,e.#d);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#d.delete(i),M(i,v),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#x(),P=this,this.#g()}#b(e){for(var t=0;t{this.#m=!1,this.linked&&this.flush()}))}transfer_effects(e,t){for(let t of e)this.#u.add(t);for(let e of t)this.#d.add(e);e.clear(),t.clear()}oncommit(e){this.#r.add(e)}ondiscard(e){this.#i.add(e)}settled(){return(this.#s??=m()).promise}static ensure(){if(P===null){let t=P=new e;!kt&&!Ot&&Qe(()=>{t.#e||t.flush()})}return P}apply(){Et=null}schedule(e){if(Dt=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}for(var t=e;t.parent!==null;){t=t.parent;var n=t.f;if(At!==null&&t===U&&(H===null||!(H.f&2)))return;if(n&96){if(!(n&1024))return;t.f^=_}}this.#c.push(t)}#x(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?wt=e:t.#t=e,this.linked=!1}}};function Ft(e){var t=Ot;Ot=!0;try{var n;for(e&&(P!==null&&!P.is_fork&&P.flush(),n=e());;){if($e(),P===null)return n;P.flush()}}finally{Ot=t}}function It(){try{Le()}catch(e){hn(e,Dt)}}var Lt=null;function Rt(e){var t=e.length;if(t!==0){for(var n=0;n0)){Ut.clear();for(let e of Lt){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Lt.has(n)&&(Lt.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||ur(n)}}Lt.clear()}}Lt=null}}function zt(e){P.schedule(e)}function Bt(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),M(e,_);for(var n=e.first;n!==null;)Bt(n,t),n=n.next}}function Vt(e){M(e,_);for(var t=e.first;t!==null;)Vt(t),t=t.next}var Ht=new Set,Ut=new Map,Wt=!1;function Gt(e,t){return{f:0,v:e,reactions:null,equals:Oe,rv:0,wv:0}}function F(e,t){let n=Gt(e,t);return Jn(n),n}function Kt(e,t=!1,n=!0){let r=Gt(e);return t||(r.equals=Ae),Ue&&n&&j!==null&&j.l!==null&&(j.l.s??=[]).push(r),r}function I(e,t,n=!1){return H!==null&&(!Wn||H.f&131072)&&Ye()&&H.f&4325394&&(qn===null||!qn.has(e))&&Ve(),qt(e,n?Qt(t):t,jt)}function qt(e,t,n=null){if(!e.equals(t)){Hn?Ut.set(e,t):Ut.has(e)||Ut.set(e,e.v);var r=Pt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&bt(t),Et===null&&tt(t)}e.wv=rr(),Zt(e,v,n),Ye()&&U!==null&&U.f&1024&&!(U.f&96)&&(Zn===null?Qn([e]):Zn.push(e)),!r.is_fork&&Ht.size>0&&!Wt&&Jt()}return t}function Jt(){Wt=!1;for(let e of Ht){e.f&1024&&M(e,y);let t;try{t=ir(e)}catch{t=!0}t&&ur(e)}Ht.clear()}function Yt(e,t=1){var n=W(e),r=t===1?n++:n--;return I(e,n),r}function Xt(e){I(e,e.v+1)}function Zt(e,t,n){var r=e.reactions;if(r!==null)for(var i=Ye(),a=r.length,o=0;o{if(tr===d)return e();var t=H,n=tr;Gn(null),nr(d);var r=e();return Gn(t),nr(n),r};return i&&r.set(`length`,F(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&ze();var i=r.get(t);return i===void 0?f(()=>{var e=F(n.value,u);return r.set(t,e),e}):I(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>F(ge,u));r.set(t,e),Xt(o)}}else I(n,ge),Xt(o);return!0},get(e,n,i){if(n===ie)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>F(Qt(s?e[n]:ge),u)),r.set(n,o)),o!==void 0){var c=W(o);return c===ge?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){var n=Reflect.getOwnPropertyDescriptor(e,t);if(n&&`value`in n){var i=r.get(t);i&&(n.value=W(i))}else if(n===void 0){var a=r.get(t),o=a?.v;if(a!==void 0&&o!==ge)return{enumerable:!0,configurable:!0,value:o,writable:!0}}return n},has(e,t){if(t===ie)return!0;var n=r.get(t),i=n!==void 0&&n.v!==ge||Reflect.has(e,t);return(n!==void 0||U!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>F(i?Qt(e[t]):ge,u)),r.set(t,n)),W(n)===ge)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dF(ge,u)),r.set(d+``,p)):I(p,ge)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>F(void 0,u)),I(c,Qt(n)),r.set(t,c));else{l=c.v!==ge;var m=f(()=>Qt(n));I(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&I(g,_+1)}Xt(o)}return!0},ownKeys(e){W(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==ge});for(var[n,i]of r)i.v!==ge&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Be()}})}function $t(e){try{if(typeof e==`object`&&e&&ie in e)return e[ie]}catch{}return e}function en(e,t){return Object.is($t(e),$t(t))}var tn,nn,rn,an;function on(){if(tn===void 0){tn=window,nn=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;rn=a(t,`firstChild`).get,an=a(t,`nextSibling`).get,u(e)&&(e[le]=void 0,e[ce]=null,e[ue]=void 0,e.__e=void 0),u(n)&&(n[de]=void 0)}}function sn(e=``){return document.createTextNode(e)}function cn(e){return rn.call(e)}function ln(e){return an.call(e)}function L(e,t){if(!O)return cn(e);var n=cn(k);if(n===null)n=k.appendChild(sn());else if(t&&n.nodeType!==3){var r=sn();return n?.before(r),Ce(r),r}return t&&pn(n),Ce(n),n}function R(e,t=!1){if(!O){var n=cn(e);return n instanceof Comment&&n.data===``?ln(n):n}if(t){if(k?.nodeType!==3){var r=sn();return k?.before(r),Ce(r),r}pn(k)}return k}function z(e,t=!1){if(!O)return cn(e);var n=L(e,t);return A(e),n}function B(e,t=1,n=!1){let r=O?k:e;for(var i;t--;)i=r,r=ln(r);if(!O)return r;if(n){if(r?.nodeType!==3){var a=sn();return r===null?i?.after(a):r.before(a),Ce(a),a}pn(r)}return Ce(r),r}function un(e){e.textContent=``}function dn(){return!1}function fn(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function pn(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function mn(e){var t=U;if(t===null)return H.f|=re,e;if(!(t.f&32768)&&!(t.f&4))throw e;hn(e,t)}function hn(e,t){if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128&&!(t.f&33570816)){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}function gn(e){U===null&&(H===null&&Ie(e),Fe()),Hn&&Pe(e)}function _n(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function vn(e,t){var n=U;n!==null&&n.f&8192&&(e|=b);var r={ctx:j,deps:null,nodes:null,f:e|v|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};P?.register_created_effect(r);var i=r;if(e&4)At===null?Pt.ensure().schedule(r):At.push(r);else if(t!==null){try{ur(r)}catch(e){throw Mn(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=w))}if(i!==null&&(i.parent=n,n!==null&&_n(i,n),H!==null&&H.f&2&&!(e&64))){var a=H;(a.effects??=[]).push(i)}return r}function yn(){return H!==null&&!Wn}function bn(e){let t=vn(8,null);return M(t,_),t.teardown=e,t}function xn(e){gn(`$effect`);var t=U.f;if(!H&&t&32&&j!==null&&!j.i){var n=j;(n.e??=[]).push(e)}else return Sn(e)}function Sn(e){return vn(4|E,e)}function Cn(e){Pt.ensure();let t=vn(64|T,e);return(e={})=>new Promise(n=>{e.outro?Fn(t,()=>{Mn(t),n(void 0)}):(Mn(t),n(void 0))})}function wn(e){return vn(4,e)}function Tn(e){return vn(ne|T,e)}function En(e,t=0){return vn(8|t,e)}function V(e,t=[],n=[],r=[]){dt(r,t,n,t=>{vn(8,()=>{e(...t.map(W))})})}function Dn(e,t=0){return vn(16|t,e)}function On(e){return vn(32|T,e)}function kn(e){var t=e.teardown;if(t!==null){let n=Hn,r=H;Un(!0),Gn(null);try{t.call(null)}catch(t){hn(t,e.parent)}finally{Un(n),Gn(r)}}}function An(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&<(()=>{e.abort(pe)});var r=n.next;n.f&64?n.parent=null:Mn(n,t),n=r}}function jn(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||Mn(t),t=n}}function Mn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Nn(e.nodes.start,e.nodes.end),n=!0),e.f|=C,An(e,t&&!n),lr(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();kn(e),e.f^=C,e.f|=x;var i=e.parent;i!==null&&i.first!==null&&Pn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Nn(e,t){for(;e!==null;){var n=e===t?null:ln(e);e.remove(),e=n}}function Pn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function Fn(e,t,n=!0){var r=[];e.f|=256,In(e,r,!0);var i=()=>{n&&Mn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function In(e,t,n){if(!(e.f&8192)){e.f^=b;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);In(i,t,o?n:!1)}i=a}}}function Ln(e){e.f&=-257,Rn(e,!0)}function Rn(e,t){if(!(e.f&256)&&e.f&8192){e.f^=b,e.f&1024||(M(e,v),Pt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Rn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function zn(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:ln(n);t.append(n),n=i}}var Bn=null,Vn=!1,Hn=!1;function Un(e){Hn=e}var H=null,Wn=!1;function Gn(e){H=e}var U=null;function Kn(e){U=e}var qn=null;function Jn(e){H!==null&&(qn??=new Set).add(e)}var Yn=null,Xn=0,Zn=null;function Qn(e){Zn=e}var $n=1,er=0,tr=er;function nr(e){tr=e}function rr(){return++$n}function ir(e){var t=e.f;if(t&2048)return!0;if(t&2&&(e.f&=~D),t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&&Et===null&&M(e,_)}return!1}function ar(e,t,n=!0){var r=e.reactions;if(r!==null&&!(qn!==null&&qn.has(e)))for(var i=0;i{e.ac.abort(pe)}),e.ac=null);try{e.f|=te;var u=e.fn,d=u();e.f|=S;var f=sr(e);if(Ye()&&Zn!==null&&!Wn&&f!==null&&!(e.f&6146))for(var p=0;p0)for(t.length=Xn+Yn.length,r=0;r{s.ac.abort(pe),s.ac=null,M(s,v)}),St(s),lr(s,0)}}function lr(e,t){var n=e.deps;if(n!==null)for(var r=t;rn?.call(this,e))}return e.startsWith(`pointer`)||e.startsWith(`touch`)||e===`wheel`?Qe(()=>{t.addEventListener(e,i,r)}):t.addEventListener(e,i,r),i}function xr(e,t,n,r,i){var a={capture:r,passive:i},o=br(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&bn(()=>{t.removeEventListener(e,o,a)})}function Sr(e,t,n){(t[_r]??={})[e]=n}function Cr(e){for(var t=0;t{Tr=!1,wr=null}));var s=0,c=wr===e&&e[_r];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[_r]=t;return}var u=a.indexOf(t);if(u===-1)return;l<=u&&(s=l)}if(o=a[s]||e.target,o!==t){i(e,`currentTarget`,{configurable:!0,get(){return o||n}});var d=H,f=U;Gn(null),Kn(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[_r]?.[r];h!=null&&(!o.disabled||e.target===o)&&h.call(o,e)}catch(e){p?m.push(e):p=e}if(e.cancelBubble)break;s++,o=s{throw e});throw p}}finally{e[_r]=t,delete e.currentTarget,Gn(d),Kn(f)}}}var Dr=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function Or(e){return Dr?.createHTML(e)??e}function kr(e){var t=fn(`template`);return t.innerHTML=Or(e.replaceAll(``,``)),t.content}function Ar(e,t){var n=U;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function G(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(O)return Ar(k,null),k;i===void 0&&(i=kr(a?e:``+e),n||(i=cn(i)));var t=r||nn?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=cn(t),s=t.lastChild;Ar(o,s)}else Ar(t,t);return t}}function jr(e,t,n=`svg`){var r=!e.startsWith(``),i=!!(t&1),a=`<${n}>${r?e:``+e}`,o;return()=>{if(O)return Ar(k,null),k;if(!o){var e=cn(kr(a));if(i)for(o=document.createDocumentFragment();cn(e);)o.appendChild(cn(e));else o=cn(e)}var t=o.cloneNode(!0);if(i){var n=cn(t),r=t.lastChild;Ar(n,r)}else Ar(t,t);return t}}function Mr(e,t){return jr(e,t,`svg`)}function Nr(e=``){if(!O){var t=sn(e+``);return Ar(t,t),t}var n=k;return n.nodeType===3?pn(n):(n.before(n=sn()),Ce(n)),Ar(n,n),n}function Pr(){if(O)return Ar(k,null),k;var e=document.createDocumentFragment(),t=document.createComment(``),n=sn();return e.append(t,n),Ar(t,n),e}function K(e,t){if(O){var n=U;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=k),we();return}e!==null&&e.before(t)}function Fr(){if(O&&k&&k.nodeType===8&&k.textContent?.startsWith(`$`)){let e=k.textContent.substring(1);return we(),e}return(window.__svelte??={}).uid??=1,`c${window.__svelte.uid++}`}function Ir(e){let t=0,n=Gt(0),r;return()=>{yn()&&(W(n),En(()=>(t===0&&(r=mr(()=>e(()=>Xt(n)))),t+=1,()=>{Qe(()=>{--t,t===0&&(r?.(),r=void 0,Xt(n))})})))}}var Lr=w|T;function Rr(e,t,n,r){new zr(e,t,n,r)}var zr=class{parent;is_pending=!1;transform_error;#e;#t=O?k:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Set;#p=new Set;#m=null;#h=Ir(()=>(this.#m=Gt(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=U;t.b=this,t.f|=128,n(e)},this.parent=U.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=Dn(()=>{if(O){let e=this.#t;we();let t=e.data===`[!`;if(e.data.startsWith(`[?`)){let t=JSON.parse(e.data.slice(2));this.#_(t)}else t?this.#y():this.#g()}else this.#b()},Lr),O&&(this.#e=k)}#g(){try{this.#a=On(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Qe(r),t&&(this.#s=On(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){xe();return}t=!0,n&&He(),this.#s!==null&&Fn(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})};return{reset:r,invoke_onerror:()=>{try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){hn(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=On(()=>e(this.#e)),Qe(()=>{var e=this.#c=document.createDocumentFragment(),t=sn(),n=!1;if(e.append(t),this.#a=this.#S(()=>{try{return On(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){hn(e,this.#i.parent)}return null}}),this.#a===null){this.#c=null,n&&this.#x(P);return}this.#u===0&&(this.#e.before(e),this.#c=null,Fn(this.#o,()=>{this.#o=null}),this.#x(P))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=On(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();zn(this.#a,e);let t=this.#n.pending;this.#o=On(()=>t(this.#e))}else this.#x(P)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){rt(e,this.#f,this.#p)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=U,n=H,r=j;Kn(this.#i),Gn(this.#i),Ge(this.#i.ctx);try{return Pt.ensure(),e()}finally{Kn(t),Gn(n),Ge(r)}}#C(e,t){if(!this.has_pending_snippet()){this.parent&&this.parent.#C(e,t);return}this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&Fn(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!(!this.#m||this.#d)&&(this.#d=!0,Qe(()=>{this.#d=!1,this.#m&&qt(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),W(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;P?.is_fork?(this.#a&&P.skip_effect(this.#a),this.#o&&P.skip_effect(this.#o),this.#s&&P.skip_effect(this.#s),P.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(Mn(this.#a),null),this.#o&&=(Mn(this.#o),null),this.#s&&=(Mn(this.#s),null),O&&(Ce(this.#t),Te(),Ce(Ee()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return On(()=>{var r=U;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return hn(e,this.#i.parent),null}}))};Qe(()=>{var t;try{t=this.transform_error(e)}catch(e){hn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>hn(e,this.#i&&this.#i.parent)):n(t)})}};function q(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[de]??=e.nodeValue)&&(e[de]=n,e.nodeValue=`${n}`)}function Br(e,t){return Hr(e,t)}var Vr=new Map;function Hr(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){on();var l=void 0,u=Cn(()=>{var s=n??t.appendChild(sn());Rr(s,{pending:()=>{}},t=>{Ke({});var n=j;if(o&&(n.c=o),a&&(i.$$events=a),O&&Ar(t,null),l=e(t,i)||Je(),O&&(U.nodes.end=k,k===null||k.nodeType!==8||k.data!==`]`))throw ye(),he;qe()},c);var u=new Set,d=e=>{for(var n=0;n{for(var e of u)for(let n of[t,document]){var r=Vr.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,Er),r.delete(e),r.size===0&&Vr.delete(n)):r.set(e,i)}yr.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return Ur.set(l,u),l}var Ur=new WeakMap,Wr=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)Ln(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(Ln(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(Mn(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();zn(r,t),t.append(sn()),this.#n.set(e,{effect:r,fragment:t})}else Mn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),Fn(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(Mn(n.effect),this.#n.delete(e))};ensure(e,t){var n=P,r=dn();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=sn();i.append(a),this.#n.set(e,{effect:On(()=>t(a)),fragment:i})}else this.#t.set(e,On(()=>t(this.anchor)))}if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else O&&(this.anchor=k),this.#a(n)}};function J(e,t,n=!1){var r;O&&(r=k,we());var i=new Wr(e),a=n?w:0;function o(e,t){if(O){var n=De(r);if(e!==parseInt(n.substring(1))){var a=Ee();Ce(a),i.anchor=a,Se(!1),i.ensure(e,t),Se(!0);return}}i.ensure(e,t)}Dn(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}var Gr=Symbol(`NaN`);function Kr(e,t,n){O&&we();var r=new Wr(e),i=!Ye();Dn(()=>{var e=t();e!==e&&(e=Gr),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function Y(e,t){return t}function qr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;Jr(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null&&e.pending.size===0;if(l){var u=n,d=u.parentNode;un(d),d.append(u),e.items.clear()}Jr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Jr(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i{var t=i();return e(t)?t:t==null?[]:r(t)}),p,m=new Map,h=!0;function g(e){v.effect.f&16384||(v.pending.delete(e),v.fallback=d,Zr(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=ee,$r(d,null,c)):Ln(d):Fn(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:Dn(()=>{p=W(f);var e=p.length;let t=!1;O&&De(c)===`[!`!=(e===0)&&(c=Ee(),Ce(c),Se(!1),t=!0);for(var r=new Set,u=P,v=dn(),y=0;ys(c)):(d=On(()=>s(Yr??=sn())),d.f|=ee)),e>r.size&&Ne(``,``,``),O&&e>0&&Ce(Ee()),!h){if(m.set(u,r),v){for(let[e,t]of l)r.has(e)||u.skip_effect(t.e);u.oncommit(g),u.ondiscard(_)}else g(u)}t&&Se(!0),W(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,O&&(c=k)}function Xr(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function Zr(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=Xr(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v0){var E=i&4&&s===0?n:null;if(o){for(v=0;v{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function Qr(e,t,n,r,i,a,o,s){var c=o&1?o&16?Gt(n):Kt(n,!1,!1):null,l=o&2?Gt(i):null;return{v:c,i:l,e:On(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function $r(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=ln(r);if(a.before(r),r===i)return;r=o}}function ei(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function ti(e,t,n){var r;O&&(r=k,we());var i=new Wr(e);Dn(()=>{var e=t()??null;if(O&&De(r)===`[`!=(e!==null)){var a=Ee();Ce(a),i.anchor=a,Se(!1),i.ensure(e,e&&(t=>n(t,e))),Se(!0);return}i.ensure(e,e&&(t=>n(t,e)))},w)}var ni=[...` +\r\f\xA0\v`];function ri(e,t,n){var r=e==null?``:``+e;if(t&&(r=r?r+` `+t:t),n){for(var i of Object.keys(n))if(n[i])r=r?r+` `+i:i;else if(r.length)for(var a=i.length,o=0;(o=r.indexOf(i,o))>=0;){var s=o+a;(o===0||ni.includes(r[o-1]))&&(s===r.length||ni.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function ii(e,t=!1){var n=t?` !important;`:`;`,r=``;for(var i of Object.keys(e)){var a=e[i];a!=null&&a!==``&&(r+=` `+i+`: `+a+n)}return r}function ai(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function oi(e,t){if(t){var n=``,r,i;if(Array.isArray(t)?(r=t[0],i=t[1]):r=t,e){e=String(e).replaceAll(/\/\*.*?\*\//g,``).trim();var a=!1,o=0,s=!1,c=[];r&&c.push(...Object.keys(r).map(ai)),i&&c.push(...Object.keys(i).map(ai));var l=0,u=-1;let t=e.length;for(var d=0;d{t.every(gi)||(`__defaultValue`in e&&di(e,!1),`__value`in e&&fi(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),bn(()=>{t.disconnect()})}function mi(e,t,n=t){var r=new WeakSet,i=!0;ut(e,`change`,t=>{var i=t?`[selected]`:`:checked`,a;if(e.multiple)a=[].map.call(e.querySelectorAll(i),hi);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&hi(o)}n(a),e.__value=a,P!==null&&r.add(P)}),wn(()=>{var a=t();if(e===document.activeElement){var o=P;if(r.has(o))return}if(fi(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=hi(s),n(a))}e.__value=a,i=!1})}function hi(e){return`__value`in e?e.__value:e.value}function gi(e){if(e.target.closest(`selectedcontent`)!==null)return!0;if(e.type===`childList`){var t=[...e.addedNodes,...e.removedNodes];return t.length>0&&t.every(e=>e.nodeName===`SELECTEDCONTENT`)}return!1}var _i=Symbol(`is custom element`),vi=Symbol(`is html`),yi=me?`link`:`LINK`;function bi(e){if(O){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;Z(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;Z(e,`checked`,null),e.checked=r}}};e[fe]=n,Qe(n),ct()}}function Z(e,t,n,r){var i=xi(e);O&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===yi)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[se]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Ci(e).has(t)?e[t]=n:e.setAttribute(t,n))}function xi(e){return e[ce]??={[_i]:e.nodeName.includes(`-`),[vi]:e.namespaceURI===_e}}var Si=new Map;function Ci(e){var t=e.getAttribute(`is`)||e.nodeName,n=Si.get(t);if(n)return n;Si.set(t,n=new Set);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.add(s);i=l(i)}return n}function wi(e,t,n=t){var r=new WeakSet;ut(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=Oi(e)?ki(a):a,n(a),P!==null&&r.add(P),await dr(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(O&&e.defaultValue!==e.value||mr(t)==null&&e.value)&&(n(Oi(e)?ki(e.value):e.value),P!==null&&r.add(P)),En(()=>{var n=t();if(e===document.activeElement){var i=P;if(r.has(i))return}Oi(e)&&n===ki(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}var Ti=new Set;function Ei(e,t,n,r,i=r){var a=n.getAttribute(`type`)===`checkbox`,o=e;let s=!1;if(t!==null)for(var c of t)o=o[c]??=[];o.push(n),ut(n,`change`,()=>{var e=n.__value;a&&(e=Di(o,e,n.checked)),i(e)},()=>i(a?[]:null)),En(()=>{var e=r();if(O&&n.defaultChecked!==n.checked){s=!0;return}a?(e||=[],n.checked=e.includes(n.__value)):n.checked=en(n.__value,e)}),bn(()=>{var e=o.indexOf(n);e!==-1&&o.splice(e,1)}),Ti.has(o)||(Ti.add(o),Qe(()=>{o.sort((e,t)=>e.compareDocumentPosition(t)===4?-1:1),Ti.delete(o)})),Qe(()=>{if(s){var e=a?Di(o,e,n.checked):o.find(e=>e.checked)?.__value;i(e)}})}function Di(e,t,n){for(var r=new Set,i=0;i{var n=this.#e.get(e);n.delete(t),n.size===0&&(this.#e.delete(e),this.#t.unobserve(e))}}#r(){return this.#t??=new ResizeObserver(t=>{for(var n of t){e.entries.set(n.target,n);for(var r of this.#e.get(n.target)||[])r(n)}})}}({box:`border-box`});function ji(e,t,n){var r=Ai.observe(e,()=>n(e[t]));wn(()=>(mr(()=>n(e[t])),r))}function Mi(e,t,n,r,i){var a=()=>{r(n[e])};n.addEventListener(t,a),i?En(()=>{n[e]=i()}):a(),(n===document.body||n===window||n===document)&&bn(()=>{n.removeEventListener(t,a)})}var Ni={get(e,t){let n=e.props.length;for(;n--;){let r=e.props[n];if(d(r)&&(r=r()),typeof r==`object`&&r&&t in r)return r[t]}},set(e,t,n){let r=e.props.length;for(;r--;){let i=e.props[r];d(i)&&(i=i());let o=a(i,t);if(o&&o.set)return o.set(n),!0}return!1},getOwnPropertyDescriptor(e,t){let n=e.props.length;for(;n--;){let r=e.props[n];if(d(r)&&(r=r()),typeof r==`object`&&r&&t in r){let e=a(r,t);return e&&!e.configurable&&(e.configurable=!0),e}}},has(e,t){if(t===ie||t===oe)return!1;for(let n of e.props)if(d(n)&&(n=n()),n!=null&&t in n)return!0;return!1},ownKeys(e){let t=[];for(let n of e.props)if(d(n)&&(n=n()),n){for(let e in n)t.includes(e)||t.push(e);for(let e of Object.getOwnPropertySymbols(n))t.includes(e)||t.push(e)}return t}};function Pi(...e){return new Proxy({props:e},Ni)}function Fi(e,t,n,r){var i=!Ue||!!(n&2),o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=ht(r),W(u)):(l&&(l=!1,c=s?mr(r):r),c);let f;if(o){var p=ie in e||oe in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=at(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&Re(t),f(m)));var g=i?()=>{var n=e[t];return n===void 0?d():(l=!0,n)}:()=>{var n=e[t];return n!==void 0&&(c=void 0),n===void 0?c:n};if(i&&!(n&4))return g;if(f){var _=e.$$legacy;return(function(e,t){return arguments.length>0?((!i||!t||_||h)&&f(t?g():e),e):g()})}var v=!1,y=(n&1?ht:vt)(()=>(v=!1,g()));o&&W(y);var b=U;return(function(e,t){if(arguments.length>0){let n=t?W(y):i&&o?Qt(e):e;return I(y,n),v=!0,c!==void 0&&(c=n),e}return Hn&&v||b.f&16384?y.v:W(y)})}function Ii(e){j===null&&je(`onMount`),Ue&&j.l!==null?Li(j).m.push(e):xn(()=>{let t=mr(e);if(typeof t==`function`)return t})}function Li(e){var t=e.l;return t.u??={a:[],b:[],m:[]}}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);function Ri(e,t){if(e instanceof RegExp)return{keys:!1,pattern:e};var n,r,i,a,o=[],s=``,c=e.split(`/`);for(c[0]||c.shift();i=c.shift();)n=i[0],n===`*`?(o.push(`wild`),s+=`/(.*)`):n===`:`?(r=i.indexOf(`?`,1),a=i.indexOf(`.`,1),o.push(i.substring(1,~r?r:~a?a:i.length)),s+=~r&&!~a?`(?:/([^/]+?))?`:`/([^/]+?)`,~a&&(s+=(~r?`?`:``)+`\\`+i.substring(a))):s+=`/`+i;return{keys:o,pattern:RegExp(`^`+s+(t?`(?=$|/)`:`/?$`),`i`)}}var zi=new class{#e=F(Bi());get _loc(){return W(this.#e)}set _loc(e){I(this.#e,e)}#t=N(()=>this._loc.location);get _location(){return W(this.#t)}set _location(e){I(this.#t,e)}#n=N(()=>this._loc.querystring);get _querystring(){return W(this.#n)}set _querystring(e){I(this.#n,e)}#r=F(void 0);get _params(){return W(this.#r)}set _params(e){I(this.#r,e)}get loc(){return this._loc}get location(){return this._location}get querystring(){return this._querystring}get params(){return this._params}constructor(){typeof window<`u`?window.addEventListener(`hashchange`,()=>{this._loc=Bi()}):console.warn(`[svelte-spa-router] window 'window' is not defined, skipping initiation`)}};function Bi(){let e=typeof window<`u`?window.location.href:``,t=e.indexOf(`#/`),n=t>-1?e.substr(t+1):`/`,r=n.indexOf(`?`),i=``;return r>-1&&(i=n.substr(r+1),n=n.substr(0,r)),{location:n,querystring:i}}function Vi(e){e?window.scrollTo(e.__svelte_spa_router_scrollX||0,e.__svelte_spa_router_scrollY||0):window.scrollTo(0,0)}function Hi(e,t){Ke(t,!0);let n=Fi(t,`routes`,19,()=>({})),r=Fi(t,`prefix`,3,``),i=Fi(t,`restoreScrollState`,3,!1),a=Fi(t,`onConditionsFailed`,3,()=>{}),o=Fi(t,`onRouteLoaded`,3,()=>{}),s=Fi(t,`onRouteLoading`,3,()=>{}),c=Fi(t,`onRouteEvent`,3,()=>{});class l{path;component;conditions;userData;props;_pattern;_keys;constructor(e,t){let n=e=>typeof e==`object`&&!!e&&e._sveltesparouter===!0;if(!t||typeof t!=`function`&&!n(t))throw Error(`Invalid component object`);if(!e||typeof e==`string`&&(e.length<1||e.charAt(0)!=`/`&&e.charAt(0)!=`*`)||typeof e==`object`&&!(e instanceof RegExp))throw Error(`Invalid value for "path" argument - strings must start with / or *`);let r=Ri(e);if(this.path=e,n(t)){let e=t;this.component=e.component,this.conditions=e.conditions||[],this.userData=e.userData,this.props=e.props||{}}else{let e=t;this.component=()=>Promise.resolve(e),this.conditions=[],this.props={}}this._pattern=r.pattern,this._keys=r.keys}match(e){if(r()){if(typeof r()==`string`){if(e.startsWith(r()))e=e.substr(r().length)||`/`;else return null}else if(r()instanceof RegExp){let t=e.match(r());if(t&&t[0])e=e.substr(t[0].length)||`/`;else return null}}let t=this._pattern.exec(e);if(t===null)return null;if(this._keys===!1)return t;let n={},i=0;for(;i{u.push(new l(t,e))}):Object.keys(n()).forEach(e=>{let t=n();u.push(new l(e,t[e]))});let d=F(null),f=F(null),p=F({}),m=null,h=null;xn(()=>{history.scrollRestoration=i()?`manual`:`auto`}),xn(()=>{if(!i())return;let e=e=>{m=e.state&&(e.state.__svelte_spa_router_scrollY||e.state.__svelte_spa_router_scrollX)?e.state:null};return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)});async function g(e,t){await dr(),e(t)}xn(()=>{let e=zi.loc,t=!1;return mr(async()=>{let n=0;for(;n{t=!0}});function _(e){return e&&typeof e==`object`&&Object.keys(e).length?e:null}var v=Pr(),y=R(v),b=e=>{let t=N(()=>W(d));var n=Pr(),r=R(n),i=e=>{var n=Pr();ti(R(n),()=>W(t),(e,t)=>{t(e,Pi({get params(){return W(f)},get onRouteEvent(){return c()}},()=>W(p)))}),K(e,n)},a=e=>{var n=Pr();ti(R(n),()=>W(t),(e,t)=>{t(e,Pi({get onRouteEvent(){return c()}},()=>W(p)))}),K(e,n)};J(r,e=>{W(f)?e(i):e(a,-1)}),K(e,n)};J(y,e=>{W(d)&&e(b)}),K(e,v),qe()}var Ui=[`bars`,`pace`,`zone`,`pie`,`fuel`,`resets`],Wi=`codexometer.web.preferences.v1`,Gi={tab:`quota`,view:`bars`,selected:``,defaultDetail:0,layouts:[]};function Ki(){try{let e=JSON.parse(localStorage.getItem(Wi)||`null`);return!e||typeof e!=`object`?Gi:{tab:[`quota`,`sessions`,`usage`].includes(e.tab)?e.tab:`quota`,view:Ui.includes(e.view)?e.view:`bars`,selected:typeof e.selected==`string`?e.selected.slice(0,256):``,defaultDetail:+(e.defaultDetail===1),layouts:Array.isArray(e.layouts)?e.layouts.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.id==`string`&&t.id.length<=256&&[0,1,2].includes(t.level)}).slice(-100):[]}}catch{return Gi}}var qi=Qt(Ki());function Ji(){let e=JSON.stringify(qi);try{localStorage.setItem(Wi,e)}catch{}}function Yi(){return qi.tab===`quota`?`/quota/`+qi.view:`/`+qi.tab}function Xi(e){return qi.layouts.find(t=>t.id===e)?.level??qi.defaultDetail}function Zi(e){qi.defaultDetail=e,qi.layouts=[]}function Qi(e,t){qi.layouts=[...qi.layouts.filter(t=>t.id!==e),{id:e,level:Math.max(0,Math.min(2,t))}].slice(-100)}var Q=Qt({data:null,connected:!1,error:``}),$=e=>e==null?`Unavailable`:e.toLocaleString(`en-GB`),$i=e=>!e||String(e).startsWith(`0001-`)?`Not yet available`:new Date(typeof e==`number`?e*1e3:e).toLocaleString(`en-GB`),ea=`codexometer.web.session`,ta=class extends Error{},na;async function ra(e,t,n){if(!na||!Q.connected||!Q.data?.control||Q.data.sessionsError)throw Error(`Session controls unavailable. Check the live connection.`);return await na(e,t,n)}function ia(){let e=new AbortController,t,n=``;na=async(t,r,i)=>{let a=await fetch(`/api/control/`+t,{method:`POST`,headers:{Authorization:`Bearer ${n}`,"Content-Type":`application/json`},body:JSON.stringify(r),signal:AbortSignal.any([e.signal,AbortSignal.timeout(8e3),...i?[i]:[]]),cache:`no-store`});if(!a.ok)throw a.status===502?Error(`Outcome uncertain. Check Codex before taking another action; nothing was retried.`):new ta(`Action rejected, expired or changed. Refresh and check Codex; nothing was retried.`);return a.json()};try{n=sessionStorage.getItem(ea)||``}catch{}let r=location.hash,i=r.startsWith(`#pair=`)?r.slice(6):``;(i||!r||r===`#`)&&(history.replaceState(null,``,`/#`+Yi()),window.dispatchEvent(new HashChangeEvent(`hashchange`)));async function a(){if(i)try{let t=await fetch(`/api/pair`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({secret:i}),signal:e.signal});if(!t.ok)throw Error(`Pairing link expired or already used. Restart --web for a fresh link.`);n=(await t.json()).token;try{sessionStorage.setItem(ea,n)}catch{}}catch(t){e.signal.aborted||(Q.error=t instanceof Error?t.message:`Pairing failed`);return}if(!n){Q.error=`Open the private pairing link printed by codexometer --web in your terminal.`;return}await o()}async function o(){try{let t=await fetch(`/api/events`,{headers:{Authorization:`Bearer ${n}`},signal:e.signal,cache:`no-store`});if(t.status===401){try{sessionStorage.removeItem(ea)}catch{}Q.error=`Browser session expired. Restart --web and open its new pairing link.`;return}if(!t.ok||!t.body)throw Error(`Live connection unavailable`);let r=t.body.getReader(),i=new TextDecoder,a=``;for(;!e.signal.aborted;){let{done:e,value:t}=await r.read();if(e)break;a+=i.decode(t,{stream:!0});let n;for(;(n=a.indexOf(` + +`))>=0;){let e=a.slice(0,n);a=a.slice(n+2),e.startsWith(`data: `)&&(Q.data=JSON.parse(e.slice(6)),Q.connected=!0,Q.error=``)}}}catch{}finally{Q.connected=!1}e.signal.aborted||(Q.error=`Connection lost — showing last observation. Reconnecting…`,t=setTimeout(o,2500))}return a(),()=>{na=void 0,e.abort(),clearTimeout(t),Q.connected=!1}}var aa=Mr(` `,1),oa=Mr(` `,1),sa=G(` `),ca=G(`
Quota observations
Observed atPeriod elapsedConsumedTrail segment
`),la=G(`


Observed quota + path, not individual session usage. Gaps are not interpolated. Expand the + observation table for times, positions and gaps.

OBSERVATION TABLE
`,1),ua=G(`
CONSUMPTIONQUOTA PERIOD ELAPSED


`,1);function da(e,t){let n=Fr();Ke(t,!0);let r=Fi(t,`trail`,19,()=>[]),i=F(!1),a=[0,25,50,75,100],o=F(400),s=F(240),c=N(()=>W(o)-24),l=N(()=>W(s)-48),u=N(()=>Math.max(1,W(c)-48)),d=N(()=>Math.max(1,W(l)-20)),f=N(()=>48+Math.max(0,Math.min(100,t.elapsed))/100*W(u)),p=N(()=>W(l)-Math.max(0,Math.min(100,t.used))/100*W(d)),m=N(()=>t.used-t.elapsed),h=N(()=>r().map((e,t)=>`${t===0||e.break?`M`:`L`}${48+e.elapsed/100*W(u)} ${W(l)-e.used/100*W(d)}`).join(` `));var g=ua(),_=R(g),v=L(_),y=L(v),b=z(y),x=B(y),S=B(x);X(S,17,()=>a,Y,(e,t)=>{var n=aa(),r=R(n),i=B(r),a=B(i),o=z(a),s=B(a),f=z(s);V(()=>{Z(r,`x1`,48+W(t)/100*W(u)),Z(r,`x2`,48+W(t)/100*W(u)),Z(r,`y2`,W(l)),Z(i,`y1`,W(l)-W(t)/100*W(d)),Z(i,`x2`,W(c)),Z(i,`y2`,W(l)-W(t)/100*W(d)),Z(a,`x`,48+W(t)/100*W(u)),Z(a,`y`,W(l)+20),q(o,`${W(t)??``}%`),Z(s,`y`,W(l)+4-W(t)/100*W(d)),q(f,`${W(t)??``}%`)}),K(e,n)});var C=B(S),w=B(C),T=B(w),E=e=>{var t=oa(),n=R(t),i=B(n),a=z(L(i));A(i),V(e=>{Z(n,`d`,W(h)),Z(i,`cx`,48+r()[0].elapsed/100*W(u)),Z(i,`cy`,W(l)-r()[0].used/100*W(d)),q(a,`First observation: ${e??``}`)},[()=>$i(r()[0].at)]),K(e,t)};J(T,e=>{r().length&&e(E)});var ee=B(T,2),D=B(ee),te=B(D),ne=z(L(te));A(te),A(v),A(_);var re=B(_,2),ie=L(re),ae=z(B(ie,3),!0);A(re);var oe=B(re,2),se=e=>{var t=la(),a=R(t),o=L(a);Te(2),A(a);var s=B(a,2),c=B(L(s),2),l=e=>{var t=ca(),n=L(t),i=B(L(n),2);X(i,21,r,Y,(e,t,n)=>{var r=sa(),i=L(r),a=L(i),o=z(a,!0);A(i);var s=B(i),c=z(s),l=B(s),u=z(l),d=z(B(l),!0);A(r),V((e,r)=>{Z(a,`datetime`,W(t).at),q(o,e),q(c,`${r??``}%`),q(u,`${W(t).used??``}%`),q(d,n===0?`First observation`:W(t).break?`Gap before this observation`:`Connected to previous observation`)},[()=>$i(W(t).at),()=>W(t).elapsed.toFixed(1)]),K(e,r)}),A(i),A(n),A(t),K(e,t)};J(c,e=>{W(i)&&e(l)}),A(s),V(e=>{Z(a,`id`,n+`-trail-summary`),q(o,`○ START ${e??``} // ${r().length??``} + ${r().length===1?`OBSERVATION`:`OBSERVATIONS`}`)},[()=>$i(r()[0].at)]),Mi(`open`,`toggle`,s,e=>I(i,e),()=>W(i)),K(e,t)};J(oe,e=>{r().length&&e(se)}),V((e,i,a,m)=>{Z(v,`viewBox`,`0 0 ${W(o)} ${W(s)}`),Z(v,`aria-describedby`,r().length?n+`-trail-summary`:void 0),Z(v,`aria-label`,e),Z(b,`id`,n),Z(x,`width`,W(u)),Z(x,`height`,W(d)),Z(x,`fill`,`url(#${n})`),Z(C,`d`,`M48 20 V${W(l)} H${W(c)}`),Z(w,`y1`,W(l)),Z(w,`x2`,W(c)),Z(ee,`x`,48+W(u)/2),Z(ee,`y`,W(s)-5),Z(D,`cx`,W(f)),Z(D,`cy`,W(p)),Z(te,`cx`,W(f)),Z(te,`cy`,W(p)),q(ne,`${t.used??``}% consumed // ${i??``}% of period elapsed`),q(ie,`${t.used??``}% USED // ${a??``}% TIME ELAPSED`),q(ae,m)},[()=>`Consumption zone: ${t.used}% consumed, ${t.elapsed.toFixed(1)}% of quota period elapsed. ${W(m)>0?`Above`:W(m)<0?`Below`:`On`} the steady-consumption line.`,()=>t.elapsed.toFixed(1),()=>t.elapsed.toFixed(1),()=>Math.abs(W(m))<.05?`ON PACE`:W(m)>0?`ABOVE THE LINE — CONSUMING FASTER THAN TIME`:`BELOW THE LINE — WITHIN PACE`]),ji(_,`clientWidth`,e=>I(o,e)),ji(_,`clientHeight`,e=>I(s,e)),K(e,g),qe()}var fa=G(` `),pa=G(`

Quota refresh failed. Values below are the last successful observation.

`),ma=G(`

Expiry details unavailable. No listed expiry does not mean no expiry.

`),ha=G(`

`),ga=G(`

Read-only preview. Use the terminal to redeem a reset.

The backend may return only some credits. This list does not establish + redemption order.

`),_a=G(` `,1),va=Mr(``),ya=Mr(``),ba=G(`
`),xa=G(`

Cycle duration or reset date unavailable — position cannot be + plotted.

`),Sa=G(`
−100 // OVER BUDGET+100 // HEADROOM

`,1),Ca=G(`

Cycle duration unavailable — pace cannot be calculated.

`),wa=G(`
EMPTYFULL
`),Ta=G(`

`,1),Ea=G(`
`,1),Da=G(`

`),Oa=G(`

`),ka=G(`

No quota windows reported yet.

`),Aa=G(`
`,1),ja=G(`

All reported windows are shown. API-equivalent learning and quota status + scoring remain in the terminal for this first preview.

`,1),Ma=G(` `,1);function Na(e,t){Ke(t,!0);let n=Fi(t,`params`,19,()=>({})),r=Ui,i=F(Qt(Date.now())),a=N(()=>r.includes(n().view||``)?n().view:`bars`);Ii(()=>{let e=setInterval(()=>I(i,Date.now(),!0),1e3);return()=>clearInterval(e)});function o(e){return!e.duration||e.duration<=0||!e.reset?null:Math.max(0,Math.min(100,100*(1-(e.reset*1e3-W(i))/(e.duration*6e4))))}xn(()=>{qi.view=W(a)});function s(e){let t=e/100*Math.PI*2;return`M60 60 L60 14 A46 46 0 ${+(e>50)} 1 ${60+46*Math.sin(t)} ${60-46*Math.cos(t)} Z`}var c=Ma(),l=R(c);X(l,21,()=>r,Y,(e,t)=>{var n=fa();let r;var i=z(n,!0);V(e=>{Z(n,`href`,`#/quota/`+W(t)),Z(n,`aria-current`,W(a)===W(t)?`page`:void 0),r=si(n,1,``,null,r,{active:W(a)===W(t)}),q(i,e)},[()=>W(t)===`pace`?`CONSUMPTION PACE`:W(t)===`zone`?`CONSUMPTION ZONE`:W(t)===`fuel`?`FUEL TANK`:W(t).toUpperCase()]),K(e,n)}),A(l);var u=B(l,2),d=e=>{var t=ja(),n=R(t),r=e=>{K(e,pa())};J(n,e=>{Q.data.quotaError&&e(r)});var i=B(n,2),c=z(i),l=B(i,2),u=e=>{var t=ga(),n=L(t),r=z(n),i=B(n,4),a=e=>{K(e,ma())};J(i,e=>{Q.data.credits.length||e(a)}),X(B(i,2),17,()=>Q.data.credits,Y,(e,t)=>{var n=ha(),r=L(n),i=z(r),a=z(B(r,2),!0);A(n),V(e=>{q(i,`${(W(t).title||`Quota reset`)??``} // ${W(t).status??``}`),q(a,e)},[()=>W(t).expiryKnown?W(t).expires?`EXPIRES `+$i(W(t).expires):`Does not expire`:`Expiry information unavailable`]),K(e,n)}),Te(2),A(t),V(()=>q(r,`RESET INVENTORY // ${Q.data.creditCount??``} AVAILABLE`)),K(e,t)},d=e=>{var t=Aa(),n=R(t);let r;X(n,21,()=>Q.data.meters,Y,(e,t)=>{let n=N(()=>o(W(t))),r=N(()=>W(n)===null?null:W(n)-W(t).used);var i=Oa(),c=L(i),l=z(c,!0),u=B(c,2),d=L(u),f=e=>{var n=_a(),r=R(n),i=z(r),a=z(B(r));V(()=>{q(i,`FREE ${100-W(t).used}%`),q(a,`USED ${W(t).used??``}%`)}),K(e,n)},p=e=>{var n=_a(),r=R(n),i=z(r),a=z(B(r));V(()=>{q(i,`USED ${W(t).used??``}%`),q(a,`FREE ${100-W(t).used}%`)}),K(e,n)};J(d,e=>{W(a)===`fuel`?e(f):e(p,-1)}),A(u);var m=B(u,2);let h;var g=L(m),_=e=>{var n=ba(),r=L(n),i=B(L(r)),a=e=>{K(e,va())},o=e=>{var n=ya();V(e=>Z(n,`d`,e),[()=>s(W(t).used)]),K(e,n)};J(i,e=>{W(t).used>=100?e(a):W(t).used>0&&e(o,1)}),A(r),A(n),V(()=>Z(r,`aria-label`,`${W(t).used}% quota used`)),K(e,n)},v=e=>{var r=Pr(),i=R(r),a=e=>{{let r=N(()=>W(t).trail||[]);da(e,{get used(){return W(t).used},get elapsed(){return W(n)},get trail(){return W(r)}})}},o=e=>{K(e,xa())};J(i,e=>{W(n)===null?e(o,-1):e(a)}),K(e,r)},y=e=>{var t=Pr(),n=R(t),i=e=>{var t=Sa(),n=R(t),i=B(L(n),2);let a;A(n);var o=B(n,4),s=L(o),c=z(B(s),!0);A(o),V(e=>{a=li(i,``,a,{left:`${(W(r)+100)/2}%`}),q(s,`${W(r)>=0?`+`:``}${e??``} PP `),q(c,W(r)>=0?`WITHIN PACE`:`USING FASTER THAN TIME`)},[()=>W(r).toFixed(1)]),K(e,t)},a=e=>{K(e,Ca())};J(n,e=>{W(r)===null?e(a,-1):e(i)}),K(e,t)},b=e=>{var r=Ea(),i=R(r),o=L(i);let s;A(i);var c=B(i,2),l=e=>{K(e,wa())};J(c,e=>{W(a)===`fuel`&&e(l)});var u=B(c,2),d=e=>{var t=Ta(),r=R(t),i=z(r),o=B(r,2),s=L(o);let c;A(o),V(e=>{q(i,`RESET CYCLE // ${e??``}% ELAPSED`),c=li(s,``,c,{width:`${W(a)===`fuel`?100-W(n):W(n)}%`})},[()=>Math.floor(W(n))]),K(e,t)};J(u,e=>{W(n)!==null&&e(d)}),V(()=>{Z(i,`aria-label`,W(a)===`fuel`?`Fuel remaining`:`Quota used`),Z(i,`aria-valuenow`,W(a)===`fuel`?100-W(t).used:W(t).used),s=li(o,``,s,{width:`${W(a)===`fuel`?100-W(t).used:W(t).used}%`})}),K(e,r)};J(g,e=>{W(a)===`pie`?e(_):W(a)===`zone`?e(v,1):W(a)===`pace`?e(y,2):e(b,-1)}),A(m);var x=B(m,2),S=z(x),C=B(x,2),w=e=>{var n=Da(),r=z(n,!0);V(()=>q(r,W(t).details)),K(e,n)};J(C,e=>{W(t).details&&e(w)}),A(i),V(e=>{q(l,W(t).name),h=si(m,1,`meter-graphic`,null,h,{"bar-graphic":W(a)===`bars`||W(a)===`fuel`}),q(S,`RESETS // ${e??``}`)},[()=>$i(W(t).reset)]),K(e,i)}),A(n);var i=B(n,2),c=e=>{K(e,ka())};J(i,e=>{Q.data.meters.length||e(c)}),V(()=>r=si(n,1,`quota-grid`,null,r,{radial:W(a)===`pie`,zone:W(a)===`zone`})),K(e,t)};J(l,e=>{W(a)===`resets`?e(u):e(d,-1)}),Te(2),V(e=>q(c,`QUOTA // OBSERVED ${e??``}`),[()=>$i(Q.data.quotaAt)]),K(e,t)};J(u,e=>{Q.data&&e(d)}),K(e,c),qe()}var Pa=G(`
`),Fa=G(`

`,1);function Ia(e,t){Ke(t,!0);let n=Fi(t,`values`,19,()=>[]),r=Fi(t,`label`,3,`Token activity`),i=Fi(t,`capacity`,3,0),a=N(()=>Math.max(0,...n())),o=N(()=>i()>n().length?[...Array(i()-n().length).fill(0),...n()]:n());var s=Fa(),c=R(s),l=z(c),u=B(c,2);X(u,21,()=>W(o),Y,(e,t)=>{var n=Pa();let r;V((e,t)=>{Z(n,`title`,e),r=li(n,``,r,{height:t})},[()=>W(t).toLocaleString(`en-GB`)+` tokens`,()=>`${100*W(t)/Math.max(1,W(a))}%`]),K(e,n)}),A(u),V((e,t)=>{q(l,`SCALE // 0 — ${e??``} TOKENS`),Z(u,`aria-label`,t)},[()=>W(a).toLocaleString(`en-GB`),()=>`${r()}. Peak ${W(a).toLocaleString(`en-GB`)} tokens.`]),K(e,s),qe()}var La=G(`

CURRENT PROFILE

MODEL / REASONING LEVEL / SPEED

 

PROPOSED PROFILE

MODEL / REASONING LEVEL / SPEED

 

Applied settings remain after Codexometer closes.

`,1),Ra=G(`

`),za=G(`

 
`,1),Ba=G(`

Command unavailable from this observation. Open Codex to inspect the + request.

`),Va=G(`

Session controls temporarily unavailable. Check Codex for current state.

`),Ha=G(`

Checking session controls…

`),Ua=G(`

`),Wa=G(`
About browser controls

Controls require a supported live request from a connected shared + app-server session. Local observations alone cannot provide them.

`),Ga=G(` `,1),Ka=G(` `),qa=G(`Grants permission beyond this one command. Check the scope + carefully.`),Ja=G(``),Ya=G(``),Xa=G(``),Za=G(``),Qa=G(` `,1),$a=G(`
  • `),eo=G(`
    View fixed choices

    Type one of these choices exactly. Your answer stays masked.

      `),to=G(` `,1),no=G(`

      `,1),ro=G(``),io=G(`

      `,1),ao=G(`

      `);function oo(e,t){Ke(t,!0);let n=[],r=Fi(t,`observedCommand`,3,``),i=Fi(t,`review`,3,``),a=Fi(t,`suspended`,3,!1),o=Fi(t,`onProtectedChange`,3,e=>{}),s=F(null),c=F(Qt([])),l=F(null),u=F(``),d=F(0),f=F(Qt(Date.now())),p=F(!1),m=F(``),h=F(!1),g=F(!1),_=F(``);xn(()=>(o()(W(p)||W(c).some(e=>e.length>0)),()=>o()(!1)));let v=N(()=>Q.data?.sessions.find(e=>e.id===t.session)?.status),y=N(()=>!Q.connected||!!Q.data?.sessionsError),b=N(()=>i()!==`profile`&&W(s)?.kind===`prompt`&&!W(s).questions?.length&&!!Q.data?.profiles?.some(e=>e.session===t.session&&e.pending)),x=N(()=>!W(y)&&!W(g)&&!!W(s)?.id&&W(s).kind===`approval`&&W(_)!==W(s).id),S=N(()=>W(x)?W(s).command:r()),C=N(()=>!!W(u)&&W(f)W(s)?.questions?.length?W(s).questions:[{text:`Follow-up message`,secret:!1,freeText:!0,options:[]}]),T=N(()=>W(s)?.kind===`approval`||W(s)?.kind===`profile`?W(l)!==null:W(c).length===W(w).length&&W(c).every((e,t)=>e.trim().length>0&&(W(w)[t].freeText||W(w)[t].options?.includes(e))));xn(()=>{(W(y)||a()||W(b)||W(f)>=W(d))&&I(u,``)});let E=new AbortController;Ii(()=>{let e,n=setInterval(()=>{I(f,Date.now(),!0)},1e3);async function r(){try{let e=await ra(`offer`,{session:t.session,...i()?{review:i()}:{}},E.signal);if(E.signal.aborted)return;I(g,!1),W(s)?.id!==e.id&&(I(u,``),I(l,null),I(c,Array(Math.max(1,e.questions?.length||0)).fill(``),!0)),I(s,e,!0),W(h)&&e.id&&e.id!==W(_)&&(I(m,``),I(h,!1))}catch{E.signal.aborted||(I(s,null),I(g,!0),I(u,``))}finally{E.signal.aborted||(e=setTimeout(r,2e3))}}return r(),()=>{E.abort(),clearTimeout(e),clearInterval(n)}});async function ee(){if(!W(s)?.id||W(p)||W(y)||a()||W(b)||!W(T))return;let e=W(s).id;I(p,!0),I(m,``),I(h,!1),I(u,``);try{let n=await ra(`prepare`,{session:t.session,...i()?{review:i()}:{},offer:e,...W(s).kind===`approval`||W(s).kind===`profile`?{choice:W(l)}:{answers:[...W(c)]}},E.signal);W(s)?.id===e&&!E.signal.aborted&&!W(y)&&!a()&&!W(b)&&(I(u,n.confirmation,!0),I(d,Date.parse(n.expires),!0))}catch(e){E.signal.aborted||I(m,e instanceof Error?e.message:`Unable to prepare action.`,!0)}finally{I(p,!1)}}async function D(){if(!W(s)?.id||W(p)||a()||W(b)||!W(C))return;let e=W(s).id,n=W(s).kind,r=W(u);I(u,``),I(p,!0),I(_,e,!0);try{await ra(`commit`,{session:t.session,...i()?{review:i()}:{},offer:e,confirmation:r},E.signal),I(h,!0),I(m,n===`profile`?`Profile decision completed.`:n===`approval`?`Decision sent.`:`Text sent.`,!0)}catch(e){I(m,e instanceof ta?e.message:`Outcome uncertain. Check Codex before taking another action; nothing was retried.`,!0)}finally{I(p,!1),I(c,[],!0),I(l,null)}}var te=Pr(),ne=R(te),re=e=>{var r=ao(),a=L(r),o=z(a,!0),b=B(a,2),E=e=>{var t=La(),n=R(t),r=z(n),i=B(n,6),a=z(i,!0),o=z(B(i,6),!0);Te(2),V(()=>{q(r,`Your ${W(s).profile.threshold??``}% quota threshold has been reached. Review + the profile for subsequent turns.`),q(a,W(s).profile.current),q(o,W(s).profile.proposed)}),K(e,t)};J(b,e=>{W(s)?.profile&&!W(y)&&!W(g)&&e(E)});var te=B(b,2),ne=e=>{var t=Ra();let n;var r=z(t,!0);V(()=>{n=si(t,1,`svelte-1oupzfc`,null,n,{notice:!W(h),sent:W(h)}),q(r,W(m))}),K(e,t)};J(te,e=>{W(m)&&e(ne)});var re=B(te,2),ie=e=>{var t=za(),n=R(t),r=z(n,!0),i=z(B(n,2),!0);V(()=>{q(r,W(x)?`EXACT COMMAND`:`LAST OBSERVED COMMAND`),q(i,W(S))}),K(e,t)},ae=e=>{K(e,Ba())};J(re,e=>{W(S)?e(ie):i()!==`profile`&&W(v)===`APPROVAL NEEDED`&&!W(h)&&e(ae,1)});var oe=B(re,2),se=e=>{K(e,Va())},ce=e=>{K(e,Ha())},le=e=>{var t=Ga(),n=R(t),r=e=>{var t=Ua(),n=z(t,!0);V(e=>q(n,e),[()=>W(v)===`WORKING`?`Codex is working — nothing to respond to.`:[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(W(v)||``)?`Respond in Codex for this request.`:`Nothing needs a response right now.`]),K(e,t)};J(n,e=>{(W(v)===`WORKING`||!W(h)&&!W(p))&&e(r)});var i=B(n,2),a=e=>{K(e,Wa())},o=N(()=>[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(W(v)||``)&&!W(h));J(i,e=>{W(o)&&e(a)}),K(e,t)},ue=e=>{var r=io(),a=R(r),o=z(a),m=B(a,2),h=L(m),g=z(h,!0),_=B(h,2),v=e=>{var r=Pr();X(R(r),17,()=>W(s).choices||[],Y,(e,r,a)=>{var o=Ja(),s=L(o);bi(s),s.value=s.__value=a;var c=B(s),u=B(c),d=e=>{var t=Ka(),n=z(t,!0);V(()=>q(n,W(r).detail)),K(e,t)};J(u,e=>{W(r).detail&&e(d)});var f=B(u,2),p=e=>{K(e,qa())};J(f,e=>{W(r).persistent&&e(p)}),A(o),V(()=>{Z(s,`name`,`decision-`+t.session+`-`+i()),q(c,` ${W(r).label??``} `)}),Ei(n,[],s,()=>W(l),e=>I(l,e)),K(e,o)}),K(e,r)},b=e=>{var t=Pr();X(R(t),17,()=>W(w),Y,(e,t,n)=>{var r=to(),i=R(r),a=L(i),o=B(a),s=e=>{var t=Ya();bi(t),wi(t,()=>W(c)[n],e=>W(c)[n]=e),K(e,t)},l=e=>{var r=Za(),i=L(r);i.value=i.__value=``,X(B(i),17,()=>W(t).options||[],Y,(e,t)=>{var n=Xa(),r=z(n,!0),i={};V(()=>{q(r,W(t)),i!==(i=W(t))&&(n.value=(n.__value=i)??``)}),K(e,n)}),A(r),pi(r),mi(r,()=>W(c)[n],e=>W(c)[n]=e),K(e,r)},u=e=>{var r=Qa(),i=R(r);ot(i);var a=B(i,2),o=e=>{var n=Ua(),r=z(n);V(e=>q(r,`Suggested answers: ${e??``}`),[()=>W(t).options.join(` · `)]),K(e,n)};J(a,e=>{W(t).options?.length&&e(o)}),wi(i,()=>W(c)[n],e=>W(c)[n]=e),K(e,r)};J(o,e=>{W(t).secret?e(s):W(t).freeText?e(u,-1):e(l,1)}),A(i);var d=B(i,2),f=e=>{var n=eo(),r=B(L(n),4);X(r,21,()=>W(t).options||[],Y,(e,t)=>{var n=$a(),r=z(n,!0);V(()=>q(r,W(t))),K(e,n)}),A(r),A(n),K(e,n)};J(d,e=>{W(t).secret&&!W(t).freeText&&e(f)}),V(()=>q(a,`${W(t).text??``} `)),K(e,r)}),K(e,t)};J(_,e=>{W(s).kind===`approval`||W(s).kind===`profile`?e(v):e(b,-1)}),A(m);var x=B(m,2),S=e=>{var t=no(),n=R(t),r=z(n),i=B(n,2),a=z(i),o=B(i,2);V(e=>{q(r,`Check the target and ${W(s).kind===`profile`?`profile above`:W(s).kind===`approval`?`exact command and permission scope`:`message above`}. This will send to Codex; it may start work + using your quota. Confirmation expires in ${e??``}s.`),i.disabled=W(p)||W(y),q(a,`CONFIRM ${(W(s).kind===`approval`||W(s).kind===`profile`?W(s).choices?.[W(l)]?.label:`SEND`)??``}`)},[()=>Math.max(0,Math.ceil((W(d)-W(f))/1e3))]),Sr(`click`,i,D),Sr(`click`,o,()=>{I(u,``)}),K(e,t)},E=e=>{var t=ro(),n=z(t,!0);V(()=>{t.disabled=W(p)||W(y)||!W(T),q(n,W(p)?`SENDING…`:`REVIEW BEFORE SENDING`)}),Sr(`click`,t,ee),K(e,t)};J(x,e=>{W(C)?e(S):e(E,-1)}),V(()=>{q(o,`TARGET // ${W(s).thread??``} // ${(W(s).directory||`Directory unavailable`)??``}`),m.disabled=W(p)||W(C)||W(y),q(g,W(s).kind===`approval`||W(s).kind===`profile`?`Choose a decision`:`Reply to this session`)}),K(e,r)};J(oe,e=>{W(y)||W(g)?e(se):W(s)?W(s).id?W(_)!==W(s).id&&e(ue,3):e(le,2):e(ce,1)}),A(r),V(()=>q(o,i()===`profile`?`QUOTA THRESHOLD`:`SESSION CONTROL // EXPERIMENTAL`)),K(e,r)};J(ne,e=>{W(b)||e(re)}),K(e,te),qe()}Cr([`click`]);var so=G(`
      `);function co(e,t){Ke(t,!0);let n=Fi(t,`active`,3,!1),r=N(()=>[`LAST REPLY`,`LAST ACTIVITY`].includes(t.session.contextKind)&&!!t.session.text.trim()),i=F(!1),a=F(``),o=F(!1);xn(()=>{if(!W(o))return;let e=setTimeout(()=>{I(o,!1)},150);return()=>clearTimeout(e)}),xn(()=>{t.session.text,t.session.status,I(a,``)});async function s(){if(!W(r)||W(i))return;let e=t.session.text;I(i,!0),I(o,!0),I(a,``);try{await navigator.clipboard.writeText(e),t.session.text===e&&I(a,`Copied.`)}catch{t.session.text===e&&I(a,`Clipboard unavailable. Select the visible text and copy it manually.`)}finally{I(i,!1)}}function c(e){!n()||!W(r)||e.defaultPrevented||e.repeat||e.ctrlKey||e.metaKey||e.altKey||e.key.toLowerCase()!==`c`||e.target instanceof Element&&e.target.closest(`input, textarea, select, [contenteditable]`)||(e.preventDefault(),s())}var l=Pr();xr(`keydown`,tn,c);var u=R(l),d=e=>{var t=so(),n=L(t),r=z(n,!0),c=B(n,2);let l;A(t),V(()=>{q(r,W(a)),c.disabled=W(i),l=si(c,1,`svelte-543j00`,null,l,{flashed:W(o)})}),Sr(`click`,c,s),K(e,t)};J(u,e=>{W(r)&&e(d)}),K(e,l),qe()}Cr([`click`]);var lo=G(`

      `),uo=G(`

      `),fo=G(`
       
      `),po=G(`

      Command unavailable from this observation. Open Codex to inspect the + request.

      `),mo=G(`

      `,1),ho=G(`

      `),go=G(`
       
      `,1),_o=G(`
      `),vo=G(`

      Session connection or refresh unavailable. Context and telemetry may be + stale.

      `),yo=G(`

      Some quota profile checks are unavailable. Only sessions with freshly + verified quota and settings can be updated; previous outcome notices remain + visible.

      `),bo=G(` `),xo=G(` `),So=G(``),Co=G(`

      Read only — reply or approve in Codex.

      `),wo=G(`

      `),To=G(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),Eo=G(`
      `),Do=G(`
      `),Oo=G(`

      This session is no longer in the current observation. Return to sessions.

      `),ko=G(`

      `),Ao=G(` `),jo=G(`

      `),Mo=G(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),No=G(` `,1),Po=G(`

      `),Fo=G(`

      TOKEN ACTIVITY // 30 SECOND SAMPLES

      `),Io=G(`

      TOKENS

      FULL DETAIL →
      `),Lo=G(`

      No locally observed sessions yet. Keep Codex running alongside + Codexometer.

      `),Ro=G(`

      ↑ ↓ SELECT SESSION // ← LESS DETAIL // → MORE DETAIL // ESC BACK

      `,1),zo=G(`

      SESSION TOTALS

      `,1);function Bo(e,t){Ke(t,!0);let n=(e,t=f,n,r)=>{let i=vt(()=>h(n?.(),!0)),a=vt(()=>h(r?.(),!1));var o=go(),s=R(o),c=e=>{var n=lo();let r;var i=z(n,!0);V(e=>{r=si(n,1,`attention-note`,null,r,{inferred:t().status===`CHECK SESSION`}),q(i,e)},[()=>b(t())]),K(e,n)},l=N(()=>b(t())&&(!W(a)||W(d)||t().status===`CHECK SESSION`));J(s,e=>{W(l)&&e(c)});var u=B(s,2),p=e=>{var n=uo(),r=z(n,!0);V(()=>q(r,t().contextKind||`LAST ACTIVITY`)),K(e,n)};J(u,e=>{W(i)&&e(p)});var m=B(u,2),g=z(m,!0),_=B(m,2),v=e=>{var n=mo(),r=B(R(n),2),i=z(r,!0),a=B(r,2),o=e=>{var n=fo(),r=z(n,!0);V(()=>q(r,t().command)),K(e,n)},s=e=>{K(e,po())};J(a,e=>{t().command?e(o):e(s,-1)}),V(()=>q(i,W(d)||t().status!==`APPROVAL NEEDED`?`LAST OBSERVED COMMAND`:Q.data?.control?`COMMAND REQUEST`:`COMMAND TO APPROVE IN CODEX`)),K(e,n)};J(_,e=>{(!W(a)||!Q.data?.control)&&(t().command||t().status===`APPROVAL NEEDED`)&&e(v)});var y=B(_,2),x=e=>{var n=ho(),r=z(n);V(()=>q(r,`CONTEXT SOURCE // ${(t().source||`LOCAL`)??``} // OBSERVATION`)),K(e,n)};J(y,e=>{W(a)||e(x)}),V(()=>q(g,t().text||`No session context available.`)),K(e,o)},r=Fi(t,`params`,19,()=>({})),i=N(()=>Q.data?.sessions||[]),a=N(()=>Q.data?.control&&Q.data.profiles||[]),o=F(!1);function s(e,t){if(r().id&&r().id!==t&&W(o)){e.preventDefault();return}_(t)}xn(()=>{let e=r().id;e&&mr(()=>{qi.selected=e,Qi(e,2)})});let c=N(()=>W(i).find(e=>e.id===r().id)),l=N(()=>new URLSearchParams(zi.querystring).get(`review`)===`profile`&&W(a).some(e=>e.session===r().id&&e.pending)),u=N(()=>W(i).some(e=>e.id===qi.selected)?qi.selected:W(i)[0]?.id),d=N(()=>!Q.connected||!!Q.data?.sessionsError),p=N(()=>[[`OBSERVED TOKENS`,$(W(i).reduce((e,t)=>e+t.tokens,0))],[`LISTED SESSIONS`,$(W(i).length)],...[[`WORKING`,`WORKING`],[`AWAITING APPROVAL`,`APPROVAL NEEDED`],[`AWAITING INPUT`,`INPUT NEEDED`],[`CHECK · INFERRED`,`CHECK SESSION`]].map(([e,t])=>[e,W(d)?`—`:$(W(i).filter(e=>e.status===t).length)])]),m=N(()=>W(i).filter(e=>[`INPUT NEEDED`,`APPROVAL NEEDED`,`CHECK SESSION`].includes(e.status)));function _(e){qi.selected=e,dr().then(()=>document.querySelector(`.session-row.selected`)?.scrollIntoView({block:`nearest`}))}function v(e,t){if(_(e),r().id){t<0&&(Qi(e,2),location.hash=`/sessions`);return}let n=Xi(e)+t;n>2?location.hash=`/sessions/`+encodeURIComponent(e):Qi(e,n)}function y(e){let t=e.target;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||t.closest(`input, textarea, select, [contenteditable="true"]`))){if(e.key===`Escape`&&r().id)e.preventDefault(),v(r().id,-1);else if([`ArrowLeft`,`ArrowRight`].includes(e.key)&&(r().id||W(u)))e.preventDefault(),v(r().id||W(u),e.key===`ArrowLeft`?-1:1);else if(!r().id&&[`ArrowUp`,`ArrowDown`].includes(e.key)&&W(i).length){e.preventDefault();let t=W(i).findIndex(e=>e.id===W(u));_(W(i)[Math.max(0,Math.min(W(i).length-1,t+(e.key===`ArrowUp`?-1:1)))].id)}}}function b(e){return W(d)?`Last observation only — refresh unavailable. Check Codex for current state.`:e.status===`CHECK SESSION`?`INFERRED INACTIVITY — a quiet session, not a confirmed input or approval request. Local tools may still be running.`:Q.data?.control&&[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(e.status)?`Open full detail for supported live controls; otherwise reply in Codex.`:e.status===`APPROVAL NEEDED`?`OBSERVED APPROVAL SIGNAL — approve or decline in Codex.`:e.status===`INPUT NEEDED`?`OBSERVED INPUT SIGNAL — reply in Codex.`:e.status===`TURN COMPLETE`?`OBSERVED TURN COMPLETION — informational, not an approval request.`:``}var x=zo();xr(`keydown`,tn,y);var S=R(x),C=z(B(L(S),2));A(S);var w=B(S,2);let T;X(w,21,()=>W(p),Y,(e,t)=>{var n=N(()=>g(W(t),2));let r=()=>W(n)[0],i=()=>W(n)[1];var a=_o(),o=L(a),s=z(o,!0),c=z(B(o,2),!0);A(a),V(()=>{q(s,r()),q(c,i())}),K(e,a)}),A(w);var E=B(w,2),ee=z(E),D=B(E,2),te=e=>{K(e,vo())};J(D,e=>{W(d)&&e(te)});var ne=B(D,2),re=e=>{K(e,yo())};J(ne,e=>{Q.data?.profileError&&e(re)});var ie=B(ne,2),ae=e=>{var t=So(),n=L(t);X(n,17,()=>W(m),Y,(e,t)=>{var n=bo();let r;var i=z(n);V(e=>{r=si(n,1,`button`,null,r,{approval:W(t).status===`APPROVAL NEEDED`}),Z(n,`href`,e),q(i,`${W(t).status??``} // ${(W(t).directory||W(t).id)??``}`)},[()=>`#/sessions/`+encodeURIComponent(W(t).id)]),Sr(`click`,n,()=>_(W(t).id)),K(e,n)}),X(B(n,2),17,()=>W(a).filter(e=>e.pending&&W(i).some(t=>t.id===e.session)),Y,(e,t)=>{var n=xo(),a=z(n);V((e,i)=>{Z(n,`title`,r().id&&r().id!==W(t).session&&W(o)?`Finish sending or clear your current draft before switching sessions.`:`Review this session’s quota threshold`),Z(n,`href`,e),q(a,`QUOTA THRESHOLD // ${i??``}`)},[()=>`#/sessions/`+encodeURIComponent(W(t).session)+`?review=profile`,()=>W(i).find(e=>e.id===W(t).session)?.directory||W(t).session]),Sr(`click`,n,e=>s(e,W(t).session)),K(e,n)}),A(t),K(e,t)},oe=N(()=>(W(m).length||W(a).some(e=>e.pending))&&!W(d));J(ie,e=>{W(oe)&&e(ae)});var se=B(ie,2),ce=e=>{var t=Pr(),i=R(t),s=e=>{var t=Do(),i=L(t),s=L(i),u=L(s);let f;var p=B(u);A(s);var m=B(s,2);A(i);var h=B(i,2),g=z(h),v=B(h,2);let y;var b=L(v),x=L(b);n(x,()=>W(c),()=>!0,()=>!0),A(b);var S=B(b,2),C=e=>{var t=Pr();Kr(R(t),()=>W(c).id,e=>{oo(e,{get session(){return W(c).id},get observedCommand(){return W(c).command},get suspended(){return W(l)},onProtectedChange:e=>{I(o,e,!0)}})}),K(e,t)},w=e=>{K(e,Co())};J(S,e=>{Q.data?.control?e(C):e(w,-1)}),A(v);var T=B(v,2);X(T,17,()=>W(a).filter(e=>e.session===W(c).id),e=>e.session,(e,t)=>{var n=Eo(),r=L(n),i=e=>{var n=wo(),r=z(n,!0);V(()=>q(r,W(t).notice)),K(e,n)};J(r,e=>{W(t).notice&&e(i)});var a=B(r,2),o=e=>{oo(e,{get session(){return W(c).id},review:`profile`})},s=e=>{var t=To();V(e=>Z(t,`href`,e),[()=>`#/sessions/`+encodeURIComponent(W(c).id)+`?review=profile`]),K(e,t)};J(a,e=>{W(t).pending&&W(l)?e(o):W(t).pending&&e(s,1)}),A(n),V(()=>Z(n,`id`,`quota-profile-`+W(c).id)),K(e,n)});var E=B(T,2),ee=e=>{var t=Pr();Kr(R(t),()=>W(c).id,e=>{co(e,{get session(){return W(c)},active:!0})}),K(e,t)};J(E,e=>{W(l)||e(ee)}),A(t),V(e=>{f=si(u,1,`lamp lit`,null,f,{working:W(c).status===`WORKING`&&!W(d)}),q(p,`${(W(d)?`STALE`:W(l)?`QUOTA THRESHOLD`:W(c).status)??``} // ${W(c).directory??``}`),q(g,`${e??``} TOKENS // ${W(c).id??``} // CONTEXT SOURCE // ${(W(c).source||`LOCAL`)??``}`),y=li(v,``,y,{display:W(l)?`none`:void 0})},[()=>$(W(c).tokens)]),Sr(`click`,m,()=>{_(r().id),Qi(r().id,2)}),K(e,t)},u=e=>{K(e,Oo())};J(i,e=>{W(c)?e(s):e(u,-1)}),K(e,t)},le=e=>{var t=Ro(),r=R(t),o=B(L(r),2),c=L(o),l=B(c,2);A(o),A(r);var f=B(r,2);X(f,17,()=>W(i),e=>e.id,(e,t)=>{let r=N(()=>Xi(W(t).id));var i=Io();let o;var c=L(i),l=L(c),f=L(l);let p;var m=B(f,1,!0);A(l);var h=B(l,2),g=z(h,!0),y=B(h,2),b=L(y);Te(),A(y);var x=B(y,2),S=z(x),C=B(x,2),w=z(C),T=B(C,2),E=L(T),ee=B(E,2),D=z(ee,!0),te=B(ee,2);A(T);var ne=B(T,2),re=B(ne,2),ie=e=>{var n=ko(),r=z(n,!0);V(()=>q(r,W(t).status===`CHECK SESSION`?`INFERRED INACTIVITY`:Q.data?.control?`OPEN FULL DETAIL OR REPLY IN CODEX`:W(t).status===`APPROVAL NEEDED`?`APPROVE OR DECLINE IN CODEX`:`REPLY IN CODEX`)),K(e,n)},ae=N(()=>!W(d)&&[`APPROVAL NEEDED`,`INPUT NEEDED`,`CHECK SESSION`].includes(W(t).status));J(re,e=>{W(ae)&&e(ie)}),A(c);var oe=B(c,2),se=e=>{var r=Po(),i=L(r),o=L(i),c=z(o,!0),l=B(o,2),f=e=>{var n=Ao(),r=z(n,!0);V(e=>{Z(n,`href`,e),q(r,Q.data?.control?`REVIEW IN FULL DETAIL ↗`:`APPROVAL IN CODEX ↗`)},[()=>`#/sessions/`+encodeURIComponent(W(t).id)]),K(e,n)};J(l,e=>{!W(d)&&W(t).status===`APPROVAL NEEDED`&&e(f)}),A(i);var p=B(i,2);n(p,()=>W(t),()=>!1);var m=B(p,2);X(m,17,()=>W(a).filter(e=>e.session===W(t).id),Y,(e,n)=>{var r=No(),i=R(r),a=e=>{var t=jo(),r=z(t,!0);V(()=>q(r,W(n).notice)),K(e,t)};J(i,e=>{W(n).notice&&e(a)});var o=B(i,2),c=e=>{var n=Mo();V(e=>Z(n,`href`,e),[()=>`#/sessions/`+encodeURIComponent(W(t).id)+`?review=profile`]),Sr(`click`,n,e=>s(e,W(t).id)),K(e,n)};J(o,e=>{W(n).pending&&e(c)}),K(e,r)});var h=B(m,2);{let e=N(()=>W(u)===W(t).id);co(h,{get session(){return W(t)},get active(){return W(e)}})}A(r),V(()=>q(c,W(t).contextKind||`LAST ACTIVITY`)),K(e,r)};J(oe,e=>{W(r)>0&&e(se)});var ce=B(oe,2),le=e=>{var n=Fo(),r=B(L(n),2);{let e=N(()=>(W(t).samples||[]).map(e=>e.tokens));Ia(r,{get values(){return W(e)},capacity:120})}var i=z(B(r,2));A(n),V(()=>q(i,`LAST ${(W(t).samples?.length||0)??``} SAMPLES // AUTO SCALE`)),K(e,n)};J(ce,e=>{W(r)<2&&e(le)}),A(i),V((e,n,a)=>{o=si(i,1,`session-row`,null,o,{selected:W(u)===W(t).id,wide:W(r)===2,split:W(r)===1}),Z(i,`aria-label`,`Session `+(W(t).directory||W(t).id)),p=si(f,1,`lamp lit`,null,p,{working:W(t).status===`WORKING`&&!W(d)}),q(m,W(d)?`STALE`:W(t).status),Z(h,`aria-pressed`,W(u)===W(t).id),q(g,W(t).directory||W(t).id),q(b,`${e??``} `),q(S,`${W(t).agents??``} LINKED AGENTS`),q(w,`ACTIVE // ${n??``}`),E.disabled=W(r)===0,Z(ee,`aria-expanded`,W(r)>0),q(D,W(r)?`HIDE DETAIL`:`SHOW DETAIL`),Z(ne,`href`,a)},[()=>$(W(t).tokens),()=>$i(W(t).activity),()=>`#/sessions/`+encodeURIComponent(W(t).id)]),Sr(`click`,h,()=>_(W(t).id)),Sr(`click`,E,()=>v(W(t).id,-1)),Sr(`click`,ee,()=>{_(W(t).id),Qi(W(t).id,+!W(r))}),Sr(`click`,te,()=>v(W(t).id,1)),Sr(`click`,ne,()=>_(W(t).id)),K(e,i)});var p=B(f,2),m=e=>{K(e,Lo())};J(p,e=>{W(i).length||e(m)}),Sr(`click`,c,()=>Zi(1)),Sr(`click`,l,()=>Zi(0)),K(e,t)};J(se,e=>{r().id?e(ce):e(le,-1)}),V(e=>{q(C,`OBSERVED ${e??``}`),T=si(w,1,`session-totals`,null,T,{stale:W(d)}),q(ee,`${W(d)?`LAST KNOWN TOTALS — live state counts unavailable. `:``}Tokens + observed since this server started for currently listed sessions; linked + agents are already included. Totals can decrease when a session leaves the + list. History samples every 30 seconds. Not account-wide totals.`)},[()=>$i(Q.data?.sessionsAt)]),K(e,x),qe()}Cr([`click`]);var Vo=864e5;function Ho(e,t){let n=new Date(e);n.setUTCDate(1),n.setUTCMonth(n.getUTCMonth()+t);let r=new Date(Date.UTC(n.getUTCFullYear(),n.getUTCMonth()+1,0)).getUTCDate();return n.setUTCDate(Math.min(e.getUTCDate(),r)),n}function Uo(e,t,n){let r=new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()));for(let e=0;;e++){let i=Ho(r,-t),a=new Date(i.getTime()+Vo);if(e===n)return{start:a,end:r};r=i}}var Wo=G(`

      History refresh failed. Any displayed history is the last successful + observation.

      `),Go=G(`

      Showing the last persisted account history while the live OpenAI refresh is + unavailable.

      `),Ko=G(``),qo=G(`
      `),Jo=G(`

      LESS ░ ▒ ▓ █ MORE // HOVER FOR DATE AND TOKENS

      `,1),Yo=G(`
      `,1),Xo=G(` `),Zo=G(`

      LIFETIME TOKENS

      PEAK DAY

      CURRENT STREAK

      DAYS

      LONGEST TURN

      SECONDS

      LONGEST STREAK

      DAYS

      Accessible data table
      Date (UTC)TokensSourceLocal

      `,1),Qo=G(`

      History unavailable or awaiting a matching account observation. Missing + history is not treated as zero usage.

      `),$o=G(`

      USAGE // ACCOUNT HISTORY

      Account-wide history reported by Codex, not the local Sessions counter. Dates + use UTC. Historical resets are not provided by this data.

      `,1);function es(e,t){Ke(t,!0);let n=F(`daily`),r=F(12),i=F(0),a=N(()=>{let e=Q.data?.usage?.dailyUsageBuckets;if(!e)return[];let{start:t,end:n}=Uo(new Date,W(r),W(i)),a=new Map,o=new Map;for(let t of e)!Number.isFinite(t.tokens)||t.tokens<0||(a.set(t.startDate,(a.get(t.startDate)||0)+t.tokens),o.set(t.startDate,t));let s=[];for(let e=t;e<=n;e=new Date(e.getTime()+864e5)){let t=e.toISOString().slice(0,10),n=o.get(t);s.push({date:t,tokens:a.get(t)||0,localTokens:n?.localTokens||0,provenance:n?.provenance||(n?`OPENAI`:`NO ACTIVITY`),inputTokens:n?.inputTokens||0,cachedInputTokens:n?.cachedInputTokens||0,outputTokens:n?.outputTokens||0})}return s}),o=N(()=>Math.max(1,...W(a).map(e=>e.tokens))),s=N(()=>W(a).length?new Date(W(a)[0].date+`T00:00:00Z`).getUTCDay():0),c=N(()=>Q.data?.usage?.coverage),l=N(()=>{if(W(n)===`monthly`){let e=new Map;for(let t of W(a)){let n=t.date.slice(0,7),r=e.get(n)||{tokens:0,localTokens:0};r.tokens+=t.tokens,r.localTokens+=t.localTokens,e.set(n,r)}return[...e].map(([e,t])=>({date:e,...t,provenance:`AGGREGATE`}))}let e=0,t=0;return W(a).map(n=>({date:n.date,tokens:e+=n.tokens,localTokens:t+=n.localTokens,provenance:`AGGREGATE`}))});var u=$o(),d=B(R(u),4),f=L(d),p=B(L(f)),m=L(p);m.value=m.__value=`daily`;var h=B(m);h.value=h.__value=`monthly`;var g=B(h);g.value=g.__value=`cumulative`,A(p),pi(p),A(f);var _=B(f),v=B(L(_)),y=L(v);y.value=y.__value=6;var b=B(y);b.value=b.__value=12,A(v),pi(v),A(_);var x=B(_),S=B(x);A(d);var C=B(d,2),w=e=>{K(e,Wo())};J(C,e=>{Q.data?.usageError&&e(w)});var T=B(C,2),E=e=>{K(e,Go())};J(T,e=>{Q.data?.usage?.stale&&e(E)});var ee=B(T,2),D=e=>{var t=Zo(),r=R(t),i=L(r),u=z(B(L(i),2),!0);A(i);var d=B(i,2),f=z(B(L(d),2),!0);A(d);var p=B(d,2),m=B(L(p),2),h=L(m);Te(),A(m),A(p);var g=B(p,2),_=B(L(g),2),v=L(_);Te(),A(_),A(g);var y=B(g,2),b=B(L(y),2),x=L(b);Te(),A(b),A(y),A(r);var S=B(r,2),C=L(S),w=B(C),T=e=>{var t=Nr();V(e=>q(t,`// LOCAL ${e??``}% ATTRIBUTED`),[()=>$(W(c).attributedPercent)]),K(e,t)};J(w,e=>{W(c)?.openaiTokens&&W(c)?.localTokens&&e(T)});var E=B(w),ee=e=>{var t=Nr();V(e=>q(t,`// ${e??``} RECOVERED DAYS`),[()=>$(W(c).recoveredDays)]),K(e,t)};J(E,e=>{W(c)?.recoveredDays&&e(ee)}),A(S);var D=B(S,2),te=L(D),ne=z(te),re=B(te,2),ie=e=>{var t=Jo(),n=R(t),r=L(n),i=L(r);X(i,17,()=>Array(W(s)),Y,(e,t)=>{K(e,Ko())}),X(B(i,2),17,()=>W(a),Y,(e,t)=>{var n=qo();let r,i;V(e=>{r=si(n,1,`heat-cell`,null,r,{zero:W(t).tokens===0}),Z(n,`title`,e),i=li(n,``,i,{opacity:W(t).tokens?.25+.75*W(t).tokens/W(o):1})},[()=>`${W(t).date}: ${$(W(t).tokens)} tokens // ${W(t).provenance} // local ${$(W(t).localTokens)} (input ${$(W(t).inputTokens)}, cached ${$(W(t).cachedInputTokens)}, output ${$(W(t).outputTokens)})`]),K(e,n)}),A(r),A(n),Te(2),K(e,t)},ae=e=>{var t=Yo(),r=R(t);{let e=N(()=>W(l).map(e=>e.tokens)),t=N(()=>W(n)+` usage`);Ia(r,{get values(){return W(e)},get label(){return W(t)}})}var i=B(r,2),a=L(i),o=z(a,!0),s=z(B(a),!0);A(i),V(e=>{q(o,W(l)[0]?.date),q(s,e)},[()=>W(l).at(-1)?.date]),K(e,t)};J(re,e=>{W(n)===`daily`?e(ie):e(ae,-1)});var oe=B(re,2),se=B(L(oe),2),ce=L(se),le=B(L(ce));X(le,21,()=>W(n)===`daily`?W(a):W(l),Y,(e,t)=>{var n=Xo(),r=L(n),i=z(r,!0),a=B(r),o=z(a,!0),s=B(a),c=z(s,!0),l=z(B(s),!0);A(n),V((e,n)=>{q(i,W(t).date),q(o,e),q(c,W(t).provenance),q(l,n)},[()=>$(W(t).tokens),()=>$(W(t).localTokens)]),K(e,n)}),A(le),A(ce),A(se),A(oe),A(D);var ue=z(B(D,2));V((e,t,n,r,i,o,s)=>{q(u,e),q(f,t),q(h,`${n??``} `),q(v,`${r??``} `),q(x,`${i??``} `),q(C,`${(W(c)?.status||`OPENAI`)??``} // UTC`),q(ne,`${W(a)[0]?.date??``} — ${o??``}`),q(ue,`OBSERVED ${s??``} // CUMULATIVE IS FOR THE SELECTED PERIOD`)},[()=>$(Q.data.usage.summary.lifetimeTokens),()=>$(Q.data.usage.summary.peakDailyTokens),()=>$(Q.data.usage.summary.currentStreakDays),()=>$(Q.data.usage.summary.longestRunningTurnSec),()=>$(Q.data.usage.summary.longestStreakDays),()=>W(a).at(-1)?.date,()=>$i(Q.data.usageAt)]),K(e,t)},te=e=>{K(e,Qo())};J(ee,e=>{Q.data?.usage&&Q.data.usage.dailyUsageBuckets!==null?e(D):e(te,-1)}),V(()=>S.disabled=W(i)===0),mi(p,()=>W(n),e=>I(n,e)),Sr(`change`,v,()=>I(i,0)),mi(v,()=>W(r),e=>I(r,e)),Sr(`click`,x,()=>Yt(i)),Sr(`click`,S,()=>Yt(i,-1)),K(e,u),qe()}Cr([`change`,`click`]),We();var ts=G(`

      Page not found

      Return to Quota

      `,1);function ns(e){var t=ts();Te(2),K(e,t)}var rs=G(` `),is=G(`

      `),as=G(`

      Connecting to your local Codexometer…

      `),os=G(``),ss=G(`
      CODEXOMETER

      Your quota. Your sessions. Your command centre.

      `);function cs(e,t){Ke(t,!0);let n={"/":Na,"/quota/:view?":Na,"/sessions/:id?":Bo,"/usage":es,"*":ns},r={quota:/^(?:\/|\/quota(?:\/[^/]+)?\/?)$/,sessions:/^\/sessions(?:\/[^/]+)?\/?$/,usage:/^\/usage\/?$/},i=F(`hacker`),a=[`hacker`,`rust`,`blue-steel`,`ultraviolet`,`nightshade`];xn(()=>{Ji()}),xn(()=>{if(Q.data)for(let[e,t]of Object.entries(r))t.test(zi.location)&&(qi.tab=e)}),Ii(()=>{try{let e=localStorage.getItem(`codexometer.web.theme`);e&&a.includes(e)&&I(i,e,!0)}catch{}return ia()});function o(){try{localStorage.setItem(`codexometer.web.theme`,W(i))}catch{}}var s=ss(),c=L(s),l=B(L(c),2),u=L(l);let d;var f=B(u,1,!0),p=z(B(f));A(l),A(c);var m=B(c,2);X(m,21,()=>Object.entries(r),Y,(e,t)=>{var n=N(()=>g(W(t),2));let r=()=>W(n)[0],i=()=>W(n)[1],a=N(()=>i().test(zi.location));var o=rs();let s;var c=z(o,!0);V(e=>{Z(o,`href`,r()===`quota`?`#/quota/`+qi.view:`#/`+r()),Z(o,`aria-current`,W(a)?`page`:void 0),s=si(o,1,``,null,s,{active:W(a)}),q(c,e)},[()=>r().toUpperCase()]),K(e,o)}),A(m);var h=B(m,2),_=L(h),v=e=>{var t=is(),n=z(t,!0);V(()=>q(n,Q.error)),K(e,t)};J(_,e=>{Q.error&&e(v)});var y=B(_,2),b=e=>{Hi(e,{get routes(){return n}})},x=e=>{K(e,as())};J(y,e=>{Q.data?e(b):Q.error||e(x,1)}),A(h);var S=B(h,2),C=L(S),w=z(C),T=B(C,2),E=z(T,!0),ee=B(T,2),D=B(L(ee));X(D,21,()=>a,Y,(e,t)=>{var n=os(),r=z(n,!0),i={};V(e=>{q(r,e),i!==(i=W(t))&&(n.value=(n.__value=i)??``)},[()=>W(t).replace(`-`,` `).toUpperCase()]),K(e,n)}),A(D),pi(D),A(ee),A(S),A(s),V(()=>{Z(s,`data-theme`,W(i)),d=si(u,1,`lamp`,null,d,{lit:Q.connected}),q(f,Q.connected?`CONNECTED`:`OFFLINE`),q(p,`EXPERIMENTAL // ${Q.data?.control?`SESSION CONTROL`:`READ ONLY`}`),q(w,`v${(Q.data?.version||`…`)??``} // LOCAL ONLY`),q(E,Q.data?.control?`Session control enabled. Stop the server to revoke access.`:`No actions can be sent from this preview.`)}),Sr(`change`,D,o),mi(D,()=>W(i),e=>I(i,e)),K(e,s),qe()}Cr([`change`]),Br(cs,{target:document.getElementById(`app`)}); \ No newline at end of file diff --git a/internal/web/dist/assets/index-S94ToOzX.js b/internal/web/dist/assets/index-S94ToOzX.js deleted file mode 100644 index 2b6de6f..0000000 --- a/internal/web/dist/assets/index-S94ToOzX.js +++ /dev/null @@ -1,26 +0,0 @@ -(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e=Array.isArray,t=Array.prototype.indexOf,n=Array.prototype.includes,r=Array.from,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyDescriptors,s=Object.prototype,c=Array.prototype,l=Object.getPrototypeOf,u=Object.isExtensible;function d(e){return typeof e==`function`}var f=()=>{};function p(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}function h(e,t,n=!1){return e===void 0?n?t():t:e}function g(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);let n=[];for(let r of e)if(n.push(r),n.length===t)break;return n}var _=1024,v=2048,y=4096,b=8192,x=16384,S=32768,C=1<<25,w=65536,T=1<<19,E=1<<20,ee=1<<25,te=65536,ne=1<<21,re=1<<22,ie=1<<23,ae=Symbol(`$state`),oe=Symbol(`component`),se=Symbol(`legacy props`),ce=Symbol(``),le=Symbol(`attributes`),ue=Symbol(`class`),de=Symbol(`style`),fe=Symbol(`text`),pe=Symbol(`form reset`),me=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},he=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),ge={},D=Symbol(`uninitialized`),_e=`http://www.w3.org/1999/xhtml`;function ve(){console.warn(`https://svelte.dev/e/derived_inert`)}function ye(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function be(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function xe(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var O=!1;function Se(e){O=e}var k;function Ce(e){if(e===null)throw ye(),ge;return k=e}function we(){return Ce(ln(k))}function A(e){if(O){if(ln(k)!==null)throw ye(),ge;k=e}}function Te(e=1){if(O){for(var t=e,n=k;t--;)n=ln(n);k=n}}function Ee(e=!0){for(var t=0,n=k;;){if(n.nodeType===8){var r=n.data;if(r===`]`){if(t===0)return n;--t}else(r===`[`||r===`[!`||r[0]===`[`&&!isNaN(Number(r.slice(1))))&&(t+=1)}var i=ln(n);e&&n.remove(),n=i}}function De(e){if(!e||e.nodeType!==8)throw ye(),ge;return e.data}function Oe(e){return e===this.v}function ke(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function Ae(e){return!ke(e,this.v)}function je(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function Me(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function Ne(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function Pe(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function Fe(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Ie(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function Le(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Re(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function ze(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Be(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Ve(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function He(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var Ue=!1;function We(){Ue=!0}var j=null;function Ge(e){j=e}function Ke(e,t=!1,n){j={p:j,i:!1,c:null,e:null,s:e,x:null,r:U,l:Ue&&!t?{s:null,u:null,$:[]}:null}}function qe(e){var t=j,n=t.e;if(n!==null){t.e=null;for(var r of n)Sn(r)}return e!==void 0&&(t.x=e),t.i=!0,j=t.p,Je(e)}function Je(e={}){return i(e,oe,{value:!0}),e}function Ye(){return!Ue||j!==null&&j.l===null}var Xe=[];function Ze(){var e=Xe;Xe=[],p(e)}function Qe(e){if(Xe.length===0&&!Ot){var t=Xe;queueMicrotask(()=>{t===Xe&&Ze()})}Xe.push(e)}function $e(){for(;Xe.length>0;)Ze()}var et=~(v|y|_);function M(e,t){e.f=e.f&et|t}function tt(e){e.f&512||e.deps===null?M(e,_):M(e,y)}function nt(e){if(e!==null)for(let t of e)t.f&2&&t.f&65536&&(t.f^=te,nt(t.deps))}function rt(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),nt(e.deps),M(e,_)}var it=!1;function at(e){var t=it;try{return it=!1,[e(),it]}finally{it=t}}function ot(e){O&&cn(e)!==null&&un(e)}var st=!1;function ct(){st||(st=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[pe]?.()})},{capture:!0}))}function lt(e){var t=H,n=U;Gn(null),Kn(null);try{return e()}finally{Gn(t),Kn(n)}}function ut(e,t,n,r=n){e.addEventListener(t,()=>lt(n));let i=e[pe];e[pe]=i?()=>{i(),r(!0)}:()=>r(!0),ct()}function dt(e,t,n,r){let i=Ye()?ht:vt;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=U,c=ft(),l=a.length===1?a[0].promise:a.length>1?Promise.all(a.map(e=>e.promise)):null;function u(e){if(!(s.f&16384)){c();try{r([...o,...e])}catch(e){hn(e,s)}pt()}}var d=mt();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>_t(e))).then(u).catch(e=>hn(e,s)).finally(d)}l?l.then(()=>{c(),f(),pt()}):f()}function ft(){var e=U,t=H,n=j,r=P;return function(i=!0){Kn(e),Gn(t),Ge(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function pt(e=!0){Kn(null),Gn(null),Ge(null),e&&P?.deactivate()}function mt(){var e=U,t=e.b,n=P,r=!!t?.is_rendered();return t?.update_pending_count(1,n),n.increment(r,e),()=>{t?.update_pending_count(-1,n),n.decrement(r,e)}}function ht(e){var t=2|v;return U!==null&&(U.f|=T),{ctx:j,deps:null,effects:null,equals:Oe,f:t,fn:e,reactions:null,rv:0,v:D,wv:0,parent:U,ac:null}}var gt=Symbol(`obsolete`);function _t(e,t,n){let r=U;r===null&&Me();var i=void 0,a=Gt(D),o=!H,s=new Set;return Tn(()=>{var t=U,n=m();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==me&&n.reject(e)}).finally(pt)}catch(e){n.reject(e),pt()}var c=P;if(o){if(t.f&32768)var l=mt();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(gt);else for(let e of s.values())e.reject(gt);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==gt&&(c.activate(),t?(a.f|=ie,qt(a,t)):(a.f&8388608&&(a.f^=ie),qt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),bn(()=>{for(let e of s)e.reject(gt)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function N(e){let t=ht(e);return Jn(t),t}function vt(e){let t=ht(e);return t.equals=Ae,t}function yt(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(me),t.ac=null}),t.fn!==null&&(t.teardown=f),lr(t,0),An(t))}function Ct(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&ur(t)}var wt=null,P=null,Tt=null,Et=null,Dt=null,Ot=!1,kt=!1,At=null,jt=null,Mt=0,Nt=1,Pt=class e{id=Nt++;#e=!1;linked=!0;#t=null;#n=null;async_deriveds=new Map;current=new Map;previous=new Map;#r=new Set;#i=new Set;#a=0;#o=new Map;#s=null;#c=[];#l=[];#u=new Set;#d=new Set;#f=new Map;#p=new Set;is_fork=!1;#m=!1;constructor(){wt===null?wt=this:(wt.#n=this,this.#t=wt),wt=this}#h(){if(this.is_fork)return!0;for(let n of this.#o.keys()){for(var e=n,t=!1;e.parent!==null;){if(this.#f.has(e)){t=!0;break}e=e.parent}if(!t)return!0}return!1}skip_effect(e){this.#f.has(e)||this.#f.set(e,{d:[],m:[]}),this.#p.delete(e)}unskip_effect(e,t=e=>this.schedule(e)){var n=this.#f.get(e);if(n){this.#f.delete(e);for(var r of n.d)M(r,v),t(r);for(r of n.m)M(r,y),t(r)}this.#p.add(e)}#g(){this.#e=!0,Mt++>1e3&&(this.#x(),It());for(let e of this.#u)this.#d.delete(e),M(e,v),this.schedule(e);for(let e of this.#d)M(e,y),this.schedule(e);let t=this.#c;this.#c=[],this.apply();var n=At=[],r=[],i=jt=[];for(let e of t)try{this.#_(e,n,r)}catch(t){throw Vt(e),this.#h()||this.discard(),t}if(P=null,i.length>0){var a=e.ensure();for(let e of i)a.schedule(e)}if(At=null,jt=null,this.#h()){this.#b(r),this.#b(n);for(let[e,t]of this.#f)Bt(e,t);i.length>0&&P.#g();return}let o=this.#v();if(o){this.#b(r),this.#b(n),o.#y(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),Tt=this,Rt(r),Rt(n),Tt=null,this.#s?.resolve();var s=P;if(this.#a===0&&(this.#c.length===0||s!==null)&&this.#x(),this.#c.length>0){if(s!==null){let e=s;e.#c.push(...this.#c.filter(t=>!e.#c.includes(t)))}else s=this}s!==null&&(Ut.clear(),s.#g())}#_(e,t,n){e.f^=_;for(var r=e.first;r!==null;){var i=r.f,a=!!(i&96);if(!(a&&i&1024||i&8192||this.#f.has(r))&&r.fn!==null){a?r.f^=_:i&4?t.push(r):ir(r)&&(i&16&&this.#d.add(r),ur(r));var o=r.first;if(o!==null){r=o;continue}}for(;r!==null;){var s=r.next;if(s!==null){r=s;break}r=r.parent}}}#v(){for(var e=this.#t;e!==null;){if(!e.is_fork){for(let[t,[,n]]of this.current)if(e.current.has(t)&&!n)return e}e=e.#t}return null}#y(e){for(let[t,n]of e.current)!this.previous.has(t)&&e.previous.has(t)&&this.previous.set(t,e.previous.get(t)),this.current.set(t,n);for(let[t,n]of e.async_deriveds){let e=this.async_deriveds.get(t);e&&n.promise.then(e.resolve).catch(e.reject)}e.async_deriveds.clear(),this.transfer_effects(e.#u,e.#d);let t=e=>{var n=e.reactions;if(n!==null&&!(e.f&2&&!(e.f&6144)))for(let e of n){var r=e.f;if(r&2)t(e);else{var i=e;r&4194320&&!this.async_deriveds.has(i)&&(this.#d.delete(i),M(i,v),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#x(),P=this,this.#g()}#b(e){for(var t=0;t{this.#m=!1,this.linked&&this.flush()}))}transfer_effects(e,t){for(let t of e)this.#u.add(t);for(let e of t)this.#d.add(e);e.clear(),t.clear()}oncommit(e){this.#r.add(e)}ondiscard(e){this.#i.add(e)}settled(){return(this.#s??=m()).promise}static ensure(){if(P===null){let t=P=new e;!kt&&!Ot&&Qe(()=>{t.#e||t.flush()})}return P}apply(){Et=null}schedule(e){if(Dt=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}for(var t=e;t.parent!==null;){t=t.parent;var n=t.f;if(At!==null&&t===U&&(H===null||!(H.f&2)))return;if(n&96){if(!(n&1024))return;t.f^=_}}this.#c.push(t)}#x(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?wt=e:t.#t=e,this.linked=!1}}};function Ft(e){var t=Ot;Ot=!0;try{var n;for(e&&(P!==null&&!P.is_fork&&P.flush(),n=e());;){if($e(),P===null)return n;P.flush()}}finally{Ot=t}}function It(){try{Le()}catch(e){hn(e,Dt)}}var Lt=null;function Rt(e){var t=e.length;if(t!==0){for(var n=0;n0)){Ut.clear();for(let e of Lt){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Lt.has(n)&&(Lt.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||ur(n)}}Lt.clear()}}Lt=null}}function zt(e){P.schedule(e)}function Bt(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),M(e,_);for(var n=e.first;n!==null;)Bt(n,t),n=n.next}}function Vt(e){M(e,_);for(var t=e.first;t!==null;)Vt(t),t=t.next}var Ht=new Set,Ut=new Map,Wt=!1;function Gt(e,t){return{f:0,v:e,reactions:null,equals:Oe,rv:0,wv:0}}function F(e,t){let n=Gt(e,t);return Jn(n),n}function Kt(e,t=!1,n=!0){let r=Gt(e);return t||(r.equals=Ae),Ue&&n&&j!==null&&j.l!==null&&(j.l.s??=[]).push(r),r}function I(e,t,n=!1){return H!==null&&(!Wn||H.f&131072)&&Ye()&&H.f&4325394&&(qn===null||!qn.has(e))&&Ve(),qt(e,n?Qt(t):t,jt)}function qt(e,t,n=null){if(!e.equals(t)){Hn?Ut.set(e,t):Ut.has(e)||Ut.set(e,e.v);var r=Pt.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&&bt(t),Et===null&&tt(t)}e.wv=rr(),Zt(e,v,n),Ye()&&U!==null&&U.f&1024&&!(U.f&96)&&(Zn===null?Qn([e]):Zn.push(e)),!r.is_fork&&Ht.size>0&&!Wt&&Jt()}return t}function Jt(){Wt=!1;for(let e of Ht){e.f&1024&&M(e,y);let t;try{t=ir(e)}catch{t=!0}t&&ur(e)}Ht.clear()}function Yt(e,t=1){var n=W(e),r=t===1?n++:n--;return I(e,n),r}function Xt(e){I(e,e.v+1)}function Zt(e,t,n){var r=e.reactions;if(r!==null)for(var i=Ye(),a=r.length,o=0;o{if(tr===d)return e();var t=H,n=tr;Gn(null),nr(d);var r=e();return Gn(t),nr(n),r};return i&&r.set(`length`,F(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&ze();var i=r.get(t);return i===void 0?f(()=>{var e=F(n.value,u);return r.set(t,e),e}):I(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>F(D,u));r.set(t,e),Xt(o)}}else I(n,D),Xt(o);return!0},get(e,n,i){if(n===ae)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>F(Qt(s?e[n]:D),u)),r.set(n,o)),o!==void 0){var c=W(o);return c===D?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){var n=Reflect.getOwnPropertyDescriptor(e,t);if(n&&`value`in n){var i=r.get(t);i&&(n.value=W(i))}else if(n===void 0){var a=r.get(t),o=a?.v;if(a!==void 0&&o!==D)return{enumerable:!0,configurable:!0,value:o,writable:!0}}return n},has(e,t){if(t===ae)return!0;var n=r.get(t),i=n!==void 0&&n.v!==D||Reflect.has(e,t);return(n!==void 0||U!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>F(i?Qt(e[t]):D,u)),r.set(t,n)),W(n)===D)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dF(D,u)),r.set(d+``,p)):I(p,D)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>F(void 0,u)),I(c,Qt(n)),r.set(t,c));else{l=c.v!==D;var m=f(()=>Qt(n));I(c,m)}var h=Reflect.getOwnPropertyDescriptor(e,t);if(h?.set&&h.set.call(s,n),!l){if(i&&typeof t==`string`){var g=r.get(`length`),_=Number(t);Number.isInteger(_)&&_>=g.v&&I(g,_+1)}Xt(o)}return!0},ownKeys(e){W(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==D});for(var[n,i]of r)i.v!==D&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Be()}})}function $t(e){try{if(typeof e==`object`&&e&&ae in e)return e[ae]}catch{}return e}function en(e,t){return Object.is($t(e),$t(t))}var tn,nn,rn,an;function on(){if(tn===void 0){tn=window,nn=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;rn=a(t,`firstChild`).get,an=a(t,`nextSibling`).get,u(e)&&(e[ue]=void 0,e[le]=null,e[de]=void 0,e.__e=void 0),u(n)&&(n[fe]=void 0)}}function sn(e=``){return document.createTextNode(e)}function cn(e){return rn.call(e)}function ln(e){return an.call(e)}function L(e,t){if(!O)return cn(e);var n=cn(k);if(n===null)n=k.appendChild(sn());else if(t&&n.nodeType!==3){var r=sn();return n?.before(r),Ce(r),r}return t&&pn(n),Ce(n),n}function R(e,t=!1){if(!O){var n=cn(e);return n instanceof Comment&&n.data===``?ln(n):n}if(t){if(k?.nodeType!==3){var r=sn();return k?.before(r),Ce(r),r}pn(k)}return k}function z(e,t=!1){if(!O)return cn(e);var n=L(e,t);return A(e),n}function B(e,t=1,n=!1){let r=O?k:e;for(var i;t--;)i=r,r=ln(r);if(!O)return r;if(n){if(r?.nodeType!==3){var a=sn();return r===null?i?.after(a):r.before(a),Ce(a),a}pn(r)}return Ce(r),r}function un(e){e.textContent=``}function dn(){return!1}function fn(e,t,n){return t==null||t===`http://www.w3.org/1999/xhtml`?n?document.createElement(e,{is:n}):document.createElement(e):n?document.createElementNS(t,e,{is:n}):document.createElementNS(t,e)}function pn(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===3;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}function mn(e){var t=U;if(t===null)return H.f|=ie,e;if(!(t.f&32768)&&!(t.f&4))throw e;hn(e,t)}function hn(e,t){if(!(t!==null&&t.f&16384)){for(;t!==null;){if(t.f&128&&!(t.f&33570816)){if(!(t.f&32768))throw e;try{t.b.error(e);return}catch(t){e=t}}t=t.parent}throw e}}function gn(e){U===null&&(H===null&&Ie(e),Fe()),Hn&&Pe(e)}function _n(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function vn(e,t){var n=U;n!==null&&n.f&8192&&(e|=b);var r={ctx:j,deps:null,nodes:null,f:e|v|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};P?.register_created_effect(r);var i=r;if(e&4)At===null?Pt.ensure().schedule(r):At.push(r);else if(t!==null){try{ur(r)}catch(e){throw Mn(r),e}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&!(i.f&524288)&&(i=i.first,e&16&&e&65536&&i!==null&&(i.f|=w))}if(i!==null&&(i.parent=n,n!==null&&_n(i,n),H!==null&&H.f&2&&!(e&64))){var a=H;(a.effects??=[]).push(i)}return r}function yn(){return H!==null&&!Wn}function bn(e){let t=vn(8,null);return M(t,_),t.teardown=e,t}function xn(e){gn(`$effect`);var t=U.f;if(!H&&t&32&&j!==null&&!j.i){var n=j;(n.e??=[]).push(e)}else return Sn(e)}function Sn(e){return vn(4|E,e)}function Cn(e){Pt.ensure();let t=vn(64|T,e);return(e={})=>new Promise(n=>{e.outro?Fn(t,()=>{Mn(t),n(void 0)}):(Mn(t),n(void 0))})}function wn(e){return vn(4,e)}function Tn(e){return vn(re|T,e)}function En(e,t=0){return vn(8|t,e)}function V(e,t=[],n=[],r=[]){dt(r,t,n,t=>{vn(8,()=>{e(...t.map(W))})})}function Dn(e,t=0){return vn(16|t,e)}function On(e){return vn(32|T,e)}function kn(e){var t=e.teardown;if(t!==null){let n=Hn,r=H;Un(!0),Gn(null);try{t.call(null)}catch(t){hn(t,e.parent)}finally{Un(n),Gn(r)}}}function An(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&<(()=>{e.abort(me)});var r=n.next;n.f&64?n.parent=null:Mn(n,t),n=r}}function jn(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||Mn(t),t=n}}function Mn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Nn(e.nodes.start,e.nodes.end),n=!0),e.f|=C,An(e,t&&!n),lr(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();kn(e),e.f^=C,e.f|=x;var i=e.parent;i!==null&&i.first!==null&&Pn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Nn(e,t){for(;e!==null;){var n=e===t?null:ln(e);e.remove(),e=n}}function Pn(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function Fn(e,t,n=!0){var r=[];e.f|=256,In(e,r,!0);var i=()=>{n&&Mn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function In(e,t,n){if(!(e.f&8192)){e.f^=b;var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)(e.is_global||n)&&t.push(e);for(var i=e.first;i!==null;){var a=i.next;if(!(i.f&64)){var o=!!(i.f&65536)||!!(i.f&32)&&!!(e.f&16);In(i,t,o?n:!1)}i=a}}}function Ln(e){e.f&=-257,Rn(e,!0)}function Rn(e,t){if(!(e.f&256)&&e.f&8192){e.f^=b,e.f&1024||(M(e,v),Pt.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Rn(n,i?t:!1),n=r}var a=e.nodes&&e.nodes.t;if(a!==null)for(let e of a)(e.is_global||t)&&e.in()}}function zn(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:ln(n);t.append(n),n=i}}var Bn=null,Vn=!1,Hn=!1;function Un(e){Hn=e}var H=null,Wn=!1;function Gn(e){H=e}var U=null;function Kn(e){U=e}var qn=null;function Jn(e){H!==null&&(qn??=new Set).add(e)}var Yn=null,Xn=0,Zn=null;function Qn(e){Zn=e}var $n=1,er=0,tr=er;function nr(e){tr=e}function rr(){return++$n}function ir(e){var t=e.f;if(t&2048)return!0;if(t&2&&(e.f&=~te),t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&&Et===null&&M(e,_)}return!1}function ar(e,t,n=!0){var r=e.reactions;if(r!==null&&!(qn!==null&&qn.has(e)))for(var i=0;i{e.ac.abort(me)}),e.ac=null);try{e.f|=ne;var u=e.fn,d=u();e.f|=S;var f=sr(e);if(Ye()&&Zn!==null&&!Wn&&f!==null&&!(e.f&6146))for(var p=0;p0)for(t.length=Xn+Yn.length,r=0;r{s.ac.abort(me),s.ac=null,M(s,v)}),St(s),lr(s,0)}}function lr(e,t){var n=e.deps;if(n!==null)for(var r=t;rn?.call(this,e))}return e.startsWith(`pointer`)||e.startsWith(`touch`)||e===`wheel`?Qe(()=>{t.addEventListener(e,i,r)}):t.addEventListener(e,i,r),i}function xr(e,t,n,r,i){var a={capture:r,passive:i},o=br(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&bn(()=>{t.removeEventListener(e,o,a)})}function G(e,t,n){(t[_r]??={})[e]=n}function Sr(e){for(var t=0;t{wr=!1,Cr=null}));var s=0,c=Cr===e&&e[_r];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[_r]=t;return}var u=a.indexOf(t);if(u===-1)return;l<=u&&(s=l)}if(o=a[s]||e.target,o!==t){i(e,`currentTarget`,{configurable:!0,get(){return o||n}});var d=H,f=U;Gn(null),Kn(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[_r]?.[r];h!=null&&(!o.disabled||e.target===o)&&h.call(o,e)}catch(e){p?m.push(e):p=e}if(e.cancelBubble)break;s++,o=s{throw e});throw p}}finally{e[_r]=t,delete e.currentTarget,Gn(d),Kn(f)}}}var Er=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy(`svelte-trusted-html`,{createHTML:e=>e});function Dr(e){return Er?.createHTML(e)??e}function Or(e){var t=fn(`template`);return t.innerHTML=Dr(e.replaceAll(``,``)),t.content}function kr(e,t){var n=U;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function K(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(O)return kr(k,null),k;i===void 0&&(i=Or(a?e:``+e),n||(i=cn(i)));var t=r||nn?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=cn(t),s=t.lastChild;kr(o,s)}else kr(t,t);return t}}function Ar(e,t,n=`svg`){var r=!e.startsWith(``),i=!!(t&1),a=`<${n}>${r?e:``+e}`,o;return()=>{if(O)return kr(k,null),k;if(!o){var e=cn(Or(a));if(i)for(o=document.createDocumentFragment();cn(e);)o.appendChild(cn(e));else o=cn(e)}var t=o.cloneNode(!0);if(i){var n=cn(t),r=t.lastChild;kr(n,r)}else kr(t,t);return t}}function jr(e,t){return Ar(e,t,`svg`)}function Mr(){if(O)return kr(k,null),k;var e=document.createDocumentFragment(),t=document.createComment(``),n=sn();return e.append(t,n),kr(t,n),e}function q(e,t){if(O){var n=U;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=k),we();return}e!==null&&e.before(t)}function Nr(){if(O&&k&&k.nodeType===8&&k.textContent?.startsWith(`$`)){let e=k.textContent.substring(1);return we(),e}return(window.__svelte??={}).uid??=1,`c${window.__svelte.uid++}`}function Pr(e){let t=0,n=Gt(0),r;return()=>{yn()&&(W(n),En(()=>(t===0&&(r=mr(()=>e(()=>Xt(n)))),t+=1,()=>{Qe(()=>{--t,t===0&&(r?.(),r=void 0,Xt(n))})})))}}var Fr=w|T;function Ir(e,t,n,r){new Lr(e,t,n,r)}var Lr=class{parent;is_pending=!1;transform_error;#e;#t=O?k:null;#n;#r;#i;#a=null;#o=null;#s=null;#c=null;#l=0;#u=0;#d=!1;#f=new Set;#p=new Set;#m=null;#h=Pr(()=>(this.#m=Gt(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=U;t.b=this,t.f|=128,n(e)},this.parent=U.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=Dn(()=>{if(O){let e=this.#t;we();let t=e.data===`[!`;if(e.data.startsWith(`[?`)){let t=JSON.parse(e.data.slice(2));this.#_(t)}else t?this.#y():this.#g()}else this.#b()},Fr),O&&(this.#e=k)}#g(){try{this.#a=On(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Qe(r),t&&(this.#s=On(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){xe();return}t=!0,n&&He(),this.#s!==null&&Fn(this.#s,()=>{this.#s=null}),this.#S(()=>{this.#b()})};return{reset:r,invoke_onerror:()=>{try{n=!0,this.#n.onerror?.(e,r),n=!1}catch(e){hn(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=On(()=>e(this.#e)),Qe(()=>{var e=this.#c=document.createDocumentFragment(),t=sn(),n=!1;if(e.append(t),this.#a=this.#S(()=>{try{return On(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){hn(e,this.#i.parent)}return null}}),this.#a===null){this.#c=null,n&&this.#x(P);return}this.#u===0&&(this.#e.before(e),this.#c=null,Fn(this.#o,()=>{this.#o=null}),this.#x(P))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=On(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();zn(this.#a,e);let t=this.#n.pending;this.#o=On(()=>t(this.#e))}else this.#x(P)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){rt(e,this.#f,this.#p)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#n.pending}#S(e){var t=U,n=H,r=j;Kn(this.#i),Gn(this.#i),Ge(this.#i.ctx);try{return Pt.ensure(),e()}finally{Kn(t),Gn(n),Ge(r)}}#C(e,t){if(!this.has_pending_snippet()){this.parent&&this.parent.#C(e,t);return}this.#u+=e,this.#u===0&&(this.#x(t),this.#o&&Fn(this.#o,()=>{this.#o=null}),this.#c&&=(this.#e.before(this.#c),null))}update_pending_count(e,t){this.#C(e,t),this.#l+=e,!(!this.#m||this.#d)&&(this.#d=!0,Qe(()=>{this.#d=!1,this.#m&&qt(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),W(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;P?.is_fork?(this.#a&&P.skip_effect(this.#a),this.#o&&P.skip_effect(this.#o),this.#s&&P.skip_effect(this.#s),P.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(Mn(this.#a),null),this.#o&&=(Mn(this.#o),null),this.#s&&=(Mn(this.#s),null),O&&(Ce(this.#t),Te(),Ce(Ee()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return On(()=>{var r=U;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return hn(e,this.#i.parent),null}}))};Qe(()=>{var t;try{t=this.transform_error(e)}catch(e){hn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>hn(e,this.#i&&this.#i.parent)):n(t)})}};function J(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[fe]??=e.nodeValue)&&(e[fe]=n,e.nodeValue=`${n}`)}function Rr(e,t){return Br(e,t)}var zr=new Map;function Br(e,{target:t,anchor:n,props:i={},events:a,context:o,intro:s=!0,transformError:c}){on();var l=void 0,u=Cn(()=>{var s=n??t.appendChild(sn());Ir(s,{pending:()=>{}},t=>{Ke({});var n=j;if(o&&(n.c=o),a&&(i.$$events=a),O&&kr(t,null),l=e(t,i)||Je(),O&&(U.nodes.end=k,k===null||k.nodeType!==8||k.data!==`]`))throw ye(),ge;qe()},c);var u=new Set,d=e=>{for(var n=0;n{for(var e of u)for(let n of[t,document]){var r=zr.get(n),i=r.get(e);--i==0?(n.removeEventListener(e,Tr),r.delete(e),r.size===0&&zr.delete(n)):r.set(e,i)}yr.delete(d),s!==n&&s.parentNode?.removeChild(s)}});return Vr.set(l,u),l}var Vr=new WeakMap,Hr=class{anchor;#e=new Map;#t=new Map;#n=new Map;#r=new Set;#i=!0;constructor(e,t=!0){this.anchor=e,this.#i=t}#a=e=>{if(this.#e.has(e)){var t=this.#e.get(e),n=this.#t.get(t);if(n)Ln(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(Ln(r.effect),this.#t.set(t,r.effect),this.#n.delete(t),r.fragment.lastChild.remove(),this.anchor.before(r.fragment),n=r.effect)}for(let[t,n]of this.#e){if(this.#e.delete(t),t===e)break;let r=this.#n.get(n);r&&(Mn(r.effect),this.#n.delete(n))}for(let[e,r]of this.#t){if(e===t||this.#r.has(e))continue;let i=()=>{if(Array.from(this.#e.values()).includes(e)){var t=document.createDocumentFragment();zn(r,t),t.append(sn()),this.#n.set(e,{effect:r,fragment:t})}else Mn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),Fn(r,i,!1)):i()}}};#o=e=>{this.#e.delete(e);let t=Array.from(this.#e.values());for(let[e,n]of this.#n)t.includes(e)||(Mn(n.effect),this.#n.delete(e))};ensure(e,t){var n=P,r=dn();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=sn();i.append(a),this.#n.set(e,{effect:On(()=>t(a)),fragment:i})}else this.#t.set(e,On(()=>t(this.anchor)))}if(this.#e.set(n,e),r){for(let[t,r]of this.#t)t===e?n.unskip_effect(r):n.skip_effect(r);for(let[t,r]of this.#n)t===e?n.unskip_effect(r.effect):n.skip_effect(r.effect);n.oncommit(this.#a),n.ondiscard(this.#o)}else O&&(this.anchor=k),this.#a(n)}};function Y(e,t,n=!1){var r;O&&(r=k,we());var i=new Hr(e),a=n?w:0;function o(e,t){if(O){var n=De(r);if(e!==parseInt(n.substring(1))){var a=Ee();Ce(a),i.anchor=a,Se(!1),i.ensure(e,t),Se(!0);return}}i.ensure(e,t)}Dn(()=>{var e=!1;t((t,n=0)=>{e=!0,o(n,t)}),e||o(-1,null)},a)}var Ur=Symbol(`NaN`);function Wr(e,t,n){O&&we();var r=new Hr(e),i=!Ye();Dn(()=>{var e=t();e!==e&&(e=Ur),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function X(e,t){return t}function Gr(e,t,n){for(var i=[],a=t.length,o,s=t.length,c=0;c{if(o){if(o.pending.delete(n),o.done.add(n),o.pending.size===0){var t=e.outrogroups;Kr(e,r(o.done)),t.delete(o),t.size===0&&(e.outrogroups=null)}}else--s},!1)}if(s===0){var l=i.length===0&&n!==null&&e.pending.size===0;if(l){var u=n,d=u.parentNode;un(d),d.append(u),e.items.clear()}Kr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Kr(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(let t of e.pending.values())for(let n of t)r.add(e.items.get(n).e)}for(var i=0;i{var t=i();return e(t)?t:t==null?[]:r(t)}),p,m=new Map,h=!0;function g(e){v.effect.f&16384||(v.pending.delete(e),v.fallback=d,Yr(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=ee,Zr(d,null,c)):Ln(d):Fn(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:Dn(()=>{p=W(f);var e=p.length;let t=!1;O&&De(c)===`[!`!=(e===0)&&(c=Ee(),Ce(c),Se(!1),t=!0);for(var r=new Set,u=P,v=dn(),y=0;ys(c)):(d=On(()=>s(qr??=sn())),d.f|=ee)),e>r.size&&Ne(``,``,``),O&&e>0&&Ce(Ee()),!h){if(m.set(u,r),v){for(let[e,t]of l)r.has(e)||u.skip_effect(t.e);u.oncommit(g),u.ondiscard(_)}else g(u)}t&&Se(!0),W(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,O&&(c=k)}function Jr(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function Yr(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=Jr(e.effect.first),u,d=null,f,p=[],m=[],h,g,_,v;if(o)for(v=0;v0){var E=i&4&&s===0?n:null;if(o){for(v=0;v{if(f!==void 0)for(_ of f)_.nodes?.a?.apply()})}function Xr(e,t,n,r,i,a,o,s){var c=o&1?o&16?Gt(n):Kt(n,!1,!1):null,l=o&2?Gt(i):null;return{v:c,i:l,e:On(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function Zr(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,a=t&&!(t.f&33554432)?t.nodes.start:n;r!==null;){var o=ln(r);if(a.before(r),r===i)return;r=o}}function Qr(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function $r(e,t,n){var r;O&&(r=k,we());var i=new Hr(e);Dn(()=>{var e=t()??null;if(O&&De(r)===`[`!=(e!==null)){var a=Ee();Ce(a),i.anchor=a,Se(!1),i.ensure(e,e&&(t=>n(t,e))),Se(!0);return}i.ensure(e,e&&(t=>n(t,e)))},w)}var ei=[...` -\r\f\xA0\v`];function ti(e,t,n){var r=e==null?``:``+e;if(t&&(r=r?r+` `+t:t),n){for(var i of Object.keys(n))if(n[i])r=r?r+` `+i:i;else if(r.length)for(var a=i.length,o=0;(o=r.indexOf(i,o))>=0;){var s=o+a;(o===0||ei.includes(r[o-1]))&&(s===r.length||ei.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function ni(e,t=!1){var n=t?` !important;`:`;`,r=``;for(var i of Object.keys(e)){var a=e[i];a!=null&&a!==``&&(r+=` `+i+`: `+a+n)}return r}function ri(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function ii(e,t){if(t){var n=``,r,i;if(Array.isArray(t)?(r=t[0],i=t[1]):r=t,e){e=String(e).replaceAll(/\/\*.*?\*\//g,``).trim();var a=!1,o=0,s=!1,c=[];r&&c.push(...Object.keys(r).map(ri)),i&&c.push(...Object.keys(i).map(ri));var l=0,u=-1;let t=e.length;for(var d=0;d{t.every(mi)||(`__defaultValue`in e&&li(e,!1),`__value`in e&&ui(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),bn(()=>{t.disconnect()})}function fi(e,t,n=t){var r=new WeakSet,i=!0;ut(e,`change`,t=>{var i=t?`[selected]`:`:checked`,a;if(e.multiple)a=[].map.call(e.querySelectorAll(i),pi);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&pi(o)}n(a),e.__value=a,P!==null&&r.add(P)}),wn(()=>{var a=t();if(e===document.activeElement){var o=P;if(r.has(o))return}if(ui(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=pi(s),n(a))}e.__value=a,i=!1})}function pi(e){return`__value`in e?e.__value:e.value}function mi(e){if(e.target.closest(`selectedcontent`)!==null)return!0;if(e.type===`childList`){var t=[...e.addedNodes,...e.removedNodes];return t.length>0&&t.every(e=>e.nodeName===`SELECTEDCONTENT`)}return!1}var hi=Symbol(`is custom element`),gi=Symbol(`is html`),_i=he?`link`:`LINK`;function vi(e){if(O){var t=!1,n=()=>{if(!t){if(t=!0,e.hasAttribute(`value`)){var n=e.value;Q(e,`value`,null),e.value=n}if(e.hasAttribute(`checked`)){var r=e.checked;Q(e,`checked`,null),e.checked=r}}};e[pe]=n,Qe(n),ct()}}function Q(e,t,n,r){var i=yi(e);O&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===_i)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[ce]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&xi(e).has(t)?e[t]=n:e.setAttribute(t,n))}function yi(e){return e[le]??={[hi]:e.nodeName.includes(`-`),[gi]:e.namespaceURI===_e}}var bi=new Map;function xi(e){var t=e.getAttribute(`is`)||e.nodeName,n=bi.get(t);if(n)return n;bi.set(t,n=new Set);for(var r,i=e,a=Element.prototype;a!==i;){for(var s in r=o(i),r)r[s].set&&s!==`innerHTML`&&s!==`textContent`&&s!==`innerText`&&n.add(s);i=l(i)}return n}function Si(e,t,n=t){var r=new WeakSet;ut(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=Ei(e)?Di(a):a,n(a),P!==null&&r.add(P),await dr(),a!==(a=t())){var o=e.selectionStart,s=e.selectionEnd,c=e.value.length;if(e.value=a??``,s!==null){var l=e.value.length;o===s&&s===c&&l>c?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(s,l))}}}),(O&&e.defaultValue!==e.value||mr(t)==null&&e.value)&&(n(Ei(e)?Di(e.value):e.value),P!==null&&r.add(P)),En(()=>{var n=t();if(e===document.activeElement){var i=P;if(r.has(i))return}Ei(e)&&n===Di(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}var Ci=new Set;function wi(e,t,n,r,i=r){var a=n.getAttribute(`type`)===`checkbox`,o=e;let s=!1;if(t!==null)for(var c of t)o=o[c]??=[];o.push(n),ut(n,`change`,()=>{var e=n.__value;a&&(e=Ti(o,e,n.checked)),i(e)},()=>i(a?[]:null)),En(()=>{var e=r();if(O&&n.defaultChecked!==n.checked){s=!0;return}a?(e||=[],n.checked=e.includes(n.__value)):n.checked=en(n.__value,e)}),bn(()=>{var e=o.indexOf(n);e!==-1&&o.splice(e,1)}),Ci.has(o)||(Ci.add(o),Qe(()=>{o.sort((e,t)=>e.compareDocumentPosition(t)===4?-1:1),Ci.delete(o)})),Qe(()=>{if(s){var e=a?Ti(o,e,n.checked):o.find(e=>e.checked)?.__value;i(e)}})}function Ti(e,t,n){for(var r=new Set,i=0;i{var n=this.#e.get(e);n.delete(t),n.size===0&&(this.#e.delete(e),this.#t.unobserve(e))}}#r(){return this.#t??=new ResizeObserver(t=>{for(var n of t){e.entries.set(n.target,n);for(var r of this.#e.get(n.target)||[])r(n)}})}}({box:`border-box`});function ki(e,t,n){var r=Oi.observe(e,()=>n(e[t]));wn(()=>(mr(()=>n(e[t])),r))}function Ai(e,t,n,r,i){var a=()=>{r(n[e])};n.addEventListener(t,a),i?En(()=>{n[e]=i()}):a(),(n===document.body||n===window||n===document)&&bn(()=>{n.removeEventListener(t,a)})}var ji={get(e,t){let n=e.props.length;for(;n--;){let r=e.props[n];if(d(r)&&(r=r()),typeof r==`object`&&r&&t in r)return r[t]}},set(e,t,n){let r=e.props.length;for(;r--;){let i=e.props[r];d(i)&&(i=i());let o=a(i,t);if(o&&o.set)return o.set(n),!0}return!1},getOwnPropertyDescriptor(e,t){let n=e.props.length;for(;n--;){let r=e.props[n];if(d(r)&&(r=r()),typeof r==`object`&&r&&t in r){let e=a(r,t);return e&&!e.configurable&&(e.configurable=!0),e}}},has(e,t){if(t===ae||t===se)return!1;for(let n of e.props)if(d(n)&&(n=n()),n!=null&&t in n)return!0;return!1},ownKeys(e){let t=[];for(let n of e.props)if(d(n)&&(n=n()),n){for(let e in n)t.includes(e)||t.push(e);for(let e of Object.getOwnPropertySymbols(n))t.includes(e)||t.push(e)}return t}};function Mi(...e){return new Proxy({props:e},ji)}function Ni(e,t,n,r){var i=!Ue||!!(n&2),o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=ht(r),W(u)):(l&&(l=!1,c=s?mr(r):r),c);let f;if(o){var p=ae in e||se in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=at(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&Re(t),f(m)));var g=i?()=>{var n=e[t];return n===void 0?d():(l=!0,n)}:()=>{var n=e[t];return n!==void 0&&(c=void 0),n===void 0?c:n};if(i&&!(n&4))return g;if(f){var _=e.$$legacy;return(function(e,t){return arguments.length>0?((!i||!t||_||h)&&f(t?g():e),e):g()})}var v=!1,y=(n&1?ht:vt)(()=>(v=!1,g()));o&&W(y);var b=U;return(function(e,t){if(arguments.length>0){let n=t?W(y):i&&o?Qt(e):e;return I(y,n),v=!0,c!==void 0&&(c=n),e}return Hn&&v||b.f&16384?y.v:W(y)})}function Pi(e){j===null&&je(`onMount`),Ue&&j.l!==null?Fi(j).m.push(e):xn(()=>{let t=mr(e);if(typeof t==`function`)return t})}function Fi(e){var t=e.l;return t.u??={a:[],b:[],m:[]}}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);function Ii(e,t){if(e instanceof RegExp)return{keys:!1,pattern:e};var n,r,i,a,o=[],s=``,c=e.split(`/`);for(c[0]||c.shift();i=c.shift();)n=i[0],n===`*`?(o.push(`wild`),s+=`/(.*)`):n===`:`?(r=i.indexOf(`?`,1),a=i.indexOf(`.`,1),o.push(i.substring(1,~r?r:~a?a:i.length)),s+=~r&&!~a?`(?:/([^/]+?))?`:`/([^/]+?)`,~a&&(s+=(~r?`?`:``)+`\\`+i.substring(a))):s+=`/`+i;return{keys:o,pattern:RegExp(`^`+s+(t?`(?=$|/)`:`/?$`),`i`)}}var Li=new class{#e=F(Ri());get _loc(){return W(this.#e)}set _loc(e){I(this.#e,e)}#t=N(()=>this._loc.location);get _location(){return W(this.#t)}set _location(e){I(this.#t,e)}#n=N(()=>this._loc.querystring);get _querystring(){return W(this.#n)}set _querystring(e){I(this.#n,e)}#r=F(void 0);get _params(){return W(this.#r)}set _params(e){I(this.#r,e)}get loc(){return this._loc}get location(){return this._location}get querystring(){return this._querystring}get params(){return this._params}constructor(){typeof window<`u`?window.addEventListener(`hashchange`,()=>{this._loc=Ri()}):console.warn(`[svelte-spa-router] window 'window' is not defined, skipping initiation`)}};function Ri(){let e=typeof window<`u`?window.location.href:``,t=e.indexOf(`#/`),n=t>-1?e.substr(t+1):`/`,r=n.indexOf(`?`),i=``;return r>-1&&(i=n.substr(r+1),n=n.substr(0,r)),{location:n,querystring:i}}function zi(e){e?window.scrollTo(e.__svelte_spa_router_scrollX||0,e.__svelte_spa_router_scrollY||0):window.scrollTo(0,0)}function Bi(e,t){Ke(t,!0);let n=Ni(t,`routes`,19,()=>({})),r=Ni(t,`prefix`,3,``),i=Ni(t,`restoreScrollState`,3,!1),a=Ni(t,`onConditionsFailed`,3,()=>{}),o=Ni(t,`onRouteLoaded`,3,()=>{}),s=Ni(t,`onRouteLoading`,3,()=>{}),c=Ni(t,`onRouteEvent`,3,()=>{});class l{path;component;conditions;userData;props;_pattern;_keys;constructor(e,t){let n=e=>typeof e==`object`&&!!e&&e._sveltesparouter===!0;if(!t||typeof t!=`function`&&!n(t))throw Error(`Invalid component object`);if(!e||typeof e==`string`&&(e.length<1||e.charAt(0)!=`/`&&e.charAt(0)!=`*`)||typeof e==`object`&&!(e instanceof RegExp))throw Error(`Invalid value for "path" argument - strings must start with / or *`);let r=Ii(e);if(this.path=e,n(t)){let e=t;this.component=e.component,this.conditions=e.conditions||[],this.userData=e.userData,this.props=e.props||{}}else{let e=t;this.component=()=>Promise.resolve(e),this.conditions=[],this.props={}}this._pattern=r.pattern,this._keys=r.keys}match(e){if(r()){if(typeof r()==`string`){if(e.startsWith(r()))e=e.substr(r().length)||`/`;else return null}else if(r()instanceof RegExp){let t=e.match(r());if(t&&t[0])e=e.substr(t[0].length)||`/`;else return null}}let t=this._pattern.exec(e);if(t===null)return null;if(this._keys===!1)return t;let n={},i=0;for(;i{u.push(new l(t,e))}):Object.keys(n()).forEach(e=>{let t=n();u.push(new l(e,t[e]))});let d=F(null),f=F(null),p=F({}),m=null,h=null;xn(()=>{history.scrollRestoration=i()?`manual`:`auto`}),xn(()=>{if(!i())return;let e=e=>{m=e.state&&(e.state.__svelte_spa_router_scrollY||e.state.__svelte_spa_router_scrollX)?e.state:null};return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)});async function g(e,t){await dr(),e(t)}xn(()=>{let e=Li.loc,t=!1;return mr(async()=>{let n=0;for(;n{t=!0}});function _(e){return e&&typeof e==`object`&&Object.keys(e).length?e:null}var v=Mr(),y=R(v),b=e=>{let t=N(()=>W(d));var n=Mr(),r=R(n),i=e=>{var n=Mr();$r(R(n),()=>W(t),(e,t)=>{t(e,Mi({get params(){return W(f)},get onRouteEvent(){return c()}},()=>W(p)))}),q(e,n)},a=e=>{var n=Mr();$r(R(n),()=>W(t),(e,t)=>{t(e,Mi({get onRouteEvent(){return c()}},()=>W(p)))}),q(e,n)};Y(r,e=>{W(f)?e(i):e(a,-1)}),q(e,n)};Y(y,e=>{W(d)&&e(b)}),q(e,v),qe()}var Vi=[`bars`,`pace`,`zone`,`pie`,`fuel`,`resets`],Hi=`codexometer.web.preferences.v1`,Ui={tab:`quota`,view:`bars`,selected:``,defaultDetail:0,layouts:[]};function Wi(){try{let e=JSON.parse(localStorage.getItem(Hi)||`null`);return!e||typeof e!=`object`?Ui:{tab:[`quota`,`sessions`,`usage`].includes(e.tab)?e.tab:`quota`,view:Vi.includes(e.view)?e.view:`bars`,selected:typeof e.selected==`string`?e.selected.slice(0,256):``,defaultDetail:+(e.defaultDetail===1),layouts:Array.isArray(e.layouts)?e.layouts.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.id==`string`&&t.id.length<=256&&[0,1,2].includes(t.level)}).slice(-100):[]}}catch{return Ui}}var Gi=Qt(Wi());function Ki(){let e=JSON.stringify(Gi);try{localStorage.setItem(Hi,e)}catch{}}function qi(){return Gi.tab===`quota`?`/quota/`+Gi.view:`/`+Gi.tab}function Ji(e){return Gi.layouts.find(t=>t.id===e)?.level??Gi.defaultDetail}function Yi(e){Gi.defaultDetail=e,Gi.layouts=[]}function Xi(e,t){Gi.layouts=[...Gi.layouts.filter(t=>t.id!==e),{id:e,level:Math.max(0,Math.min(2,t))}].slice(-100)}var $=Qt({data:null,connected:!1,error:``}),Zi=e=>e==null?`Unavailable`:e.toLocaleString(`en-GB`),Qi=e=>!e||String(e).startsWith(`0001-`)?`Not yet available`:new Date(typeof e==`number`?e*1e3:e).toLocaleString(`en-GB`),$i=`codexometer.web.session`,ea=class extends Error{},ta;async function na(e,t,n){if(!ta||!$.connected||!$.data?.control||$.data.sessionsError)throw Error(`Session controls unavailable. Check the live connection.`);return await ta(e,t,n)}function ra(){let e=new AbortController,t,n=``;ta=async(t,r,i)=>{let a=await fetch(`/api/control/`+t,{method:`POST`,headers:{Authorization:`Bearer ${n}`,"Content-Type":`application/json`},body:JSON.stringify(r),signal:AbortSignal.any([e.signal,AbortSignal.timeout(8e3),...i?[i]:[]]),cache:`no-store`});if(!a.ok)throw a.status===502?Error(`Outcome uncertain. Check Codex before taking another action; nothing was retried.`):new ea(`Action rejected, expired or changed. Refresh and check Codex; nothing was retried.`);return a.json()};try{n=sessionStorage.getItem($i)||``}catch{}let r=location.hash,i=r.startsWith(`#pair=`)?r.slice(6):``;(i||!r||r===`#`)&&(history.replaceState(null,``,`/#`+qi()),window.dispatchEvent(new HashChangeEvent(`hashchange`)));async function a(){if(i)try{let t=await fetch(`/api/pair`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({secret:i}),signal:e.signal});if(!t.ok)throw Error(`Pairing link expired or already used. Restart --web for a fresh link.`);n=(await t.json()).token;try{sessionStorage.setItem($i,n)}catch{}}catch(t){e.signal.aborted||($.error=t instanceof Error?t.message:`Pairing failed`);return}if(!n){$.error=`Open the private pairing link printed by codexometer --web in your terminal.`;return}await o()}async function o(){try{let t=await fetch(`/api/events`,{headers:{Authorization:`Bearer ${n}`},signal:e.signal,cache:`no-store`});if(t.status===401){try{sessionStorage.removeItem($i)}catch{}$.error=`Browser session expired. Restart --web and open its new pairing link.`;return}if(!t.ok||!t.body)throw Error(`Live connection unavailable`);let r=t.body.getReader(),i=new TextDecoder,a=``;for(;!e.signal.aborted;){let{done:e,value:t}=await r.read();if(e)break;a+=i.decode(t,{stream:!0});let n;for(;(n=a.indexOf(` - -`))>=0;){let e=a.slice(0,n);a=a.slice(n+2),e.startsWith(`data: `)&&($.data=JSON.parse(e.slice(6)),$.connected=!0,$.error=``)}}}catch{}finally{$.connected=!1}e.signal.aborted||($.error=`Connection lost — showing last observation. Reconnecting…`,t=setTimeout(o,2500))}return a(),()=>{ta=void 0,e.abort(),clearTimeout(t),$.connected=!1}}var ia=jr(` `,1),aa=jr(` `,1),oa=K(` `),sa=K(`
      Quota observations
      Observed atPeriod elapsedConsumedTrail segment
      `),ca=K(`


      Observed quota - path, not individual session usage. Gaps are not interpolated. Expand the - observation table for times, positions and gaps.

      OBSERVATION TABLE
      `,1),la=K(`
      CONSUMPTIONQUOTA PERIOD ELAPSED


      `,1);function ua(e,t){let n=Nr();Ke(t,!0);let r=Ni(t,`trail`,19,()=>[]),i=F(!1),a=[0,25,50,75,100],o=F(400),s=F(240),c=N(()=>W(o)-24),l=N(()=>W(s)-48),u=N(()=>Math.max(1,W(c)-48)),d=N(()=>Math.max(1,W(l)-20)),f=N(()=>48+Math.max(0,Math.min(100,t.elapsed))/100*W(u)),p=N(()=>W(l)-Math.max(0,Math.min(100,t.used))/100*W(d)),m=N(()=>t.used-t.elapsed),h=N(()=>r().map((e,t)=>`${t===0||e.break?`M`:`L`}${48+e.elapsed/100*W(u)} ${W(l)-e.used/100*W(d)}`).join(` `));var g=la(),_=R(g),v=L(_),y=L(v),b=z(y),x=B(y),S=B(x);Z(S,17,()=>a,X,(e,t)=>{var n=ia(),r=R(n),i=B(r),a=B(i),o=z(a),s=B(a),f=z(s);V(()=>{Q(r,`x1`,48+W(t)/100*W(u)),Q(r,`x2`,48+W(t)/100*W(u)),Q(r,`y2`,W(l)),Q(i,`y1`,W(l)-W(t)/100*W(d)),Q(i,`x2`,W(c)),Q(i,`y2`,W(l)-W(t)/100*W(d)),Q(a,`x`,48+W(t)/100*W(u)),Q(a,`y`,W(l)+20),J(o,`${W(t)??``}%`),Q(s,`y`,W(l)+4-W(t)/100*W(d)),J(f,`${W(t)??``}%`)}),q(e,n)});var C=B(S),w=B(C),T=B(w),E=e=>{var t=aa(),n=R(t),i=B(n),a=z(L(i));A(i),V(e=>{Q(n,`d`,W(h)),Q(i,`cx`,48+r()[0].elapsed/100*W(u)),Q(i,`cy`,W(l)-r()[0].used/100*W(d)),J(a,`First observation: ${e??``}`)},[()=>Qi(r()[0].at)]),q(e,t)};Y(T,e=>{r().length&&e(E)});var ee=B(T,2),te=B(ee),ne=B(te),re=z(L(ne));A(ne),A(v),A(_);var ie=B(_,2),ae=L(ie),oe=z(B(ae,3),!0);A(ie);var se=B(ie,2),ce=e=>{var t=ca(),a=R(t),o=L(a);Te(2),A(a);var s=B(a,2),c=B(L(s),2),l=e=>{var t=sa(),n=L(t),i=B(L(n),2);Z(i,21,r,X,(e,t,n)=>{var r=oa(),i=L(r),a=L(i),o=z(a,!0);A(i);var s=B(i),c=z(s),l=B(s),u=z(l),d=z(B(l),!0);A(r),V((e,r)=>{Q(a,`datetime`,W(t).at),J(o,e),J(c,`${r??``}%`),J(u,`${W(t).used??``}%`),J(d,n===0?`First observation`:W(t).break?`Gap before this observation`:`Connected to previous observation`)},[()=>Qi(W(t).at),()=>W(t).elapsed.toFixed(1)]),q(e,r)}),A(i),A(n),A(t),q(e,t)};Y(c,e=>{W(i)&&e(l)}),A(s),V(e=>{Q(a,`id`,n+`-trail-summary`),J(o,`○ START ${e??``} // ${r().length??``} - ${r().length===1?`OBSERVATION`:`OBSERVATIONS`}`)},[()=>Qi(r()[0].at)]),Ai(`open`,`toggle`,s,e=>I(i,e),()=>W(i)),q(e,t)};Y(se,e=>{r().length&&e(ce)}),V((e,i,a,m)=>{Q(v,`viewBox`,`0 0 ${W(o)} ${W(s)}`),Q(v,`aria-describedby`,r().length?n+`-trail-summary`:void 0),Q(v,`aria-label`,e),Q(b,`id`,n),Q(x,`width`,W(u)),Q(x,`height`,W(d)),Q(x,`fill`,`url(#${n})`),Q(C,`d`,`M48 20 V${W(l)} H${W(c)}`),Q(w,`y1`,W(l)),Q(w,`x2`,W(c)),Q(ee,`x`,48+W(u)/2),Q(ee,`y`,W(s)-5),Q(te,`cx`,W(f)),Q(te,`cy`,W(p)),Q(ne,`cx`,W(f)),Q(ne,`cy`,W(p)),J(re,`${t.used??``}% consumed // ${i??``}% of period elapsed`),J(ae,`${t.used??``}% USED // ${a??``}% TIME ELAPSED`),J(oe,m)},[()=>`Consumption zone: ${t.used}% consumed, ${t.elapsed.toFixed(1)}% of quota period elapsed. ${W(m)>0?`Above`:W(m)<0?`Below`:`On`} the steady-consumption line.`,()=>t.elapsed.toFixed(1),()=>t.elapsed.toFixed(1),()=>Math.abs(W(m))<.05?`ON PACE`:W(m)>0?`ABOVE THE LINE — CONSUMING FASTER THAN TIME`:`BELOW THE LINE — WITHIN PACE`]),ki(_,`clientWidth`,e=>I(o,e)),ki(_,`clientHeight`,e=>I(s,e)),q(e,g),qe()}var da=K(` `),fa=K(`

      Quota refresh failed. Values below are the last successful observation.

      `),pa=K(`

      Expiry details unavailable. No listed expiry does not mean no expiry.

      `),ma=K(`

      `),ha=K(`

      Read-only preview. Use the terminal to redeem a reset.

      The backend may return only some credits. This list does not establish - redemption order.

      `),ga=K(` `,1),_a=jr(``),va=jr(``),ya=K(`
      `),ba=K(`

      Cycle duration or reset date unavailable — position cannot be - plotted.

      `),xa=K(`
      −100 // OVER BUDGET+100 // HEADROOM

      `,1),Sa=K(`

      Cycle duration unavailable — pace cannot be calculated.

      `),Ca=K(`
      EMPTYFULL
      `),wa=K(`

      `,1),Ta=K(`
      `,1),Ea=K(`

      `),Da=K(`

      `),Oa=K(`

      No quota windows reported yet.

      `),ka=K(`
      `,1),Aa=K(`

      All reported windows are shown. API-equivalent learning and quota status - scoring remain in the terminal for this first preview.

      `,1),ja=K(` `,1);function Ma(e,t){Ke(t,!0);let n=Ni(t,`params`,19,()=>({})),r=Vi,i=F(Qt(Date.now())),a=N(()=>r.includes(n().view||``)?n().view:`bars`);Pi(()=>{let e=setInterval(()=>I(i,Date.now(),!0),1e3);return()=>clearInterval(e)});function o(e){return!e.duration||e.duration<=0||!e.reset?null:Math.max(0,Math.min(100,100*(1-(e.reset*1e3-W(i))/(e.duration*6e4))))}xn(()=>{Gi.view=W(a)});function s(e){let t=e/100*Math.PI*2;return`M60 60 L60 14 A46 46 0 ${+(e>50)} 1 ${60+46*Math.sin(t)} ${60-46*Math.cos(t)} Z`}var c=ja(),l=R(c);Z(l,21,()=>r,X,(e,t)=>{var n=da();let r;var i=z(n,!0);V(e=>{Q(n,`href`,`#/quota/`+W(t)),Q(n,`aria-current`,W(a)===W(t)?`page`:void 0),r=ai(n,1,``,null,r,{active:W(a)===W(t)}),J(i,e)},[()=>W(t)===`pace`?`CONSUMPTION PACE`:W(t)===`zone`?`CONSUMPTION ZONE`:W(t)===`fuel`?`FUEL TANK`:W(t).toUpperCase()]),q(e,n)}),A(l);var u=B(l,2),d=e=>{var t=Aa(),n=R(t),r=e=>{q(e,fa())};Y(n,e=>{$.data.quotaError&&e(r)});var i=B(n,2),c=z(i),l=B(i,2),u=e=>{var t=ha(),n=L(t),r=z(n),i=B(n,4),a=e=>{q(e,pa())};Y(i,e=>{$.data.credits.length||e(a)}),Z(B(i,2),17,()=>$.data.credits,X,(e,t)=>{var n=ma(),r=L(n),i=z(r),a=z(B(r,2),!0);A(n),V(e=>{J(i,`${(W(t).title||`Quota reset`)??``} // ${W(t).status??``}`),J(a,e)},[()=>W(t).expiryKnown?W(t).expires?`EXPIRES `+Qi(W(t).expires):`Does not expire`:`Expiry information unavailable`]),q(e,n)}),Te(2),A(t),V(()=>J(r,`RESET INVENTORY // ${$.data.creditCount??``} AVAILABLE`)),q(e,t)},d=e=>{var t=ka(),n=R(t);let r;Z(n,21,()=>$.data.meters,X,(e,t)=>{let n=N(()=>o(W(t))),r=N(()=>W(n)===null?null:W(n)-W(t).used);var i=Da(),c=L(i),l=z(c,!0),u=B(c,2),d=L(u),f=e=>{var n=ga(),r=R(n),i=z(r),a=z(B(r));V(()=>{J(i,`FREE ${100-W(t).used}%`),J(a,`USED ${W(t).used??``}%`)}),q(e,n)},p=e=>{var n=ga(),r=R(n),i=z(r),a=z(B(r));V(()=>{J(i,`USED ${W(t).used??``}%`),J(a,`FREE ${100-W(t).used}%`)}),q(e,n)};Y(d,e=>{W(a)===`fuel`?e(f):e(p,-1)}),A(u);var m=B(u,2);let h;var g=L(m),_=e=>{var n=ya(),r=L(n),i=B(L(r)),a=e=>{q(e,_a())},o=e=>{var n=va();V(e=>Q(n,`d`,e),[()=>s(W(t).used)]),q(e,n)};Y(i,e=>{W(t).used>=100?e(a):W(t).used>0&&e(o,1)}),A(r),A(n),V(()=>Q(r,`aria-label`,`${W(t).used}% quota used`)),q(e,n)},v=e=>{var r=Mr(),i=R(r),a=e=>{{let r=N(()=>W(t).trail||[]);ua(e,{get used(){return W(t).used},get elapsed(){return W(n)},get trail(){return W(r)}})}},o=e=>{q(e,ba())};Y(i,e=>{W(n)===null?e(o,-1):e(a)}),q(e,r)},y=e=>{var t=Mr(),n=R(t),i=e=>{var t=xa(),n=R(t),i=B(L(n),2);let a;A(n);var o=B(n,4),s=L(o),c=z(B(s),!0);A(o),V(e=>{a=si(i,``,a,{left:`${(W(r)+100)/2}%`}),J(s,`${W(r)>=0?`+`:``}${e??``} PP `),J(c,W(r)>=0?`WITHIN PACE`:`USING FASTER THAN TIME`)},[()=>W(r).toFixed(1)]),q(e,t)},a=e=>{q(e,Sa())};Y(n,e=>{W(r)===null?e(a,-1):e(i)}),q(e,t)},b=e=>{var r=Ta(),i=R(r),o=L(i);let s;A(i);var c=B(i,2),l=e=>{q(e,Ca())};Y(c,e=>{W(a)===`fuel`&&e(l)});var u=B(c,2),d=e=>{var t=wa(),r=R(t),i=z(r),o=B(r,2),s=L(o);let c;A(o),V(e=>{J(i,`RESET CYCLE // ${e??``}% ELAPSED`),c=si(s,``,c,{width:`${W(a)===`fuel`?100-W(n):W(n)}%`})},[()=>Math.floor(W(n))]),q(e,t)};Y(u,e=>{W(n)!==null&&e(d)}),V(()=>{Q(i,`aria-label`,W(a)===`fuel`?`Fuel remaining`:`Quota used`),Q(i,`aria-valuenow`,W(a)===`fuel`?100-W(t).used:W(t).used),s=si(o,``,s,{width:`${W(a)===`fuel`?100-W(t).used:W(t).used}%`})}),q(e,r)};Y(g,e=>{W(a)===`pie`?e(_):W(a)===`zone`?e(v,1):W(a)===`pace`?e(y,2):e(b,-1)}),A(m);var x=B(m,2),S=z(x),C=B(x,2),w=e=>{var n=Ea(),r=z(n,!0);V(()=>J(r,W(t).details)),q(e,n)};Y(C,e=>{W(t).details&&e(w)}),A(i),V(e=>{J(l,W(t).name),h=ai(m,1,`meter-graphic`,null,h,{"bar-graphic":W(a)===`bars`||W(a)===`fuel`}),J(S,`RESETS // ${e??``}`)},[()=>Qi(W(t).reset)]),q(e,i)}),A(n);var i=B(n,2),c=e=>{q(e,Oa())};Y(i,e=>{$.data.meters.length||e(c)}),V(()=>r=ai(n,1,`quota-grid`,null,r,{radial:W(a)===`pie`,zone:W(a)===`zone`})),q(e,t)};Y(l,e=>{W(a)===`resets`?e(u):e(d,-1)}),Te(2),V(e=>J(c,`QUOTA // OBSERVED ${e??``}`),[()=>Qi($.data.quotaAt)]),q(e,t)};Y(u,e=>{$.data&&e(d)}),q(e,c),qe()}var Na=K(`
      `),Pa=K(`

      `,1);function Fa(e,t){Ke(t,!0);let n=Ni(t,`values`,19,()=>[]),r=Ni(t,`label`,3,`Token activity`),i=Ni(t,`capacity`,3,0),a=N(()=>Math.max(0,...n())),o=N(()=>i()>n().length?[...Array(i()-n().length).fill(0),...n()]:n());var s=Pa(),c=R(s),l=z(c),u=B(c,2);Z(u,21,()=>W(o),X,(e,t)=>{var n=Na();let r;V((e,t)=>{Q(n,`title`,e),r=si(n,``,r,{height:t})},[()=>W(t).toLocaleString(`en-GB`)+` tokens`,()=>`${100*W(t)/Math.max(1,W(a))}%`]),q(e,n)}),A(u),V((e,t)=>{J(l,`SCALE // 0 — ${e??``} TOKENS`),Q(u,`aria-label`,t)},[()=>W(a).toLocaleString(`en-GB`),()=>`${r()}. Peak ${W(a).toLocaleString(`en-GB`)} tokens.`]),q(e,s),qe()}var Ia=K(`

      CURRENT PROFILE

      MODEL / REASONING LEVEL / SPEED

       

      PROPOSED PROFILE

      MODEL / REASONING LEVEL / SPEED

       

      Applied settings remain after Codexometer closes.

      `,1),La=K(`

      `),Ra=K(`

       
      `,1),za=K(`

      Command unavailable from this observation. Open Codex to inspect the - request.

      `),Ba=K(`

      Session controls temporarily unavailable. Check Codex for current state.

      `),Va=K(`

      Checking session controls…

      `),Ha=K(`

      `),Ua=K(`
      About browser controls

      Controls require a supported live request from a connected shared - app-server session. Local observations alone cannot provide them.

      `),Wa=K(` `,1),Ga=K(` `),Ka=K(`Grants permission beyond this one command. Check the scope - carefully.`),qa=K(``),Ja=K(``),Ya=K(``),Xa=K(``),Za=K(` `,1),Qa=K(`
    • `),$a=K(`
      View fixed choices

      Type one of these choices exactly. Your answer stays masked.

        `),eo=K(` `,1),to=K(`

        `,1),no=K(``),ro=K(`

        `,1),io=K(`

        `);function ao(e,t){Ke(t,!0);let n=[],r=Ni(t,`observedCommand`,3,``),i=Ni(t,`review`,3,``),a=Ni(t,`suspended`,3,!1),o=Ni(t,`onProtectedChange`,3,e=>{}),s=F(null),c=F(Qt([])),l=F(null),u=F(``),d=F(0),f=F(Qt(Date.now())),p=F(!1),m=F(``),h=F(!1),g=F(!1),_=F(``);xn(()=>(o()(W(p)||W(c).some(e=>e.length>0)),()=>o()(!1)));let v=N(()=>$.data?.sessions.find(e=>e.id===t.session)?.status),y=N(()=>!$.connected||!!$.data?.sessionsError),b=N(()=>i()!==`profile`&&W(s)?.kind===`prompt`&&!W(s).questions?.length&&!!$.data?.profiles?.some(e=>e.session===t.session&&e.pending)),x=N(()=>!W(y)&&!W(g)&&!!W(s)?.id&&W(s).kind===`approval`&&W(_)!==W(s).id),S=N(()=>W(x)?W(s).command:r()),C=N(()=>!!W(u)&&W(f)W(s)?.questions?.length?W(s).questions:[{text:`Follow-up message`,secret:!1,freeText:!0,options:[]}]),T=N(()=>W(s)?.kind===`approval`||W(s)?.kind===`profile`?W(l)!==null:W(c).length===W(w).length&&W(c).every((e,t)=>e.trim().length>0&&(W(w)[t].freeText||W(w)[t].options?.includes(e))));xn(()=>{(W(y)||a()||W(b)||W(f)>=W(d))&&I(u,``)});let E=new AbortController;Pi(()=>{let e,n=setInterval(()=>{I(f,Date.now(),!0)},1e3);async function r(){try{let e=await na(`offer`,{session:t.session,...i()?{review:i()}:{}},E.signal);if(E.signal.aborted)return;I(g,!1),W(s)?.id!==e.id&&(I(u,``),I(l,null),I(c,Array(Math.max(1,e.questions?.length||0)).fill(``),!0)),I(s,e,!0),W(h)&&e.id&&e.id!==W(_)&&(I(m,``),I(h,!1))}catch{E.signal.aborted||(I(s,null),I(g,!0),I(u,``))}finally{E.signal.aborted||(e=setTimeout(r,2e3))}}return r(),()=>{E.abort(),clearTimeout(e),clearInterval(n)}});async function ee(){if(!W(s)?.id||W(p)||W(y)||a()||W(b)||!W(T))return;let e=W(s).id;I(p,!0),I(m,``),I(h,!1),I(u,``);try{let n=await na(`prepare`,{session:t.session,...i()?{review:i()}:{},offer:e,...W(s).kind===`approval`||W(s).kind===`profile`?{choice:W(l)}:{answers:[...W(c)]}},E.signal);W(s)?.id===e&&!E.signal.aborted&&!W(y)&&!a()&&!W(b)&&(I(u,n.confirmation,!0),I(d,Date.parse(n.expires),!0))}catch(e){E.signal.aborted||I(m,e instanceof Error?e.message:`Unable to prepare action.`,!0)}finally{I(p,!1)}}async function te(){if(!W(s)?.id||W(p)||a()||W(b)||!W(C))return;let e=W(s).id,n=W(s).kind,r=W(u);I(u,``),I(p,!0),I(_,e,!0);try{await na(`commit`,{session:t.session,...i()?{review:i()}:{},offer:e,confirmation:r},E.signal),I(h,!0),I(m,n===`profile`?`Profile decision completed.`:n===`approval`?`Decision sent.`:`Text sent.`,!0)}catch(e){I(m,e instanceof ea?e.message:`Outcome uncertain. Check Codex before taking another action; nothing was retried.`,!0)}finally{I(p,!1),I(c,[],!0),I(l,null)}}var ne=Mr(),re=R(ne),ie=e=>{var r=io(),a=L(r),o=z(a,!0),b=B(a,2),E=e=>{var t=Ia(),n=R(t),r=z(n),i=B(n,6),a=z(i,!0),o=z(B(i,6),!0);Te(2),V(()=>{J(r,`Your ${W(s).profile.threshold??``}% quota threshold has been reached. Review - the profile for subsequent turns.`),J(a,W(s).profile.current),J(o,W(s).profile.proposed)}),q(e,t)};Y(b,e=>{W(s)?.profile&&!W(y)&&!W(g)&&e(E)});var ne=B(b,2),re=e=>{var t=La();let n;var r=z(t,!0);V(()=>{n=ai(t,1,`svelte-1oupzfc`,null,n,{notice:!W(h),sent:W(h)}),J(r,W(m))}),q(e,t)};Y(ne,e=>{W(m)&&e(re)});var ie=B(ne,2),ae=e=>{var t=Ra(),n=R(t),r=z(n,!0),i=z(B(n,2),!0);V(()=>{J(r,W(x)?`EXACT COMMAND`:`LAST OBSERVED COMMAND`),J(i,W(S))}),q(e,t)},oe=e=>{q(e,za())};Y(ie,e=>{W(S)?e(ae):i()!==`profile`&&W(v)===`APPROVAL NEEDED`&&!W(h)&&e(oe,1)});var se=B(ie,2),ce=e=>{q(e,Ba())},le=e=>{q(e,Va())},ue=e=>{var t=Wa(),n=R(t),r=e=>{var t=Ha(),n=z(t,!0);V(e=>J(n,e),[()=>W(v)===`WORKING`?`Codex is working — nothing to respond to.`:[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(W(v)||``)?`Respond in Codex for this request.`:`Nothing needs a response right now.`]),q(e,t)};Y(n,e=>{(W(v)===`WORKING`||!W(h)&&!W(p))&&e(r)});var i=B(n,2),a=e=>{q(e,Ua())},o=N(()=>[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(W(v)||``)&&!W(h));Y(i,e=>{W(o)&&e(a)}),q(e,t)},de=e=>{var r=ro(),a=R(r),o=z(a),m=B(a,2),h=L(m),g=z(h,!0),_=B(h,2),v=e=>{var r=Mr();Z(R(r),17,()=>W(s).choices||[],X,(e,r,a)=>{var o=qa(),s=L(o);vi(s),s.value=s.__value=a;var c=B(s),u=B(c),d=e=>{var t=Ga(),n=z(t,!0);V(()=>J(n,W(r).detail)),q(e,t)};Y(u,e=>{W(r).detail&&e(d)});var f=B(u,2),p=e=>{q(e,Ka())};Y(f,e=>{W(r).persistent&&e(p)}),A(o),V(()=>{Q(s,`name`,`decision-`+t.session+`-`+i()),J(c,` ${W(r).label??``} `)}),wi(n,[],s,()=>W(l),e=>I(l,e)),q(e,o)}),q(e,r)},b=e=>{var t=Mr();Z(R(t),17,()=>W(w),X,(e,t,n)=>{var r=eo(),i=R(r),a=L(i),o=B(a),s=e=>{var t=Ja();vi(t),Si(t,()=>W(c)[n],e=>W(c)[n]=e),q(e,t)},l=e=>{var r=Xa(),i=L(r);i.value=i.__value=``,Z(B(i),17,()=>W(t).options||[],X,(e,t)=>{var n=Ya(),r=z(n,!0),i={};V(()=>{J(r,W(t)),i!==(i=W(t))&&(n.value=(n.__value=i)??``)}),q(e,n)}),A(r),di(r),fi(r,()=>W(c)[n],e=>W(c)[n]=e),q(e,r)},u=e=>{var r=Za(),i=R(r);ot(i);var a=B(i,2),o=e=>{var n=Ha(),r=z(n);V(e=>J(r,`Suggested answers: ${e??``}`),[()=>W(t).options.join(` · `)]),q(e,n)};Y(a,e=>{W(t).options?.length&&e(o)}),Si(i,()=>W(c)[n],e=>W(c)[n]=e),q(e,r)};Y(o,e=>{W(t).secret?e(s):W(t).freeText?e(u,-1):e(l,1)}),A(i);var d=B(i,2),f=e=>{var n=$a(),r=B(L(n),4);Z(r,21,()=>W(t).options||[],X,(e,t)=>{var n=Qa(),r=z(n,!0);V(()=>J(r,W(t))),q(e,n)}),A(r),A(n),q(e,n)};Y(d,e=>{W(t).secret&&!W(t).freeText&&e(f)}),V(()=>J(a,`${W(t).text??``} `)),q(e,r)}),q(e,t)};Y(_,e=>{W(s).kind===`approval`||W(s).kind===`profile`?e(v):e(b,-1)}),A(m);var x=B(m,2),S=e=>{var t=to(),n=R(t),r=z(n),i=B(n,2),a=z(i),o=B(i,2);V(e=>{J(r,`Check the target and ${W(s).kind===`profile`?`profile above`:W(s).kind===`approval`?`exact command and permission scope`:`message above`}. This will send to Codex; it may start work - using your quota. Confirmation expires in ${e??``}s.`),i.disabled=W(p)||W(y),J(a,`CONFIRM ${(W(s).kind===`approval`||W(s).kind===`profile`?W(s).choices?.[W(l)]?.label:`SEND`)??``}`)},[()=>Math.max(0,Math.ceil((W(d)-W(f))/1e3))]),G(`click`,i,te),G(`click`,o,()=>{I(u,``)}),q(e,t)},E=e=>{var t=no(),n=z(t,!0);V(()=>{t.disabled=W(p)||W(y)||!W(T),J(n,W(p)?`SENDING…`:`REVIEW BEFORE SENDING`)}),G(`click`,t,ee),q(e,t)};Y(x,e=>{W(C)?e(S):e(E,-1)}),V(()=>{J(o,`TARGET // ${W(s).thread??``} // ${(W(s).directory||`Directory unavailable`)??``}`),m.disabled=W(p)||W(C)||W(y),J(g,W(s).kind===`approval`||W(s).kind===`profile`?`Choose a decision`:`Reply to this session`)}),q(e,r)};Y(se,e=>{W(y)||W(g)?e(ce):W(s)?W(s).id?W(_)!==W(s).id&&e(de,3):e(ue,2):e(le,1)}),A(r),V(()=>J(o,i()===`profile`?`QUOTA THRESHOLD`:`SESSION CONTROL // EXPERIMENTAL`)),q(e,r)};Y(re,e=>{W(b)||e(ie)}),q(e,ne),qe()}Sr([`click`]);var oo=K(`
        `);function so(e,t){Ke(t,!0);let n=Ni(t,`active`,3,!1),r=N(()=>[`LAST REPLY`,`LAST ACTIVITY`].includes(t.session.contextKind)&&!!t.session.text.trim()),i=F(!1),a=F(``),o=F(!1);xn(()=>{if(!W(o))return;let e=setTimeout(()=>{I(o,!1)},150);return()=>clearTimeout(e)}),xn(()=>{t.session.text,t.session.status,I(a,``)});async function s(){if(!W(r)||W(i))return;let e=t.session.text;I(i,!0),I(o,!0),I(a,``);try{await navigator.clipboard.writeText(e),t.session.text===e&&I(a,`Copied.`)}catch{t.session.text===e&&I(a,`Clipboard unavailable. Select the visible text and copy it manually.`)}finally{I(i,!1)}}function c(e){!n()||!W(r)||e.defaultPrevented||e.repeat||e.ctrlKey||e.metaKey||e.altKey||e.key.toLowerCase()!==`c`||e.target instanceof Element&&e.target.closest(`input, textarea, select, [contenteditable]`)||(e.preventDefault(),s())}var l=Mr();xr(`keydown`,tn,c);var u=R(l),d=e=>{var t=oo(),n=L(t),r=z(n,!0),c=B(n,2);let l;A(t),V(()=>{J(r,W(a)),c.disabled=W(i),l=ai(c,1,`svelte-543j00`,null,l,{flashed:W(o)})}),G(`click`,c,s),q(e,t)};Y(u,e=>{W(r)&&e(d)}),q(e,l),qe()}Sr([`click`]);var co=K(`

        `),lo=K(`

        `),uo=K(`
         
        `),fo=K(`

        Command unavailable from this observation. Open Codex to inspect the - request.

        `),po=K(`

        `,1),mo=K(`

        `),ho=K(`
         
        `,1),go=K(`
        `),_o=K(`

        Session connection or refresh unavailable. Context and telemetry may be - stale.

        `),vo=K(`

        Some quota profile checks are unavailable. Only sessions with freshly - verified quota and settings can be updated; previous outcome notices remain - visible.

        `),yo=K(` `),bo=K(` `),xo=K(``),So=K(`

        Read only — reply or approve in Codex.

        `),Co=K(`

        `),wo=K(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),To=K(`
        `),Eo=K(`
        `),Do=K(`

        This session is no longer in the current observation. Return to sessions.

        `),Oo=K(`

        `),ko=K(` `),Ao=K(`

        `),jo=K(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),Mo=K(` `,1),No=K(`

        `),Po=K(`

        TOKEN ACTIVITY // 30 SECOND SAMPLES

        `),Fo=K(`

        TOKENS

        FULL DETAIL →
        `),Io=K(`

        No locally observed sessions yet. Keep Codex running alongside - Codexometer.

        `),Lo=K(`

        ↑ ↓ SELECT SESSION // ← LESS DETAIL // → MORE DETAIL // ESC BACK

        `,1),Ro=K(`

        SESSION TOTALS

        `,1);function zo(e,t){Ke(t,!0);let n=(e,t=f,n,r)=>{let i=vt(()=>h(n?.(),!0)),a=vt(()=>h(r?.(),!1));var o=ho(),s=R(o),c=e=>{var n=co();let r;var i=z(n,!0);V(e=>{r=ai(n,1,`attention-note`,null,r,{inferred:t().status===`CHECK SESSION`}),J(i,e)},[()=>b(t())]),q(e,n)},l=N(()=>b(t())&&(!W(a)||W(d)||t().status===`CHECK SESSION`));Y(s,e=>{W(l)&&e(c)});var u=B(s,2),p=e=>{var n=lo(),r=z(n,!0);V(()=>J(r,t().contextKind||`LAST ACTIVITY`)),q(e,n)};Y(u,e=>{W(i)&&e(p)});var m=B(u,2),g=z(m,!0),_=B(m,2),v=e=>{var n=po(),r=B(R(n),2),i=z(r,!0),a=B(r,2),o=e=>{var n=uo(),r=z(n,!0);V(()=>J(r,t().command)),q(e,n)},s=e=>{q(e,fo())};Y(a,e=>{t().command?e(o):e(s,-1)}),V(()=>J(i,W(d)||t().status!==`APPROVAL NEEDED`?`LAST OBSERVED COMMAND`:$.data?.control?`COMMAND REQUEST`:`COMMAND TO APPROVE IN CODEX`)),q(e,n)};Y(_,e=>{(!W(a)||!$.data?.control)&&(t().command||t().status===`APPROVAL NEEDED`)&&e(v)});var y=B(_,2),x=e=>{var n=mo(),r=z(n);V(()=>J(r,`CONTEXT SOURCE // ${(t().source||`LOCAL`)??``} // OBSERVATION`)),q(e,n)};Y(y,e=>{W(a)||e(x)}),V(()=>J(g,t().text||`No session context available.`)),q(e,o)},r=Ni(t,`params`,19,()=>({})),i=N(()=>$.data?.sessions||[]),a=N(()=>$.data?.control&&$.data.profiles||[]),o=F(!1);function s(e,t){if(r().id&&r().id!==t&&W(o)){e.preventDefault();return}_(t)}xn(()=>{let e=r().id;e&&mr(()=>{Gi.selected=e,Xi(e,2)})});let c=N(()=>W(i).find(e=>e.id===r().id)),l=N(()=>new URLSearchParams(Li.querystring).get(`review`)===`profile`&&W(a).some(e=>e.session===r().id&&e.pending)),u=N(()=>W(i).some(e=>e.id===Gi.selected)?Gi.selected:W(i)[0]?.id),d=N(()=>!$.connected||!!$.data?.sessionsError),p=N(()=>[[`OBSERVED TOKENS`,Zi(W(i).reduce((e,t)=>e+t.tokens,0))],[`LISTED SESSIONS`,Zi(W(i).length)],...[[`WORKING`,`WORKING`],[`AWAITING APPROVAL`,`APPROVAL NEEDED`],[`AWAITING INPUT`,`INPUT NEEDED`],[`CHECK · INFERRED`,`CHECK SESSION`]].map(([e,t])=>[e,W(d)?`—`:Zi(W(i).filter(e=>e.status===t).length)])]),m=N(()=>W(i).filter(e=>[`INPUT NEEDED`,`APPROVAL NEEDED`,`CHECK SESSION`].includes(e.status)));function _(e){Gi.selected=e,dr().then(()=>document.querySelector(`.session-row.selected`)?.scrollIntoView({block:`nearest`}))}function v(e,t){if(_(e),r().id){t<0&&(Xi(e,2),location.hash=`/sessions`);return}let n=Ji(e)+t;n>2?location.hash=`/sessions/`+encodeURIComponent(e):Xi(e,n)}function y(e){let t=e.target;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||t.closest(`input, textarea, select, [contenteditable="true"]`))){if(e.key===`Escape`&&r().id)e.preventDefault(),v(r().id,-1);else if([`ArrowLeft`,`ArrowRight`].includes(e.key)&&(r().id||W(u)))e.preventDefault(),v(r().id||W(u),e.key===`ArrowLeft`?-1:1);else if(!r().id&&[`ArrowUp`,`ArrowDown`].includes(e.key)&&W(i).length){e.preventDefault();let t=W(i).findIndex(e=>e.id===W(u));_(W(i)[Math.max(0,Math.min(W(i).length-1,t+(e.key===`ArrowUp`?-1:1)))].id)}}}function b(e){return W(d)?`Last observation only — refresh unavailable. Check Codex for current state.`:e.status===`CHECK SESSION`?`INFERRED INACTIVITY — a quiet session, not a confirmed input or approval request. Local tools may still be running.`:$.data?.control&&[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(e.status)?`Open full detail for supported live controls; otherwise reply in Codex.`:e.status===`APPROVAL NEEDED`?`OBSERVED APPROVAL SIGNAL — approve or decline in Codex.`:e.status===`INPUT NEEDED`?`OBSERVED INPUT SIGNAL — reply in Codex.`:e.status===`TURN COMPLETE`?`OBSERVED TURN COMPLETION — informational, not an approval request.`:``}var x=Ro();xr(`keydown`,tn,y);var S=R(x),C=z(B(L(S),2));A(S);var w=B(S,2);let T;Z(w,21,()=>W(p),X,(e,t)=>{var n=N(()=>g(W(t),2));let r=()=>W(n)[0],i=()=>W(n)[1];var a=go(),o=L(a),s=z(o,!0),c=z(B(o,2),!0);A(a),V(()=>{J(s,r()),J(c,i())}),q(e,a)}),A(w);var E=B(w,2),ee=z(E),te=B(E,2),ne=e=>{q(e,_o())};Y(te,e=>{W(d)&&e(ne)});var re=B(te,2),ie=e=>{q(e,vo())};Y(re,e=>{$.data?.profileError&&e(ie)});var ae=B(re,2),oe=e=>{var t=xo(),n=L(t);Z(n,17,()=>W(m),X,(e,t)=>{var n=yo();let r;var i=z(n);V(e=>{r=ai(n,1,`button`,null,r,{approval:W(t).status===`APPROVAL NEEDED`}),Q(n,`href`,e),J(i,`${W(t).status??``} // ${(W(t).directory||W(t).id)??``}`)},[()=>`#/sessions/`+encodeURIComponent(W(t).id)]),G(`click`,n,()=>_(W(t).id)),q(e,n)}),Z(B(n,2),17,()=>W(a).filter(e=>e.pending&&W(i).some(t=>t.id===e.session)),X,(e,t)=>{var n=bo(),a=z(n);V((e,i)=>{Q(n,`title`,r().id&&r().id!==W(t).session&&W(o)?`Finish sending or clear your current draft before switching sessions.`:`Review this session’s quota threshold`),Q(n,`href`,e),J(a,`QUOTA THRESHOLD // ${i??``}`)},[()=>`#/sessions/`+encodeURIComponent(W(t).session)+`?review=profile`,()=>W(i).find(e=>e.id===W(t).session)?.directory||W(t).session]),G(`click`,n,e=>s(e,W(t).session)),q(e,n)}),A(t),q(e,t)},se=N(()=>(W(m).length||W(a).some(e=>e.pending))&&!W(d));Y(ae,e=>{W(se)&&e(oe)});var ce=B(ae,2),le=e=>{var t=Mr(),i=R(t),s=e=>{var t=Eo(),i=L(t),s=L(i),u=L(s);let f;var p=B(u);A(s);var m=B(s,2);A(i);var h=B(i,2),g=z(h),v=B(h,2);let y;var b=L(v),x=L(b);n(x,()=>W(c),()=>!0,()=>!0),A(b);var S=B(b,2),C=e=>{var t=Mr();Wr(R(t),()=>W(c).id,e=>{ao(e,{get session(){return W(c).id},get observedCommand(){return W(c).command},get suspended(){return W(l)},onProtectedChange:e=>{I(o,e,!0)}})}),q(e,t)},w=e=>{q(e,So())};Y(S,e=>{$.data?.control?e(C):e(w,-1)}),A(v);var T=B(v,2);Z(T,17,()=>W(a).filter(e=>e.session===W(c).id),e=>e.session,(e,t)=>{var n=To(),r=L(n),i=e=>{var n=Co(),r=z(n,!0);V(()=>J(r,W(t).notice)),q(e,n)};Y(r,e=>{W(t).notice&&e(i)});var a=B(r,2),o=e=>{ao(e,{get session(){return W(c).id},review:`profile`})},s=e=>{var t=wo();V(e=>Q(t,`href`,e),[()=>`#/sessions/`+encodeURIComponent(W(c).id)+`?review=profile`]),q(e,t)};Y(a,e=>{W(t).pending&&W(l)?e(o):W(t).pending&&e(s,1)}),A(n),V(()=>Q(n,`id`,`quota-profile-`+W(c).id)),q(e,n)});var E=B(T,2),ee=e=>{var t=Mr();Wr(R(t),()=>W(c).id,e=>{so(e,{get session(){return W(c)},active:!0})}),q(e,t)};Y(E,e=>{W(l)||e(ee)}),A(t),V(e=>{f=ai(u,1,`lamp lit`,null,f,{working:W(c).status===`WORKING`&&!W(d)}),J(p,`${(W(d)?`STALE`:W(l)?`QUOTA THRESHOLD`:W(c).status)??``} // ${W(c).directory??``}`),J(g,`${e??``} TOKENS // ${W(c).id??``} // CONTEXT SOURCE // ${(W(c).source||`LOCAL`)??``}`),y=si(v,``,y,{display:W(l)?`none`:void 0})},[()=>Zi(W(c).tokens)]),G(`click`,m,()=>{_(r().id),Xi(r().id,2)}),q(e,t)},u=e=>{q(e,Do())};Y(i,e=>{W(c)?e(s):e(u,-1)}),q(e,t)},ue=e=>{var t=Lo(),r=R(t),o=B(L(r),2),c=L(o),l=B(c,2);A(o),A(r);var f=B(r,2);Z(f,17,()=>W(i),e=>e.id,(e,t)=>{let r=N(()=>Ji(W(t).id));var i=Fo();let o;var c=L(i),l=L(c),f=L(l);let p;var m=B(f,1,!0);A(l);var h=B(l,2),g=z(h,!0),y=B(h,2),b=L(y);Te(),A(y);var x=B(y,2),S=z(x),C=B(x,2),w=z(C),T=B(C,2),E=L(T),ee=B(E,2),te=z(ee,!0),ne=B(ee,2);A(T);var re=B(T,2),ie=B(re,2),ae=e=>{var n=Oo(),r=z(n,!0);V(()=>J(r,W(t).status===`CHECK SESSION`?`INFERRED INACTIVITY`:$.data?.control?`OPEN FULL DETAIL OR REPLY IN CODEX`:W(t).status===`APPROVAL NEEDED`?`APPROVE OR DECLINE IN CODEX`:`REPLY IN CODEX`)),q(e,n)},oe=N(()=>!W(d)&&[`APPROVAL NEEDED`,`INPUT NEEDED`,`CHECK SESSION`].includes(W(t).status));Y(ie,e=>{W(oe)&&e(ae)}),A(c);var se=B(c,2),ce=e=>{var r=No(),i=L(r),o=L(i),c=z(o,!0),l=B(o,2),f=e=>{var n=ko(),r=z(n,!0);V(e=>{Q(n,`href`,e),J(r,$.data?.control?`REVIEW IN FULL DETAIL ↗`:`APPROVAL IN CODEX ↗`)},[()=>`#/sessions/`+encodeURIComponent(W(t).id)]),q(e,n)};Y(l,e=>{!W(d)&&W(t).status===`APPROVAL NEEDED`&&e(f)}),A(i);var p=B(i,2);n(p,()=>W(t),()=>!1);var m=B(p,2);Z(m,17,()=>W(a).filter(e=>e.session===W(t).id),X,(e,n)=>{var r=Mo(),i=R(r),a=e=>{var t=Ao(),r=z(t,!0);V(()=>J(r,W(n).notice)),q(e,t)};Y(i,e=>{W(n).notice&&e(a)});var o=B(i,2),c=e=>{var n=jo();V(e=>Q(n,`href`,e),[()=>`#/sessions/`+encodeURIComponent(W(t).id)+`?review=profile`]),G(`click`,n,e=>s(e,W(t).id)),q(e,n)};Y(o,e=>{W(n).pending&&e(c)}),q(e,r)});var h=B(m,2);{let e=N(()=>W(u)===W(t).id);so(h,{get session(){return W(t)},get active(){return W(e)}})}A(r),V(()=>J(c,W(t).contextKind||`LAST ACTIVITY`)),q(e,r)};Y(se,e=>{W(r)>0&&e(ce)});var le=B(se,2),ue=e=>{var n=Po(),r=B(L(n),2);{let e=N(()=>(W(t).samples||[]).map(e=>e.tokens));Fa(r,{get values(){return W(e)},capacity:120})}var i=z(B(r,2));A(n),V(()=>J(i,`LAST ${(W(t).samples?.length||0)??``} SAMPLES // AUTO SCALE`)),q(e,n)};Y(le,e=>{W(r)<2&&e(ue)}),A(i),V((e,n,a)=>{o=ai(i,1,`session-row`,null,o,{selected:W(u)===W(t).id,wide:W(r)===2,split:W(r)===1}),Q(i,`aria-label`,`Session `+(W(t).directory||W(t).id)),p=ai(f,1,`lamp lit`,null,p,{working:W(t).status===`WORKING`&&!W(d)}),J(m,W(d)?`STALE`:W(t).status),Q(h,`aria-pressed`,W(u)===W(t).id),J(g,W(t).directory||W(t).id),J(b,`${e??``} `),J(S,`${W(t).agents??``} LINKED AGENTS`),J(w,`ACTIVE // ${n??``}`),E.disabled=W(r)===0,Q(ee,`aria-expanded`,W(r)>0),J(te,W(r)?`HIDE DETAIL`:`SHOW DETAIL`),Q(re,`href`,a)},[()=>Zi(W(t).tokens),()=>Qi(W(t).activity),()=>`#/sessions/`+encodeURIComponent(W(t).id)]),G(`click`,h,()=>_(W(t).id)),G(`click`,E,()=>v(W(t).id,-1)),G(`click`,ee,()=>{_(W(t).id),Xi(W(t).id,+!W(r))}),G(`click`,ne,()=>v(W(t).id,1)),G(`click`,re,()=>_(W(t).id)),q(e,i)});var p=B(f,2),m=e=>{q(e,Io())};Y(p,e=>{W(i).length||e(m)}),G(`click`,c,()=>Yi(1)),G(`click`,l,()=>Yi(0)),q(e,t)};Y(ce,e=>{r().id?e(le):e(ue,-1)}),V(e=>{J(C,`OBSERVED ${e??``}`),T=ai(w,1,`session-totals`,null,T,{stale:W(d)}),J(ee,`${W(d)?`LAST KNOWN TOTALS — live state counts unavailable. `:``}Tokens - observed since this server started for currently listed sessions; linked - agents are already included. Totals can decrease when a session leaves the - list. History samples every 30 seconds. Not account-wide totals.`)},[()=>Qi($.data?.sessionsAt)]),q(e,x),qe()}Sr([`click`]);var Bo=864e5;function Vo(e,t){let n=new Date(e);n.setUTCDate(1),n.setUTCMonth(n.getUTCMonth()+t);let r=new Date(Date.UTC(n.getUTCFullYear(),n.getUTCMonth()+1,0)).getUTCDate();return n.setUTCDate(Math.min(e.getUTCDate(),r)),n}function Ho(e,t,n){let r=new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()));for(let e=0;;e++){let i=Vo(r,-t),a=new Date(i.getTime()+Bo);if(e===n)return{start:a,end:r};r=i}}var Uo=K(`

        History refresh failed. Any displayed history is the last successful - observation.

        `),Wo=K(``),Go=K(`
        `),Ko=K(`

        LESS ░ ▒ ▓ █ MORE // HOVER FOR DATE AND TOKENS

        `,1),qo=K(`
        `,1),Jo=K(` `),Yo=K(`

        LIFETIME TOKENS

        PEAK DAY

        CURRENT STREAK

        DAYS

        Accessible data table
        Date (UTC)Tokens

        `,1),Xo=K(`

        History unavailable or awaiting a matching account observation. Missing - history is not treated as zero usage.

        `),Zo=K(`

        USAGE // ACCOUNT HISTORY

        Account-wide history reported by Codex, not the local Sessions counter. Dates - use UTC. Historical resets are not provided by this data.

        `,1);function Qo(e,t){Ke(t,!0);let n=F(`daily`),r=F(12),i=F(0),a=N(()=>{let e=$.data?.usage?.dailyUsageBuckets;if(!e)return[];let{start:t,end:n}=Ho(new Date,W(r),W(i)),a=new Map;for(let t of e)!Number.isFinite(t.tokens)||t.tokens<0||a.set(t.startDate,(a.get(t.startDate)||0)+t.tokens);let o=[];for(let e=t;e<=n;e=new Date(e.getTime()+864e5)){let t=e.toISOString().slice(0,10);o.push({date:t,tokens:a.get(t)||0})}return o}),o=N(()=>Math.max(1,...W(a).map(e=>e.tokens))),s=N(()=>W(a).length?new Date(W(a)[0].date+`T00:00:00Z`).getUTCDay():0),c=N(()=>{if(W(n)===`monthly`){let e=new Map;for(let t of W(a))e.set(t.date.slice(0,7),(e.get(t.date.slice(0,7))||0)+t.tokens);return[...e].map(([e,t])=>({date:e,tokens:t}))}let e=0;return W(a).map(t=>({date:t.date,tokens:e+=t.tokens}))});var l=Zo(),u=B(R(l),4),d=L(u),f=B(L(d)),p=L(f);p.value=p.__value=`daily`;var m=B(p);m.value=m.__value=`monthly`;var h=B(m);h.value=h.__value=`cumulative`,A(f),di(f),A(d);var g=B(d),_=B(L(g)),v=L(_);v.value=v.__value=6;var y=B(v);y.value=y.__value=12,A(_),di(_),A(g);var b=B(g),x=B(b);A(u);var S=B(u,2),C=e=>{q(e,Uo())};Y(S,e=>{$.data?.usageError&&e(C)});var w=B(S,2),T=e=>{var t=Yo(),r=R(t),i=L(r),l=z(B(L(i),2),!0);A(i);var u=B(i,2),d=z(B(L(u),2),!0);A(u);var f=B(u,2),p=B(L(f),2),m=L(p);Te(),A(p),A(f),A(r);var h=B(r,2),g=L(h),_=z(g),v=B(g,2),y=e=>{var t=Ko(),n=R(t),r=L(n),i=L(r);Z(i,17,()=>Array(W(s)),X,(e,t)=>{q(e,Wo())}),Z(B(i,2),17,()=>W(a),X,(e,t)=>{var n=Go();let r,i;V(e=>{r=ai(n,1,`heat-cell`,null,r,{zero:W(t).tokens===0}),Q(n,`title`,e),i=si(n,``,i,{opacity:W(t).tokens?.25+.75*W(t).tokens/W(o):1})},[()=>`${W(t).date}: ${Zi(W(t).tokens)} tokens`]),q(e,n)}),A(r),A(n),Te(2),q(e,t)},b=e=>{var t=qo(),r=R(t);{let e=N(()=>W(c).map(e=>e.tokens)),t=N(()=>W(n)+` usage`);Fa(r,{get values(){return W(e)},get label(){return W(t)}})}var i=B(r,2),a=L(i),o=z(a,!0),s=z(B(a),!0);A(i),V(e=>{J(o,W(c)[0]?.date),J(s,e)},[()=>W(c).at(-1)?.date]),q(e,t)};Y(v,e=>{W(n)===`daily`?e(y):e(b,-1)});var x=B(v,2),S=B(L(x),2),C=L(S),w=B(L(C));Z(w,21,()=>W(n)===`daily`?W(a):W(c),X,(e,t)=>{var n=Jo(),r=L(n),i=z(r,!0),a=z(B(r),!0);A(n),V(e=>{J(i,W(t).date),J(a,e)},[()=>Zi(W(t).tokens)]),q(e,n)}),A(w),A(C),A(S),A(x),A(h);var T=z(B(h,2));V((e,t,n,r,i)=>{J(l,e),J(d,t),J(m,`${n??``} `),J(_,`${W(a)[0]?.date??``} — ${r??``}`),J(T,`OBSERVED ${i??``} // CUMULATIVE IS FOR THE SELECTED PERIOD`)},[()=>Zi($.data.usage.summary.lifetimeTokens),()=>Zi($.data.usage.summary.peakDailyTokens),()=>Zi($.data.usage.summary.currentStreakDays),()=>W(a).at(-1)?.date,()=>Qi($.data.usageAt)]),q(e,t)},E=e=>{q(e,Xo())};Y(w,e=>{$.data?.usage&&$.data.usage.dailyUsageBuckets!==null?e(T):e(E,-1)}),V(()=>x.disabled=W(i)===0),fi(f,()=>W(n),e=>I(n,e)),G(`change`,_,()=>I(i,0)),fi(_,()=>W(r),e=>I(r,e)),G(`click`,b,()=>Yt(i)),G(`click`,x,()=>Yt(i,-1)),q(e,l),qe()}Sr([`change`,`click`]),We();var $o=K(`

        Page not found

        Return to Quota

        `,1);function es(e){var t=$o();Te(2),q(e,t)}var ts=K(` `),ns=K(`

        `),rs=K(`

        Connecting to your local Codexometer…

        `),is=K(``),as=K(`
        CODEXOMETER

        Your quota. Your sessions. Your command centre.

        `);function os(e,t){Ke(t,!0);let n={"/":Ma,"/quota/:view?":Ma,"/sessions/:id?":zo,"/usage":Qo,"*":es},r={quota:/^(?:\/|\/quota(?:\/[^/]+)?\/?)$/,sessions:/^\/sessions(?:\/[^/]+)?\/?$/,usage:/^\/usage\/?$/},i=F(`hacker`),a=[`hacker`,`rust`,`blue-steel`,`ultraviolet`,`nightshade`];xn(()=>{Ki()}),xn(()=>{if($.data)for(let[e,t]of Object.entries(r))t.test(Li.location)&&(Gi.tab=e)}),Pi(()=>{try{let e=localStorage.getItem(`codexometer.web.theme`);e&&a.includes(e)&&I(i,e,!0)}catch{}return ra()});function o(){try{localStorage.setItem(`codexometer.web.theme`,W(i))}catch{}}var s=as(),c=L(s),l=B(L(c),2),u=L(l);let d;var f=B(u,1,!0),p=z(B(f));A(l),A(c);var m=B(c,2);Z(m,21,()=>Object.entries(r),X,(e,t)=>{var n=N(()=>g(W(t),2));let r=()=>W(n)[0],i=()=>W(n)[1],a=N(()=>i().test(Li.location));var o=ts();let s;var c=z(o,!0);V(e=>{Q(o,`href`,r()===`quota`?`#/quota/`+Gi.view:`#/`+r()),Q(o,`aria-current`,W(a)?`page`:void 0),s=ai(o,1,``,null,s,{active:W(a)}),J(c,e)},[()=>r().toUpperCase()]),q(e,o)}),A(m);var h=B(m,2),_=L(h),v=e=>{var t=ns(),n=z(t,!0);V(()=>J(n,$.error)),q(e,t)};Y(_,e=>{$.error&&e(v)});var y=B(_,2),b=e=>{Bi(e,{get routes(){return n}})},x=e=>{q(e,rs())};Y(y,e=>{$.data?e(b):$.error||e(x,1)}),A(h);var S=B(h,2),C=L(S),w=z(C),T=B(C,2),E=z(T,!0),ee=B(T,2),te=B(L(ee));Z(te,21,()=>a,X,(e,t)=>{var n=is(),r=z(n,!0),i={};V(e=>{J(r,e),i!==(i=W(t))&&(n.value=(n.__value=i)??``)},[()=>W(t).replace(`-`,` `).toUpperCase()]),q(e,n)}),A(te),di(te),A(ee),A(S),A(s),V(()=>{Q(s,`data-theme`,W(i)),d=ai(u,1,`lamp`,null,d,{lit:$.connected}),J(f,$.connected?`CONNECTED`:`OFFLINE`),J(p,`EXPERIMENTAL // ${$.data?.control?`SESSION CONTROL`:`READ ONLY`}`),J(w,`v${($.data?.version||`…`)??``} // LOCAL ONLY`),J(E,$.data?.control?`Session control enabled. Stop the server to revoke access.`:`No actions can be sent from this preview.`)}),G(`change`,te,o),fi(te,()=>W(i),e=>I(i,e)),q(e,s),qe()}Sr([`change`]),Rr(os,{target:document.getElementById(`app`)}); \ No newline at end of file diff --git a/internal/web/dist/index.html b/internal/web/dist/index.html index a58492a..b6d52cd 100644 --- a/internal/web/dist/index.html +++ b/internal/web/dist/index.html @@ -5,7 +5,7 @@ Codexometer // Experimental web - + diff --git a/intro-post.md b/intro-post.md index cf24388..ff624da 100644 --- a/intro-post.md +++ b/intro-post.md @@ -26,7 +26,7 @@ The interface has four main tabs: - **Quota** — switch between Bars, Consumption Pace, Pie, and Fuel Tank presentations. Compare consumption directly with elapsed reset-cycle time, see countdowns and reset dates, and get a pace-aware health signal or an early-exhaustion projection. Learned API-equivalent estimates show both current spend and what 100% of a primary quota window might represent, with conservative confidence and a pricing-source/date footer when space permits. Eligible banked resets can be redeemed with a separate confirmation click. - **Sessions** — your session command centre, combining per-session context and eligible live reply/approval controls with metrics and scrolling, auto-scaling graphs on a shared 30-second tick. Compare local token shares, model calls, activity, output size, and time to first token; explicitly linked subagents are folded into their parent session. The wider **SESSION TOTALS** readout keeps a clickable Reset beside it; Pause/Resume is keyboard-only with `p` and pauses measurement, not Codex. Page through sessions and dismiss finished rows with `[×]` without closing them: fresh activity brings them back. -- **Usage** — explore account token history in a GitHub-style daily activity grid, weekly bars, or a cumulative graph. Choose 6 or 12 months (26/52 weeks), browse older periods, and see reported lifetime tokens, peak daily usage, and the current streak. This is server-side history, not the Sessions tab’s live local counters, so it can lag ongoing work; it does not invent historical dollar costs or per-model breakdowns. +- **Usage** — explore persistent account token history in a GitHub-style daily activity grid, weekly bars, or a cumulative graph. Choose 6 or 12 months (26/52 weeks), browse older periods, and see lifetime tokens, peak usage, longest turn, and activity streaks. OpenAI daily totals backfill missed days while retained local rollouts show how much can be attributed locally; gaps are not turned into invented costs or model breakdowns. - **Benchmark** — run programmatically checked challenges across selected model and reasoning-level combinations, then compare outcomes, wall time, tokens, estimated API-equivalent cost, and rankings. Use `Tab` / `Shift+Tab` or the mouse to navigate. Quota refreshes every minute by default. Passive monitoring and history views do not start model turns; explicitly sent follow-ups and benchmark runs do consume model usage. diff --git a/main.go b/main.go index fb125b1..ae78804 100644 --- a/main.go +++ b/main.go @@ -141,18 +141,26 @@ func quotaStepSpeedFlag(tier string) string { func (d *demoFetcher) FetchAccountUsage(context.Context) (codex.AccountUsage, error) { now := time.Now() history := codex.AccountUsage{AccountFingerprint: "demo-account", FetchedAt: now, DailyUsageBuckets: []codex.AccountUsageDay{}} - var total, peak int64 + var total, localTotal, peak int64 for i := 363; i >= 0; i-- { tokens := int64((i * 7919) % 80000) if i%7 == 0 { tokens = 0 } total += tokens + local := tokens * 3 / 4 + localTotal += local peak = max(peak, tokens) - history.DailyUsageBuckets = append(history.DailyUsageBuckets, codex.AccountUsageDay{StartDate: now.UTC().AddDate(0, 0, -i).Format("2006-01-02"), Tokens: tokens}) + history.DailyUsageBuckets = append(history.DailyUsageBuckets, codex.AccountUsageDay{StartDate: now.UTC().AddDate(0, 0, -i).Format("2006-01-02"), Tokens: tokens, LocalTokens: local, InputTokens: local * 9 / 10, CachedInputTokens: local * 6 / 10, OutputTokens: local / 10, Provenance: "OPENAI"}) } history.Summary.LifetimeTokens = &total history.Summary.PeakDailyTokens = &peak + longestTurn, currentStreak, longestStreak := int64(547), int64(8), int64(21) + history.Summary.LongestRunningTurnSec = &longestTurn + history.Summary.CurrentStreakDays = ¤tStreak + history.Summary.LongestStreakDays = &longestStreak + history.Coverage = codex.AccountUsageCoverage{Status: "OPENAI", OpenAITokens: total, LocalTokens: localTotal, AttributedPct: 75, OpenAIDays: len(history.DailyUsageBuckets)} + history.Persisted = true return history, nil } @@ -494,6 +502,9 @@ func run(args []string, stdout, stderr io.Writer, deps dependencies) int { if *webMode { // Web mode deliberately gets no benchmark credentials or discovery calls. client := codex.Client{Binary: *codexPath, QuotaSteps: quotaSteps} + if history, historyErr := codex.NewDefaultHistoryStore(); historyErr == nil { + client.History = history + } if liveUsage, err := codex.NewLiveUsageReader(""); err == nil { client.LiveUsage = liveUsage } @@ -520,6 +531,9 @@ func run(args []string, stdout, stderr io.Writer, deps dependencies) int { } digBenchGames = normalizeDigBenchGames(digBenchGames) client := codex.Client{Binary: *codexPath, BenchmarkAPIKey: benchmarkAPIKey, DigBenchToken: digBenchToken, DigBenchGames: digBenchGames, QuotaSteps: quotaSteps} + if history, historyErr := codex.NewDefaultHistoryStore(); historyErr == nil { + client.History = history + } if liveUsage, err := codex.NewLiveUsageReader(""); err == nil { client.LiveUsage = liveUsage } diff --git a/web/src/Usage.svelte b/web/src/Usage.svelte index 5036e2b..9f963cd 100644 --- a/web/src/Usage.svelte +++ b/web/src/Usage.svelte @@ -10,21 +10,40 @@ if (!buckets) return []; const { start, end } = usageRange(new Date(), months, offset); const lookup = new Map(); + const detail = new Map(); for (const bucket of buckets) { if (!Number.isFinite(bucket.tokens) || bucket.tokens < 0) continue; lookup.set( bucket.startDate, (lookup.get(bucket.startDate) || 0) + bucket.tokens, ); + detail.set(bucket.startDate, bucket); } - const result: { date: string; tokens: number }[] = []; + const result: { + date: string; + tokens: number; + localTokens: number; + provenance: string; + inputTokens: number; + cachedInputTokens: number; + outputTokens: number; + }[] = []; for ( let day = start; day <= end; day = new Date(day.getTime() + 86400000) ) { const date = day.toISOString().slice(0, 10); - result.push({ date, tokens: lookup.get(date) || 0 }); + const source = detail.get(date); + result.push({ + date, + tokens: lookup.get(date) || 0, + localTokens: source?.localTokens || 0, + provenance: source?.provenance || (source ? 'OPENAI' : 'NO ACTIVITY'), + inputTokens: source?.inputTokens || 0, + cachedInputTokens: source?.cachedInputTokens || 0, + outputTokens: source?.outputTokens || 0, + }); } return result; }); @@ -32,20 +51,33 @@ let leading = $derived( days.length ? new Date(days[0].date + 'T00:00:00Z').getUTCDay() : 0, ); + let coverage = $derived(live.data?.usage?.coverage); let bars = $derived.by(() => { if (mode === 'monthly') { - const grouped = new Map(); - for (const day of days) - grouped.set( - day.date.slice(0, 7), - (grouped.get(day.date.slice(0, 7)) || 0) + day.tokens, - ); - return [...grouped].map(([date, tokens]) => ({ date, tokens })); + const grouped = new Map< + string, + { tokens: number; localTokens: number } + >(); + for (const day of days) { + const date = day.date.slice(0, 7); + const current = grouped.get(date) || { tokens: 0, localTokens: 0 }; + current.tokens += day.tokens; + current.localTokens += day.localTokens; + grouped.set(date, current); + } + return [...grouped].map(([date, values]) => ({ + date, + ...values, + provenance: 'AGGREGATE', + })); } let total = 0; + let local = 0; return days.map((day) => ({ date: day.date, tokens: (total += day.tokens), + localTokens: (local += day.localTokens), + provenance: 'AGGREGATE', })); }); @@ -79,6 +111,10 @@ History refresh failed. Any displayed history is the last successful observation.

        {/if} +{#if live.data?.usage?.stale}

        + Showing the last persisted account history while the live OpenAI refresh is + unavailable. +

        {/if} {#if live.data?.usage && live.data.usage.dailyUsageBuckets !== null}
        @@ -95,7 +131,25 @@ {number(live.data.usage.summary.currentStreakDays)} DAYS

        +
        +

        LONGEST TURN

        +

        + {number(live.data.usage.summary.longestRunningTurnSec)} + SECONDS +

        +
        +
        +

        LONGEST STREAK

        +

        + {number(live.data.usage.summary.longestStreakDays)} DAYS +

        +
        +

        + {coverage?.status || 'OPENAI'} // UTC{#if coverage?.openaiTokens && coverage?.localTokens} + // LOCAL {number(coverage.attributedPercent)}% ATTRIBUTED{/if}{#if coverage?.recoveredDays} + // {number(coverage.recoveredDays)} RECOVERED DAYS{/if} +

        {days[0]?.date} — {days.at(-1)?.date}

        {#if mode === 'daily'}
        @@ -109,7 +163,7 @@ class="heat-cell" class:zero={day.tokens === 0} style:opacity={day.tokens ? 0.25 + (0.75 * day.tokens) / peak : 1} - title={`${day.date}: ${number(day.tokens)} tokens`} + title={`${day.date}: ${number(day.tokens)} tokens // ${day.provenance} // local ${number(day.localTokens)} (input ${number(day.inputTokens)}, cached ${number(day.cachedInputTokens)}, output ${number(day.outputTokens)})`} >
        {/each} @@ -122,9 +176,16 @@ Accessible data table
        - {#each mode === 'daily' ? days : bars as row}{/each}
        Date (UTC)Tokens
        Date (UTC)TokensSourceLocal
        {row.date}{number(row.tokens)}
        {row.date}{number(row.tokens)}{row.provenance}{number(row.localTokens)}
        diff --git a/web/src/state.svelte.ts b/web/src/state.svelte.ts index 554edd4..bd7d86b 100644 --- a/web/src/state.svelte.ts +++ b/web/src/state.svelte.ts @@ -34,9 +34,32 @@ export interface Usage { summary: { lifetimeTokens: number | null; peakDailyTokens: number | null; + longestRunningTurnSec: number | null; currentStreakDays: number | null; + longestStreakDays: number | null; }; - dailyUsageBuckets: { startDate: string; tokens: number }[] | null; + dailyUsageBuckets: + | { + startDate: string; + tokens: number; + localTokens?: number; + inputTokens?: number; + cachedInputTokens?: number; + outputTokens?: number; + reasoningTokens?: number; + provenance?: string; + }[] + | null; + coverage: { + status?: string; + openaiTokens?: number; + localTokens?: number; + attributedPercent?: number; + openaiDays?: number; + recoveredDays?: number; + }; + persisted: boolean; + stale: boolean; } export interface Snapshot { profiles?: { diff --git a/web/tests/browser.spec.ts b/web/tests/browser.spec.ts index 6336d3b..63d505a 100644 --- a/web/tests/browser.spec.ts +++ b/web/tests/browser.spec.ts @@ -951,10 +951,29 @@ test('history aggregates duplicate dates and excludes negative buckets in every sessionsError: false, usageError: false, usage: { - summary: {}, + summary: { + longestRunningTurnSec: 45, + longestStreakDays: 9, + }, + coverage: { + status: 'OPENAI', + openaiTokens: 370, + localTokens: 280, + attributedPercent: 76, + }, + persisted: true, + stale: false, dailyUsageBuckets: [ { startDate: '2026-09-10', tokens: 100 }, - { startDate: '2026-09-10', tokens: 250 }, + { + startDate: '2026-09-10', + tokens: 250, + localTokens: 260, + inputTokens: 240, + cachedInputTokens: 200, + outputTokens: 20, + provenance: 'OPENAI', + }, { startDate: '2026-09-10', tokens: -50 }, { startDate: '2026-09-11', tokens: 20 }, { startDate: '2026-09-09', tokens: -500 }, @@ -972,17 +991,24 @@ test('history aggregates duplicate dates and excludes negative buckets in every await page.goto(pairingURL); await page.getByRole('link', { name: 'USAGE', exact: true }).click(); await expect( - page.locator('.heat-cell[title="2026-09-10: 350 tokens"]'), + page.locator('.heat-cell[title^="2026-09-10: 350 tokens"]'), ).toHaveCount(1); await expect( - page.locator('.heat-cell[title="2026-09-09: 0 tokens"]'), + page.locator('.heat-cell[title^="2026-09-09: 0 tokens"]'), ).toHaveCount(1); + await expect(page.getByText('LONGEST TURN')).toBeVisible(); + await expect(page.getByText(/LOCAL 76% ATTRIBUTED/)).toBeVisible(); await page.getByText('Accessible data table').click(); await expect( page.getByRole('row').filter({ has: page.getByRole('cell', { name: '2026-09-10', exact: true }), }), ).toContainText('350'); + await expect( + page.getByRole('row').filter({ + has: page.getByRole('cell', { name: '2026-09-10', exact: true }), + }), + ).toContainText('260'); await page.getByLabel('Usage view').selectOption('monthly'); await expect( page.getByRole('row').filter({