From 007beec8f2b5abf96365c1a8a575ae44884d720d Mon Sep 17 00:00:00 2001 From: merefield Date: Sat, 10 Oct 2026 17:17:00 +0100 Subject: [PATCH 1/7] Add session directory commands and audit slash support --- README.md | 29 +- docs/slash-command-support.md | 111 +++++++ internal/codex/daemon_status.go | 9 +- internal/codex/daemon_status_unix.go | 72 +++-- internal/codex/live_usage.go | 18 +- internal/codex/live_usage_test.go | 24 +- internal/codex/session_commands.go | 18 +- internal/codex/session_commands_unix.go | 70 +++- internal/codex/session_directory_unix.go | 111 +++++++ internal/codex/session_directory_unix_test.go | 299 ++++++++++++++++++ internal/codex/session_settings_unix_test.go | 23 +- internal/ui/monitor_commands.go | 21 +- internal/ui/monitor_commands_test.go | 47 +++ internal/web/control_commands.go | 2 + internal/web/control_commands_test.go | 19 ++ .../{index-LUN8vjss.js => index-E1h87Zp5.js} | 7 +- internal/web/dist/index.html | 2 +- web/src/SessionCommands.svelte | 23 +- web/tests/browser.spec.ts | 274 ++++++++++------ 19 files changed, 1006 insertions(+), 173 deletions(-) create mode 100644 docs/slash-command-support.md create mode 100644 internal/codex/session_directory_unix.go create mode 100644 internal/codex/session_directory_unix_test.go rename internal/web/dist/assets/{index-LUN8vjss.js => index-E1h87Zp5.js} (93%) diff --git a/README.md b/README.md index 52d420b..b14e326 100644 --- a/README.md +++ b/README.md @@ -1577,6 +1577,8 @@ are clickable. Writable web mode exposes the same catalogue through | Command family | Live options and behaviour | | --- | --- | +| `/cd` | Change the selected session’s directory after review and confirmation while idle and with no queued messages. Absolute, session-relative and `~/` paths are supported; success is verified from running configuration. Retains thread ID/history; does not reproduce native project-config reload/fork. | +| `/cwd`, `/pwd` | Read-only aliases showing the running session’s current directory, including during active turns. | | `/rename` | Edit the selected session’s saved name, review it and confirm. Uses Codex’s name API; works during an active turn and does not send a prompt or change model settings. | | `/model` | Advertised models, their descriptions and supported reasoning levels. Choosing a model resets its explicit speed override to the server default. | | Advertised speed commands, such as `/fast` | Names, IDs and descriptions come from the current model's service-tier catalogue; enable a tier or clear the explicit override. No speed names or tier IDs are assumed. | @@ -1608,8 +1610,8 @@ Codex does not expose a general slash-command discovery/execution API. These are explicit adapters to supported app-server catalogues, not a reproduction of every CLI command. Options and help are fetched on demand, not hard-coded or persisted; installed-server support determines what appears. Plugin lifecycle -endpoints are deliberately excluded while OpenAI marks them unsuitable for -production clients. Experimental flags are browse-only because their mutation +actions are excluded because installation, authentication and configuration +review flows are not implemented. Experimental flags are browse-only because their mutation scope is process-wide rather than session-local. See the official [app-server API overview](https://learn.chatgpt.com/docs/app-server#api-overview) for the upstream catalogues. @@ -1626,15 +1628,20 @@ confirmations retain the draft and error context. These changes do not modify gl quota thresholds may later supersede model settings. Uncertain requests are not retried automatically. Read-only web mode offers no command-control endpoint. -**Remaining CLI command gaps** (compared with the official documented CLI list): - -| Area | Commands not implemented as Codexometer slash commands | -| --- | --- | -| Session lifecycle and conversation actions | `/new`, `/clear`, `/resume`, `/fork`, `/archive`, `/delete`, `/compact`, `/review`, `/init`, `/goal`, `/side`, `/btw`, `/approve` | -| CLI navigation and display | `/agent`, `/subagents`, `/copy`, `/diff`, `/status`, `/usage`, `/raw`, `/title`, `/theme`, `/pets`, `/pet`, `/keymap`, `/vim`, `/app`, `/exit`, `/quit` | -| Configuration and tools | `/ide`, `/plugins`, `/memories`, `/import`, `/feedback`, `/logout`, `/mention`, `/personality`, `/ps`, `/stop`, `/setup-default-sandbox`, `/sandbox-add-read-dir`, `/debug-config` | - -`/apps`, `/skills`, `/mcp`, `/hooks` and `/experimental` remain **browse-only** here; CLI invocation, installation, authentication, trust and toggle actions are not implemented. `/plan` changes mode but does not implement the CLI's optional prompt argument. `/fast` and other advertised tiers are session overrides, rather than persistent CLI defaults. `/statusline` configures Codexometer's own footer. Existing session navigation, copying and telemetry views provide some analogous actions without those slash names. Availability upstream varies by platform, version and enabled features; see the [official CLI command reference](https://learn.chatgpt.com/docs/developer-commands#built-in-slash-commands). +**Slash-command audit:** the [complete version-matched inventory](docs/slash-command-support.md) +compares Codexometer with Codex CLI **0.162.1**, including aliases, partial support +and the reason for each missing adapter. Several missing commands already have +server APIs (`/compact`, `/fork`, `/review`, `/goal`, `/ps`, `/stop`); they need +Codexometer workflows. Native display commands need local UI implementations. +The published reference is incomplete for this version and includes older names. + +`/cd` requires an existing local directory and no queued messages. Confirmation +rechecks the target (including symlinks), current running directory and session +state. The server retains current permission settings and other workspace roots. +The native CLI’s project trust/configuration reload and conversation-fork workflow +is not performed; use native `/cd` for that full transition. `/cwd` and `/pwd` +read running configuration rather than captured thread metadata. Failed or +unconfirmed directory updates are not reported as completed or retried. Slash commands cannot be sent, steered, queued or scheduled as ordinary prompts. Use `//` to send a literal leading slash (for example `//tmp/file` sends diff --git a/docs/slash-command-support.md b/docs/slash-command-support.md new file mode 100644 index 0000000..3ae22c6 --- /dev/null +++ b/docs/slash-command-support.md @@ -0,0 +1,111 @@ +# Slash-command support audit + +Audited on 2026-10-10 against **Codex CLI 0.162.1** (`rust-v0.162.1`), using its [command registry](https://github.com/openai/codex/blob/rust-v0.162.1/codex-rs/tui/src/slash_command.rs), [native directory-change workflow](https://github.com/openai/codex/blob/rust-v0.162.1/codex-rs/tui/src/app/working_directory.rs), and protocol types generated with `codex app-server generate-ts --experimental`. Server directory behavior is defined in the matching [turn processor](https://github.com/openai/codex/blob/rust-v0.162.1/codex-rs/app-server/src/request_processors/turn_processor.rs). + +The tables cover all **63 registered commands**, including aliases. Platform, feature and debug-build filters affect actual visibility. The [published reference](https://learn.chatgpt.com/docs/developer-commands#built-in-slash-commands) omits some commands in this registry and also lists older names. Codexometer has explicit adapters/local UI implementations; it does not send slash commands as model prompts. There is no generic server endpoint to discover or execute the CLI's slash commands. + +“Missing” below means no Codexometer slash adapter, **not** that the server lacks the capability. Live commands require a loaded session and shared app-server; browser control commands require writable mode. Windows' existing file-based monitoring path does not gain live server commands from this change. + +## Implemented and partial support + +| Command | Support | Implementation and limits | +| --- | --- | --- | +| `/rename` | Implemented | Confirmed `thread/name/set`; works during active turns. | +| `/cd ` | Implemented with narrower semantics | Confirmed `thread/settings/update`, sending only `threadId` and `cwd`. Requires idle/local session, empty queue, no pending approval and an existing directory. Resolves relative paths from the running session directory, expands `~`/`~/`, rechecks symlinks and verifies the result from running configuration. No write retries. See the semantics below. | +| `/pwd`, `/cwd` | Implemented aliases | Read-only `thread/resume` **without overrides** reports the running directory, including during active turns. Captured `thread/read.cwd` metadata is not used as the answer. The session directory/footer also follows live directory reads and settings notifications. | +| `/model` | Session adapter | Live model/reasoning catalogue, confirmed while idle. Clears explicit speed override when selecting a model; does not reproduce native CLI persistence. | +| `/plan` | Partial | Advertised collaboration-mode selection; no native optional prompt argument. | +| `/permissions` | Session adapter | Live allowed named profiles for the directory, confirmed while idle. Not every native permission-dialog action is implemented. | +| `/skills` | Browse only | `skills/list` inventory/help. No invocation or configuration flow; `skills/config/write` exists but needs scope/review UI. | +| `/apps` | Browse only | `app/list` inventory/help. Installation, linking and authentication workflows are absent. | +| `/mcp` | Browse only | `mcpServerStatus/list` and tool help. No `/mcp login`, resource browser or arbitrary tool invocation. Related APIs exist but need dedicated authentication/execution UI. | +| `/hooks` | Browse only | `hooks/list`. No editor/review for lifecycle-hook configuration or its command execution scope. | +| `/experimental` | Browse only | `experimentalFeature/list`. Enablement changes process/configuration scope, rather than a single session; no mutation UI. | +| `/statusline` | Local equivalent | Codexometer's own footer picker; also available in read-only web mode. Does not edit the native CLI's status line. | + +`/help` is Codexometer's catalogue entry, absent from this upstream registry. Speed aliases such as `/fast` appear only when the current model advertises that tier; IDs are not guessed. They change session overrides rather than native persistent defaults. + +### Directory-change semantics + +Codexometer's `/cd` keeps the selected thread ID/history. In 0.162.1, the server replaces the previous directory in default workspace roots, retains other roots and applies existing permission validation. Codexometer sends no permission/model/global configuration overrides. Directory changes are restricted to local execution environments; `/cwd` can display a remote session's reported directory. + +Native `/cd` is a larger client workflow: destination project-configuration reload, trust checks, checks for subagents/background terminals, and potentially a conversation fork into a new thread. Codexometer **does not perform that workflow**, reload project configuration/instruction sources, or move subagents or already-running terminals. Other clients attached to the same thread share its server settings, but may retain their own local project/UI context and send their own directory overrides. The confirmation explains this. Use native `/cd` for its full project-context transition. Success is reported only after running configuration reflects the new directory; ignored fields, server rejection, timeout or reconnection remain unconfirmed. + +## Missing commands with server capabilities or conversation workflows + +These are adapter/workflow gaps. Where an API exists it is listed; this PR only adds directory commands. + +| Command | Mechanism / why missing | +| --- | --- | +| `/new` | `thread/start` exists; needs creation options and selection/handoff to the new thread. | +| `/clear` | Native clear starts a new chat and clears its terminal; no combined local clear/`thread/start` workflow. Hiding monitor rows is different. | +| `/resume` | `thread/list`/`thread/resume` exist; no saved-session picker. Monitor selection observes loaded sessions. | +| `/fork` | `thread/fork` exists; needs options, confirmation and handoff while preserving source drafts. | +| `/worktree` | Needs actual Git worktree creation/ownership/cleanup plus thread creation/fork. No worktree manager; a cwd update is insufficient. | +| `/archive` | `thread/archive` exists; no archive confirmation/handoff. Close/Close All only hide rows. | +| `/delete` | `thread/delete` exists; no destructive-delete confirmation and history/selection cleanup. | +| `/compact` | `thread/compact/start` exists; needs state checks and completion/error progress rather than reporting a queued operation as done. | +| `/recap` | Native summarization workflow has no adapter/progress UI; verify that workflow before choosing a server operation or prompt. | +| `/review` | `review/start` exists; no review-target picker, delivery mode or progress UI. | +| `/goal` | `thread/goal/get`, `set`, `clear` exist; no goal editor, budget/clear confirmation or goal state. | +| `/side`, `/btw` | Ephemeral forks need a temporary conversation/draft view, thread routing and cleanup. | +| `/approve` | `thread/approveGuardianDeniedAction` exists; needs exact targeting of a recent automatic-review denial. Ordinary approval buttons are a different action. | +| `/ps` | `thread/backgroundTerminals/list` exists; no list/detail adapter. Telemetry process/session views do not reproduce it. | +| `/stop`, `/clean` | `thread/backgroundTerminals/clean` exists; no session-scoped stop-all review and verification. Turn interruption is a different action. | +| `/usage` | `account/usage/read`, rate-limit/reset-credit APIs exist. Usage/reset-token UI already exists; no slash alias opens it. Account reset credits are different from Sessions Zero. | +| `/status` | Settings/usage reads exist; detail/footer show related data, but no consolidated status slash view. | +| `/debug-config` | `config/read` with layers and `configRequirements/read` exist; no directory-aware configuration-source/requirements inspector. | +| `/daybreak` | `thread/metadata/update` can save Daybreak choice; no dedicated feature-aware toggle/state adapter. Do not invent an experimental flag ID. | +| `/memories` | `memory/status`, `thread/memoryMode/set` and configuration APIs exist; no scope-specific settings UI. Thread mode and global generation settings differ. | +| `/import` | `externalAgentConfig/detect`/`import` exist; no selection, preview, progress or configuration/history confirmation. | +| `/plugins` | Listing/search/read/install/uninstall APIs exist; no lifecycle/authentication and installation/configuration-review workflow. | +| `/logout` | `account/logout` exists; needs account-level confirmation and recovery for consequences to shared clients. | +| `/feedback` | `feedback/upload` exists; no log-selection and data-sharing preview/consent workflow. | +| `/setup-default-sandbox` | `windowsSandbox/setupStart`/`readiness` exist; no Windows elevated-sandbox setup workflow. Not applicable to macOS local sessions. | +| `/voice` | `thread/realtime/*`, including voice listing, exist; no microphone/audio transport, device settings or realtime conversation UI. | +| `/daemon` | Native daemon management and `server/diagnostics` exist; no lifecycle-management command. Stopping/restarting affects other clients. | +| `/warnings` | Server/config warning notifications exist; no retained warning/diagnostic browser. Ordinary error notices are only partial analogues. | + +## Missing native UI commands + +These require Codexometer UX, not forwarding the command name to a server. + +| Command | Why missing / existing analogue | +| --- | --- | +| `/agents` | Native agent command center has no adapter; linked-session grouping is not a matching management center. | +| `/subagents` | Linked agents are visible in grouping; no slash picker switches their native CLI views. | +| `/copy` | Copy controls exist; no slash alias/picker for the last response or selected transcript parts. | +| `/export` | No Markdown export; needs complete paginated history plus a file/download destination. | +| `/diff` | No repository diff browser with tracked/untracked handling and explicit repository context. | +| `/mention` | No structured file-mention picker or associated attachment/input metadata routing. | +| `/init` | Native command asks Codex to create `AGENTS.md`; no explicit generation/overwrite review. It is deliberately not silently converted to a prompt. | +| `/ide` | No native IDE-context integration for selection/open files. | +| `/app` | No desktop-app handoff/deep-link action; upstream visibility is platform-dependent. | +| `/raw` | Native raw-scrollback toggle cannot control Codexometer's separate rendering; no equivalent local switch. | +| `/tui` | Chooses native CLI mode for its next launch; no corresponding Codexometer launch-mode picker. | +| `/title` | No local title-field picker or native title configuration editor. | +| `/theme` | Codexometer theme preferences exist; no slash entry reproduces the native syntax-highlighting picker. | +| `/pets`, `/pet` | Native terminal-pet picker has no counterpart here. | +| `/keymap` | No shortcut-remapping editor; native keybindings belong to another interface. | +| `/vim` | No Vim-mode composer. | +| `/exit`, `/quit` | Existing local Quit controls exit Codexometer, without slash aliases. Native CLI exit/server shutdown has different scope. | + +## Debug entries and older documented names + +| Command | Treatment | +| --- | --- | +| `/rollout` | Debug-build registry entry; no rollout-path slash inspector. | +| `/test-approval` | Debug-build synthetic approval request; not a user command here. Real approvals already have dedicated controls. | +| `/debug-m-drop`, `/debug-m-update` | Registry descriptions say “DO NOT USE”; intentionally not exposed. | +| `/agent` | Older published name; this registry uses `/agents`, not a separate `/agent` command. | +| `/personality` | Published but absent from this registry; protocol personality fields are deprecated. No current CLI style selector to reproduce. | +| `/sandbox-add-read-dir` | Published/platform-specific older entry, absent from this registry. Do not assume availability in every installed version. | + +## Follow-up priorities + +1. Add slash entry points to existing read-only/local views: `/status`, `/usage`, `/copy`, `/subagents`, plus a background-terminal `/ps` view. +2. Add `/compact`, `/review` and `/goal` with completion/state tracking; then `/new`, `/resume` and `/fork` with thread handoff. +3. Add `/diff`, `/export` and background-terminal stop controls with explicit target scope. +4. Keep account/global configuration, import, installation, sandbox and daemon actions in dedicated reviewed workflows. Their omission is mainly absent UX/scope handling, not absent APIs. + +For future updates, compare both the next installed version's registry and generated protocol. Omission from the published list is not evidence that a command is unsupported. diff --git a/internal/codex/daemon_status.go b/internal/codex/daemon_status.go index 329a45e..bbd54e7 100644 --- a/internal/codex/daemon_status.go +++ b/internal/codex/daemon_status.go @@ -18,10 +18,11 @@ type sessionStatusProvider interface { } type sessionDaemonSnapshot struct { - Contexts map[string]SessionContext - Statuses map[string]sessionRuntimeStatus - ModelObservations []resolvedModelObservation - SubscribedThreads map[string]struct{} + Contexts map[string]SessionContext + WorkingDirectories map[string]string + Statuses map[string]sessionRuntimeStatus + ModelObservations []resolvedModelObservation + SubscribedThreads map[string]struct{} } // resolvedModelObservation links one exact app-server response usage event to diff --git a/internal/codex/daemon_status_unix.go b/internal/codex/daemon_status_unix.go index 1d8eb18..c66a7e1 100644 --- a/internal/codex/daemon_status_unix.go +++ b/internal/codex/daemon_status_unix.go @@ -27,24 +27,25 @@ type daemonStatusProvider struct { contexts map[string]*daemonContextState socketPath string - mu sync.Mutex - connection *websocket.Conn - nextRequestID int64 - pending map[int64]chan daemonEnvelope - subscribed map[string]struct{} - reroutedTurns map[daemonTurnKey]string - observations []resolvedModelObservation - nextSequence uint64 - lastStatusAt time.Time - statusThreads map[string]struct{} - statuses map[string]sessionRuntimeStatus - threadSettings map[string]QuotaSession - settingsVersions map[string]uint64 - settingsVersion uint64 - settingsSignal chan struct{} - settingsMu sync.Mutex - settingsClosed bool - writeMu sync.Mutex + mu sync.Mutex + connection *websocket.Conn + nextRequestID int64 + pending map[int64]chan daemonEnvelope + subscribed map[string]struct{} + reroutedTurns map[daemonTurnKey]string + observations []resolvedModelObservation + nextSequence uint64 + lastStatusAt time.Time + statusThreads map[string]struct{} + statuses map[string]sessionRuntimeStatus + threadSettings map[string]QuotaSession + threadDirectories map[string]string + settingsVersions map[string]uint64 + settingsVersion uint64 + settingsSignal chan struct{} + settingsMu sync.Mutex + settingsClosed bool + writeMu sync.Mutex } type daemonTurnKey struct { @@ -80,7 +81,7 @@ func (p *daemonStatusProvider) Fetch(ctx context.Context, threadIDs []string) (s if _, ok := loaded[threadID]; !ok || p.isSubscribed(threadID) { continue } - var resumed json.RawMessage + var resumed struct{ Cwd string } if err := p.request(ctx, "thread/resume", map[string]any{ "threadId": threadID, "excludeTurns": true, }, &resumed); err != nil { @@ -88,6 +89,9 @@ func (p *daemonStatusProvider) Fetch(ctx context.Context, threadIDs []string) (s } p.mu.Lock() p.subscribed[threadID] = struct{}{} + if filepath.IsAbs(resumed.Cwd) { + p.threadDirectories[threadID] = resumed.Cwd + } p.mu.Unlock() } } @@ -134,12 +138,16 @@ func (p *daemonStatusProvider) cachedStatusSnapshot(threadIDs []string, now time func (p *daemonStatusProvider) statusSnapshotLocked(threadIDs []string) sessionDaemonSnapshot { statuses := make(map[string]sessionRuntimeStatus, len(threadIDs)) + directories := make(map[string]string, len(threadIDs)) for _, threadID := range threadIDs { if status, ok := p.statuses[threadID]; ok { if state := p.contexts[threadID]; status == sessionRuntimeIdle && state != nil && state.completed { status = sessionRuntimeComplete } statuses[threadID] = status + if cwd := p.threadDirectories[threadID]; cwd != "" { + directories[threadID] = cwd + } } } subscribed := make(map[string]struct{}, len(p.subscribed)) @@ -147,10 +155,11 @@ func (p *daemonStatusProvider) statusSnapshotLocked(threadIDs []string) sessionD subscribed[threadID] = struct{}{} } return sessionDaemonSnapshot{ - Contexts: daemonContextSnapshot(p.contexts, threadIDs, statuses), - Statuses: statuses, - ModelObservations: append([]resolvedModelObservation(nil), p.observations...), - SubscribedThreads: subscribed, + Contexts: daemonContextSnapshot(p.contexts, threadIDs, statuses), + WorkingDirectories: directories, + Statuses: statuses, + ModelObservations: append([]resolvedModelObservation(nil), p.observations...), + SubscribedThreads: subscribed, } } @@ -203,6 +212,7 @@ func (p *daemonStatusProvider) unsubscribeMissing(ctx context.Context, threadIDs p.mu.Lock() delete(p.subscribed, threadID) delete(p.contexts, threadID) + delete(p.threadDirectories, threadID) for key := range p.reroutedTurns { if key.threadID == threadID { delete(p.reroutedTurns, key) @@ -245,6 +255,7 @@ func (p *daemonStatusProvider) ensureConnected(ctx context.Context) error { p.subscribed = make(map[string]struct{}) p.reroutedTurns = make(map[daemonTurnKey]string) p.threadSettings = make(map[string]QuotaSession) + p.threadDirectories = make(map[string]string) p.settingsVersions = make(map[string]uint64) p.settingsSignal = make(chan struct{}) p.mu.Unlock() @@ -415,16 +426,26 @@ func (p *daemonStatusProvider) handleNotification(method string, params json.Raw var notification struct { ThreadID string `json:"threadId"` ThreadSettings struct { + Cwd string `json:"cwd"` Model string `json:"model"` Effort string `json:"effort"` ServiceTier *string `json:"serviceTier"` } `json:"threadSettings"` } - if json.Unmarshal(params, ¬ification) != nil || notification.ThreadID == "" || - notification.ThreadSettings.Model == "" || notification.ThreadSettings.Effort == "" { + if json.Unmarshal(params, ¬ification) != nil || notification.ThreadID == "" { return } p.mu.Lock() + if filepath.IsAbs(notification.ThreadSettings.Cwd) { + if p.threadDirectories == nil { + p.threadDirectories = map[string]string{} + } + p.threadDirectories[notification.ThreadID] = notification.ThreadSettings.Cwd + } + if notification.ThreadSettings.Model == "" || notification.ThreadSettings.Effort == "" { + p.mu.Unlock() + return + } if p.threadSettings == nil { p.threadSettings = make(map[string]QuotaSession) } @@ -516,6 +537,7 @@ func (p *daemonStatusProvider) disconnect(connection *websocket.Conn) { p.statusThreads = nil p.statuses = nil p.threadSettings = nil + p.threadDirectories = nil if p.settingsSignal != nil { close(p.settingsSignal) p.settingsSignal = nil diff --git a/internal/codex/live_usage.go b/internal/codex/live_usage.go index e485fa1..544a77a 100644 --- a/internal/codex/live_usage.go +++ b/internal/codex/live_usage.go @@ -109,12 +109,13 @@ type LiveTurnTiming struct { // sessions. It also extracts bounded display-only replies and request context; // reasoning and arbitrary tool output are never retained. type LiveUsageReader struct { - sessionNames map[string]string - nameIndexInfo os.FileInfo - daemonContexts map[string]SessionContext - SessionsRoot string - WriterLocksRoot string - statusProvider sessionStatusProvider + sessionNames map[string]string + nameIndexInfo os.FileInfo + daemonContexts map[string]SessionContext + daemonDirectories map[string]string + SessionsRoot string + WriterLocksRoot string + statusProvider sessionStatusProvider mu sync.Mutex initialized bool @@ -340,6 +341,7 @@ func (r *LiveUsageReader) fetchTokenUsage(ctx context.Context, forceFullDiscover exactStatuses := map[string]sessionRuntimeStatus(nil) r.daemonContexts = nil + r.daemonDirectories = nil appServerUp := false r.daemonSubscribedThreads = nil if r.statusProvider != nil { @@ -347,6 +349,7 @@ func (r *LiveUsageReader) fetchTokenUsage(ctx context.Context, forceFullDiscover appServerUp = true exactStatuses = daemonSnapshot.Statuses r.daemonContexts = daemonSnapshot.Contexts + r.daemonDirectories = daemonSnapshot.WorkingDirectories r.ingestResolvedModelObservations(daemonSnapshot.ModelObservations) r.daemonSubscribedThreads = daemonSnapshot.SubscribedThreads } @@ -1278,6 +1281,9 @@ func (r *LiveUsageReader) sessionSnapshots(now time.Time, liveWriters map[string if root := byID[session.ID]; root != nil && !session.Unattributed { session.ModelSettings = root.modelSettings } + if cwd := r.daemonDirectories[session.ID]; cwd != "" { + session.WorkingDirectory = cwd + } session.Working = groupWorking[session.ID] if session.Attention == SessionAttentionComplete && groupWorking[session.ID] { session.Attention = SessionAttentionNone diff --git a/internal/codex/live_usage_test.go b/internal/codex/live_usage_test.go index b2f5cb6..fcb26ee 100644 --- a/internal/codex/live_usage_test.go +++ b/internal/codex/live_usage_test.go @@ -727,6 +727,7 @@ func TestLiveUsageReaderFinalizesRequestedModelWhenDaemonHasNoReroute(t *testing type stubSessionStatusProvider struct { statuses map[string]sessionRuntimeStatus + directories map[string]string observations []resolvedModelObservation subscribed map[string]struct{} unavailable bool @@ -737,7 +738,7 @@ func (s stubSessionStatusProvider) Fetch(context.Context, []string) (sessionDaem return sessionDaemonSnapshot{}, false } return sessionDaemonSnapshot{ - Statuses: s.statuses, ModelObservations: s.observations, SubscribedThreads: s.subscribed, + Statuses: s.statuses, ModelObservations: s.observations, SubscribedThreads: s.subscribed, WorkingDirectories: s.directories, }, true } @@ -1281,3 +1282,24 @@ func TestRolloutHelpers(t *testing.T) { t.Fatal("non-event token payload was accepted") } } + +func TestLiveUsageDirectoryFollowsRuntimeAndFallsBackAfterDisconnect(t *testing.T) { + home := t.TempDir() + now := time.Now() + path := testRolloutPath(t, home, now, "directory") + writeRollout(t, path, sessionMetaLine("directory", `"cli"`, "/original", nil)+"\n") + reader, err := NewLiveUsageReader(home) + if err != nil { + t.Fatal(err) + } + reader.statusProvider = stubSessionStatusProvider{statuses: map[string]sessionRuntimeStatus{"directory": sessionRuntimeIdle}, directories: map[string]string{"directory": "/changed"}} + usage, err := reader.FetchTokenUsage(context.Background()) + if err != nil || len(usage.Sessions) != 1 || usage.Sessions[0].WorkingDirectory != "/changed" { + t.Fatal("stale displayed directory", usage, err) + } + reader.statusProvider = stubSessionStatusProvider{unavailable: true} + usage, err = reader.FetchTokenUsage(context.Background()) + if err != nil || usage.Sessions[0].WorkingDirectory != "/original" { + t.Fatal("stale runtime directory survived disconnect", usage, err) + } +} diff --git a/internal/codex/session_commands.go b/internal/codex/session_commands.go index 96d82ca..87ce776 100644 --- a/internal/codex/session_commands.go +++ b/internal/codex/session_commands.go @@ -20,14 +20,16 @@ type SessionCommandChoice struct { } type SessionCommandMenu struct { - Title string `json:"title"` - Help string `json:"help"` - Path string `json:"path"` - Revision string `json:"revision"` - Multiple bool `json:"multiple,omitempty"` - Input bool `json:"input,omitempty"` - Value string `json:"value,omitempty"` - Choices []SessionCommandChoice `json:"choices"` + Title string `json:"title"` + Help string `json:"help"` + Path string `json:"path"` + Revision string `json:"revision"` + Multiple bool `json:"multiple,omitempty"` + Input bool `json:"input,omitempty"` + InputLabel string `json:"inputLabel,omitempty"` + InputLimit int `json:"inputLimit,omitempty"` + Value string `json:"value,omitempty"` + Choices []SessionCommandChoice `json:"choices"` } type SessionCommandsClient interface { diff --git a/internal/codex/session_commands_unix.go b/internal/codex/session_commands_unix.go index e994043..2f4bf0e 100644 --- a/internal/codex/session_commands_unix.go +++ b/internal/codex/session_commands_unix.go @@ -11,6 +11,7 @@ import ( "sort" "strings" "sync" + "time" ) type commandModel struct { @@ -23,6 +24,9 @@ type commandModel struct { type commandThread struct { ID, Cwd, Name string Status struct{ Type string } + Environments []struct { + EnvironmentID string `json:"environmentId"` + } } func commandDigest(value any) string { @@ -110,6 +114,12 @@ func (p *daemonStatusProvider) SessionCommands(ctx context.Context, id, path str if name, ok := strings.CutPrefix(path, "rename "); ok { path = "rename/" + url.PathEscape(strings.TrimSpace(name)) } + if directory, ok := strings.CutPrefix(path, "cd "); ok { + path = "cd/" + url.PathEscape(strings.TrimSpace(directory)) + } + if len(path) > 2048 { + return SessionCommandMenu{}, ErrSessionCommand + } thread, err := p.commandThread(ctx, id) if err != nil { return SessionCommandMenu{}, err @@ -153,8 +163,22 @@ func normalizeCommandMenu(menu SessionCommandMenu) SessionCommandMenu { func (p *daemonStatusProvider) commandMenu(ctx context.Context, t commandThread, path string) (SessionCommandMenu, error) { m := SessionCommandMenu{Title: "/" + path, Help: "Live options from the shared Codex app-server.", Choices: []SessionCommandChoice{}} parts := strings.Split(path, "/") + // Directory-scoped inventories must follow running settings after /cd, + // even while the captured thread metadata still contains the old cwd. + if parts[0] == "permissions" || parts[0] == "skills" || parts[0] == "hooks" { + p.mu.Lock() + conn := p.connection + p.mu.Unlock() + cwd, err := p.commandDirectory(ctx, conn, t.ID) + if err != nil { + return m, err + } + t.Cwd = cwd + m.Revision = commandDigest(cwd) + } + if path == "" || path == "help" { - families := []string{"rename", "model", "plan", "permissions", "skills", "apps", "mcp", "hooks", "experimental"} + families := []string{"rename", "cd", "cwd", "pwd", "model", "plan", "permissions", "skills", "apps", "mcp", "hooks", "experimental"} menus := make([]SessionCommandMenu, len(families)) errs := make([]error, len(families)) var wg sync.WaitGroup @@ -186,11 +210,15 @@ func (p *daemonStatusProvider) commandMenu(ctx context.Context, t commandThread, m.Help = "Choose a command. Options/help are discovered live. Changes target this session only and require confirmation. Model and permission settings are available only while idle. Catalogues marked browse-only do not execute tools or change global configuration." return m, nil } + if parts[0] == "cd" || parts[0] == "cwd" || parts[0] == "pwd" { + return p.commandDirectoryMenu(ctx, t, path) + } if parts[0] == "rename" { m.Title = "/rename" m.Help = "Rename this session in Codex. Enter a single-line name, then review and confirm the change. It does not send a prompt or change model settings." if path == "rename" { m.Input = true + m.InputLabel, m.InputLimit = "Session name", 512 m.Value = commandLabel(t.Name) return m, nil } @@ -213,7 +241,7 @@ func (p *daemonStatusProvider) commandMenu(ctx context.Context, t commandThread, if err != nil { return m, err } - m.Revision = commandDigest(current) + m.Revision = commandDigest([]any{current, t.Cwd}) setting := func(label, help string, params map[string]any) { params["threadId"] = t.ID if t.Status.Type != "idle" { @@ -319,7 +347,7 @@ func (p *daemonStatusProvider) commandMenu(ctx context.Context, t commandThread, } func commandReserved(s string) bool { - for _, name := range []string{"help", "rename", "model", "tier", "plan", "permissions", "skills", "apps", "mcp", "hooks", "experimental"} { + for _, name := range []string{"help", "rename", "cd", "cwd", "pwd", "model", "tier", "plan", "permissions", "skills", "apps", "mcp", "hooks", "experimental"} { if s == name { return true } @@ -351,6 +379,42 @@ func (p *daemonStatusProvider) ExecuteSessionCommand(ctx context.Context, id, pa if !valid { return ErrSessionCommand } + if cwd, changingDirectory := o.params["cwd"].(string); changingDirectory { + var queue struct { + Data *[]json.RawMessage + NextCursor *string + } + if err := p.requestOn(ctx, conn, "thread/queue/list", map[string]any{"threadId": id, "limit": 1}, &queue); err != nil { + return err + } + if queue.Data == nil || len(*queue.Data) != 0 || (queue.NextCursor != nil && *queue.NextCursor != "") { + return ErrSessionCommand + } + if err := p.requestOn(ctx, conn, o.method, o.params, nil); err != nil { + return err + } + // An empty settings response acknowledges queuing only. Read the + // running configuration before reporting success; old servers may + // silently ignore a field they do not recognise. Never retry writes. + verifyCtx, cancel := context.WithTimeout(ctx, daemonStatusRefreshEvery) + defer cancel() + ticker := time.NewTicker(100 * time.Millisecond) + defer ticker.Stop() + for { + active, err := p.commandDirectory(verifyCtx, conn, id) + if err != nil { + return err + } + if active == cwd { + return nil + } + select { + case <-verifyCtx.Done(): + return fmt.Errorf("directory update unconfirmed: %w", verifyCtx.Err()) + case <-ticker.C: + } + } + } return p.requestOn(ctx, conn, o.method, o.params, nil) } } diff --git a/internal/codex/session_directory_unix.go b/internal/codex/session_directory_unix.go new file mode 100644 index 0000000..dbf8def --- /dev/null +++ b/internal/codex/session_directory_unix.go @@ -0,0 +1,111 @@ +//go:build unix + +package codex + +import ( + "context" + "errors" + "net/url" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/gorilla/websocket" +) + +// Resume without overrides reads the running configuration of a loaded thread. +// thread/read.cwd is captured metadata and need not reflect a settings update. +func (p *daemonStatusProvider) commandDirectory(ctx context.Context, conn *websocket.Conn, id string) (string, error) { + var response struct { + Cwd string + Thread struct{ ID string } + } + if err := p.requestOn(ctx, conn, "thread/resume", map[string]any{"threadId": id, "excludeTurns": true}, &response); err != nil { + return "", err + } + if response.Thread.ID != id || !filepath.IsAbs(response.Cwd) { + return "", errors.New("running session directory unavailable; use Codex") + } + p.mu.Lock() + if p.connection != conn { + p.mu.Unlock() + return "", ErrSessionCommand + } + if p.threadDirectories == nil { + p.threadDirectories = map[string]string{} + } + p.threadDirectories[id] = response.Cwd + p.mu.Unlock() + return response.Cwd, nil +} + +func (p *daemonStatusProvider) commandDirectoryMenu(ctx context.Context, t commandThread, path string) (SessionCommandMenu, error) { + m := SessionCommandMenu{Title: "/" + strings.Split(path, "/")[0], Choices: []SessionCommandChoice{}} + p.mu.Lock() + conn := p.connection + p.mu.Unlock() + cwd, err := p.commandDirectory(ctx, conn, t.ID) + if err != nil { + return m, err + } + m.Revision = commandDigest(cwd) + if path == "cwd" || path == "pwd" { + m.Help = "Current working directory from this session's running Codex configuration. /cwd and /pwd are aliases." + m.Choices = append(m.Choices, SessionCommandChoice{Label: strconv.Quote(cwd), Help: "Working directory: " + strconv.Quote(cwd)}) + return m, nil + } + if path != "cd" && !strings.HasPrefix(path, "cd/") { + return m, ErrSessionCommand + } + m.Help = "Change this session's directory for subsequent turns. History and session ID are retained. The server adjusts its directory workspace root and retains other roots and permission settings. This does not perform the native CLI's project-configuration reload or conversation fork. Review and confirm while idle, with no queued messages." + for _, env := range t.Environments { + if env.EnvironmentID != "local" { + return m, errors.New("directory changes for remote or multiple execution environments require Codex") + } + } + if len(t.Environments) > 1 { + return m, ErrSessionCommand + } + if path == "cd" { + m.Input, m.InputLabel, m.InputLimit, m.Value = true, "Working directory", 1024, cwd + return m, nil + } + input, err := url.PathUnescape(strings.TrimPrefix(path, "cd/")) + if err != nil || input == "" || strings.Contains(input, "\x00") { + return m, ErrSessionCommand + } + // The review retains the supplied path; resolving it again at confirmation + // invalidates the choice if a symlink has been retargeted in the meantime. + target := input + if target == "~" || strings.HasPrefix(target, "~/") { + home, err := os.UserHomeDir() + if err != nil { + return m, err + } + target = filepath.Join(home, strings.TrimPrefix(strings.TrimPrefix(target, "~"), "/")) + } + if !filepath.IsAbs(target) { + target = filepath.Join(cwd, target) + } + target, err = filepath.EvalSymlinks(filepath.Clean(target)) + if err != nil { + return m, err + } + info, err := os.Stat(target) + if err != nil { + return m, err + } + if !info.IsDir() { + return m, errors.New("target is not a directory") + } + help := "Current directory: " + strconv.Quote(cwd) + "\nNew directory: " + strconv.Quote(target) + choice := SessionCommandChoice{Label: "Change working directory", Help: help} + if t.Status.Type == "idle" { + choice.method, choice.params = "thread/settings/update", map[string]any{"threadId": t.ID, "cwd": target} + } else { + choice.Help += "\nAvailable when this session is idle." + } + m.Choices = append(m.Choices, choice) + return m, nil +} diff --git a/internal/codex/session_directory_unix_test.go b/internal/codex/session_directory_unix_test.go new file mode 100644 index 0000000..839abf9 --- /dev/null +++ b/internal/codex/session_directory_unix_test.go @@ -0,0 +1,299 @@ +//go:build unix + +package codex + +import ( + "context" + "net/url" + "os" + "path/filepath" + "strings" + "testing" + "time" +) + +func directoryFixture(t *testing.T) (*daemonStatusProvider, *quotaDaemonFixture, string) { + t.Helper() + p, f := newQuotaDaemon(t) + base, err := filepath.EvalSymlinks(t.TempDir()) + if err != nil { + t.Fatal(err) + } + f.cwds = map[string]string{"one": base, "two": "/other"} + return p, f, base +} + +func TestSessionDirectoryReadAndScopedChange(t *testing.T) { + p, f, base := directoryFixture(t) + ctx := context.Background() + target := filepath.Join(base, "two spaces 界") + if err := os.Mkdir(target, 0700); err != nil { + t.Fatal(err) + } + for _, alias := range []string{"cwd", "pwd"} { + m, err := p.SessionCommands(ctx, "one", alias) + if err != nil || len(m.Choices) != 1 || m.Choices[0].Action || !strings.Contains(m.Choices[0].Help, base) { + t.Fatal(m, err) + } + if err := p.ExecuteSessionCommand(ctx, "one", m.Path, m.Revision, m.Choices[0].ID); err == nil { + t.Fatal("read-only directory executed") + } + } + root, err := p.SessionCommands(ctx, "one", "") + if err != nil { + t.Fatal(err) + } + for _, command := range []string{"cd", "cwd", "pwd"} { + found := false + for _, o := range root.Choices { + found = found || o.Next == command + } + if !found || !commandReserved(command) { + t.Fatal("missing directory command", command) + } + } + editor, err := p.SessionCommands(ctx, "one", "cd") + if err != nil || !editor.Input || editor.Value != base || editor.InputLabel != "Working directory" { + t.Fatal(editor, err) + } + m, err := p.SessionCommands(ctx, "one", "/cd two spaces 界") + if err != nil || len(m.Choices) != 1 || !m.Choices[0].Action || !strings.Contains(m.Choices[0].Help, target) { + t.Fatal(m, err) + } + if len(f.writes) != 0 { + t.Fatal("review changed directory") + } + if err := p.ExecuteSessionCommand(ctx, "two", m.Path, m.Revision, m.Choices[0].ID); err == nil { + t.Fatal("cross-session directory change") + } + if err := p.ExecuteSessionCommand(ctx, "one", m.Path, m.Revision, m.Choices[0].ID); err != nil { + t.Fatal(err) + } + f.mu.Lock() + if len(f.writes) != 1 || len(f.writes[0]) != 2 || f.writes[0]["cwd"] != target || f.cwds["one"] != target || f.cwds["two"] != "/other" || f.sessions["one"].Model != "large" { + t.Error("incorrect mutation", f.writes) + } + f.mu.Unlock() + // The fixture intentionally keeps thread/read.cwd stale, like captured + // metadata. /cwd must still report the running configuration's new path. + m, err = p.SessionCommands(ctx, "one", "cwd") + if err != nil || !strings.Contains(m.Choices[0].Help, target) { + t.Fatal("stale cwd after change", m, err) + } +} + +func TestSessionDirectoryTargetsAndRevalidation(t *testing.T) { + p, f, base := directoryFixture(t) + ctx := context.Background() + other := filepath.Join(base, "other") + if err := os.Mkdir(other, 0700); err != nil { + t.Fatal(err) + } + link := filepath.Join(base, "link") + if err := os.Symlink(base, link); err != nil { + t.Fatal(err) + } + m, err := p.SessionCommands(ctx, "one", "cd/"+url.PathEscape(link)) + if err != nil { + t.Fatal(err) + } + if err := os.Remove(link); err != nil { + t.Fatal(err) + } + if err := os.Symlink(other, link); err != nil { + t.Fatal(err) + } + if err := p.ExecuteSessionCommand(ctx, "one", m.Path, m.Revision, m.Choices[0].ID); err == nil { + t.Fatal("retargeted symlink accepted") + } + home, _ := os.UserHomeDir() + home, _ = filepath.EvalSymlinks(home) + m, err = p.SessionCommands(ctx, "one", "cd/~") + if err != nil || m.Choices[0].params["cwd"] != home { + t.Fatal("home expansion", m, err) + } + file := filepath.Join(base, "file") + if err := os.WriteFile(file, nil, 0600); err != nil { + t.Fatal(err) + } + for _, input := range []string{"", "%zz", url.PathEscape(file), url.PathEscape(filepath.Join(base, "missing")), "%00"} { + if _, err := p.SessionCommands(ctx, "one", "cd/"+input); err == nil { + t.Fatal("accepted invalid directory", input) + } + } + for _, mode := range []string{"changed-directory", "active", "queued", "server-rejection", "pending-approval", "reconnect"} { + t.Run(mode, func(t *testing.T) { + p, f, base := directoryFixture(t) + m, err := p.SessionCommands(ctx, "one", "cd/"+url.PathEscape(base)) + if err != nil { + t.Fatal(err) + } + f.mu.Lock() + switch mode { + case "changed-directory": + f.cwds["one"] = "/changed" + case "active": + f.commandStatus = "active" + case "queued": + f.queued = true + case "server-rejection": + f.fail = "cwd" + } + f.mu.Unlock() + if mode == "pending-approval" { + p.mu.Lock() + p.contexts = map[string]*daemonContextState{"one": {requests: map[string]SessionContext{"r": {}}}} + p.mu.Unlock() + } + if mode == "reconnect" { + p.disconnect(nil) + } + if err := p.ExecuteSessionCommand(ctx, "one", m.Path, m.Revision, m.Choices[0].ID); err == nil { + t.Fatal("accepted changed directory context") + } + f.mu.Lock() + defer f.mu.Unlock() + if mode != "server-rejection" && len(f.writes) != 0 { + t.Fatal("unexpected directory write", f.writes) + } + }) + } + f.mu.Lock() + f.commandStatus = "active" + f.mu.Unlock() + m, err = p.SessionCommands(ctx, "one", "cd/"+url.PathEscape(base)) + if err != nil || m.Choices[0].Action { + t.Fatal("active directory mutation available", m, err) + } + if _, err = p.SessionCommands(ctx, "one", "cwd"); err != nil { + t.Fatal("cannot read active cwd", err) + } +} + +func TestSessionDirectoryAcknowledgementIsNotConfirmation(t *testing.T) { + p, f, base := directoryFixture(t) + other := filepath.Join(base, "next") + if err := os.Mkdir(other, 0700); err != nil { + t.Fatal(err) + } + f.ignoreCwd = true + m, err := p.SessionCommands(context.Background(), "one", "cd/"+url.PathEscape(other)) + if err != nil { + t.Fatal(err) + } + ctx, cancel := context.WithTimeout(context.Background(), 350*time.Millisecond) + defer cancel() + if err := p.ExecuteSessionCommand(ctx, "one", m.Path, m.Revision, m.Choices[0].ID); err == nil { + t.Fatal("ignored cwd field reported as changed") + } + f.mu.Lock() + defer f.mu.Unlock() + if len(f.writes) != 1 || f.cwds["one"] != base { + t.Fatal("unconfirmed write was retried", f.writes) + } +} + +func TestSessionDirectoryRejectsRemoteEnvironments(t *testing.T) { + p, f, _ := directoryFixture(t) + f.environments = []any{map[string]any{"environmentId": "remote"}} + if _, err := p.SessionCommands(context.Background(), "one", "cd"); err == nil { + t.Fatal("resolved remote directory on local filesystem") + } + if _, err := p.SessionCommands(context.Background(), "one", "cwd"); err != nil { + t.Fatal("remote directory read unavailable", err) + } +} + +func TestSessionDirectoryWaitsForQueuedApplication(t *testing.T) { + p, f, base := directoryFixture(t) + target := filepath.Join(base, "later") + if err := os.Mkdir(target, 0700); err != nil { + t.Fatal(err) + } + f.ignoreCwd = true + m, err := p.SessionCommands(context.Background(), "one", "cd/"+url.PathEscape(target)) + if err != nil { + t.Fatal(err) + } + applied := make(chan struct{}) + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + go func() { + defer close(applied) + ticker := time.NewTicker(20 * time.Millisecond) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + f.mu.Lock() + wrote := len(f.writes) == 1 + if wrote { + f.cwds["one"] = target + } + f.mu.Unlock() + if wrote { + return + } + } + } + }() + if err := p.ExecuteSessionCommand(ctx, "one", m.Path, m.Revision, m.Choices[0].ID); err != nil { + t.Fatal(err) + } + <-applied + f.mu.Lock() + defer f.mu.Unlock() + if len(f.writes) != 1 { + t.Fatal("settings write retried") + } +} + +func TestSessionDirectoryScopedCataloguesFollowRunningCwd(t *testing.T) { + p, f, base := directoryFixture(t) + f.catalogues = map[string]map[string]any{ + "skills/list": {"data": []any{map[string]any{"cwd": base, "skills": []any{map[string]any{"name": "current-project", "description": "Current directory help", "enabled": true}}}}}, + "permissionProfile/list": {"data": []any{map[string]any{"id": "safe", "description": "Read-only", "allowed": true}}}, + } + ctx := context.Background() + m, err := p.SessionCommands(ctx, "one", "skills") + if err != nil || len(m.Choices) != 1 || m.Choices[0].Label != "current-project" { + t.Fatal("used captured metadata cwd", m, err) + } + m, err = p.SessionCommands(ctx, "one", "permissions") + if err != nil { + t.Fatal(err) + } + f.mu.Lock() + f.cwds["one"] = "/changed" + f.mu.Unlock() + if err := p.ExecuteSessionCommand(ctx, "one", m.Path, m.Revision, m.Choices[0].ID); err == nil { + t.Fatal("directory-scoped setting ignored concurrent cwd change") + } +} + +func TestSessionDirectoryTelemetryTracksReadAndSettingsEvents(t *testing.T) { + p, _, base := directoryFixture(t) + snapshot, ok := p.Fetch(context.Background(), []string{"one"}) + if !ok || snapshot.WorkingDirectories["one"] != base { + t.Fatal("initial running directory missing", snapshot, ok) + } + // Cwd is useful even if a model has no explicit reasoning effort. + p.handleNotification("thread/settings/updated", []byte(`{"threadId":"one","threadSettings":{"cwd":"/changed","effort":null}}`)) + snapshot, ok = p.Fetch(context.Background(), []string{"one"}) + if !ok || snapshot.WorkingDirectories["one"] != "/changed" { + t.Fatal("directory notification ignored", snapshot, ok) + } + snapshot.WorkingDirectories["one"] = "/modified-copy" + snapshot, _ = p.Fetch(context.Background(), []string{"one"}) + if snapshot.WorkingDirectories["one"] != "/changed" { + t.Fatal("snapshot aliases internal directory state") + } + p.disconnect(nil) + p.mu.Lock() + defer p.mu.Unlock() + if len(p.threadDirectories) != 0 { + t.Fatal("directory observations retained after disconnect") + } +} diff --git a/internal/codex/session_settings_unix_test.go b/internal/codex/session_settings_unix_test.go index 8da6143..88539ff 100644 --- a/internal/codex/session_settings_unix_test.go +++ b/internal/codex/session_settings_unix_test.go @@ -30,6 +30,9 @@ type quotaDaemonFixture struct { historyReads []map[string]any names map[string]string nameWrites []map[string]any + cwds map[string]string + ignoreCwd bool + environments []any } func TestQuotaEffortDefaultFallback(t *testing.T) { @@ -108,13 +111,17 @@ func newQuotaDaemon(t *testing.T) (*daemonStatusProvider, *quotaDaemonFixture) { case "thread/resume": s, ok := fixture.sessions[id] failure = !ok || fixture.fail == id - result = map[string]any{"model": s.Model, "reasoningEffort": s.Effort, "serviceTier": s.Tier, "thread": map[string]any{"id": id}} + cwd := fixture.cwds[id] + if cwd == "" { + cwd = "/work" + } + result = map[string]any{"cwd": cwd, "model": s.Model, "reasoningEffort": s.Effort, "serviceTier": s.Tier, "thread": map[string]any{"id": id}} case "thread/read": status := fixture.commandStatus if status == "" { status = "idle" } - result["thread"] = map[string]any{"id": id, "cwd": "/work", "status": map[string]any{"type": status}, "name": fixture.names[id]} + result["thread"] = map[string]any{"id": id, "cwd": "/work", "status": map[string]any{"type": status}, "name": fixture.names[id], "environments": fixture.environments} case "thread/name/set": fixture.nameWrites = append(fixture.nameWrites, req.Params) failure = fixture.fail == "rename" @@ -124,8 +131,20 @@ func newQuotaDaemon(t *testing.T) (*daemonStatusProvider, *quotaDaemonFixture) { } fixture.names[id], _ = req.Params["name"].(string) } + case "thread/queue/list": + result = map[string]any{"data": []any{}} + if fixture.queued { + result["data"] = []any{map[string]any{"id": "queued"}} + } case "thread/settings/update": fixture.writes = append(fixture.writes, req.Params) + failure = fixture.fail == "cwd" + if cwd, ok := req.Params["cwd"].(string); ok && !failure && !fixture.queued && !fixture.ignoreCwd { + if fixture.cwds == nil { + fixture.cwds = map[string]string{} + } + fixture.cwds[id] = cwd + } desired := fixture.sessions[id] if v, ok := req.Params["model"].(string); ok { desired.Model = v diff --git a/internal/ui/monitor_commands.go b/internal/ui/monitor_commands.go index d8b288f..261926a 100644 --- a/internal/ui/monitor_commands.go +++ b/internal/ui/monitor_commands.go @@ -186,7 +186,11 @@ func (m Model) monitorCommandRows(width, height int) []commandDisplayRow { return rows } if p.menu.Input { - rows = append(rows, commandDisplayRow{text: "SESSION NAME", choice: -1}) + label := p.menu.InputLabel + if label == "" { + label = "Session name" + } + rows = append(rows, commandDisplayRow{text: strings.ToUpper(label), choice: -1}) p.input.SetWidth(max(w-2, 1)) rows = append(rows, commandDisplayRow{text: p.input.View(), choice: -1}) for _, line := range strings.Split(ansi.Hardwrap(p.menu.Help, w, true), "\n") { @@ -207,6 +211,8 @@ func (m Model) monitorCommandRows(width, height int) []commandDisplayRow { text += "\n\nTARGET // " + p.session if strings.HasPrefix(p.menu.Path, "rename/") { text += "\nOnly this session's saved name changes. Confirm after reviewing the new name." + } else if strings.HasPrefix(p.menu.Path, "cd/") { + text += "\nOnly this session’s directory changes; project configuration is not reloaded. Confirm after reviewing both paths." } else { text += "\nChanges apply to subsequent turns of this session. They are not global defaults. Confirm only after reviewing the option. Automatic quota thresholds may later supersede model settings." } @@ -342,19 +348,24 @@ func (m Model) updateMonitorCommands(msg tea.Msg) (Model, tea.Cmd, bool) { m.monitorPrompt.notice = "Change requested. Codex will apply it to subsequent turns." if strings.HasPrefix(r.path, "rename/") { m.monitorPrompt.notice = "Session renamed." + } else if strings.HasPrefix(r.path, "cd/") { + m.monitorPrompt.notice = "Working directory changed." } return m, cmd, true } else { p.menu = r.menu if p.menu.Input { p.input = textinput.New() - p.input.CharLimit = 512 + p.input.CharLimit = p.menu.InputLimit + if p.input.CharLimit <= 0 { + p.input.CharLimit = 512 + } p.input.SetWidth(max(m.monitorDashboardLayout().contentWidth-6, 1)) p.input.SetValue(p.menu.Value) cmd := p.input.Focus() return m, cmd, true } - if strings.HasPrefix(p.menu.Path, "rename/") && len(p.menu.Choices) == 1 { + if (strings.HasPrefix(p.menu.Path, "rename/") || strings.HasPrefix(p.menu.Path, "cd/")) && len(p.menu.Choices) == 1 { p.detail = true p.until = time.Now().Add(30 * time.Second) } @@ -532,13 +543,13 @@ func (m Model) updateMonitorCommands(msg tea.Msg) (Model, tea.Cmd, bool) { func (m Model) reviewMonitorCommandInput() (Model, tea.Cmd, bool) { p := &m.monitorCommands - if !p.menu.Input || p.menu.Path != "rename" || p.busy { + if !p.menu.Input || (p.menu.Path != "rename" && p.menu.Path != "cd") || p.busy { return m, nil, true } name := strings.TrimSpace(p.input.Value()) if name == "" { return m, nil, true } - cmd := m.loadMonitorCommands("rename/" + url.PathEscape(name)) + cmd := m.loadMonitorCommands(p.menu.Path + "/" + url.PathEscape(name)) return m, cmd, true } diff --git a/internal/ui/monitor_commands_test.go b/internal/ui/monitor_commands_test.go index adb60d3..0aef908 100644 --- a/internal/ui/monitor_commands_test.go +++ b/internal/ui/monitor_commands_test.go @@ -327,3 +327,50 @@ func TestMonitorRenameEditorKeepsBackgroundUpdates(t *testing.T) { } }) } + +// Directory input uses the same event-preserving editor as rename, with its own +// label, length and confirmation notice. The ordinary composer draft survives. +type directoryTestClient struct { + *commandTestClient + path string +} + +func (f *directoryTestClient) SessionCommands(_ context.Context, _ string, path string) (codex.SessionCommandMenu, error) { + f.path = path + m := codex.SessionCommandMenu{Title: "/cd", Path: path, Revision: "directory-revision"} + if path == "cd" { + m.Input, m.InputLabel, m.InputLimit, m.Value = true, "Working directory", 1024, "/old" + } else { + m.Choices = []codex.SessionCommandChoice{{ID: "directory", Label: "Change working directory", Help: "New directory: /new path 界", Action: true}} + } + return m, nil +} +func TestMonitorDirectoryEditorReviewAndConfirmation(t *testing.T) { + m, base := commandTestModel(t) + f := &directoryTestClient{commandTestClient: base} + m.fetcher = f + m.monitorPrompt.input.SetValue("unsent directory draft") + m, cmd, _ := m.openMonitorCommands("cd") + next, _ := m.Update(cmd()) + m = next.(Model) + if m.monitorCommands.input.Value() != "/old" || m.monitorCommands.input.CharLimit != 1024 || !strings.Contains(ansi.Strip(m.render()), "WORKING DIRECTORY") { + t.Fatal("directory editor missing") + } + m.monitorCommands.input.SetValue("/new path 界") + m, cmd, _ = m.reviewMonitorCommandInput() + next, _ = m.Update(cmd()) + m = next.(Model) + if f.path != "cd/"+url.PathEscape("/new path 界") || !m.monitorCommands.detail || f.calls != 0 { + t.Fatal("directory not reviewed") + } + _, cmd, _ = m.updateMonitorCommands(tea.KeyPressMsg{Code: tea.KeyEnter}) + if cmd != nil { + t.Fatal("Enter bypassed confirmation") + } + m, cmd, _ = m.confirmMonitorCommand() + next, _ = m.Update(cmd()) + m = next.(Model) + if f.calls != 1 || m.monitorCommands.open || m.monitorPrompt.input.Value() != "unsent directory draft" || m.monitorPrompt.notice != "Working directory changed." { + t.Fatal("directory change lost draft or notice") + } +} diff --git a/internal/web/control_commands.go b/internal/web/control_commands.go index 4e05e7c..8701511 100644 --- a/internal/web/control_commands.go +++ b/internal/web/control_commands.go @@ -52,6 +52,8 @@ func (c *control) handleCommands(w http.ResponseWriter, r *http.Request, body ac message := "Change requested. Codex will apply it to subsequent turns." if strings.HasPrefix(q.Path, "rename/") { message = "Session renamed." + } else if strings.HasPrefix(q.Path, "cd/") { + message = "Working directory changed." } _ = json.NewEncoder(w).Encode(map[string]string{"message": message}) return diff --git a/internal/web/control_commands_test.go b/internal/web/control_commands_test.go index b5a3820..1a7d3ab 100644 --- a/internal/web/control_commands_test.go +++ b/internal/web/control_commands_test.go @@ -82,3 +82,22 @@ func TestCommandsRejectStaleAndMixedRequests(t *testing.T) { t.Fatal("invalid request mutated settings") } } + +func TestDirectoryCommandReportsVerifiedSuccess(t *testing.T) { + s, _, token := controlServer(t) + f := &commandsFake{revision: "current"} + s.control.commands = f + b := actionRequest{Session: "parent", Command: &commandRequest{Mode: "prepare", Path: "cd/new", Revision: "current", Choice: "choice"}} + w := actionCall(s, token, "commands", b) + var response struct{ Confirmation string } + if w.Code != 200 || json.Unmarshal(w.Body.Bytes(), &response) != nil { + t.Fatal(w.Body) + } + b.Confirmation = response.Confirmation + b.Command = &commandRequest{Mode: "commit"} + w = actionCall(s, token, "commands", b) + var result struct{ Message string } + if w.Code != 200 || json.Unmarshal(w.Body.Bytes(), &result) != nil || result.Message != "Working directory changed." || f.calls != 1 { + t.Fatal(w.Body) + } +} diff --git a/internal/web/dist/assets/index-LUN8vjss.js b/internal/web/dist/assets/index-E1h87Zp5.js similarity index 93% rename from internal/web/dist/assets/index-LUN8vjss.js rename to internal/web/dist/assets/index-E1h87Zp5.js index c87c05f..14933af 100644 --- a/internal/web/dist/assets/index-LUN8vjss.js +++ b/internal/web/dist/assets/index-E1h87Zp5.js @@ -9,10 +9,11 @@ USED`)),J(e,n)};X(je,e=>{i()?e(Me):e(Ne,-1)});var Pe=V(je),Fe=V(Pe,3),Ie=B(Fe,!0),Le=V(Fe,2),Re=e=>{var t=Oa(),n=B(V(z(t)));H(e=>Y(n,`TREND // ${e??``}`),[()=>i()?`${G(k).projected-100>0?`+`:``}${(G(k).projected-100).toFixed(1)} PP AT RESET`:G(k).projected>=100?`QUOTA EXHAUSTION PROJECTED`:`${G(k).projected.toFixed(1)}% PROJECTED AT RESET`]),J(e,t)};X(Le,e=>{G(k)&&e(Re)}),M(Ae);var ze=V(Ae,2),Be=R(ze),Ve=R(Be);xi(Ve),Ce(),M(Be);var He=V(Be,2),N=V(R(He),2),Ue=R(N);Ue.value=Ue.__value=`off`;var Ke=V(Ue),qe=B(Ke);Ke.value=Ke.__value=`halfHour`;var Je=V(Ke),Ye=B(Je);Je.value=Je.__value=`hour`;var Xe=V(Je),Ze=B(Xe);Xe.value=Xe.__value=`day`;var Qe=V(Xe),$e=B(Qe);Qe.value=Qe.__value=`window`,M(N),mi(N),M(He);var et=B(V(He,2));M(ze),M(ke);var tt=V(ke,2),nt=e=>{var t=ja(),n=V(R(t),2),i=e=>{var t=Aa(),n=R(t),i=V(R(n),2);Z(i,21,r,qr,(e,t,n)=>{var r=ka(),i=R(r),a=R(i),o=B(a,!0);M(i);var s=V(i),c=B(s),l=V(s),u=B(l),d=B(V(l),!0);M(r),H((e,r)=>{Q(a,`datetime`,G(t).at),Y(o,e),Y(c,`${r??``}%`),Y(u,`${G(t).used??``}%`),Y(d,n===0?`First observation`:G(t).break?`Gap before this observation`:`Connected to previous observation`)},[()=>da(G(t).at),()=>G(t).elapsed.toFixed(1)]),J(e,r)}),M(i),M(n),M(t),J(e,t)};X(n,e=>{G(a)&&e(i)}),M(t),Li(`open`,`toggle`,t,e=>L(a,e),()=>G(a)),J(e,t)};X(tt,e=>{r().length&&e(nt)}),H((e,r,a,o,s,c,l)=>{Q(ae,`viewBox`,`0 0 ${G(p)} ${G(m)}`),Q(ae,`aria-label`,e),oe=ui(ae,``,oe,{"--trend-color":G(k)?.safe?`#115b35`:`#7f1825`}),Q(ce,`id`,n),Q(ce,`x2`,i()?`0%`:`100%`),Q(de,`stop-color`,i()?`#ae903b`:`#8c793d`),Q(fe,`id`,n+`-trend-arrow`),Q(pe,`width`,G(_)),Q(pe,`height`,G(v)),Q(pe,`fill`,`url(#${n})`),Q(ge,`d`,`M48 20 V${G(g)} H${G(h)}`),Q(_e,`y1`,r),Q(_e,`x2`,G(h)),Q(_e,`y2`,a),Y(we,i()?`DISTANCE FROM SAFETY (PP)`:`CONSUMPTION`),Q(Te,`x`,48+G(_)/2),Q(Te,`y`,G(m)-5),Q(Ee,`cx`,G(y)),Q(Ee,`cy`,G(S)),Q(De,`cx`,G(y)),Q(De,`cy`,G(S)),Y(Oe,`${t.used??``}% consumed // ${o??``}% of period elapsed${s??``}`),Y(Pe,` // ${c??``}% TIME ELAPSED`),Y(Ie,l),Ke.disabled=!G(D).halfHour,Y(qe,`LAST 30 MINUTES${G(D).halfHour?``:` — UNAVAILABLE`}`),Je.disabled=!G(D).hour,Y(Ye,`LAST HOUR${G(D).hour?``:` — UNAVAILABLE`}`),Xe.disabled=!G(D).day,Y(Ze,`LAST 24 HOURS${G(D).day?``:` — UNAVAILABLE`}`),Qe.disabled=!G(D).window,Y($e,`FROM WINDOW START${G(D).window?``:` — NO TIME ELAPSED`}`),Y(et,`HISTORY // ${G(ne)??``}`)},[()=>`${i()?`Pace zone`:`Consumption zone`}: ${t.used}% consumed, ${t.elapsed.toFixed(1)}% of quota period elapsed. ${i()?`${G(C).toFixed(1)} percentage points from safety.`:`${G(C)>0?`Above`:G(C)<0?`Below`:`On`} the steady-consumption line.`}${G(o)&&r().length?` Trace path contains ${r().length} ${r().length===1?`observation`:`observations`}; gaps are not interpolated.`:``}`,()=>b(0),()=>i()?b(0):b(100),()=>t.elapsed.toFixed(1),()=>i()?` // ${G(C).toFixed(1)} PP from safety`:``,()=>t.elapsed.toFixed(1),()=>Math.abs(G(C))<.05?`ON PACE`:G(C)>0?i()?`ABOVE SAFETY — CONSUMPTION AHEAD OF TIME`:`ABOVE THE LINE — CONSUMING FASTER THAN TIME`:i()?`BELOW SAFETY — QUOTA HEADROOM`:`BELOW THE LINE — WITHIN PACE`]),Pi(ie,`clientWidth`,e=>L(p,e)),Pi(ie,`clientHeight`,e=>L(m,e)),ki(Ve,()=>G(o),e=>L(o,e)),hi(N,()=>G(s),e=>L(s,e)),J(e,re),Ge()}var Pa=q(` `),Fa=q(`

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

`),Ia=q(`

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

`),La=q(`

`),Ra=q(`

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

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

`),za=q(` `,1),Ba=Mr(``),Va=Mr(``),Ha=q(`
`),Ua=q(`

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

`),Wa=q(`
EMPTYFULL
`),Ga=q(`

`,1),Ka=q(`
`,1),qa=q(`

`),Ja=q(`

`),Ya=q(`

No quota windows reported yet.

`),Xa=q(`
`,1),Za=q(`

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

`,1),Qa=q(` `,1);function $a(e,t){We(t,!0);let n=Wi(t,`params`,19,()=>({})),r=P(()=>$i.filter(e=>e!==`thresholds`||!!$.data?.thresholds?.length)),i=I(Xt(Date.now())),a=P(()=>G(r).includes(n().view||``)?n().view:`bars`);Gi(()=>{let e=setInterval(()=>L(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-G(i))/(e.duration*6e4))))}yn(()=>{ra.view=G(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=Qa(),l=z(c);Z(l,21,()=>G(r),qr,(e,t)=>{var n=Pa();let r;var i=B(n,!0);H(e=>{Q(n,`href`,`#/quota/`+G(t)),Q(n,`aria-current`,G(a)===G(t)?`page`:void 0),r=ci(n,1,``,null,r,{active:G(a)===G(t)}),Y(i,e)},[()=>G(t)===`fuel`?`FUEL TANK`:G(t).toUpperCase()]),J(e,n)}),M(l);var u=V(l,2),d=e=>{var t=Za(),n=z(t),r=e=>{J(e,Fa())};X(n,e=>{$.data.quotaError&&e(r)});var i=V(n,2),c=B(i),l=V(i,2),u=e=>{xa(e,{})},d=e=>{var t=Ra(),n=R(t),r=B(n),i=V(n,4),a=e=>{J(e,Ia())};X(i,e=>{$.data.credits.length||e(a)}),Z(V(i,2),17,()=>$.data.credits,qr,(e,t)=>{var n=La(),r=R(n),i=B(r),a=B(V(r,2),!0);M(n),H(e=>{Y(i,`${(G(t).title||`Quota reset`)??``} // ${G(t).status??``}`),Y(a,e)},[()=>G(t).expiryKnown?G(t).expires?`EXPIRES `+da(G(t).expires):`Does not expire`:`Expiry information unavailable`]),J(e,n)}),Ce(2),M(t),H(()=>Y(r,`RESET INVENTORY // ${$.data.creditCount??``} AVAILABLE`)),J(e,t)},f=e=>{var t=Xa(),n=z(t);let r;Z(n,21,()=>$.data.meters,qr,(e,t)=>{let n=P(()=>o(G(t)));var r=Ja(),i=R(r),c=B(i,!0),l=V(i,2),u=R(l),d=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`FREE ${100-G(t).used}%`),Y(a,`USED ${G(t).used??``}%`)}),J(e,n)},f=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`USED ${G(t).used??``}%`),Y(a,`FREE ${100-G(t).used}%`)}),J(e,n)};X(u,e=>{G(a)===`fuel`?e(d):e(f,-1)}),M(l);var p=V(l,2);let m;var h=R(p),g=e=>{var n=Ha(),r=R(n),i=V(R(r)),a=e=>{J(e,Ba())},o=e=>{var n=Va();H(e=>Q(n,`d`,e),[()=>s(G(t).used)]),J(e,n)};X(i,e=>{G(t).used>=100?e(a):G(t).used>0&&e(o,1)}),M(r),M(n),H(()=>Q(r,`aria-label`,`${G(t).used}% quota used`)),J(e,n)},_=e=>{var r=Pr(),i=z(r),o=e=>{{let r=P(()=>G(t).trail||[]),i=P(()=>G(a)===`pace`);Na(e,{get used(){return G(t).used},get elapsed(){return G(n)},get trail(){return G(r)},get duration(){return G(t).duration},get paceView(){return G(i)}})}},s=e=>{J(e,Ua())};X(i,e=>{G(n)===null?e(s,-1):e(o)}),J(e,r)},v=e=>{var r=Ka(),i=z(r),o=R(i);let s;M(i);var c=V(i,2),l=e=>{J(e,Wa())};X(c,e=>{G(a)===`fuel`&&e(l)});var u=V(c,2),d=e=>{var t=Ga(),r=z(t),i=B(r),o=V(r,2),s=R(o);let c;M(o),H(e=>{Y(i,`RESET CYCLE // ${e??``}% ELAPSED`),c=ui(s,``,c,{width:`${G(a)===`fuel`?100-G(n):G(n)}%`})},[()=>Math.floor(G(n))]),J(e,t)};X(u,e=>{G(n)!==null&&e(d)}),H(()=>{Q(i,`aria-label`,G(a)===`fuel`?`Fuel remaining`:`Quota used`),Q(i,`aria-valuenow`,G(a)===`fuel`?100-G(t).used:G(t).used),s=ui(o,``,s,{width:`${G(a)===`fuel`?100-G(t).used:G(t).used}%`})}),J(e,r)};X(h,e=>{G(a)===`pie`?e(g):G(a)===`zone`||G(a)===`pace`?e(_,1):e(v,-1)}),M(p);var y=V(p,2),b=B(y),x=V(y,2),S=e=>{var n=qa(),r=B(n,!0);H(()=>Y(r,G(t).details)),J(e,n)};X(x,e=>{G(t).details&&e(S)}),M(r),H(e=>{Y(c,G(t).name),m=ci(p,1,`meter-graphic`,null,m,{"bar-graphic":G(a)===`bars`||G(a)===`fuel`}),Y(b,`RESETS // ${e??``}`)},[()=>da(G(t).reset)]),J(e,r)}),M(n);var i=V(n,2),c=e=>{J(e,Ya())};X(i,e=>{$.data.meters.length||e(c)}),H(()=>r=ci(n,1,`quota-grid`,null,r,{radial:G(a)===`pie`,zone:G(a)===`zone`||G(a)===`pace`})),J(e,t)};X(l,e=>{G(a)===`thresholds`?e(u):G(a)===`resets`?e(d,1):e(f,-1)}),Ce(2),H(e=>Y(c,`QUOTA // OBSERVED ${e??``}`),[()=>da($.data.quotaAt)]),J(e,t)};X(u,e=>{$.data&&e(d)}),J(e,c),Ge()}var eo=q(`
`),to=q(`

`,1);function no(e,t){We(t,!0);let n=Wi(t,`values`,19,()=>[]),r=Wi(t,`label`,3,`Token activity`),i=Wi(t,`capacity`,3,0),a=P(()=>Math.max(0,...n())),o=P(()=>i()>n().length?[...Array(i()-n().length).fill(0),...n()]:n());var s=to(),c=z(s),l=B(c),u=V(c,2);Z(u,21,()=>G(o),qr,(e,t)=>{var n=eo();let r;H((e,t)=>{Q(n,`title`,e),r=ui(n,``,r,{height:t})},[()=>G(t).toLocaleString(`en-GB`)+` tokens`,()=>`${100*G(t)/Math.max(1,G(a))}%`]),J(e,n)}),M(u),H((e,t)=>{Y(l,`SCALE // 0 — ${e??``} TOKENS`),Q(u,`aria-label`,t)},[()=>G(a).toLocaleString(`en-GB`),()=>`${r()}. Peak ${G(a).toLocaleString(`en-GB`)} tokens.`]),J(e,s),Ge()}var ro=q(`

`),io=q(`

`,1),ao=q(`

`),oo=q(`

Loading / sending…

`),so=q(`
`),co=q(`

Confirmation expired. Reopen the option.

`),lo=q(`

`,1),uo=q(`

 
`,1),fo=q(` `),po=q(``),mo=q(`

No available matching commands.

`),ho=q(`

↑/↓ select · Tab complete · Enter options · Escape dismiss

`),go=q(`
`,1),_o=q(` `,1),vo=q(`
`),yo=q(`
`);function bo(e,t){We(t,!0);let n=Wi(t,`query`,3,``),r=Wi(t,`onchange`,3,()=>{}),i=Wi(t,`oncomplete`,3,e=>{}),a=I(!1),o=I(!1),s=I(``),c=I(null),l=I(null),u=I(``),d=I(0),f=I(Xt(Date.now())),p=I(``),m=0,h=I(0),g=I(null),_=I(void 0),v=setInterval(()=>{L(f,Date.now(),!0)},1e3);Ki(()=>{clearInterval(v),m++});let y=P(()=>n().trim().startsWith(`/`)&&!n().trim().startsWith(`//`)),b=P(()=>G(c)?.path===``&&G(y)?n().trim().slice(1).toLowerCase():``),x=P(()=>(G(c)?.choices||[]).filter(e=>!G(b)||e.label.toLowerCase().startsWith(`/`+G(b)))),S=P(()=>!$.connected||!!$.data?.sessionsError),C=P(()=>G(a)&&G(y)&&(!G(c)||G(c).path===``)&&!G(l));yn(()=>{n(),L(h,0)}),yn(()=>{let e=G(h);G(x),G(C)&&ur().then(()=>{let t=G(_)?.children[e];if(!t||!G(_))return;let n=G(_).getBoundingClientRect(),r=t.getBoundingClientRect();r.topn.bottom&&(G(_).scrollTop+=r.bottom-n.bottom)})});function w(e){if(!G(y)||!G(a)||G(c)&&G(c).path!==``||G(l)||G(S)||e.isComposing||e.ctrlKey||e.metaKey||e.altKey||![`ArrowUp`,`ArrowDown`,`Tab`,`Enter`,`Escape`].includes(e.key)||e.key===`Tab`&&e.shiftKey)return;if(e.preventDefault(),e.key===`Escape`){L(a,!1),L(g,n()),L(u,``);return}if(e.key===`ArrowUp`||e.key===`ArrowDown`){L(h,Math.min(Math.max(G(h)+(e.key===`ArrowUp`?-1:1),0),Math.max(G(x).length-1,0)),!0);return}let t=G(x)[G(h)];t&&!G(o)&&(e.key===`Tab`?i()(t.label):E(t))}yn(()=>{G(S)&&(m++,L(o,!1),L(u,``),G(a)&&(L(a,!1),L(g,n())),L(c,null),L(l,null))}),yn(()=>{G(y)&&!G(a)&&n()!==G(g)&&!G(S)&&(L(a,!0),T(``))});async function T(e){let n=++m;L(o,!0),L(l,null),L(u,``),L(s,``);try{let r=await ha(`commands`,{session:t.session,command:{mode:`list`,path:e}});n===m&&((e===``||e===`help`)&&r.choices.push({id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}),L(c,r,!0),L(p,r.value||``,!0),r.path.startsWith(`rename/`)&&r.choices.length===1&&E(r.choices[0]))}catch{n===m&&(L(s,`Command catalogue unavailable. Use Codex.`),(e===``||e===`help`)&&L(c,{title:`/ COMMANDS`,help:`Local display settings remain available.`,path:``,revision:``,choices:[{id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}]},!0))}finally{n===m&&L(o,!1)}}async function E(e){if(e.next===`statusline`){ia.open=!0,L(a,!1),L(g,n());return}if(e.next){await T(e.next);return}if(L(l,e,!0),L(u,``),L(s,``),!e.action||!G(c))return;let r=++m;L(o,!0);try{let n=await ha(`commands`,{session:t.session,command:{mode:`prepare`,path:G(c).path,revision:G(c).revision,choice:e.id}});r===m&&(L(u,n.confirmation,!0),L(d,Date.parse(n.expires),!0))}catch{r===m&&L(s,`Option changed or unavailable. Refresh before retrying.`)}finally{r===m&&L(o,!1)}}async function ee(){if(!G(u)||G(S)||G(o)||G(f)>=G(d)||!G(c))return;let e=G(u);L(u,``),L(o,!0);let n=++m;try{let i=await ha(`commands`,{session:t.session,confirmation:e,command:{mode:`commit`,path:G(c).path}});n===m&&(L(s,i.message,!0),L(a,!1),L(c,null),L(l,null),L(d,0),L(g,null),r()())}catch{n===m&&L(s,`Change unconfirmed. Check Codex before retrying.`)}finally{n===m&&L(o,!1)}}var D={handleKey:w},O=yo(),te=R(O),k=V(te,2),ne=e=>{var t=ro(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(k,e=>{G(s)&&!G(a)&&e(ne)});var re=V(k,2),ie=e=>{var n=vo();let r;var i=R(n),a=e=>{var t=io(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(c)?.title||`/ COMMANDS`),Y(i,G(c)?.help||`Loading live options…`)}),J(e,t)};X(i,e=>{G(C)||e(a)});var m=V(i,2),g=e=>{var t=ao(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(m,e=>{G(s)&&e(g)});var v=V(m,2),b=e=>{J(e,oo())};X(v,e=>{G(o)&&e(b)});var w=V(v,2),D=e=>{var t=so(),n=R(t),r=V(R(n));xi(r),M(n);var i=V(n,2);M(t),H(e=>{r.disabled=G(o)||G(S),i.disabled=e},[()=>G(o)||G(S)||!G(p).trim()]),Sr(`submit`,t,e=>{e.preventDefault(),G(p).trim()&&!G(o)&&!G(S)&&T(`rename/`+encodeURIComponent(G(p).trim()))}),Ei(r,()=>G(p),e=>L(p,e)),J(e,t)},O=e=>{var n=uo(),r=z(n),i=B(r,!0),a=V(r,2),s=B(a,!0),p=V(a,2),m=e=>{var n=lo(),r=z(n),i=R(r),a=V(i),s=e=>{J(e,Nr(`Only this session's saved name - changes.`))},l=P(()=>G(c)?.path.startsWith(`rename/`)),p=e=>{J(e,Nr(`Changes affect subsequent turns of this session, not global + scoring remain in the terminal for this first preview.

`,1),Qa=q(` `,1);function $a(e,t){We(t,!0);let n=Wi(t,`params`,19,()=>({})),r=P(()=>$i.filter(e=>e!==`thresholds`||!!$.data?.thresholds?.length)),i=I(Xt(Date.now())),a=P(()=>G(r).includes(n().view||``)?n().view:`bars`);Gi(()=>{let e=setInterval(()=>L(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-G(i))/(e.duration*6e4))))}yn(()=>{ra.view=G(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=Qa(),l=z(c);Z(l,21,()=>G(r),qr,(e,t)=>{var n=Pa();let r;var i=B(n,!0);H(e=>{Q(n,`href`,`#/quota/`+G(t)),Q(n,`aria-current`,G(a)===G(t)?`page`:void 0),r=ci(n,1,``,null,r,{active:G(a)===G(t)}),Y(i,e)},[()=>G(t)===`fuel`?`FUEL TANK`:G(t).toUpperCase()]),J(e,n)}),M(l);var u=V(l,2),d=e=>{var t=Za(),n=z(t),r=e=>{J(e,Fa())};X(n,e=>{$.data.quotaError&&e(r)});var i=V(n,2),c=B(i),l=V(i,2),u=e=>{xa(e,{})},d=e=>{var t=Ra(),n=R(t),r=B(n),i=V(n,4),a=e=>{J(e,Ia())};X(i,e=>{$.data.credits.length||e(a)}),Z(V(i,2),17,()=>$.data.credits,qr,(e,t)=>{var n=La(),r=R(n),i=B(r),a=B(V(r,2),!0);M(n),H(e=>{Y(i,`${(G(t).title||`Quota reset`)??``} // ${G(t).status??``}`),Y(a,e)},[()=>G(t).expiryKnown?G(t).expires?`EXPIRES `+da(G(t).expires):`Does not expire`:`Expiry information unavailable`]),J(e,n)}),Ce(2),M(t),H(()=>Y(r,`RESET INVENTORY // ${$.data.creditCount??``} AVAILABLE`)),J(e,t)},f=e=>{var t=Xa(),n=z(t);let r;Z(n,21,()=>$.data.meters,qr,(e,t)=>{let n=P(()=>o(G(t)));var r=Ja(),i=R(r),c=B(i,!0),l=V(i,2),u=R(l),d=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`FREE ${100-G(t).used}%`),Y(a,`USED ${G(t).used??``}%`)}),J(e,n)},f=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`USED ${G(t).used??``}%`),Y(a,`FREE ${100-G(t).used}%`)}),J(e,n)};X(u,e=>{G(a)===`fuel`?e(d):e(f,-1)}),M(l);var p=V(l,2);let m;var h=R(p),g=e=>{var n=Ha(),r=R(n),i=V(R(r)),a=e=>{J(e,Ba())},o=e=>{var n=Va();H(e=>Q(n,`d`,e),[()=>s(G(t).used)]),J(e,n)};X(i,e=>{G(t).used>=100?e(a):G(t).used>0&&e(o,1)}),M(r),M(n),H(()=>Q(r,`aria-label`,`${G(t).used}% quota used`)),J(e,n)},_=e=>{var r=Pr(),i=z(r),o=e=>{{let r=P(()=>G(t).trail||[]),i=P(()=>G(a)===`pace`);Na(e,{get used(){return G(t).used},get elapsed(){return G(n)},get trail(){return G(r)},get duration(){return G(t).duration},get paceView(){return G(i)}})}},s=e=>{J(e,Ua())};X(i,e=>{G(n)===null?e(s,-1):e(o)}),J(e,r)},v=e=>{var r=Ka(),i=z(r),o=R(i);let s;M(i);var c=V(i,2),l=e=>{J(e,Wa())};X(c,e=>{G(a)===`fuel`&&e(l)});var u=V(c,2),d=e=>{var t=Ga(),r=z(t),i=B(r),o=V(r,2),s=R(o);let c;M(o),H(e=>{Y(i,`RESET CYCLE // ${e??``}% ELAPSED`),c=ui(s,``,c,{width:`${G(a)===`fuel`?100-G(n):G(n)}%`})},[()=>Math.floor(G(n))]),J(e,t)};X(u,e=>{G(n)!==null&&e(d)}),H(()=>{Q(i,`aria-label`,G(a)===`fuel`?`Fuel remaining`:`Quota used`),Q(i,`aria-valuenow`,G(a)===`fuel`?100-G(t).used:G(t).used),s=ui(o,``,s,{width:`${G(a)===`fuel`?100-G(t).used:G(t).used}%`})}),J(e,r)};X(h,e=>{G(a)===`pie`?e(g):G(a)===`zone`||G(a)===`pace`?e(_,1):e(v,-1)}),M(p);var y=V(p,2),b=B(y),x=V(y,2),S=e=>{var n=qa(),r=B(n,!0);H(()=>Y(r,G(t).details)),J(e,n)};X(x,e=>{G(t).details&&e(S)}),M(r),H(e=>{Y(c,G(t).name),m=ci(p,1,`meter-graphic`,null,m,{"bar-graphic":G(a)===`bars`||G(a)===`fuel`}),Y(b,`RESETS // ${e??``}`)},[()=>da(G(t).reset)]),J(e,r)}),M(n);var i=V(n,2),c=e=>{J(e,Ya())};X(i,e=>{$.data.meters.length||e(c)}),H(()=>r=ci(n,1,`quota-grid`,null,r,{radial:G(a)===`pie`,zone:G(a)===`zone`||G(a)===`pace`})),J(e,t)};X(l,e=>{G(a)===`thresholds`?e(u):G(a)===`resets`?e(d,1):e(f,-1)}),Ce(2),H(e=>Y(c,`QUOTA // OBSERVED ${e??``}`),[()=>da($.data.quotaAt)]),J(e,t)};X(u,e=>{$.data&&e(d)}),J(e,c),Ge()}var eo=q(`
`),to=q(`

`,1);function no(e,t){We(t,!0);let n=Wi(t,`values`,19,()=>[]),r=Wi(t,`label`,3,`Token activity`),i=Wi(t,`capacity`,3,0),a=P(()=>Math.max(0,...n())),o=P(()=>i()>n().length?[...Array(i()-n().length).fill(0),...n()]:n());var s=to(),c=z(s),l=B(c),u=V(c,2);Z(u,21,()=>G(o),qr,(e,t)=>{var n=eo();let r;H((e,t)=>{Q(n,`title`,e),r=ui(n,``,r,{height:t})},[()=>G(t).toLocaleString(`en-GB`)+` tokens`,()=>`${100*G(t)/Math.max(1,G(a))}%`]),J(e,n)}),M(u),H((e,t)=>{Y(l,`SCALE // 0 — ${e??``} TOKENS`),Q(u,`aria-label`,t)},[()=>G(a).toLocaleString(`en-GB`),()=>`${r()}. Peak ${G(a).toLocaleString(`en-GB`)} tokens.`]),J(e,s),Ge()}var ro=q(`

`),io=q(`

`,1),ao=q(`

`),oo=q(`

Loading / sending…

`),so=q(`
`),co=q(`

Confirmation expired. Reopen the option.

`),lo=q(`

`,1),uo=q(`

 
`,1),fo=q(` `),po=q(``),mo=q(`

No available matching commands.

`),ho=q(`

↑/↓ select · Tab complete · Enter options · Escape dismiss

`),go=q(`
`,1),_o=q(` `,1),vo=q(`
`),yo=q(`
`);function bo(e,t){We(t,!0);let n=Wi(t,`query`,3,``),r=Wi(t,`onchange`,3,()=>{}),i=Wi(t,`oncomplete`,3,e=>{}),a=I(!1),o=I(!1),s=I(``),c=I(null),l=I(null),u=I(``),d=I(0),f=I(Xt(Date.now())),p=I(``),m=0,h=I(0),g=I(null),_=I(void 0),v=setInterval(()=>{L(f,Date.now(),!0)},1e3);Ki(()=>{clearInterval(v),m++});let y=P(()=>n().trim().startsWith(`/`)&&!n().trim().startsWith(`//`)),b=P(()=>G(c)?.path===``&&G(y)?n().trim().slice(1).toLowerCase():``),x=P(()=>(G(c)?.choices||[]).filter(e=>!G(b)||e.label.toLowerCase().startsWith(`/`+G(b)))),S=P(()=>!$.connected||!!$.data?.sessionsError),C=P(()=>G(a)&&G(y)&&(!G(c)||G(c).path===``)&&!G(l));yn(()=>{n(),L(h,0)}),yn(()=>{let e=G(h);G(x),G(C)&&ur().then(()=>{let t=G(_)?.children[e];if(!t||!G(_))return;let n=G(_).getBoundingClientRect(),r=t.getBoundingClientRect();r.topn.bottom&&(G(_).scrollTop+=r.bottom-n.bottom)})});function w(e){if(!G(y)||!G(a)||G(c)&&G(c).path!==``||G(l)||G(S)||e.isComposing||e.ctrlKey||e.metaKey||e.altKey||![`ArrowUp`,`ArrowDown`,`Tab`,`Enter`,`Escape`].includes(e.key)||e.key===`Tab`&&e.shiftKey)return;if(e.preventDefault(),e.key===`Escape`){L(a,!1),L(g,n()),L(u,``);return}if(e.key===`ArrowUp`||e.key===`ArrowDown`){L(h,Math.min(Math.max(G(h)+(e.key===`ArrowUp`?-1:1),0),Math.max(G(x).length-1,0)),!0);return}let t=G(x)[G(h)];t&&!G(o)&&(e.key===`Tab`?i()(t.label):E(t))}yn(()=>{G(S)&&(m++,L(o,!1),L(u,``),G(a)&&(L(a,!1),L(g,n())),L(c,null),L(l,null))}),yn(()=>{G(y)&&!G(a)&&n()!==G(g)&&!G(S)&&(L(a,!0),T(``))});async function T(e){let n=++m;L(o,!0),L(l,null),L(u,``),L(s,``);try{let r=await ha(`commands`,{session:t.session,command:{mode:`list`,path:e}});n===m&&((e===``||e===`help`)&&r.choices.push({id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}),L(c,r,!0),L(p,r.value||``,!0),(r.path.startsWith(`rename/`)||r.path.startsWith(`cd/`))&&r.choices.length===1&&E(r.choices[0]))}catch{n===m&&(L(s,`Command catalogue unavailable. Use Codex.`),(e===``||e===`help`)&&L(c,{title:`/ COMMANDS`,help:`Local display settings remain available.`,path:``,revision:``,choices:[{id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}]},!0))}finally{n===m&&L(o,!1)}}async function E(e){if(e.next===`statusline`){ia.open=!0,L(a,!1),L(g,n());return}if(e.next){await T(e.next);return}if(L(l,e,!0),L(u,``),L(s,``),!e.action||!G(c))return;let r=++m;L(o,!0);try{let n=await ha(`commands`,{session:t.session,command:{mode:`prepare`,path:G(c).path,revision:G(c).revision,choice:e.id}});r===m&&(L(u,n.confirmation,!0),L(d,Date.parse(n.expires),!0))}catch{r===m&&L(s,`Option changed or unavailable. Refresh before retrying.`)}finally{r===m&&L(o,!1)}}async function ee(){if(!G(u)||G(S)||G(o)||G(f)>=G(d)||!G(c))return;let e=G(u);L(u,``),L(o,!0);let n=++m;try{let i=await ha(`commands`,{session:t.session,confirmation:e,command:{mode:`commit`,path:G(c).path}});n===m&&(L(s,i.message,!0),L(a,!1),L(c,null),L(l,null),L(d,0),L(g,null),r()())}catch{n===m&&L(s,`Change unconfirmed. Check Codex before retrying.`)}finally{n===m&&L(o,!1)}}var D={handleKey:w},O=yo(),te=R(O),k=V(te,2),ne=e=>{var t=ro(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(k,e=>{G(s)&&!G(a)&&e(ne)});var re=V(k,2),ie=e=>{var n=vo();let r;var i=R(n),a=e=>{var t=io(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(c)?.title||`/ COMMANDS`),Y(i,G(c)?.help||`Loading live options…`)}),J(e,t)};X(i,e=>{G(C)||e(a)});var m=V(i,2),g=e=>{var t=ao(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(m,e=>{G(s)&&e(g)});var v=V(m,2),b=e=>{J(e,oo())};X(v,e=>{G(o)&&e(b)});var w=V(v,2),D=e=>{var t=so(),n=R(t),r=R(n),i=V(r);xi(i),M(n);var a=V(n,2),s=B(a);M(t),H((e,t)=>{Y(r,`${e??``} `),Q(i,`aria-label`,G(c).inputLabel||`Session name`),Q(i,`maxlength`,G(c).inputLimit||512),i.disabled=G(o)||G(S),a.disabled=t,Y(s,`REVIEW ${G(c).path===`cd`?`DIRECTORY`:`RENAME`}`)},[()=>(G(c).inputLabel||`Session name`).toUpperCase(),()=>G(o)||G(S)||!G(p).trim()]),Sr(`submit`,t,e=>{e.preventDefault(),G(c)&&G(p).trim()&&!G(o)&&!G(S)&&T(G(c).path+`/`+encodeURIComponent(G(p).trim()))}),Ei(i,()=>G(p),e=>L(p,e)),J(e,t)},O=e=>{var n=uo(),r=z(n),i=B(r,!0),a=V(r,2),s=B(a,!0),p=V(a,2),m=e=>{var n=lo(),r=z(n),i=R(r),a=V(i),s=e=>{J(e,Nr(`Only this session's saved name + changes.`))},l=P(()=>G(c)?.path.startsWith(`rename/`)),p=e=>{J(e,Nr(`Only this session’s directory + changes; project configuration is not reloaded.`))},m=P(()=>G(c)?.path.startsWith(`cd/`)),h=e=>{J(e,Nr(`Changes affect subsequent turns of this session, not global defaults. Automatic quota thresholds may later supersede model - settings.`))};X(a,e=>{G(l)?e(s):e(p,-1)}),M(r);var m=V(r,2),h=V(m,2),g=e=>{J(e,co())};X(h,e=>{G(u)&&G(f)>=G(d)&&e(g)}),H(()=>{Y(i,`TARGET // ${t.session??``}. `),m.disabled=G(o)||G(S)||!G(u)||G(f)>=G(d)}),K(`click`,m,ee),J(e,n)};X(p,e=>{G(l).action&&e(m)});var h=V(p,2);H(()=>{Y(i,G(l).label),Y(s,G(l).help||`No additional help supplied by Codex.`),h.disabled=G(o)}),K(`click`,h,()=>{L(l,null),L(u,``)}),J(e,n)},te=e=>{var t=go(),n=z(t);let r;Z(n,23,()=>G(x),e=>e.id,(e,t,n)=>{var r=po();let i;var a=R(r),s=B(a,!0),l=V(a),u=B(l,!0),d=V(l),f=e=>{var n=fo(),r=B(n,!0);H(()=>Y(r,G(t).help)),J(e,n)};X(d,e=>{G(y)&&G(c)?.path===``&&e(f)}),M(r),H(()=>{r.disabled=G(o)||G(S),Q(r,`title`,G(t).help),Q(r,`aria-label`,G(t).label+(G(t).next?` →`:G(t).action?``:` // HELP`)),i=ci(r,1,`svelte-7bfwr9`,null,i,{suggested:G(y)&&G(c)?.path===``&&G(h)===G(n)}),Y(s,G(t).label),Y(u,G(t).next?` →`:G(t).action?``:` // HELP`)}),K(`click`,r,()=>E(G(t))),J(e,r)}),M(n),Ii(n,e=>L(_,e),()=>G(_));var i=V(n,2),a=e=>{J(e,mo())};X(i,e=>{!G(o)&&!G(x).length&&e(a)});var s=V(i,2),l=e=>{J(e,ho())};X(s,e=>{G(y)&&G(c)?.path===``&&e(l)}),H(()=>r=ci(n,1,`command-options svelte-7bfwr9`,null,r,{vertical:G(C)})),J(e,t)};X(w,e=>{G(c)?.input?e(D):G(l)?e(O,1):e(te,-1)});var k=V(w,2),ne=e=>{var t=_o(),n=z(t),r=V(n,2);H(()=>{n.disabled=G(o),r.disabled=G(o)}),K(`click`,n,()=>T(``)),K(`click`,r,()=>T(G(c)?.path||``)),J(e,t)};X(k,e=>{G(C)||e(ne)}),M(n),H(()=>{Q(n,`aria-label`,G(C)?`Slash command suggestions`:void 0),r=ci(n,1,`svelte-7bfwr9`,null,r,{"command-popup":G(C)})}),J(e,n)};return X(re,e=>{G(a)&&e(ie)}),M(O),H(()=>te.disabled=G(S)||G(o)),K(`click`,te,()=>{L(a,!G(a)),L(g,G(a)?null:n(),!0),L(u,``),G(a)&&T(``)}),J(e,O),Ge(D)}Cr([`click`]);var xo=q(` `,1),So=q(`
`),Co=q(`
/
`);function wo(e,t){We(t,!0);let n=P(()=>t.lines.filter(e=>e.kind===`addition`).length),r=P(()=>t.lines.filter(e=>e.kind===`removal`).length);var i=Co(),a=R(i),o=R(a),s=B(o),c=B(V(o,2));M(a),Z(V(a,2),17,()=>t.lines,qr,(e,t)=>{var n=So();let r;var i=R(n),a=e=>{var n=xo(),r=z(n),i=B(r,!0),a=B(V(r),!0);H(()=>{Y(i,G(t).old||``),Y(a,G(t).new||``)}),J(e,n)};X(i,e=>{G(t).kind!==`heading`&&G(t).kind!==`metadata`&&e(a)});var o=B(V(i),!0);M(n),H(()=>{r=ci(n,1,`diff-line svelte-x4gtb6`,null,r,{added:G(t).kind===`addition`,removed:G(t).kind===`removal`,heading:G(t).kind===`heading`}),Y(o,G(t).text)}),J(e,n)}),M(i),H(()=>{Q(a,`aria-label`,`${G(n)} lines added, ${G(r)} lines removed`),Y(s,`+${G(n)??``}`),Y(c,`−${G(r)??``}`)}),J(e,i),Ge()}var To=q(`

`),Eo=q(`

Send this saved prompt now? This starts Codex work and consumes quota.

`,1),Do=q(``),Oo=q(`

 

In memory only. Follows session model, reasoning and speed. Closing + settings.`))};X(a,e=>{G(l)?e(s):G(m)?e(p,1):e(h,-1)}),M(r);var g=V(r,2),_=V(g,2),v=e=>{J(e,co())};X(_,e=>{G(u)&&G(f)>=G(d)&&e(v)}),H(()=>{Y(i,`TARGET // ${t.session??``}. `),g.disabled=G(o)||G(S)||!G(u)||G(f)>=G(d)}),K(`click`,g,ee),J(e,n)};X(p,e=>{G(l).action&&e(m)});var h=V(p,2);H(()=>{Y(i,G(l).label),Y(s,G(l).help||`No additional help supplied by Codex.`),h.disabled=G(o)}),K(`click`,h,()=>{L(l,null),L(u,``)}),J(e,n)},te=e=>{var t=go(),n=z(t);let r;Z(n,23,()=>G(x),e=>e.id,(e,t,n)=>{var r=po();let i;var a=R(r),s=B(a,!0),l=V(a),u=B(l,!0),d=V(l),f=e=>{var n=fo(),r=B(n,!0);H(()=>Y(r,G(t).help)),J(e,n)};X(d,e=>{G(y)&&G(c)?.path===``&&e(f)}),M(r),H(()=>{r.disabled=G(o)||G(S),Q(r,`title`,G(t).help),Q(r,`aria-label`,G(t).label+(G(t).next?` →`:G(t).action?``:` // HELP`)),i=ci(r,1,`svelte-7bfwr9`,null,i,{suggested:G(y)&&G(c)?.path===``&&G(h)===G(n)}),Y(s,G(t).label),Y(u,G(t).next?` →`:G(t).action?``:` // HELP`)}),K(`click`,r,()=>E(G(t))),J(e,r)}),M(n),Ii(n,e=>L(_,e),()=>G(_));var i=V(n,2),a=e=>{J(e,mo())};X(i,e=>{!G(o)&&!G(x).length&&e(a)});var s=V(i,2),l=e=>{J(e,ho())};X(s,e=>{G(y)&&G(c)?.path===``&&e(l)}),H(()=>r=ci(n,1,`command-options svelte-7bfwr9`,null,r,{vertical:G(C)})),J(e,t)};X(w,e=>{G(c)?.input?e(D):G(l)?e(O,1):e(te,-1)});var k=V(w,2),ne=e=>{var t=_o(),n=z(t),r=V(n,2);H(()=>{n.disabled=G(o),r.disabled=G(o)}),K(`click`,n,()=>T(``)),K(`click`,r,()=>T(G(c)?.path||``)),J(e,t)};X(k,e=>{G(C)||e(ne)}),M(n),H(()=>{Q(n,`aria-label`,G(C)?`Slash command suggestions`:void 0),r=ci(n,1,`svelte-7bfwr9`,null,r,{"command-popup":G(C)})}),J(e,n)};return X(re,e=>{G(a)&&e(ie)}),M(O),H(()=>te.disabled=G(S)||G(o)),K(`click`,te,()=>{L(a,!G(a)),L(g,G(a)?null:n(),!0),L(u,``),G(a)&&T(``)}),J(e,O),Ge(D)}Cr([`click`]);var xo=q(` `,1),So=q(`

`),Co=q(`
/
`);function wo(e,t){We(t,!0);let n=P(()=>t.lines.filter(e=>e.kind===`addition`).length),r=P(()=>t.lines.filter(e=>e.kind===`removal`).length);var i=Co(),a=R(i),o=R(a),s=B(o),c=B(V(o,2));M(a),Z(V(a,2),17,()=>t.lines,qr,(e,t)=>{var n=So();let r;var i=R(n),a=e=>{var n=xo(),r=z(n),i=B(r,!0),a=B(V(r),!0);H(()=>{Y(i,G(t).old||``),Y(a,G(t).new||``)}),J(e,n)};X(i,e=>{G(t).kind!==`heading`&&G(t).kind!==`metadata`&&e(a)});var o=B(V(i),!0);M(n),H(()=>{r=ci(n,1,`diff-line svelte-x4gtb6`,null,r,{added:G(t).kind===`addition`,removed:G(t).kind===`removal`,heading:G(t).kind===`heading`}),Y(o,G(t).text)}),J(e,n)}),M(i),H(()=>{Q(a,`aria-label`,`${G(n)} lines added, ${G(r)} lines removed`),Y(s,`+${G(n)??``}`),Y(c,`−${G(r)??``}`)}),J(e,i),Ge()}var To=q(`

`),Eo=q(`

Send this saved prompt now? This starts Codex work and consumes quota.

`,1),Do=q(``),Oo=q(`

 

In memory only. Follows session model, reasoning and speed. Closing Codexometer cancels pending work.

`),ko=q(`

CURRENT PROFILE

MODEL / REASONING LEVEL / SPEED

 

PROPOSED PROFILE

MODEL / REASONING LEVEL / SPEED

 

Applied settings remain after Codexometer closes.

`,1),Ao=q(`

`),jo=q(`

 
`,1),Mo=q(`

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

`),No=q(`

Session controls temporarily unavailable. Check Codex for current state.

`),Po=q(`

Checking session controls…

`),Fo=q(`

`),Io=q(`
About browser controls

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

`),Lo=q(` `,1),Ro=q(` `),zo=q(`Grants permission beyond this one action. Check the scope diff --git a/internal/web/dist/index.html b/internal/web/dist/index.html index 06efbf1..c331ec2 100644 --- a/internal/web/dist/index.html +++ b/internal/web/dist/index.html @@ -5,7 +5,7 @@ Codexometer // Experimental web - + diff --git a/web/src/SessionCommands.svelte b/web/src/SessionCommands.svelte index c9ad74a..47f55c8 100644 --- a/web/src/SessionCommands.svelte +++ b/web/src/SessionCommands.svelte @@ -27,6 +27,8 @@ revision: string; choices: Choice[]; input?: boolean; + inputLabel?: string; + inputLimit?: number; value?: string; } let open = $state(false), @@ -158,7 +160,11 @@ }); menu = result; name = result.value || ''; - if (result.path.startsWith('rename/') && result.choices.length === 1) + if ( + (result.path.startsWith('rename/') || + result.path.startsWith('cd/')) && + result.choices.length === 1 + ) void choose(result.choices[0]); } } catch { @@ -283,20 +289,21 @@
{ event.preventDefault(); - if (name.trim() && !busy && !unavailable) - void load('rename/' + encodeURIComponent(name.trim())); + if (menu && name.trim() && !busy && !unavailable) + void load(menu.path + '/' + encodeURIComponent(name.trim())); }} > REVIEW {menu.path === 'cd' ? 'DIRECTORY' : 'RENAME'}
{:else if selected} @@ -306,6 +313,8 @@ TARGET // {session}. {#if menu?.path.startsWith('rename/')}Only this session's saved name changes. + {:else if menu?.path.startsWith('cd/')}Only this session’s directory + changes; project configuration is not reloaded. {:else}Changes affect subsequent turns of this session, not global defaults. Automatic quota thresholds may later supersede model settings.{/if} diff --git a/web/tests/browser.spec.ts b/web/tests/browser.spec.ts index dea4778..15c76ce 100644 --- a/web/tests/browser.spec.ts +++ b/web/tests/browser.spec.ts @@ -1330,7 +1330,7 @@ test('slash commands discover help and require a separate confirmation', async ( const panel = page.getByRole('region', { name: 'Session slash commands' }); await expect( panel.getByRole('button', { name: '/model →', exact: true }), - ).toBeVisible(); + ).toBeEnabled(); const popup = panel.locator('.command-popup'); await expect(popup).toBeVisible(); const initialPopup = await popup.boundingBox(); @@ -1375,7 +1375,10 @@ test('slash commands discover help and require a separate confirmation', async ( await panel.getByRole('button', { name: '/ COMMANDS', exact: true }).click(); await expect( panel.getByRole('button', { name: '/model →', exact: true }), - ).toBeVisible(); + ).toBeEnabled(); + await expect( + panel.getByRole('button', { name: '/model →', exact: true }), + ).toBeEnabled(); await text.fill('/mo'); await expect(popup.locator('.command-options button')).toHaveCount(1); const filteredPopup = await popup.boundingBox(); @@ -1392,7 +1395,7 @@ test('slash commands discover help and require a separate confirmation', async ( await text.fill('/mod'); await expect( panel.getByRole('button', { name: '/model →', exact: true }), - ).toBeVisible(); + ).toBeEnabled(); await text.press('Enter'); await panel.getByRole('button', { name: 'Medium', exact: true }).click(); await expect(panel).toContainText('Server effort description'); @@ -1448,100 +1451,117 @@ test('slash commands discover help and require a separate confirmation', async ( ).toBeDisabled(); }); -test('rename edits and reviews a name before a separate confirmation', async ({ - page, - pairingURL, -}) => { - const { calls } = await mockActions(page, 'prompt'); - const modes: string[] = []; - let reviewed = ''; - await page.route('**/api/control/commands', async (route) => { - const body = route.request().postDataJSON(); - const { mode, path } = body.command; - modes.push(mode); - let result: object; - if (mode === 'prepare') { - expect(path).toBe('rename/' + encodeURIComponent('quota / review 界')); - result = { - confirmation: 'rename-token', - expires: new Date(Date.now() + 30000).toISOString(), - }; - } else if (mode === 'commit') { - expect(body.confirmation).toBe('rename-token'); - result = { message: 'Session renamed.' }; - } else if (path === '') { - result = { - title: '/ COMMANDS', - help: 'Commands', - path: '', - revision: 'r', - choices: [ - { - id: 'rename', - label: '/rename', - help: 'Rename the session', - next: 'rename', - }, - ], - }; - } else if (path === 'rename') { - result = { - title: '/rename', - help: 'Enter a name, review and confirm.', - path, - revision: 'r', - input: true, - value: 'Current name', - choices: [], - }; - } else { - reviewed = decodeURIComponent(path.slice('rename/'.length)); - result = { - title: '/rename', - help: 'Only the saved name changes.', - path, - revision: 'r', - choices: [ - { - id: 'name', - label: 'Rename to ' + reviewed, - help: 'New name: ' + reviewed, - action: true, - }, - ], - }; - } - await route.fulfill({ json: result }); - }); - await page.goto(pairingURL); - await page.evaluate(() => { - location.hash = '/sessions/parent'; - }); - const text = page - .locator('.detail-workspace') - .getByRole('textbox', { name: 'Follow-up message' }); - await text.fill('/ren'); - const panel = page.getByRole('region', { name: 'Session slash commands' }); - await panel.getByRole('button', { name: '/rename →', exact: true }).click(); - const input = panel.getByRole('textbox', { - name: 'Session name', - exact: true, - }); - await expect(input).toHaveValue('Current name'); - await input.fill('quota / review 界'); - await panel.getByRole('button', { name: 'REVIEW RENAME' }).click(); - await expect( - panel.getByRole('heading', { name: 'Rename to quota / review 界' }), - ).toBeVisible(); - expect(reviewed).toBe('quota / review 界'); - expect(modes.filter((m) => m === 'commit')).toHaveLength(0); - await panel.getByRole('button', { name: 'CONFIRM CHANGE' }).click(); - await expect( - panel.getByRole('button', { name: 'CONFIRM CHANGE' }), - ).toHaveCount(0); - expect(modes.filter((m) => m === 'commit')).toHaveLength(1); - expect(calls.filter((call) => call.action === 'prepare')).toHaveLength(0); -}); +for (const command of ['rename', 'cd']) { + test( + command + ' edits and reviews input before a separate confirmation', + async ({ page, pairingURL }) => { + const { calls } = await mockActions(page, 'prompt'); + const value = + command === 'cd' ? '/new directory 界' : 'quota / review 界'; + const label = command === 'cd' ? 'Working directory' : 'Session name'; + const message = + command === 'cd' ? 'Working directory changed.' : 'Session renamed.'; + const modes: string[] = []; + let reviewed = ''; + await page.route('**/api/control/commands', async (route) => { + const body = route.request().postDataJSON(); + const { mode, path } = body.command; + modes.push(mode); + let result: object; + if (mode === 'prepare') { + expect(path).toBe(command + '/' + encodeURIComponent(value)); + result = { + confirmation: command + '-token', + expires: new Date(Date.now() + 30000).toISOString(), + }; + } else if (mode === 'commit') { + expect(body.confirmation).toBe(command + '-token'); + result = { message }; + } else if (path === '') { + result = { + title: '/ COMMANDS', + help: 'Commands', + path: '', + revision: 'r', + choices: [ + { + id: 'rename', + label: '/' + command, + help: 'Rename the session', + next: command, + }, + ], + }; + } else if (path === command) { + result = { + title: '/' + command, + help: 'Enter a name, review and confirm.', + path, + revision: 'r', + input: true, + inputLabel: label, + inputLimit: command === 'cd' ? 1024 : 512, + value: 'Current name', + choices: [], + }; + } else { + reviewed = decodeURIComponent(path.slice(command.length + 1)); + result = { + title: '/' + command, + help: 'Only the saved name changes.', + path, + revision: 'r', + choices: [ + { + id: 'name', + label: 'Review ' + reviewed, + help: 'New name: ' + reviewed, + action: true, + }, + ], + }; + } + await route.fulfill({ json: result }); + }); + await page.goto(pairingURL); + await page.evaluate(() => { + location.hash = '/sessions/parent'; + }); + const text = page + .locator('.detail-workspace') + .getByRole('textbox', { name: 'Follow-up message' }); + await text.fill('/' + command); + const panel = page.getByRole('region', { + name: 'Session slash commands', + }); + await panel + .getByRole('button', { name: '/' + command + ' →', exact: true }) + .click(); + const input = panel.getByRole('textbox', { + name: label, + exact: true, + }); + await expect(input).toHaveValue('Current name'); + await input.fill(value); + await panel + .getByRole('button', { + name: command === 'cd' ? 'REVIEW DIRECTORY' : 'REVIEW RENAME', + }) + .click(); + await expect( + panel.getByRole('heading', { name: 'Review ' + value }), + ).toBeVisible(); + expect(reviewed).toBe(value); + expect(modes.filter((m) => m === 'commit')).toHaveLength(0); + await panel.getByRole('button', { name: 'CONFIRM CHANGE' }).click(); + await expect( + panel.getByRole('button', { name: 'CONFIRM CHANGE' }), + ).toHaveCount(0); + expect(modes.filter((m) => m === 'commit')).toHaveLength(1); + expect(calls.filter((call) => call.action === 'prepare')).toHaveLength(0); + }, + ); +} test('unavailable slash commands close without losing the draft and recover with a fresh catalogue', async ({ page, @@ -3469,3 +3489,63 @@ test('session content is text, not HTML or executable instructions', async ({ expect(dialogs).toEqual([]); expect(externalRequests).toEqual([]); }); + +test('cwd shows the running directory without preparing a mutation', async ({ + page, + pairingURL, +}) => { + await mockActions(page, 'prompt'); + const modes: string[] = []; + await page.route('**/api/control/commands', async (route) => { + const { mode, path } = route.request().postDataJSON().command; + modes.push(mode); + await route.fulfill({ + json: + path === '' + ? { + title: '/ COMMANDS', + help: 'Commands', + path: '', + revision: 'r', + choices: [ + { + id: 'cwd', + label: '/cwd', + help: 'Show directory', + next: 'cwd', + }, + ], + } + : { + title: '/cwd', + help: 'Running directory', + path: 'cwd', + revision: 'r', + choices: [ + { + id: 'directory', + label: 'Current directory', + help: 'Working directory: /dev/projects', + }, + ], + }, + }); + }); + await page.goto(pairingURL); + await page.evaluate(() => { + location.hash = '/sessions/parent'; + }); + const panel = page.getByRole('region', { name: 'Session slash commands' }); + await panel.getByRole('button', { name: '/ COMMANDS', exact: true }).click(); + await panel.getByRole('button', { name: '/cwd →', exact: true }).click(); + await panel + .getByRole('button', { name: 'Current directory // HELP', exact: true }) + .click(); + await expect( + panel.getByText('Working directory: /dev/projects', { exact: true }), + ).toBeVisible(); + await expect( + panel.getByRole('button', { name: 'CONFIRM CHANGE' }), + ).toHaveCount(0); + expect(modes.every((mode) => mode === 'list')).toBe(true); +}); From 26d13e052976851355284809a8e84e983ccb634d Mon Sep 17 00:00:00 2001 From: merefield Date: Sat, 10 Oct 2026 17:31:02 +0100 Subject: [PATCH 2/7] Prioritize slash-command gaps and estimate implementation complexity --- docs/slash-command-support.md | 184 ++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 78 deletions(-) diff --git a/docs/slash-command-support.md b/docs/slash-command-support.md index 3ae22c6..d35f463 100644 --- a/docs/slash-command-support.md +++ b/docs/slash-command-support.md @@ -6,22 +6,47 @@ The tables cover all **63 registered commands**, including aliases. Platform, fe “Missing” below means no Codexometer slash adapter, **not** that the server lacks the capability. Live commands require a loaded session and shared app-server; browser control commands require writable mode. Windows' existing file-based monitoring path does not gain live server commands from this change. +## Priority and complexity scale + +These are proposed priorities for Codexometer's session-monitoring/control role, informed by the recent directory and approval issues and opportunities to reuse existing UI. They are judgments, not measured demand or delivery commitments. **Complexity rates the proposed next increment below**, across terminal and browser interfaces where applicable, including state/reconnect handling, confirmation and meaningful regression coverage. It does not rate the implementation already completed, or promise full native CLI parity. + +| Priority | Meaning | +| --- | --- | +| **P1 — next** | Common workflow, diagnostics or an operation that unblocks a session; address before optional expansion. | +| **P2 — later** | Useful capability after the core session controls and lifecycle foundation. | +| **P3 — optional** | Niche, cosmetic or broader account/configuration integration; schedule when demand justifies it. | +| **Defer** | A substantial expansion beyond the current product; no near-term implementation recommended. | +| **Done** | Current scoped implementation is sufficient; no additional increment proposed. | +| **Exclude** | Internal/debug, retired or unregistered names; no product implementation proposed. | + +| Complexity | Meaning | +| --- | --- | +| **Low** | Reuse an existing action/view, add an alias or a small local preference; little new state. | +| **Medium** | Add a bounded API adapter, editor/picker or progress view with target/state validation. | +| **High** | Add a stateful lifecycle, history/repository, authentication, configuration or input workflow spanning several components. | +| **Very high** | Add project-context/trust transitions, multimodal transport or an external integration with substantial new infrastructure. | +| **—** | Not applicable: no further implementation is proposed for Done/Exclude entries. | + +Aliases on one row share the rating and implementation. Lifecycle commands share a thread-handoff foundation, so their costs should not be added as independent projects. P1 is a value/need ranking, not a claim that every P1 is a quick win. Work blocked on a foundation comes after that foundation even if it has the same priority. + ## Implemented and partial support -| Command | Support | Implementation and limits | -| --- | --- | --- | -| `/rename` | Implemented | Confirmed `thread/name/set`; works during active turns. | -| `/cd ` | Implemented with narrower semantics | Confirmed `thread/settings/update`, sending only `threadId` and `cwd`. Requires idle/local session, empty queue, no pending approval and an existing directory. Resolves relative paths from the running session directory, expands `~`/`~/`, rechecks symlinks and verifies the result from running configuration. No write retries. See the semantics below. | -| `/pwd`, `/cwd` | Implemented aliases | Read-only `thread/resume` **without overrides** reports the running directory, including during active turns. Captured `thread/read.cwd` metadata is not used as the answer. The session directory/footer also follows live directory reads and settings notifications. | -| `/model` | Session adapter | Live model/reasoning catalogue, confirmed while idle. Clears explicit speed override when selecting a model; does not reproduce native CLI persistence. | -| `/plan` | Partial | Advertised collaboration-mode selection; no native optional prompt argument. | -| `/permissions` | Session adapter | Live allowed named profiles for the directory, confirmed while idle. Not every native permission-dialog action is implemented. | -| `/skills` | Browse only | `skills/list` inventory/help. No invocation or configuration flow; `skills/config/write` exists but needs scope/review UI. | -| `/apps` | Browse only | `app/list` inventory/help. Installation, linking and authentication workflows are absent. | -| `/mcp` | Browse only | `mcpServerStatus/list` and tool help. No `/mcp login`, resource browser or arbitrary tool invocation. Related APIs exist but need dedicated authentication/execution UI. | -| `/hooks` | Browse only | `hooks/list`. No editor/review for lifecycle-hook configuration or its command execution scope. | -| `/experimental` | Browse only | `experimentalFeature/list`. Enablement changes process/configuration scope, rather than a single session; no mutation UI. | -| `/statusline` | Local equivalent | Codexometer's own footer picker; also available in read-only web mode. Does not edit the native CLI's status line. | +| Command | Support | Priority | Complexity | Implementation and limits | +| --- | --- | --- | --- | --- | +| `/rename` | Implemented | Done | — | Confirmed `thread/name/set`; works during active turns. | +| `/cd ` | Implemented with narrower semantics | P1 | Very high | Confirmed `thread/settings/update`, sending only `threadId` and `cwd`. Requires idle/local session, empty queue, no pending approval and an existing directory. Resolves relative paths from the running session directory, expands `~`/`~/`, rechecks symlinks and verifies the result from running configuration. No write retries. See the semantics below. Proposed next increment: destination project-context reload with trust/permission validation and a verified conversation handoff. Reuse the lifecycle foundation below; native-client cooperation may still be necessary. | +| `/pwd`, `/cwd` | Implemented aliases | Done | — | Read-only `thread/resume` **without overrides** reports the running directory, including during active turns. Captured `thread/read.cwd` metadata is not used as the answer. The session directory/footer also follows live directory reads and settings notifications. | +| `/model` | Session adapter | Done | — | Live model/reasoning catalogue, confirmed while idle. Clears explicit speed override when selecting a model; does not reproduce native CLI persistence. Session-only scope is intentional; no global-default editor is proposed. | +| `/plan` | Partial | P2 | Medium | Advertised collaboration-mode selection; no native optional prompt argument. Proposed next increment: explicit review of an inline plan prompt and confirmed mode/prompt submission without losing the draft. | +| `/permissions` | Session adapter | Done | — | Live allowed named profiles for the directory, confirmed while idle. Not every native permission-dialog action is implemented. The named-profile session adapter is the proposed scope; broader native dialogs are not scheduled. | +| `/skills` | Browse only | P2 | Medium | `skills/list` inventory/help. No invocation or configuration flow; `skills/config/write` exists but needs scope/review UI. Proposed next increment: invoke an advertised skill through structured input after review. Configuration/enablement writes are a separate High-complexity extension. | +| `/apps` | Browse only | P3 | High | `app/list` inventory/help. Installation, linking and authentication workflows are absent. Proposed next increment: a guided linking/authentication workflow with return/cancellation handling; reuse upstream flows rather than inventing installation semantics. | +| `/mcp` | Browse only | P2 | High | `mcpServerStatus/list` and tool help. No `/mcp login`, resource browser or arbitrary tool invocation. Related APIs exist but need dedicated authentication/execution UI. Proposed next increment: server-specific login/status and verbose inspection. Arbitrary tool execution remains a separate reviewed workflow. | +| `/hooks` | Browse only | P3 | High | `hooks/list`. No editor/review for lifecycle-hook configuration or its command execution scope. Proposed next increment: a scope-aware hook configuration editor with preview and reload handling. | +| `/experimental` | Browse only | P3 | Medium | `experimentalFeature/list`. Enablement changes process/configuration scope, rather than a single session; no mutation UI. Proposed next increment: review an advertised enablement change with its process/configuration scope and refresh/restart effects made clear. | +| `/statusline` | Local equivalent | Done | — | Codexometer's own footer picker; also available in read-only web mode. Does not edit the native CLI's status line. | +| `/help` | Local catalogue | Done | — | Codexometer catalogue entry; absent from the upstream registry. | +| Advertised speed aliases, e.g. `/fast` | Session adapter | Done | — | Use live model-advertised tier names/IDs, with confirmed session overrides; global defaults remain out of scope. | `/help` is Codexometer's catalogue entry, absent from this upstream registry. Speed aliases such as `/fast` appear only when the current model advertises that tier; IDs are not guessed. They change session overrides rather than native persistent defaults. @@ -35,77 +60,80 @@ Native `/cd` is a larger client workflow: destination project-configuration relo These are adapter/workflow gaps. Where an API exists it is listed; this PR only adds directory commands. -| Command | Mechanism / why missing | -| --- | --- | -| `/new` | `thread/start` exists; needs creation options and selection/handoff to the new thread. | -| `/clear` | Native clear starts a new chat and clears its terminal; no combined local clear/`thread/start` workflow. Hiding monitor rows is different. | -| `/resume` | `thread/list`/`thread/resume` exist; no saved-session picker. Monitor selection observes loaded sessions. | -| `/fork` | `thread/fork` exists; needs options, confirmation and handoff while preserving source drafts. | -| `/worktree` | Needs actual Git worktree creation/ownership/cleanup plus thread creation/fork. No worktree manager; a cwd update is insufficient. | -| `/archive` | `thread/archive` exists; no archive confirmation/handoff. Close/Close All only hide rows. | -| `/delete` | `thread/delete` exists; no destructive-delete confirmation and history/selection cleanup. | -| `/compact` | `thread/compact/start` exists; needs state checks and completion/error progress rather than reporting a queued operation as done. | -| `/recap` | Native summarization workflow has no adapter/progress UI; verify that workflow before choosing a server operation or prompt. | -| `/review` | `review/start` exists; no review-target picker, delivery mode or progress UI. | -| `/goal` | `thread/goal/get`, `set`, `clear` exist; no goal editor, budget/clear confirmation or goal state. | -| `/side`, `/btw` | Ephemeral forks need a temporary conversation/draft view, thread routing and cleanup. | -| `/approve` | `thread/approveGuardianDeniedAction` exists; needs exact targeting of a recent automatic-review denial. Ordinary approval buttons are a different action. | -| `/ps` | `thread/backgroundTerminals/list` exists; no list/detail adapter. Telemetry process/session views do not reproduce it. | -| `/stop`, `/clean` | `thread/backgroundTerminals/clean` exists; no session-scoped stop-all review and verification. Turn interruption is a different action. | -| `/usage` | `account/usage/read`, rate-limit/reset-credit APIs exist. Usage/reset-token UI already exists; no slash alias opens it. Account reset credits are different from Sessions Zero. | -| `/status` | Settings/usage reads exist; detail/footer show related data, but no consolidated status slash view. | -| `/debug-config` | `config/read` with layers and `configRequirements/read` exist; no directory-aware configuration-source/requirements inspector. | -| `/daybreak` | `thread/metadata/update` can save Daybreak choice; no dedicated feature-aware toggle/state adapter. Do not invent an experimental flag ID. | -| `/memories` | `memory/status`, `thread/memoryMode/set` and configuration APIs exist; no scope-specific settings UI. Thread mode and global generation settings differ. | -| `/import` | `externalAgentConfig/detect`/`import` exist; no selection, preview, progress or configuration/history confirmation. | -| `/plugins` | Listing/search/read/install/uninstall APIs exist; no lifecycle/authentication and installation/configuration-review workflow. | -| `/logout` | `account/logout` exists; needs account-level confirmation and recovery for consequences to shared clients. | -| `/feedback` | `feedback/upload` exists; no log-selection and data-sharing preview/consent workflow. | -| `/setup-default-sandbox` | `windowsSandbox/setupStart`/`readiness` exist; no Windows elevated-sandbox setup workflow. Not applicable to macOS local sessions. | -| `/voice` | `thread/realtime/*`, including voice listing, exist; no microphone/audio transport, device settings or realtime conversation UI. | -| `/daemon` | Native daemon management and `server/diagnostics` exist; no lifecycle-management command. Stopping/restarting affects other clients. | -| `/warnings` | Server/config warning notifications exist; no retained warning/diagnostic browser. Ordinary error notices are only partial analogues. | +| Command | Priority | Complexity | Mechanism / why missing | +| --- | --- | --- | --- | +| `/new` | P1 | High | `thread/start` exists; needs creation options and selection/handoff to the new thread. Proposed next increment: build the common thread-creation/handoff foundation, including subscriptions, drafts and selection. | +| `/clear` | P2 | Medium | Native clear starts a new chat and clears its terminal; no combined local clear/`thread/start` workflow. Hiding monitor rows is different. Proposed next increment: a local clear/new-chat action after the /new foundation exists; Medium assumes that dependency is complete. | +| `/resume` | P1 | High | `thread/list`/`thread/resume` exist; no saved-session picker. Monitor selection observes loaded sessions. Proposed next increment: a paginated saved-session picker with verified load/handoff; share the lifecycle foundation with /new and /fork. | +| `/fork` | P1 | High | `thread/fork` exists; needs options, confirmation and handoff while preserving source drafts. Proposed next increment: a reviewed fork and verified new-thread selection, retaining source history/draft and correct telemetry accounting. | +| `/worktree` | P2 | Very high | Needs actual Git worktree creation/ownership/cleanup plus thread creation/fork. No worktree manager; a cwd update is insufficient. Proposed next increment: managed worktree creation and conversation transition after thread handoff and project-context changes are supported. | +| `/archive` | P2 | Medium | `thread/archive` exists; no archive confirmation/handoff. Close/Close All only hide rows. Proposed next increment: confirm the exact session, observe archive completion and select another row without discarding unrelated drafts. | +| `/delete` | P3 | Medium | `thread/delete` exists; no destructive-delete confirmation and history/selection cleanup. Proposed next increment: explicit permanent-delete confirmation and verified removal, with stale-target and selection/history cleanup. | +| `/compact` | P1 | Medium | `thread/compact/start` exists; needs state checks and completion/error progress rather than reporting a queued operation as done. Proposed next increment: confirmed start plus completion/error tracking, keeping polling and approvals responsive throughout. | +| `/recap` | P2 | High | Native summarization workflow has no adapter/progress UI; verify that workflow before choosing a server operation or prompt. Provisional estimate: first establish the native summarization semantics, then add a reviewed summary workflow without changing the source conversation unexpectedly. | +| `/review` | P2 | High | `review/start` exists; no review-target picker, delivery mode or progress UI. Proposed next increment: target/delivery selection, confirmed start and a dedicated review-progress/result view. | +| `/goal` | P2 | Medium | `thread/goal/get`, `set`, `clear` exist; no goal editor, budget/clear confirmation or goal state. Proposed next increment: read/edit/clear goal and budget with session targeting, confirmation and live state refresh. | +| `/side`, `/btw` | P3 | High | Ephemeral forks need a temporary conversation/draft view, thread routing and cleanup. Proposed next increment: an isolated ephemeral conversation UI with separate drafts, lifecycle cleanup and source-thread return. | +| `/approve` | P1 | High | `thread/approveGuardianDeniedAction` exists; needs exact targeting of a recent automatic-review denial. Ordinary approval buttons are a different action. Proposed next increment: identify the exact retained denied action, review its original scope, confirm the retry and track the result. A generic approval shortcut is insufficient. | +| `/ps` | P1 | Medium | `thread/backgroundTerminals/list` exists; no list/detail adapter. Telemetry process/session views do not reproduce it. Proposed next increment: a read-only, session-scoped terminal list with command/state detail and refresh; foundation for /stop. | +| `/stop`, `/clean` | P1 | Medium | `thread/backgroundTerminals/clean` exists; no session-scoped stop-all review and verification. Turn interruption is a different action. Proposed next increment: confirm and verify stop-all for the selected session, using the /ps inventory and leaving other sessions alone. | +| `/usage` | P1 | Low | `account/usage/read`, rate-limit/reset-credit APIs exist. Usage/reset-token UI already exists; no slash alias opens it. Account reset credits are different from Sessions Zero. Proposed next increment: open the existing usage/reset views through a slash alias; reuse their current confirmation flow rather than adding new account mutations. | +| `/status` | P1 | Medium | Settings/usage reads exist; detail/footer show related data, but no consolidated status slash view. Proposed next increment: a consolidated read-only view of running configuration, permission scope, directory and usage; live configuration adds work beyond a navigation alias. | +| `/debug-config` | P2 | Medium | `config/read` with layers and `configRequirements/read` exist; no directory-aware configuration-source/requirements inspector. Proposed next increment: a read-only effective-layer/requirements inspector with bounded display and sensitive-value handling. | +| `/daybreak` | P3 | Medium | `thread/metadata/update` can save Daybreak choice; no dedicated feature-aware toggle/state adapter. Do not invent an experimental flag ID. Proposed next increment: show availability/current choice and confirm the per-thread metadata update; it must not imply access is granted. | +| `/memories` | P3 | High | `memory/status`, `thread/memoryMode/set` and configuration APIs exist; no scope-specific settings UI. Thread mode and global generation settings differ. Proposed next increment: display current memory state, then review thread-mode changes separately from persistent generation/configuration changes. | +| `/import` | P3 | Very high | `externalAgentConfig/detect`/`import` exist; no selection, preview, progress or configuration/history confirmation. Proposed next increment: preview/import selected configuration and history with conflict handling, progress and recovery; optional cross-tool scope. | +| `/plugins` | P3 | High | Listing/search/read/install/uninstall APIs exist; no lifecycle/authentication and installation/configuration-review workflow. Proposed next increment: read installed/available details, then reviewed installation/removal with dependency, authentication and effective-scope handling. | +| `/logout` | P3 | Medium | `account/logout` exists; needs account-level confirmation and recovery for consequences to shared clients. Proposed next increment: account-level identity/scope confirmation and a clear disconnected/re-authentication state for shared clients. | +| `/feedback` | P3 | High | `feedback/upload` exists; no log-selection and data-sharing preview/consent workflow. Proposed next increment: select and preview the actual diagnostic payload before consent/upload, with bounded collection and failure/cancellation handling. | +| `/setup-default-sandbox` | P3 | High | `windowsSandbox/setupStart`/`readiness` exist; no Windows elevated-sandbox setup workflow. Not applicable to macOS local sessions. Proposed next increment: the Windows setup/readiness/elevation workflow and platform-specific recovery; requires real Windows verification. | +| `/voice` | Defer | Very high | `thread/realtime/*`, including voice listing, exist; no microphone/audio transport, device settings or realtime conversation UI. Proposed scope if demanded: audio-device permissions, transport, realtime state, cancellation and reconnection in both interfaces. This is a major product expansion. | +| `/daemon` | P2 | Medium | Native daemon management and `server/diagnostics` exist; no lifecycle-management command. Stopping/restarting affects other clients. Proposed next increment: read-only daemon diagnostics/status. Start/stop/restart management is a separate P3/High workflow with shared-client confirmation and disconnection/recovery handling. | +| `/warnings` | P1 | Medium | Server/config warning notifications exist; no retained warning/diagnostic browser. Ordinary error notices are only partial analogues. Proposed next increment: a bounded retained-warning view with source/time, details and freshness; useful for explaining stalled or rejected actions. | ## Missing native UI commands These require Codexometer UX, not forwarding the command name to a server. -| Command | Why missing / existing analogue | -| --- | --- | -| `/agents` | Native agent command center has no adapter; linked-session grouping is not a matching management center. | -| `/subagents` | Linked agents are visible in grouping; no slash picker switches their native CLI views. | -| `/copy` | Copy controls exist; no slash alias/picker for the last response or selected transcript parts. | -| `/export` | No Markdown export; needs complete paginated history plus a file/download destination. | -| `/diff` | No repository diff browser with tracked/untracked handling and explicit repository context. | -| `/mention` | No structured file-mention picker or associated attachment/input metadata routing. | -| `/init` | Native command asks Codex to create `AGENTS.md`; no explicit generation/overwrite review. It is deliberately not silently converted to a prompt. | -| `/ide` | No native IDE-context integration for selection/open files. | -| `/app` | No desktop-app handoff/deep-link action; upstream visibility is platform-dependent. | -| `/raw` | Native raw-scrollback toggle cannot control Codexometer's separate rendering; no equivalent local switch. | -| `/tui` | Chooses native CLI mode for its next launch; no corresponding Codexometer launch-mode picker. | -| `/title` | No local title-field picker or native title configuration editor. | -| `/theme` | Codexometer theme preferences exist; no slash entry reproduces the native syntax-highlighting picker. | -| `/pets`, `/pet` | Native terminal-pet picker has no counterpart here. | -| `/keymap` | No shortcut-remapping editor; native keybindings belong to another interface. | -| `/vim` | No Vim-mode composer. | -| `/exit`, `/quit` | Existing local Quit controls exit Codexometer, without slash aliases. Native CLI exit/server shutdown has different scope. | +| Command | Priority | Complexity | Why missing / existing analogue | +| --- | --- | --- | --- | +| `/agents` | P2 | High | Native agent command center has no adapter; linked-session grouping is not a matching management center. Proposed next increment: a dedicated agent state/management view with capability-aware controls and exact child/root routing. | +| `/subagents` | P1 | Medium | Linked agents are visible in grouping; no slash picker switches their native CLI views. Proposed next increment: a linked-agent picker with separate child detail and preserved root/draft state; native-client switching is not implied. | +| `/copy` | P1 | Low | Copy controls exist; no slash alias/picker for the last response or selected transcript parts. Proposed next increment: open the existing session-copy action from a slash alias; selection of arbitrary historical fragments can follow separately. | +| `/export` | P2 | High | No Markdown export; needs complete paginated history plus a file/download destination. Proposed next increment: complete paginated transcript retrieval and Markdown export with bounded streaming/file/download handling; existing excerpts are insufficient. | +| `/diff` | P2 | High | No repository diff browser with tracked/untracked handling and explicit repository context. Proposed next increment: a directory-aware tracked/untracked diff view with large/binary-file handling and no inferred repository scope. | +| `/mention` | P2 | High | No structured file-mention picker or associated attachment/input metadata routing. Proposed next increment: file search/selection plus structured input metadata through review, send/steer and draft handling. | +| `/init` | P2 | Medium | Native command asks Codex to create `AGENTS.md`; no explicit generation/overwrite review. It is deliberately not silently converted to a prompt. Proposed next increment: explicitly review a request to generate AGENTS.md in the selected directory; report request/agent result rather than claiming the file was created immediately. | +| `/ide` | Defer | Very high | No native IDE-context integration for selection/open files. Proposed scope if demanded: discover/connect an editor and securely route selections/open-file context, including stale/different-workspace handling. | +| `/app` | P3 | Medium | No desktop-app handoff/deep-link action; upstream visibility is platform-dependent. Proposed next increment: a platform-aware desktop-app handoff with validated thread/directory identity and an unavailable-app fallback. | +| `/raw` | P3 | High | Native raw-scrollback toggle cannot control Codexometer's separate rendering; no equivalent local switch. Proposed next increment: a Codexometer-owned scrollback/copy-friendly rendering mode that preserves live input and state; it is not a server toggle. | +| `/tui` | P3 | Medium | Chooses native CLI mode for its next launch; no corresponding Codexometer launch-mode picker. Proposed next increment: local next-launch mode preferences with explicit precedence over flags and terminal capability checks. | +| `/title` | P3 | Medium | No local title-field picker or native title configuration editor. Proposed next increment: a local title-field picker with persistence and safe terminal/browser title updates, reusing statusline field selection. | +| `/theme` | P2 | Low | Codexometer theme preferences exist; no slash entry reproduces the native syntax-highlighting picker. Proposed next increment: open Codexometer’s existing theme preferences; native syntax-theme parity is a separate, larger feature. | +| `/pets`, `/pet` | Defer | High | Native terminal-pet picker has no counterpart here. Proposed scope if demanded: terminal/browser pet assets, animation/state and preference UI; cosmetic expansion outside core monitoring. | +| `/keymap` | P3 | High | No shortcut-remapping editor; native keybindings belong to another interface. Proposed next increment: local remapping with composer/modal precedence, conflict checks and accurate help across all views. | +| `/vim` | P3 | High | No Vim-mode composer. Proposed next increment: composer modes/editing with Unicode, paste, shortcuts, focus and review-modal interactions verified in both interfaces. | +| `/exit`, `/quit` | P2 | Low | Existing local Quit controls exit Codexometer, without slash aliases. Native CLI exit/server shutdown has different scope. Proposed next increment: aliases for local Codexometer exit/leave behavior, clearly labelled; never treat them as shared-daemon shutdown or native CLI exit. | ## Debug entries and older documented names -| Command | Treatment | -| --- | --- | -| `/rollout` | Debug-build registry entry; no rollout-path slash inspector. | -| `/test-approval` | Debug-build synthetic approval request; not a user command here. Real approvals already have dedicated controls. | -| `/debug-m-drop`, `/debug-m-update` | Registry descriptions say “DO NOT USE”; intentionally not exposed. | -| `/agent` | Older published name; this registry uses `/agents`, not a separate `/agent` command. | -| `/personality` | Published but absent from this registry; protocol personality fields are deprecated. No current CLI style selector to reproduce. | -| `/sandbox-add-read-dir` | Published/platform-specific older entry, absent from this registry. Do not assume availability in every installed version. | - -## Follow-up priorities - -1. Add slash entry points to existing read-only/local views: `/status`, `/usage`, `/copy`, `/subagents`, plus a background-terminal `/ps` view. -2. Add `/compact`, `/review` and `/goal` with completion/state tracking; then `/new`, `/resume` and `/fork` with thread handoff. -3. Add `/diff`, `/export` and background-terminal stop controls with explicit target scope. -4. Keep account/global configuration, import, installation, sandbox and daemon actions in dedicated reviewed workflows. Their omission is mainly absent UX/scope handling, not absent APIs. +| Command | Priority | Complexity | Treatment | +| --- | --- | --- | --- | +| `/rollout` | Exclude | — | Debug-build registry entry; no rollout-path slash inspector. | +| `/test-approval` | Exclude | — | Debug-build synthetic approval request; not a user command here. Real approvals already have dedicated controls. | +| `/debug-m-drop`, `/debug-m-update` | Exclude | — | Registry descriptions say “DO NOT USE”; intentionally not exposed. | +| `/agent` | Exclude | — | Older published name; this registry uses `/agents`, not a separate `/agent` command. Track /agents above instead; add a compatibility alias only if there is demonstrated need. | +| `/personality` | Exclude | — | Published but absent from this registry; protocol personality fields are deprecated. No current CLI style selector to reproduce. | +| `/sandbox-add-read-dir` | Exclude | — | Published/platform-specific older entry, absent from this registry. Do not assume availability in every installed version. Reassess only against a version/platform that actually advertises this operation. | + +## Recommended delivery order + +1. **Small P1 additions:** `/usage` and `/copy` aliases, then `/status`, `/warnings` and `/ps` read-only views. They build on existing controls and improve visibility before adding more mutations. +2. **P1 session controls:** `/compact`, the linked-agent `/subagents` picker, and reviewed `/stop`/`clean` built on `/ps`. Add `/approve` as its own High-complexity workflow with exact denied-action targeting. +3. **P1 lifecycle foundation:** `/new`, `/resume` and `/fork`, sharing subscription, selection, draft and history-handoff handling. Then pursue full `/cd` project-context parity; it depends on this foundation and remains Very high complexity. +4. **P2 extensions:** inexpensive local `/theme` and `/exit`/`quit` aliases; `/plan` inline prompts, `/goal`, `/archive`, `/debug-config`, daemon diagnostics and reviewed `/init`; then `/review`, `/export`, `/diff`, `/mention`, skill invocation and MCP login/inspection. Put `/clear` after `/new`, agent management after linked-agent navigation, and `/worktree` after lifecycle/project-context support. +5. **P3/Defer:** optional global/account, import, installation, sandbox, daemon lifecycle, keymap and composer-mode work require explicit scope and demand. Treat daemon diagnostics as the smaller first step to its P2 workflow. Voice, IDE integration and pets should not displace core monitoring/control work. Exclude internal debug and retired/unregistered names. + +The next small PR should cover **`/usage`, `/copy`, `/status`, `/warnings` and `/ps`**. Subsequent PRs can add compaction and background-terminal stopping using those views. Full directory-context transitions need a separate design and PR covering project configuration/trust loading, conversation handoff and attached-client behavior. For future updates, compare both the next installed version's registry and generated protocol. Omission from the published list is not evidence that a command is unsupported. From 438988addec8c528ac53f4d57371c4293c6f8e9c Mon Sep 17 00:00:00 2001 From: merefield Date: Sat, 10 Oct 2026 19:41:48 +0100 Subject: [PATCH 3/7] Keep Zone as Pace and remove the alternate quota graph --- README.md | 53 +++--- internal/quotagraph/graph.go | 6 +- internal/quotagraph/graph_test.go | 17 +- internal/ui/english_snapshot_test.go | 4 +- internal/ui/meters.go | 8 +- internal/ui/meters_test.go | 3 +- internal/ui/preferences.go | 5 +- internal/ui/quota_graph.go | 52 +---- internal/ui/quota_graph_test.go | 177 ++++++++---------- internal/ui/tabs.go | 8 +- internal/ui/tabs_test.go | 6 +- internal/ui/theme.go | 3 - internal/ui/view_test.go | 2 +- internal/web/dist/assets/index-4j3sNB-h.css | 1 - internal/web/dist/assets/index-E1h87Zp5.js | 45 ----- internal/web/dist/assets/index-ED7GoxW0.css | 1 + internal/web/dist/assets/index-KFu7j0xL.js | 44 +++++ internal/web/dist/index.html | 4 +- ...tionZone.svelte => ConsumptionPace.svelte} | 84 ++------- web/src/Quota.svelte | 23 ++- web/src/preferences.svelte.ts | 8 +- web/tests/browser.spec.ts | 159 ++++++++-------- 22 files changed, 309 insertions(+), 404 deletions(-) delete mode 100644 internal/web/dist/assets/index-4j3sNB-h.css delete mode 100644 internal/web/dist/assets/index-E1h87Zp5.js create mode 100644 internal/web/dist/assets/index-ED7GoxW0.css create mode 100644 internal/web/dist/assets/index-KFu7j0xL.js rename web/src/{ConsumptionZone.svelte => ConsumptionPace.svelte} (81%) diff --git a/README.md b/README.md index b14e326..080efba 100644 --- a/README.md +++ b/README.md @@ -590,8 +590,8 @@ codexometer --codex /path/to/codex | `z` | Zero the Sessions baseline | | `s` | Open Benchmark Scope (Benchmark view only) | | `o` | Arm Close All in the Sessions overview; press again to confirm, or `Esc` to cancel | -| `g` | Cycle available trend periods in Quota → Pace or Zone | -| `h` | Toggle the trace in Quota → Pace or Zone; in Sessions, reset all rows to graph-only / split detail-and-graph, closing full detail and clearing individual row choices | +| `g` | Cycle available trend periods in Quota → Pace | +| `h` | Toggle the trace in Quota → Pace; in Sessions, reset all rows to graph-only / split detail-and-graph, closing full detail and clearing individual row choices | | `Left` / `Right` | In Sessions, less / more detail for the selected session: graph ↔ split ↔ wide ↔ full screen; stops at either end | | `b` | Run the selected benchmark scope (Benchmark view only) | | `a` | Arm, then confirm, Run All (Benchmark view only) | @@ -613,7 +613,7 @@ codexometer --codex /path/to/codex The responsive top rail below the account status selects Quota, Sessions, Usage, or Benchmark by mouse, `Tab`, or `Shift+Tab`. Quota adds a second rail for Bars, -Pace, Zone, Pie, Fuel Tank, and Resets; select these with the mouse or cycle them +Pace, Pie, Fuel Tank, and Resets; select these with the mouse or cycle them with `v`. Codexometer remembers the selected Quota view when you leave and return. Both rails condense automatically as the terminal narrows. The footer presents the remaining actions as clickable buttons, including View @@ -873,27 +873,23 @@ The default remains the original green hacker-terminal presentation. ## Views and quota presentations The top-level tabs are **Quota**, **Sessions**, **Usage**, and **Benchmark**. Within Quota, -choose one of these six views with its sub-tab or `v`: +choose one of these five views with its sub-tab or `v`: 1. **Bars** — chunky quota bars, with one full-width rate-limit window per row. -2. **Pace** — elapsed-window time on X, consumed percentage minus elapsed - percentage on Y (−100 to +100 percentage points). Above the horizontal safe - line means consumption is ahead of time; below it means headroom. Dark colour - bands fade from amber at safety toward red above and green below. -3. **Zone** — elapsed-window time on X and 0–100% consumption on Y, with a +2. **Pace** — elapsed-window time on X and 0–100% consumption on Y, with a diagonal steady-consumption line and a red/amber/green background. Above the diagonal means over pace; below it means headroom. -4. **Pie** — clockwise-filled circles rendered on a 2×4 sub-cell Braille canvas +3. **Pie** — clockwise-filled circles rendered on a 2×4 sub-cell Braille canvas for clean curves at any size. -5. **Fuel Tank** — a reverse gauge whose bright segment shows remaining range +4. **Fuel Tank** — a reverse gauge whose bright segment shows remaining range and whose dark segment shows consumed capacity, labelled from Empty to Full; one full-width tank appears per row. Its reset-cycle comparison also drains backward and aligns exactly with the tank's first and last inner cells. -6. **Resets** — available reset credits, grant dates, expiry dates and backend +5. **Resets** — available reset credits, grant dates, expiry dates and backend descriptions. Expiring credits appear first, non-expiring credits last. Scroll with Up/Down or Page Up/Page Down when necessary. -Pace and Zone use terminal-cell backgrounds and densely plotted, continuous +Pace uses terminal-cell backgrounds and densely plotted, continuous Braille strokes for traces, trends and the safety reference. The current dot is bright; the observed trace is pale for contrast against the dark background. Click **Trend** (`g`) to cycle **Window Start**, **Last 30 Minutes**, @@ -910,7 +906,7 @@ in memory only, collected at each quota refresh even on other tabs, and cleared when the account or quota cycle changes. Failed refreshes leave gaps rather than connecting an invented path. Graphs share rows when width permits, add rows for extra windows, and fall back to compact readouts when too small to plot. -Unknown window timing cannot be graphed. The browser offers the same variants +Unknown window timing cannot be graphed. The browser offers the same graph and trend choices with smoother SVG lines, directional arrows and backgrounds. The reset shortcut opens Resets and asks for confirmation before redeeming. @@ -1185,7 +1181,7 @@ Meter rows always use identical heights; indivisible spare rows become quiet space above the footer instead of stretching one quota block more than another. Pie uses at least two columns when multiple limits exist, adding rows when that preserves more radial detail and adding columns when the terminal is wide -enough. Pace and Zone use as many graph columns as remain readable and scale +enough. Pace uses as many graph columns as remain readable and scales both axes to each card's remaining space. Bars, Pie and Fuel Tank also show a `RESET CYCLE` comparison: its label and countdown occupy one line, while its progress bar occupies a @@ -1193,8 +1189,8 @@ separate line with the same width and active colour as the main visualization. Its percentage is elapsed time from the calculated window start (`reset - duration`) to the next reset. When Codex supplies a monthly reset but not a cycle start, the card says `CYCLE START UNAVAILABLE`, shows the known -countdown, and leaves the comparison bar unfilled. Pace and Zone instead -show elapsed time on their X axes and retain a separate reset countdown. +countdown, and leaves the comparison bar unfilled. Pace instead +shows elapsed time on its X axis and retains a separate reset countdown. Every visualization receives its card's remaining width and height, and resizing the terminal immediately reflows and rescales it. The underlying values and reset information @@ -2597,14 +2593,14 @@ codexometer --web --web-port 8765 5. Press Ctrl+C in the launching terminal to stop the server and invalidate access. This preview is **read-only by default and UK-English-only**, not feature parity with -the terminal. It includes Bars, Pace, Zone, Pie and Fuel Tank quota +the terminal. It includes Bars, Pace, Pie and Fuel Tank quota presentations; reset inventory with disclosed expiry information; local session telemetry with expandable/full-page context and synchronised activity graphs; and account history with a daily heatmap, monthly/cumulative bars, a 6/12-month selector and an accessible data table. Five browser themes are available. `CODEXOMETER_LANG` continues to configure the terminal, not this preview. -**Zone** plots each window's elapsed quota period horizontally and +**Pace** plots each window's elapsed quota period horizontally and 0–100% consumption vertically. The bottom-left to top-right diagonal represents steady consumption: above it means usage is outpacing elapsed time, below it means headroom. The background fades from red at the top left through amber to green at @@ -2621,15 +2617,10 @@ supplies the same retained history as text: observation time, elapsed period, consumed percentage and breaks between segments. It updates alongside the plotted trail. -**Pace** is a separate quota view using the same graph and controls. -It replaces the former horizontal Consumption Pace gauge in both interfaces, -keeps the elapsed-period X axis and shows -consumed percentage minus elapsed-period percentage on Y, in percentage points -from −100 to +100. Zero is the horizontal safe line: positive values mean usage -is ahead of time, negative values mean headroom. Its background is uniform -across each row, fading from amber at safety through orange to red above, and -from amber to green below. The dot, observed path and projection all use the -same transformed coordinates. +Pace preserves the former Zone graph. The former distance-from-safety Pace +view has been removed. Saved `zone` selections and browser `#/quota/zone` +links open the retained graph as Pace; older `consumption-pace` selections +also resolve to it. The **TREND** selector defaults to **FROM WINDOW START** and can be switched off. When enough uninterrupted observations exist, it can instead fit recent @@ -2642,10 +2633,8 @@ elapsed in a known quota window. The dotted projection starts at the beginning of the selected trend period, passes through the current dot and continues to the graph edge. It uses periodic arrows to show direction; its caption estimates consumption at reset or -warns when exhaustion is projected first. Both presentations colour it green +warns when exhaustion is projected first. Both interfaces colour it green when projected consumption at reset is at most 100%, dark red otherwise. -In Pace, the selected trend period controls the slope relative to safety: -slower-than-steady consumption slopes downward, faster consumption upward. Recent periods without enough observed history remain visible but disabled. This is a linear extrapolation of coarse whole-percentage observations, not an OpenAI forecast. @@ -2711,7 +2700,7 @@ session IDs. Navigation and layout controls never send actions to Codex. The browser uses a compact dashboard layout: quota plots share the available width and height below the tabs. Pie charts retain their circular shape, while -Zone and Pace scale each axis independently and keep text legible. On short +Pace scales each axis independently and keeps text legible. On short windows or with many quota windows, content scrolls without hiding the footer controls or shrinking plots below a readable minimum. diff --git a/internal/quotagraph/graph.go b/internal/quotagraph/graph.go index 0188cce..991f471 100644 --- a/internal/quotagraph/graph.go +++ b/internal/quotagraph/graph.go @@ -230,12 +230,8 @@ func Project(mode Mode, window codex.Window, points []Point, now time.Time) (Tre type Segment struct{ X1, Y1, X2, Y2 float64 } -func (t Trend) Segment(pace bool) (Segment, bool) { +func (t Trend) Segment() (Segment, bool) { slope, lower, upper := t.Slope, 0.0, 100.0 - if pace { - slope-- - lower = -100 - } x1, x2 := t.Start, 100.0 if slope != 0 { a, b := (lower-t.Intercept)/slope, (upper-t.Intercept)/slope diff --git a/internal/quotagraph/graph_test.go b/internal/quotagraph/graph_test.go index b7c95f6..ea0c00b 100644 --- a/internal/quotagraph/graph_test.go +++ b/internal/quotagraph/graph_test.go @@ -20,14 +20,10 @@ func TestWindowStartUsesSnapshotWithoutHistory(t *testing.T) { if !ok || trend.Slope != .5 || trend.Projected != 50 || trend.Start != 0 || trend.Intercept != 0 { t.Fatalf("origin projection: %+v %v", trend, ok) } - zone, ok := trend.Segment(false) + zone, ok := trend.Segment() if !ok || zone != (Segment{0, 0, 100, 50}) { t.Fatalf("zone segment: %+v %v", zone, ok) } - pace, ok := trend.Segment(true) - if !ok || pace != (Segment{0, 0, 100, -50}) { - t.Fatalf("pace segment: %+v %v", pace, ok) - } w.UsedPercent = 0 if trend, ok = Project(WindowStart, w, nil, now); !ok || trend.Projected != 0 { t.Fatal("zero consumption should have a safe projection") @@ -79,19 +75,18 @@ func TestRecentRegressionRequiresContinuousCoverage(t *testing.T) { func TestTrendClipping(t *testing.T) { for _, test := range []struct { trend Trend - pace bool want Segment }{ - {Trend{Slope: 2}, false, Segment{0, 0, 50, 100}}, - {Trend{Slope: 3}, true, Segment{0, 0, 50, 100}}, - {Trend{Slope: 1, Intercept: -20, Start: 10}, false, Segment{20, 0, 100, 80}}, + {Trend{Slope: 2}, Segment{0, 0, 50, 100}}, + {Trend{Slope: 4}, Segment{0, 0, 25, 100}}, + {Trend{Slope: 1, Intercept: -20, Start: 10}, Segment{20, 0, 100, 80}}, } { - got, ok := test.trend.Segment(test.pace) + got, ok := test.trend.Segment() if !ok || got != test.want { t.Fatalf("clip %+v: %+v %v", test, got, ok) } } - if _, ok := (Trend{Intercept: 200}).Segment(false); ok { + if _, ok := (Trend{Intercept: 200}).Segment(); ok { t.Fatal("horizontal line outside plot should be omitted") } } diff --git a/internal/ui/english_snapshot_test.go b/internal/ui/english_snapshot_test.go index 18a35a6..bfab44d 100644 --- a/internal/ui/english_snapshot_test.go +++ b/internal/ui/english_snapshot_test.go @@ -36,10 +36,10 @@ func TestEnglishPresentationSnapshot(t *testing.T) { } } got := fmt.Sprintf("%x", hash.Sum(nil)) - // Baseline includes Pace/Zone graph controls, explicit panel/border + // Baseline includes Pace graph controls, explicit panel/border // backgrounds and Sessions Zero/Close All; every theme, view and size // remains covered. - const want = "07592d4740f0a32a45f7dd70c153e889f4101e5793e33cb61daf35c0a4edd34c" + const want = "19ec27af5176579e3145b5af72749d86f293f9ab00e7d3358970eeee0b513e50" if got != want { t.Fatalf("English presentation changed: got %s, want %s", got, want) } diff --git a/internal/ui/meters.go b/internal/ui/meters.go index 801cb7e..a025cf3 100644 --- a/internal/ui/meters.go +++ b/internal/ui/meters.go @@ -16,7 +16,7 @@ import ( func usesMeterGrid(view meterViewID) bool { switch view { - case viewBars, viewPie, viewPace, viewZone, viewFuel: + case viewBars, viewPie, viewPace, viewFuel: return true default: return false @@ -188,7 +188,7 @@ func renderMeterArea(width, height int, meter codex.Meter, view meterViewID, col if len(graphs) > 0 { options = graphs[0] } - visual = renderQuotaPlot(innerWidth, visualHeight, meter.Window, now, view == viewPace, options, colors) + visual = renderQuotaPlot(innerWidth, visualHeight, meter.Window, now, options, colors) } gaugeWidth := min(max(lipgloss.Width(visual), 1), innerWidth) resetGauge := renderResetGauge(innerWidth, gaugeWidth, meter.Window, now, reset, color, colors) @@ -314,9 +314,7 @@ func renderVisualizationSized(width, height, used int, view meterViewID, color i case viewPie: return renderPieSized(width, height, used, color, colors) case viewPace: - return renderQuotaPlot(width, height, codex.Window{}, time.Now(), true, quotaPlotOptions{}, colors) - case viewZone: - return renderQuotaPlot(width, height, codex.Window{}, time.Now(), false, quotaPlotOptions{}, colors) + return renderQuotaPlot(width, height, codex.Window{}, time.Now(), quotaPlotOptions{}, colors) case viewFuel: return renderFuelTankSized(width, height, used, color, colors) case viewBars: diff --git a/internal/ui/meters_test.go b/internal/ui/meters_test.go index f9b0918..93ff086 100644 --- a/internal/ui/meters_test.go +++ b/internal/ui/meters_test.go @@ -12,7 +12,7 @@ import ( "github.com/merefield/codexometer/internal/codex" ) -var quotaMeterViews = []meterViewID{viewBars, viewPace, viewZone, viewPie, viewFuel} +var quotaMeterViews = []meterViewID{viewBars, viewPace, viewPie, viewFuel} func TestEveryMeterViewHasDistinctiveOutput(t *testing.T) { colors := paletteFor(themeHacker) @@ -23,7 +23,6 @@ func TestEveryMeterViewHasDistinctiveOutput(t *testing.T) { {viewBars, "█"}, {viewPie, "BRAILLE PIE"}, {viewPace, "GRAPH DATA UNAVAILABLE"}, - {viewZone, "GRAPH DATA UNAVAILABLE"}, {viewFuel, "RANGE"}, } for _, test := range tests { diff --git a/internal/ui/preferences.go b/internal/ui/preferences.go index 562ccb7..5155703 100644 --- a/internal/ui/preferences.go +++ b/internal/ui/preferences.go @@ -145,7 +145,7 @@ func reverseThemePreferences(values map[themeID]string) map[string]themeID { } var quotaViewPreferenceNames = map[meterViewID]string{ - viewBars: "bars", viewPie: "pie", viewPace: "pace", viewZone: "zone", viewFuel: "fuel-tank", viewResets: "resets", viewThresholds: "thresholds", + viewBars: "bars", viewPie: "pie", viewPace: "pace", viewFuel: "fuel-tank", viewResets: "resets", viewThresholds: "thresholds", } var quotaViewPreferenceIDs = reverseViewPreferences(quotaViewPreferenceNames) @@ -155,9 +155,10 @@ func reverseViewPreferences(values map[meterViewID]string) map[string]meterViewI for id, value := range values { reversed[value] = id } - // Preserve the previous Consumption Pace preference after the rename. + // Restore previous graph selections to the former Zone, now named Pace. if _, ok := values[viewPace]; ok { reversed["consumption-pace"] = viewPace + reversed["zone"] = viewPace } return reversed } diff --git a/internal/ui/quota_graph.go b/internal/ui/quota_graph.go index 4711743..f90145b 100644 --- a/internal/ui/quota_graph.go +++ b/internal/ui/quota_graph.go @@ -14,7 +14,7 @@ import ( "github.com/merefield/codexometer/internal/quotagraph" ) -func isQuotaGraph(view meterViewID) bool { return view == viewPace || view == viewZone } +func isQuotaGraph(view meterViewID) bool { return view == viewPace } type quotaPlotOptions struct { points []quotagraph.Point @@ -105,14 +105,10 @@ type quotaPlotCell struct { type quotaCanvas struct { width, height int - pace bool cells []quotaPlotCell } func (c quotaCanvas) position(x, y float64) (int, int) { - if c.pace { - y = (y + 100) / 2 - } return int(math.Round(x / 100 * float64(c.width*2-1))), int(math.Round((1 - y/100) * float64(c.height*4-1))) } @@ -166,7 +162,7 @@ func quotaFieldColor(risk float64) color.Color { return color.RGBA{R: uint8(float64(amber.R)*(1-weight) + float64(end.R)*weight), G: uint8(float64(amber.G)*(1-weight) + float64(end.G)*weight), B: uint8(float64(amber.B)*(1-weight) + float64(end.B)*weight), A: 255} } -func renderQuotaPlot(width, height int, window codex.Window, now time.Time, pace bool, options quotaPlotOptions, colors palette) string { +func renderQuotaPlot(width, height int, window codex.Window, now time.Time, options quotaPlotOptions, colors palette) string { width = max(width, 1) if height <= 0 { height = 10 @@ -177,9 +173,6 @@ func renderQuotaPlot(width, height int, window codex.Window, now time.Time, pace } used := float64(max(0, min(100, window.UsedPercent))) status := i18n.Format("%.0f%% USED // %.1f%% TIME", used, elapsed) - if pace { - status = i18n.Format("%+.1f PP FROM SAFETY", used-elapsed) - } trend, projected := quotagraph.Project(options.mode, window, options.points, now) trendInk := colors.dim if projected { @@ -191,9 +184,6 @@ func renderQuotaPlot(width, height int, window codex.Window, now time.Time, pace projection := "" if projected { projection = i18n.Format("TREND // %.1f%% AT RESET", trend.Projected) - if pace { - projection = i18n.Format("TREND // %+.1f PP AT RESET", trend.Projected-100) - } } else if options.mode != quotagraph.Off { projection = i18n.Text("TREND UNAVAILABLE") } @@ -203,54 +193,35 @@ func renderQuotaPlot(width, height int, window codex.Window, now time.Time, pace return quotaPlotFit([]string{status, projection}, width, height) } plotWidth, plotHeight := width-6, height-4 - canvas := quotaCanvas{width: plotWidth, height: plotHeight, pace: pace, cells: make([]quotaPlotCell, plotWidth*plotHeight)} - value := func(x, y float64) float64 { - if pace { - return y - x - } - return y - } + canvas := quotaCanvas{width: plotWidth, height: plotHeight, cells: make([]quotaPlotCell, plotWidth*plotHeight)} guide := lipgloss.Color("#708276") - canvas.line(0, 0, 100, value(100, 100), guide, 1, 0) + canvas.line(0, 0, 100, 100, guide, 1, 0) if !options.hideTrace { for i, point := range options.points { if i > 0 && !point.Break { before := options.points[i-1] - canvas.line(before.Elapsed, value(before.Elapsed, float64(before.Used)), point.Elapsed, value(point.Elapsed, float64(point.Used)), lipgloss.Color("#BAD4C7"), 2, 0) + canvas.line(before.Elapsed, float64(before.Used), point.Elapsed, float64(point.Used), lipgloss.Color("#BAD4C7"), 2, 0) } } if len(options.points) > 0 { p := options.points[0] - canvas.mark(p.Elapsed, value(p.Elapsed, float64(p.Used)), '○', guide, 2) + canvas.mark(p.Elapsed, float64(p.Used), '○', guide, 2) } } if projected { - if segment, ok := trend.Segment(pace); ok { + if segment, ok := trend.Segment(); ok { canvas.line(segment.X1, segment.Y1, segment.X2, segment.Y2, trendInk, 3, 0) } } - canvas.mark(elapsed, value(elapsed, used), '●', lipgloss.Color("#FFFFFF"), 4) + canvas.mark(elapsed, used, '●', lipgloss.Color("#FFFFFF"), 4) caption := i18n.Text("CONSUMPTION") - if pace { - caption = i18n.Text("DISTANCE FROM SAFETY (PP)") - } lines := []string{colors.dimmed().Render(ansi.Truncate(caption, width, ""))} for row := 0; row < plotHeight; row++ { label := " " if row == 0 { - if pace { - label = "+100" - } else { - label = "100%" - } + label = "100%" } else if row == plotHeight-1 { - if pace { - label = "-100" - } else { - label = " 0%" - } - } else if row == plotHeight/2 && pace { - label = " 0" + label = " 0%" } var line strings.Builder line.WriteString(colors.dimmed().Render(label + "│")) @@ -259,9 +230,6 @@ func renderQuotaPlot(width, height int, window codex.Window, now time.Time, pace x := float64(col) / float64(max(plotWidth-1, 1)) y := 1 - float64(row)/float64(max(plotHeight-1, 1)) risk := y - x - if pace { - risk = 2*y - 1 - } style := lipgloss.NewStyle().Background(quotaFieldColor(risk)) r := ' ' if cell.mask != 0 { diff --git a/internal/ui/quota_graph_test.go b/internal/ui/quota_graph_test.go index 0275671..54f9f55 100644 --- a/internal/ui/quota_graph_test.go +++ b/internal/ui/quota_graph_test.go @@ -21,17 +21,15 @@ func graphWindow(now time.Time, used int) codex.Window { func TestQuotaPlotsFitResponsiveRectangles(t *testing.T) { now := time.Unix(1800000000, 0) - for _, pace := range []bool{false, true} { - for _, width := range []int{1, 9, 17, 18, 30, 80, 140} { - for _, height := range []int{1, 2, 5, 6, 12, 30} { - for _, used := range []int{0, 25, 75, 100} { - out := renderQuotaPlot(width, height, graphWindow(now, used), now, pace, quotaPlotOptions{}, paletteFor(themeHacker)) - if lipgloss.Width(out) > width || lipgloss.Height(out) != height { - t.Fatalf("pace=%v %dx%d used=%d rendered %dx%d", pace, width, height, used, lipgloss.Width(out), lipgloss.Height(out)) - } - if width >= 18 && height >= 6 && !strings.Contains(out, "●") { - t.Fatal("current dot missing") - } + for _, width := range []int{1, 9, 17, 18, 30, 80, 140} { + for _, height := range []int{1, 2, 5, 6, 12, 30} { + for _, used := range []int{0, 25, 75, 100} { + out := renderQuotaPlot(width, height, graphWindow(now, used), now, quotaPlotOptions{}, paletteFor(themeHacker)) + if lipgloss.Width(out) > width || lipgloss.Height(out) != height { + t.Fatalf("%dx%d used=%d rendered %dx%d", width, height, used, lipgloss.Width(out), lipgloss.Height(out)) + } + if width >= 18 && height >= 6 && !strings.Contains(out, "●") { + t.Fatal("current dot missing") } } } @@ -41,28 +39,25 @@ func TestQuotaPlotsFitResponsiveRectangles(t *testing.T) { func TestQuotaPlotAxesAndProjection(t *testing.T) { now := time.Unix(1800000000, 0) w := graphWindow(now, 25) - zone := ansi.Strip(renderQuotaPlot(60, 15, w, now, false, quotaPlotOptions{}, paletteFor(themeHacker))) - pace := ansi.Strip(renderQuotaPlot(60, 15, w, now, true, quotaPlotOptions{}, paletteFor(themeHacker))) + pace := ansi.Strip(renderQuotaPlot(60, 15, w, now, quotaPlotOptions{}, paletteFor(themeHacker))) for _, want := range []string{"100%", "TIME ELAPSED", "25% USED // 50.0% TIME", "50.0% AT RESET"} { - if !strings.Contains(zone, want) { - t.Fatalf("Zone missing %q:\n%s", want, zone) - } - } - for _, want := range []string{"+100", "-100", "-25.0 PP FROM SAFETY", "-50.0 PP AT RESET"} { if !strings.Contains(pace, want) { t.Fatalf("Pace missing %q:\n%s", want, pace) } } - for _, graph := range []string{zone, pace} { - if strings.ContainsAny(graph, "↗↘▸") { - t.Fatal("terminal graph still contains trend arrows") + for _, removed := range []string{"+100", "-100", "PP FROM SAFETY", "PP AT RESET", "DISTANCE FROM SAFETY"} { + if strings.Contains(pace, removed) { + t.Fatalf("removed graph transform still present: %q", removed) } } - off := ansi.Strip(renderQuotaPlot(60, 15, w, now, false, quotaPlotOptions{mode: quotagraph.Off}, paletteFor(themeHacker))) - if strings.Join(strings.Split(zone, "\n")[1:12], "\n") == strings.Join(strings.Split(off, "\n")[1:12], "\n") { + if strings.ContainsAny(pace, "↗↘▸") { + t.Fatal("terminal graph still contains trend arrows") + } + off := ansi.Strip(renderQuotaPlot(60, 15, w, now, quotaPlotOptions{mode: quotagraph.Off}, paletteFor(themeHacker))) + if strings.Join(strings.Split(pace, "\n")[1:12], "\n") == strings.Join(strings.Split(off, "\n")[1:12], "\n") { t.Fatal("removing arrows also removed the trend line") } - if strings.Contains(renderQuotaPlot(60, 15, w, now, true, quotaPlotOptions{mode: quotagraph.Off}, paletteFor(themeHacker)), "AT RESET") { + if strings.Contains(renderQuotaPlot(60, 15, w, now, quotaPlotOptions{mode: quotagraph.Off}, paletteFor(themeHacker)), "AT RESET") { t.Fatal("Off still rendered projection") } } @@ -71,31 +66,26 @@ func TestQuotaUnavailableTrendIsMuted(t *testing.T) { now := time.Unix(1800000000, 0) for theme := themeHacker; theme < themeCount; theme++ { colors := paletteFor(theme) - for _, pace := range []bool{false, true} { - for _, options := range []quotaPlotOptions{{mode: quotagraph.HalfHour}, {mode: quotagraph.Hour}, {mode: quotagraph.Day}} { - out := renderQuotaPlot(60, 15, graphWindow(now, 25), now, pace, options, colors) - if got, want := strings.Split(out, "\n")[14], colors.dimmed().Render("TREND UNAVAILABLE"); got != want { - t.Fatalf("theme=%v pace=%v mode=%v unavailable trend is not muted: %q", theme, pace, options.mode, got) - } + for _, options := range []quotaPlotOptions{{mode: quotagraph.HalfHour}, {mode: quotagraph.Hour}, {mode: quotagraph.Day}} { + out := renderQuotaPlot(60, 15, graphWindow(now, 25), now, options, colors) + if got, want := strings.Split(out, "\n")[14], colors.dimmed().Render("TREND UNAVAILABLE"); got != want { + t.Fatalf("theme=%v mode=%v unavailable trend is not muted: %q", theme, options.mode, got) } - for _, test := range []struct { - used int - ink string - projected float64 - }{ - {25, "#45DB79", 50}, - {50, "#45DB79", 100}, - {75, "#9D2537", 150}, - } { - out := renderQuotaPlot(60, 15, graphWindow(now, test.used), now, pace, quotaPlotOptions{}, colors) - text := fmt.Sprintf("TREND // %.1f%% AT RESET", test.projected) - if pace { - text = fmt.Sprintf("TREND // %+.1f PP AT RESET", test.projected-100) - } - want := lipgloss.NewStyle().Foreground(lipgloss.Color(test.ink)).Render(text) - if got := strings.Split(out, "\n")[14]; got != want { - t.Fatalf("valid projection lost its endpoint colour: %q", got) - } + } + for _, test := range []struct { + used int + ink string + projected float64 + }{ + {25, "#45DB79", 50}, + {50, "#45DB79", 100}, + {75, "#9D2537", 150}, + } { + out := renderQuotaPlot(60, 15, graphWindow(now, test.used), now, quotaPlotOptions{}, colors) + text := fmt.Sprintf("TREND // %.1f%% AT RESET", test.projected) + want := lipgloss.NewStyle().Foreground(lipgloss.Color(test.ink)).Render(text) + if got := strings.Split(out, "\n")[14]; got != want { + t.Fatalf("valid projection lost its endpoint colour: %q", got) } } } @@ -105,55 +95,47 @@ func TestQuotaLinesUseDenseBrailleWithoutDashGaps(t *testing.T) { now := time.Unix(1800000000, 0) w := graphWindow(now, 75) const width, height = 60, 15 - for _, pace := range []bool{false, true} { - out := ansi.Strip(renderQuotaPlot(width, height, w, now, pace, quotaPlotOptions{hideTrace: true}, paletteFor(themeHacker))) - if strings.ContainsAny(out, "╭╮╰╯↗↘▸") { - t.Fatal("dense Braille graph contains box-drawing elbows or arrows") - } - trend, ok := quotagraph.Project(quotagraph.WindowStart, w, nil, now) - if !ok { - t.Fatal("missing test projection") - } - segment, ok := trend.Segment(pace) - if !ok { - t.Fatal("missing test segment") - } - canvas := quotaCanvas{width: width - 6, height: height - 4, pace: pace, cells: make([]quotaPlotCell, (width-6)*(height-4))} - guideEnd := 100.0 - if pace { - guideEnd = 0 - } - canvas.line(0, 0, 100, guideEnd, nil, 1, 0) - canvas.line(segment.X1, segment.Y1, segment.X2, segment.Y2, nil, 3, 0) - elapsed, _ := quotagraph.Elapsed(w, now) - y := float64(w.UsedPercent) - if pace { - y -= elapsed - } - canvas.mark(elapsed, y, '●', nil, 4) - lines := strings.Split(out, "\n") - for row := 0; row < canvas.height; row++ { - runes := []rune(lines[row+1]) - for col := 0; col < canvas.width; col++ { - cell := canvas.cells[row*canvas.width+col] - if cell.priority > 0 && cell.priority < 4 && runes[col+5] != rune(0x2800+cell.mask) { - t.Fatalf("pace=%v line priority=%d has a gap at %d,%d", pace, cell.priority, col, row) - } + out := ansi.Strip(renderQuotaPlot(width, height, w, now, quotaPlotOptions{hideTrace: true}, paletteFor(themeHacker))) + if strings.ContainsAny(out, "╭╮╰╯↗↘▸") { + t.Fatal("dense Braille graph contains box-drawing elbows or arrows") + } + trend, ok := quotagraph.Project(quotagraph.WindowStart, w, nil, now) + if !ok { + t.Fatal("missing test projection") + } + segment, ok := trend.Segment() + if !ok { + t.Fatal("missing test segment") + } + canvas := quotaCanvas{width: width - 6, height: height - 4, cells: make([]quotaPlotCell, (width-6)*(height-4))} + guideEnd := 100.0 + canvas.line(0, 0, 100, guideEnd, nil, 1, 0) + canvas.line(segment.X1, segment.Y1, segment.X2, segment.Y2, nil, 3, 0) + elapsed, _ := quotagraph.Elapsed(w, now) + y := float64(w.UsedPercent) + canvas.mark(elapsed, y, '●', nil, 4) + lines := strings.Split(out, "\n") + for row := 0; row < canvas.height; row++ { + runes := []rune(lines[row+1]) + for col := 0; col < canvas.width; col++ { + cell := canvas.cells[row*canvas.width+col] + if cell.priority > 0 && cell.priority < 4 && runes[col+5] != rune(0x2800+cell.mask) { + t.Fatalf("line priority=%d has a gap at %d,%d", cell.priority, col, row) } } } } func TestQuotaCanvasPreservesDotAndDirection(t *testing.T) { - c := quotaCanvas{width: 20, height: 10, pace: true, cells: make([]quotaPlotCell, 200)} - _, above := c.position(50, 25) - _, below := c.position(50, -25) + c := quotaCanvas{width: 20, height: 10, cells: make([]quotaPlotCell, 200)} + _, above := c.position(50, 75) + _, below := c.position(50, 25) if above >= below { - t.Fatal("positive pace must appear above safety") + t.Fatal("greater consumption must appear above safety") } - c.mark(50, 0, '●', nil, 4) - c.line(0, 0, 100, 0, nil, 3, 0) - px, py := c.position(50, 0) + c.mark(50, 50, '●', nil, 4) + c.line(0, 0, 100, 100, nil, 3, 0) + px, py := c.position(50, 50) if c.cells[(py/4)*c.width+px/2].symbol != '●' { t.Fatal("trend overwrote the current dot") } @@ -163,7 +145,7 @@ func TestQuotaCanvasPreservesDotAndDirection(t *testing.T) { } func TestQuotaGraphButtonsTrackRenderedSurfaces(t *testing.T) { - for _, view := range []meterViewID{viewPace, viewZone} { + for _, view := range []meterViewID{viewPace} { for _, width := range []int{24, 40, 80, 120} { m := Model{snapshot: codex.DemoSnapshot(), meterView: view, width: width, height: 30} layout := m.dashboardLayout() @@ -240,18 +222,23 @@ func TestQuotaGraphRefreshCollectionIsIndependentOfSelectedTab(t *testing.T) { } } -func TestQuotaGraphPreferencesPreserveRenameAndNewView(t *testing.T) { - for saved, want := range map[string]meterViewID{"consumption-pace": viewPace, "pace": viewPace, "zone": viewZone} { - m := Model{} +func TestQuotaGraphPreferencesRestoreFormerZoneAsPace(t *testing.T) { + for saved, want := range map[string]meterViewID{"consumption-pace": viewPace, "pace": viewPace, "zone": viewPace} { + store := &memoryPreferenceStore{} + m := Model{preferenceStore: store} m.applyPreferences(Preferences{QuotaView: saved}) - if m.meterView != want { + if m.meterView != want || m.quotaMeterView != want || quotaViewPreferenceNames[want] != "pace" { t.Fatalf("saved %q restored %v", saved, m.meterView) } + m.persistPreferences() + if store.preferences.QuotaView != "pace" { + t.Fatalf("saved alias %q was not canonicalised", saved) + } } } func TestQuotaGraphsUseMultipleColumnsOnlyWhenReadable(t *testing.T) { - for _, view := range []meterViewID{viewPace, viewZone} { + for _, view := range []meterViewID{viewPace} { if meterGridColumns(36, 24, 4, view) != 1 || meterGridColumns(80, 24, 4, view) != 2 || meterGridColumns(160, 30, 4, view) != 4 { t.Fatal("graph grid does not adapt to available width and window count") } diff --git a/internal/ui/tabs.go b/internal/ui/tabs.go index d23fd0a..4492062 100644 --- a/internal/ui/tabs.go +++ b/internal/ui/tabs.go @@ -92,10 +92,10 @@ func mainTabLayout(width int, showMonitorLight bool) ([]mainTab, string) { func quotaViewTabLayout(width int, thresholds ...bool) ([]viewTab, string) { order := append([]meterViewID(nil), quotaViewOrder[:]...) tiers := [][]string{ - {i18n.Text("╭ BARS ╮"), i18n.Text("╭ PACE ╮"), i18n.Text("╭ ZONE ╮"), i18n.Text("╭ PIE ╮"), i18n.Text("╭ FUEL TANK ╮"), i18n.Text("╭ RESETS ╮")}, - {"╭BAR╮", "╭PACE╮", "╭ZONE╮", "╭PIE╮", "╭FUEL╮", "╭RST╮"}, - {"[B]", "[C]", "[Z]", "[P]", "[F]", "[R]"}, - {"B", "C", "Z", "P", "F", "R"}, + {i18n.Text("╭ BARS ╮"), i18n.Text("╭ PACE ╮"), i18n.Text("╭ PIE ╮"), i18n.Text("╭ FUEL TANK ╮"), i18n.Text("╭ RESETS ╮")}, + {"╭BAR╮", "╭PACE╮", "╭PIE╮", "╭FUEL╮", "╭RST╮"}, + {"[B]", "[C]", "[P]", "[F]", "[R]"}, + {"B", "C", "P", "F", "R"}, } if len(thresholds) > 0 && thresholds[0] { order = append(order, viewThresholds) diff --git a/internal/ui/tabs_test.go b/internal/ui/tabs_test.go index 59d2cf2..8595ac3 100644 --- a/internal/ui/tabs_test.go +++ b/internal/ui/tabs_test.go @@ -44,7 +44,7 @@ func TestMainTabsChooseResponsiveLabels(t *testing.T) { func TestThresholdTabOnlyAppearsWithConfiguredSteps(t *testing.T) { without, _ := quotaViewTabLayout(160, false) with, _ := quotaViewTabLayout(160, true) - if len(without) != 6 || len(with) != 7 || with[6].view != viewThresholds || with[5].view != viewResets { + if len(without) != 5 || len(with) != 6 || with[5].view != viewThresholds || with[4].view != viewResets { t.Fatal("Thresholds must follow Resets only when configured") } m := Model{meterView: viewResets, quotaSteps: []codex.QuotaStep{{Threshold: 80}}} @@ -110,7 +110,7 @@ func TestQuotaViewTabsChooseResponsiveLabels(t *testing.T) { if !strings.Contains(labels.String(), test.want) { t.Fatalf("width %d labels %q do not contain %q", test.width, labels.String(), test.want) } - if len(tabs) >= 4 && (tabs[1].view != viewPace || !strings.Contains(tabs[1].label, test.want) || tabs[2].view != viewZone || tabs[3].view != viewPie) { + if len(tabs) >= 4 && (tabs[1].view != viewPace || !strings.Contains(tabs[1].label, test.want) || tabs[2].view != viewPie) { t.Fatalf("width %d tab order/labels do not match views: %#v", test.width, tabs) } }) @@ -226,7 +226,7 @@ func TestQuotaStyleIsRememberedAcrossMainTabNavigation(t *testing.T) { func TestVSelectsQuotaViewAndMonitorShortcutsStayScoped(t *testing.T) { model := Model{meterView: viewBars} - for _, want := range []meterViewID{viewPace, viewZone, viewPie, viewFuel, viewResets, viewBars} { + for _, want := range []meterViewID{viewPace, viewPie, viewFuel, viewResets, viewBars} { updated, command := model.Update(key('v')) model = updated.(Model) if command == nil || model.meterView != want || model.quotaMeterView != want || model.flashedButton != footerButtonView { diff --git a/internal/ui/theme.go b/internal/ui/theme.go index a472bbe..93592bb 100644 --- a/internal/ui/theme.go +++ b/internal/ui/theme.go @@ -35,14 +35,12 @@ const ( viewUsage viewResets viewThresholds - viewZone viewCount ) var quotaViewOrder = [...]meterViewID{ viewBars, viewPace, - viewZone, viewPie, viewFuel, viewResets, @@ -83,7 +81,6 @@ func (s meterViewID) name() string { i18n.Text("USAGE"), i18n.Text("RESETS"), i18n.Text("THRESHOLDS"), - i18n.Text("ZONE"), }[s] } diff --git a/internal/ui/view_test.go b/internal/ui/view_test.go index e8e0600..7148212 100644 --- a/internal/ui/view_test.go +++ b/internal/ui/view_test.go @@ -318,7 +318,7 @@ func TestPieViewPlacesQuotaWindowsSideBySide(t *testing.T) { } func TestGaugeGridViewClassification(t *testing.T) { - for _, view := range []meterViewID{viewBars, viewPie, viewPace, viewZone, viewFuel} { + for _, view := range []meterViewID{viewBars, viewPie, viewPace, viewFuel} { if got := usesMeterGrid(view); !got { t.Errorf("usesMeterGrid(%s) = false, want true", view.name()) } diff --git a/internal/web/dist/assets/index-4j3sNB-h.css b/internal/web/dist/assets/index-4j3sNB-h.css deleted file mode 100644 index 0e4c2d8..0000000 --- a/internal/web/dist/assets/index-4j3sNB-h.css +++ /dev/null @@ -1 +0,0 @@ -.observation-details.svelte-1wk8llw{font-size:12px}summary.svelte-1wk8llw{cursor:pointer;color:var(--accent)}.observation-table.svelte-1wk8llw{max-height:240px;overflow:auto}.zone-canvas.svelte-1wk8llw{flex:1;min-height:170px;margin-top:6px;position:relative}svg.svelte-1wk8llw{width:100%;height:100%;display:block;position:absolute;inset:0}text.svelte-1wk8llw{fill:var(--ink);font:14px Cascadia Code,Consolas,monospace}.axis-title.svelte-1wk8llw{letter-spacing:.04em;font-size:12px}.safe-label.svelte-1wk8llw{fill:#fff;font-size:11px}.grid.svelte-1wk8llw{stroke:#fff;stroke-opacity:.14;stroke-width:1px}.axes.svelte-1wk8llw{stroke:var(--ink);stroke-width:1.5px;fill:none}.pace-line.svelte-1wk8llw{stroke:#fff;stroke-width:2px;stroke-dasharray:6 4}.position-halo.svelte-1wk8llw{fill:#101820;stroke:#fff;stroke-width:1.5px}.position-dot.svelte-1wk8llw{fill:#fff}.observation-trail.svelte-1wk8llw{fill:none;stroke:#101820;stroke-width:2.5px;stroke-linejoin:round}.observation-trail-casing.svelte-1wk8llw{fill:none;stroke:#ffffff73;stroke-width:4.5px;stroke-linejoin:round}.trail-start.svelte-1wk8llw{fill:#101820;stroke:#ffffffb3;stroke-width:2px}.trend-line.svelte-1wk8llw{fill:none;stroke:var(--trend-color);stroke-width:2px;stroke-dasharray:3 6}.trend-arrow.svelte-1wk8llw{fill:var(--trend-color);stroke:#ffffff73;stroke-width:.5px}.trend-casing.svelte-1wk8llw{fill:none;stroke:#ffffff73;stroke-width:4px;stroke-dasharray:3 6}.zone-caption.svelte-1wk8llw{min-width:0;color:var(--accent);flex:auto;margin:0}.trend-summary.svelte-1wk8llw{color:var(--ink)}.zone-footer.svelte-1wk8llw{justify-content:space-between;align-items:flex-start;gap:12px;margin-top:4px;display:flex}.zone-controls.svelte-1wk8llw{color:var(--muted);text-align:right;flex-direction:column;align-items:flex-end;gap:5px;font-size:11px;display:flex}.trace-control.svelte-1wk8llw,.trend-control.svelte-1wk8llw{cursor:pointer;white-space:nowrap}.trace-control.svelte-1wk8llw input:where(.svelte-1wk8llw){accent-color:var(--accent)}.trend-control.svelte-1wk8llw select:where(.svelte-1wk8llw){border:1px solid var(--edge);background:var(--panel);max-width:min(230px,45vw);color:var(--ink);font:inherit}.trend-control.svelte-1wk8llw option:where(.svelte-1wk8llw):disabled{color:var(--muted)}.zone-controls.svelte-1wk8llw small:where(.svelte-1wk8llw){font-size:10px}@container (width<=560px){.zone-footer.svelte-1wk8llw{flex-direction:column}.zone-controls.svelte-1wk8llw{align-self:stretch;align-items:flex-end}}.slash-commands.svelte-7bfwr9{margin:.4rem 0;position:relative}.command-popup.svelte-7bfwr9{z-index:5;box-sizing:border-box;border:1px solid var(--accent);background:var(--panel);width:min(40rem,100%);padding:.35rem;position:absolute;bottom:100%;left:0;box-shadow:0 .3rem 1rem #0006}.command-popup.svelte-7bfwr9 p:where(.svelte-7bfwr9){margin:.3rem 0;font-size:.8em}.command-options.vertical.svelte-7bfwr9{flex-flow:column;gap:.15rem;display:flex}.vertical.svelte-7bfwr9 button:where(.svelte-7bfwr9){text-align:left;white-space:nowrap;width:100%;min-width:0;color:var(--muted);background:var(--panel);border-color:#0000;flex:none;align-items:baseline;gap:.4rem;display:flex}.vertical.svelte-7bfwr9 .command-name:where(.svelte-7bfwr9),.vertical.svelte-7bfwr9 .command-tail:where(.svelte-7bfwr9){flex:none}.vertical.svelte-7bfwr9 .command-name:where(.svelte-7bfwr9){text-overflow:ellipsis;max-width:100%;overflow:hidden}.vertical.svelte-7bfwr9 button.suggested:where(.svelte-7bfwr9){outline:none}.vertical.svelte-7bfwr9 button.suggested:where(.svelte-7bfwr9) .command-name:where(.svelte-7bfwr9),.vertical.svelte-7bfwr9 button:where(.svelte-7bfwr9):hover .command-name:where(.svelte-7bfwr9){background:var(--accent);color:var(--bg)}.vertical.svelte-7bfwr9 .command-help:where(.svelte-7bfwr9){min-width:0;max-width:none;color:var(--muted);flex:1}.command-options.svelte-7bfwr9{flex-wrap:wrap;gap:.35rem;max-height:35vh;display:flex;overflow:auto}.command-options.svelte-7bfwr9 .suggested:where(.svelte-7bfwr9){outline:1px solid var(--accent)}.command-help.svelte-7bfwr9{text-overflow:ellipsis;white-space:nowrap;opacity:.75;max-width:32ch;font-size:.8em;display:block;overflow:hidden}pre.svelte-7bfwr9{white-space:pre-wrap;overflow-wrap:anywhere;max-height:35vh;overflow:auto}.file-diff.svelte-x4gtb6{border:1px solid var(--muted);max-height:60vh;padding:.5rem;font-family:monospace;overflow:auto}.diff-line.svelte-x4gtb6{white-space:pre;min-height:1.3em;display:flex}.line-number.svelte-x4gtb6{text-align:right;opacity:.75;-webkit-user-select:none;user-select:none;flex:0 0 5ch;padding-right:1ch;display:inline-block}.added.svelte-x4gtb6{color:#67d391;background:#67d39112}.removed.svelte-x4gtb6{color:#ff6b83;background:#ff6b8312}.heading.svelte-x4gtb6{padding:.5rem 0;font-weight:700}.saved-prompt.svelte-1oupzfc{white-space:pre-wrap;overflow-wrap:anywhere}fieldset.svelte-1oupzfc{border:1px solid;margin:.5rem 0;padding:.35rem .6rem}.decision.svelte-1oupzfc,.answer.svelte-1oupzfc{margin:.3rem 0;display:block}.decision.svelte-1oupzfc code:where(.svelte-1oupzfc),.decision.svelte-1oupzfc span:where(.svelte-1oupzfc){overflow-wrap:anywhere;margin:.3rem 0 .3rem 1.5rem;display:block}textarea.svelte-1oupzfc,.answer.svelte-1oupzfc input:where(.svelte-1oupzfc),.answer.svelte-1oupzfc select:where(.svelte-1oupzfc){box-sizing:border-box;background:var(--bg);width:100%;color:inherit;font:inherit;border:1px solid;margin-top:.4rem;padding:.5rem;display:block}textarea.svelte-1oupzfc{resize:vertical;background:color-mix(in srgb, currentColor 8%, var(--bg))}button.svelte-1oupzfc{margin:.3rem .5rem .3rem 0}h3.svelte-1oupzfc,p.svelte-1oupzfc{margin-block:.4rem}.sent.svelte-1oupzfc{color:var(--accent)}.status-line.svelte-gprptn{align-items:center;gap:.5rem;min-width:0;margin-top:.5rem;display:flex}.status-line.svelte-gprptn p:where(.svelte-gprptn){white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;margin:0;font-size:.8rem;overflow:hidden}.configure.svelte-gprptn{padding:.15rem .35rem;font-size:.75rem}.status-picker.svelte-gprptn{border:1px solid var(--edge);margin:.5rem 0;padding:.6rem}.fields.svelte-gprptn{max-height:35vh;overflow:auto}.field.svelte-gprptn{align-items:center;gap:.35rem;display:flex}.field.svelte-gprptn label:where(.svelte-gprptn){flex:1;align-items:center;gap:.4rem;display:flex}.field.svelte-gprptn label:where(.svelte-gprptn) span:where(.svelte-gprptn){font-size:.75rem}.field.svelte-gprptn button:where(.svelte-gprptn){padding:.1rem .35rem}.session-copy.svelte-543j00{justify-content:flex-end;align-items:center;gap:8px;margin-top:auto;padding-top:6px;display:flex}span.svelte-543j00{color:var(--muted);overflow-wrap:anywhere;font-size:12px}button.svelte-543j00{color:var(--accent);flex-shrink:0;padding:3px 7px}button.svelte-543j00:hover,button.flashed.svelte-543j00{color:var(--bg);background:var(--accent)}h3.svelte-1fbui7h,.window-dates.svelte-1fbui7h,.report-value.svelte-1fbui7h{color:var(--accent);font-weight:700}.quality-warning.svelte-1fbui7h,.quota-near.svelte-1fbui7h{color:var(--approval)}.quota-full.svelte-1fbui7h{color:#ff6680}.alternate.svelte-1fbui7h .report-fill:where(.svelte-1fbui7h){background:radial-gradient(circle, var(--panel) .7px, transparent .9px) 0 0 / 3px 3px, var(--accent)}.unknown.svelte-1fbui7h,.unknown.svelte-1fbui7h .report-value:where(.svelte-1fbui7h){color:var(--muted)}.unknown.svelte-1fbui7h .report-fill:where(.svelte-1fbui7h){background:var(--muted);opacity:1}.report-bars.svelte-1fbui7h{grid-template-columns:minmax(5rem,1fr) minmax(2rem,3fr) auto;gap:.6rem;display:grid}.report-row.svelte-1fbui7h,.report-head.svelte-1fbui7h{grid-column:1/-1;grid-template-columns:subgrid;align-items:center;gap:.6rem;display:grid}.report-head.svelte-1fbui7h{color:var(--muted);font-size:.85rem}.report-head.svelte-1fbui7h>span:where(.svelte-1fbui7h):last-child,.report-value.svelte-1fbui7h{text-align:right}.report-row.svelte-1fbui7h>span:where(.svelte-1fbui7h):first-child{overflow-wrap:anywhere}.report-track.svelte-1fbui7h{background:var(--panel);height:1rem}.report-fill.svelte-1fbui7h{background:var(--accent);height:100%}:root{font-synthesis:none;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;background:#080e0c;font-family:Cascadia Code,SFMono-Regular,Consolas,monospace}*{box-sizing:border-box}body{margin:0}.shell{--accent:#80edac;--approval:#ffca58;--muted:#98aaa0;--edge:#31473a;--panel:#101c16;--bg:#080e0c;--ink:#e2eee5;background:var(--bg);height:100dvh;color:var(--ink);grid-template-rows:auto auto minmax(0,1fr) auto;padding:clamp(10px,1.2vw,20px);display:grid}.shell[data-theme=rust]{--approval:#ff8a3d;--accent:#ffbc75;--muted:#bfac95;--edge:#59412c;--panel:#261b14;--bg:#140e0a}.shell[data-theme=blue-steel]{--approval:#e8c46a;--accent:#85c8ff;--muted:#9cacc4;--edge:#334d69;--panel:#142235;--bg:#0b1421}.shell[data-theme=ultraviolet]{--approval:#f9a8d4;--accent:#c5adff;--muted:#b3a6c9;--edge:#4b3c68;--panel:#241a35;--bg:#140d22}.shell[data-theme=nightshade]{--approval:#8f7cff;--accent:#e59bff;--muted:#c6a7cf;--edge:#673976;--panel:#301739;--bg:#1c0b24}header,.spread,footer,.controls{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:10px;display:flex}header{margin-bottom:10px}.brand{letter-spacing:.08em;color:var(--accent);text-shadow:0 0 22px color-mix(in srgb, var(--accent) 20%, transparent);font-size:clamp(22px,2.5vw,32px);font-weight:800;text-decoration:none}header p{color:var(--muted);margin:3px 0 0;font-size:13px}.connection{color:var(--accent);text-align:right}small,.eyebrow{letter-spacing:.04em;font-size:12px}.connection small{color:var(--muted);margin-top:4px;display:block}.lamp{background:var(--muted);border-radius:50%;width:9px;height:9px;margin-right:9px;display:inline-block}.lamp.lit{background:var(--accent);box-shadow:0 0 8px color-mix(in srgb, var(--accent) 40%, transparent)}.working{animation:1.5s ease-in-out infinite pulse}@keyframes pulse{50%{opacity:.3}}nav{flex-wrap:wrap;gap:6px;margin-bottom:10px;display:flex}nav a,button,.button,select{font:inherit;color:var(--accent);border:1px solid var(--edge);background:var(--panel);cursor:pointer;border-radius:3px;padding:7px 11px;font-size:13px;text-decoration:none}button:hover,.button:hover,nav a:hover{border-color:var(--accent)}nav a.active,nav button.active{background:var(--accent);color:var(--bg);border-color:var(--accent)}:focus-visible{outline:2px solid var(--accent);outline-offset:4px}.secondary{margin-bottom:8px}.secondary a,.secondary button{padding:6px 10px;font-size:12px}main{scrollbar-gutter:stable;flex-direction:column;min-width:0;min-height:0;display:flex;overflow:auto}main>*{flex-shrink:0}.panel{border:1px solid var(--edge);border-top:2px solid var(--accent);background:var(--panel);border-radius:4px;min-width:0;padding:clamp(10px,1vw,16px)}h1{color:var(--accent);font-size:20px}h2{letter-spacing:.04em;color:var(--accent);overflow-wrap:anywhere;margin:0 0 10px;font-size:13px}h3{overflow-wrap:anywhere;font-size:13px}p{margin:6px 0;font-size:13px;line-height:1.45}a{color:var(--accent)}.muted,.eyebrow{color:var(--muted)}.notice{color:#ffe0aa;background:#332611;border-left:3px solid #ffc26e;padding:12px 16px}.empty{color:var(--muted);padding:35px 0}.quota-grid{flex:1 0 auto;grid-auto-rows:minmax(220px,1fr);gap:10px;display:grid}.quota-card{flex-direction:column;min-height:0;display:flex;container-type:inline-size}.quota-card>:not(.meter-graphic){flex-shrink:0}.meter-graphic{flex-direction:column;flex:1;min-height:100px;display:flex}.bar-graphic{min-height:65px}.quota-card .gauge{flex:2;height:auto;min-height:16px;margin:7px 0}.quota-card .timeline{flex:1;min-height:8px}.quota-grid.zone{grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr));grid-auto-rows:minmax(330px,1fr)}.quota-grid.radial{grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));grid-auto-rows:minmax(260px,1fr)}.gauge{background:var(--edge);height:35px;margin:15px 0;overflow:hidden}.gauge>div{background:repeating-linear-gradient(90deg, var(--accent) 0, var(--accent) 9px, transparent 9px, transparent 12px);height:100%;transition:width .5s}.gauge.timeline{height:14px}.pie-wrap{flex:1;min-height:100px;margin:6px 0;position:relative}.pie-wrap svg{width:100%;height:100%;position:absolute;inset:0}.pie-base{fill:var(--edge);stroke:var(--accent);stroke-width:1px}.pie-fill{fill:var(--accent)}.readout{overflow-wrap:anywhere;color:var(--accent);margin:18px 0;font-size:clamp(22px,3vw,34px)}.credit+.credit{border-top:1px solid var(--edge);padding-top:20px}.credit{margin-top:24px}.session-row{grid-template-columns:minmax(210px,1.1fr) minmax(0,1.2fr) minmax(0,1.5fr);align-items:stretch;gap:14px;margin:18px 0;display:grid}.session-totals{grid-template-columns:repeat(auto-fit,minmax(min(145px,100%),1fr));gap:8px;margin:8px 0;display:grid}.session-totals>div{border:1px solid var(--edge);min-width:0;padding:10px}.session-totals dt{color:var(--muted);font-size:11px}.session-totals dd{color:var(--accent);overflow-wrap:anywhere;margin:6px 0 0;font-size:24px}.session-totals.stale dd{color:var(--muted)}.session-row.selected{outline:1px solid var(--accent);outline-offset:4px}.session-row.wide .context{grid-column:2/-1}.detail-controls{flex-wrap:wrap;gap:6px;display:flex}.attention-summary{flex-wrap:wrap;gap:8px;margin-block:8px;display:flex}.attention-summary .approval{color:var(--approval);border-color:var(--approval)}.attention-summary .approval:hover{background:color-mix(in srgb, var(--approval) 12%, var(--panel))}.attention-summary .approval:focus-visible{outline-color:var(--approval)}.attention-note,.attention-badge{color:var(--accent);border-left:3px solid;padding-left:8px}.attention-note.inferred{color:var(--muted)}.attention-badge{font-size:12px}.session-select{text-align:left;overflow-wrap:anywhere;max-width:100%}.status-detail{color:inherit;text-decoration:none}.status-detail:hover{text-decoration:underline}button:disabled{opacity:.4;cursor:default}.session-row .graph-panel{flex-direction:column;grid-column:2/-1;display:flex}.session-row.split .graph-panel{grid-column:auto}.session-row .button,.session-row button{margin-top:8px;display:inline-block}.context pre{max-height:230px;overflow:auto}.session-row .context{flex-direction:column;display:flex}pre{font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:1.7}.full-detail{margin-top:6px}.detail-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;display:flex}.detail-heading h2{flex:250px;min-width:0;margin:0}.detail-metadata{overflow-wrap:anywhere}.detail-workspace{border-top:1px solid var(--edge);flex-direction:column;gap:10px;margin-top:8px;padding-top:4px;display:flex}.detail-context,.detail-workspace .session-actions{min-width:0}.detail-workspace .session-actions{border-top:1px solid var(--edge);padding-top:6px}.full-detail h3{margin-block:8px}.full-detail pre{margin-block:8px;line-height:1.5}.full-detail hr{margin-block:12px}.full-detail .command,.full-detail .notice{padding:8px 10px}.command{background:var(--bg);border-left:3px solid var(--accent);padding:16px}hr{border:0;border-top:1px solid var(--edge);margin:24px 0}.chart{border-bottom:1px solid var(--muted);align-items:flex-end;gap:2px;height:clamp(120px,22vh,320px);margin-top:18px;display:flex}.chart-bar{background:var(--accent);flex:1;min-width:0;max-height:100%}.controls{justify-content:flex-start;margin:20px 0}.summary-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:16px;margin:20px 0;display:grid}.thresholds-panel{padding:clamp(14px,2vw,22px)}.thresholds-panel h1{margin-top:0}.threshold-list{gap:8px;margin-top:16px;display:grid}.threshold-list article{border:1px solid var(--edge);grid-template-columns:minmax(64px,.5fr) minmax(220px,3fr) minmax(64px,.6fr) minmax(120px,1.2fr);align-items:center;gap:12px;padding:10px 12px;display:grid}.threshold-list article.active{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}.threshold-list article.next{border-color:var(--approval);box-shadow:inset 3px 0 0 var(--approval)}.threshold-list p{color:var(--muted);margin:3px 0 0;font-size:12px}.threshold-trigger{color:var(--accent);font-size:22px;font-weight:800}.threshold-mode,.threshold-state{color:var(--muted);font-size:12px;font-weight:700}.threshold-list article.active .threshold-state{color:var(--accent)}.threshold-list article.next .threshold-state{color:var(--approval)}.heat-scroll{overflow-x:auto}.heatmap{grid-template-rows:repeat(7,13px);grid-auto-columns:minmax(9px,1fr);grid-auto-flow:column;gap:4px;min-width:620px;margin:25px 0;display:grid}.heat-cell{background:var(--accent);border-radius:2px}.heat-cell.zero{background:var(--edge)}.table-scroll{max-height:280px;overflow:auto}table{border-collapse:collapse;width:100%;margin-top:15px}th,td{text-align:left;border-bottom:1px solid var(--edge);padding:8px}summary{cursor:pointer;color:var(--accent);padding-top:14px}footer{border-top:1px solid var(--edge);color:var(--muted);margin-top:8px;padding-top:8px;font-size:11px}footer select{padding:6px}@media (width<=850px){.session-row{grid-template-columns:minmax(0,1fr)}.session-row.wide .context,.session-row .graph-panel{grid-column:auto}.connection{text-align:left}.threshold-list article{grid-template-columns:64px minmax(0,1fr)}.threshold-mode,.threshold-state{grid-column:2}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none!important;animation:none!important}} diff --git a/internal/web/dist/assets/index-E1h87Zp5.js b/internal/web/dist/assets/index-E1h87Zp5.js deleted file mode 100644 index 14933af..0000000 --- a/internal/web/dist/assets/index-E1h87Zp5.js +++ /dev/null @@ -1,45 +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){return e()}function m(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}function g(e,t,n=!1){return e===void 0?n?t():t:e}function _(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 v=1024,y=2048,b=4096,x=8192,S=16384,C=32768,w=1<<25,T=65536,E=1<<19,ee=1<<20,D=1<<25,O=1<<21,te=1<<22,k=1<<23,ne=Symbol(`$state`),re=Symbol(`component`),ie=Symbol(`legacy props`),ae=Symbol(``),oe=Symbol(`attributes`),se=Symbol(`class`),ce=Symbol(`style`),le=Symbol(`text`),ue=Symbol(`form reset`),de=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},fe=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),pe={},me=Symbol(`uninitialized`),he=`http://www.w3.org/1999/xhtml`;function ge(){console.warn(`https://svelte.dev/e/derived_inert`)}function _e(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function ve(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function ye(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var A=!1;function be(e){A=e}var j;function xe(e){if(e===null)throw _e(),pe;return j=e}function Se(){return xe(sn(j))}function M(e){if(A){if(sn(j)!==null)throw _e(),pe;j=e}}function Ce(e=1){if(A){for(var t=e,n=j;t--;)n=sn(n);j=n}}function we(e=!0){for(var t=0,n=j;;){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=sn(n);e&&n.remove(),n=i}}function Te(e){if(!e||e.nodeType!==8)throw _e(),pe;return e.data}function Ee(e){return e===this.v}function De(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function Oe(e){return!De(e,this.v)}function ke(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function Ae(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function je(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function Me(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function Ne(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Pe(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function Fe(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Ie(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function Le(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Re(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function ze(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function Be(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var Ve=!1;function He(){Ve=!0}var N=null;function Ue(e){N=e}function We(e,t=!1,n){N={p:N,i:!1,c:null,e:null,s:e,x:null,r:W,l:Ve&&!t?{s:null,u:null,$:[]}:null}}function Ge(e){var t=N,n=t.e;if(n!==null){t.e=null;for(var r of n)bn(r)}return e!==void 0&&(t.x=e),t.i=!0,N=t.p,Ke(e)}function Ke(e={}){return i(e,re,{value:!0}),e}function qe(){return!Ve||N!==null&&N.l===null}var Je=[];function Ye(){var e=Je;Je=[],m(e)}function Xe(e){if(Je.length===0&&!wt){var t=Je;queueMicrotask(()=>{t===Je&&Ye()})}Je.push(e)}function Ze(){for(;Je.length>0;)Ye()}var Qe=~(y|b|v);function $e(e,t){e.f=e.f&Qe|t}function et(e){e.f&512||e.deps===null?$e(e,v):$e(e,b)}function tt(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),$e(e,v)}function nt(e){A&&on(e)!==null&&cn(e)}var rt=!1;function it(){rt||(rt=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[ue]?.()})},{capture:!0}))}function at(e){var t=U,n=W;Wn(null),Gn(null);try{return e()}finally{Wn(t),Gn(n)}}function ot(e,t,n,r=n){e.addEventListener(t,()=>at(n));let i=e[ue];e[ue]=i?()=>{i(),r(!0)}:()=>r(!0),it()}function st(e,t,n,r){let i=qe()?dt:mt;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=W,c=ct(),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){pn(e,s)}lt()}}var d=ut();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>pt(e))).then(u).catch(e=>pn(e,s)).finally(d)}l?l.then(()=>{c(),f(),lt()}):f()}function ct(){var e=W,t=U,n=N,r=F;return function(i=!0){Gn(e),Wn(t),Ue(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function lt(e=!0){Gn(null),Wn(null),Ue(null),e&&F?.deactivate()}function ut(){var e=W,t=e.b,n=F,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 dt(e){var t=2|y;return W!==null&&(W.f|=E),{ctx:N,deps:null,effects:null,equals:Ee,f:t,fn:e,reactions:null,rv:0,v:me,wv:0,parent:W,ac:null}}var ft=Symbol(`obsolete`);function pt(e,t,n){let r=W;r===null&&Ae();var i=void 0,a=Vt(me),o=!U,s=new Set;return wn(()=>{var t=W,n=h();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==de&&n.reject(e)}).finally(lt)}catch(e){n.reject(e),lt()}var c=F;if(o){if(t.f&32768)var l=ut();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(ft);else for(let e of s.values())e.reject(ft);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==ft&&(c.activate(),t?(a.f|=k,Gt(a,t)):(a.f&8388608&&(a.f^=k),Gt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),vn(()=>{for(let e of s)e.reject(ft)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function P(e){let t=dt(e);return qn(t),t}function mt(e){let t=dt(e);return t.equals=Oe,t}function ht(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(de),t.ac=null}),t.fn!==null&&(t.teardown=f),cr(t,0),kn(t))}function yt(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&lr(t)}var bt=null,F=null,xt=null,St=null,Ct=null,wt=!1,Tt=!1,Et=null,Dt=null,Ot=0,kt=1,At=class e{id=kt++;#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(){bt===null?bt=this:(bt.#n=this,this.#t=bt),bt=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)$e(r,y),t(r);for(r of n.m)$e(r,b),t(r)}this.#p.add(e)}#g(){var e=[];for(let i of this.#c)if(!(i.f&16384||!(i.f&6144))){for(var t=i,n=!1;t.parent!==null;){t=t.parent;var r=t.f;if(r&96){if(!(r&1024)){n=!0;break}t.f^=v}}n||e.push(t)}return this.#c=[],e}#_(){this.#e=!0;for(let e of this.#u)this.#d.delete(e),$e(e,y),this.schedule(e);for(let e of this.#d)$e(e,b),this.schedule(e);this.apply();for(var t=Et=[],n=[],r=Dt=[];this.#c.length>0;){Ot++>1e3&&(this.#S(),Mt());for(let e of this.#g())try{this.#v(e,t,n)}catch(t){throw Lt(e),this.#h()||this.discard(),t}}if(F=null,r.length>0){var i=e.ensure();for(let e of r)i.schedule(e)}if(Et=null,Dt=null,this.#h()){this.#x(n),this.#x(t);for(let[e,t]of this.#f)It(e,t);r.length>0&&F.#_();return}let a=this.#y();if(a){this.#x(n),this.#x(t),a.#b(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),xt=this,Pt(n),Pt(t),xt=null,this.#s?.resolve();var o=F;if(this.#a===0&&(this.#c.length===0||o!==null)&&this.#S(),this.#c.length>0){if(o!==null){for(let e of this.#c)o.#c.push(e);this.#c=[]}else o=this}o!==null&&(zt.clear(),o.#_())}#v(e,t,n){e.f^=v;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^=v:i&4?t.push(r):rr(r)&&(i&16&&this.#d.add(r),lr(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}}}#y(){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}#b(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),$e(i,y),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#S(),F=this,this.#_()}#x(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??=h()).promise}static ensure(){if(F===null){let t=F=new e;!Tt&&!wt&&Xe(()=>{t.#e||t.flush()})}return F}apply(){St=null}schedule(e){if(Ct=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}this.#c.push(e)}#S(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?bt=e:t.#t=e,this.linked=!1}}};function jt(e){var t=wt;wt=!0;try{var n;for(e&&(F!==null&&!F.is_fork&&F.flush(),n=e());;){if(Ze(),F===null)return n;F.flush()}}finally{wt=t}}function Mt(){try{Fe()}catch(e){pn(e,Ct)}}var Nt=null;function Pt(e){var t=e.length;if(t!==0){for(var n=0;n0)){zt.clear();for(let e of Nt){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Nt.has(n)&&(Nt.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||lr(n)}}Nt.clear()}}Nt=null}}function Ft(e){F.schedule(e)}function It(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),$e(e,v);for(var n=e.first;n!==null;)It(n,t),n=n.next}}function Lt(e){$e(e,v);for(var t=e.first;t!==null;)Lt(t),t=t.next}var Rt=new Set,zt=new Map,Bt=!1;function Vt(e,t){return{f:0,v:e,reactions:null,equals:Ee,rv:0,wv:0}}function I(e,t){let n=Vt(e,t);return qn(n),n}function Ht(e,t=!1,n=!0){let r=Vt(e);return t||(r.equals=Oe),Ve&&n&&N!==null&&N.l!==null&&(N.l.s??=[]).push(r),r}function L(e,t,n=!1){return U!==null&&(!Un||U.f&131072)&&qe()&&U.f&4325394&&(Kn===null||!Kn.has(e))&&ze(),Gt(e,n?Xt(t):t,Dt)}var Ut=null,Wt=0;function Gt(e,t,n=null){if(!e.equals(t)){Vn?zt.set(e,t):zt.has(e)||zt.set(e,e.v);var r=At.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&>(t),St===null&&et(t)}e.wv=nr(),Ut=null,Wt=0,Yt(e,y,n),Ut=null,qe()&&W!==null&&W.f&1024&&!(W.f&96)&&(Xn===null?Zn([e]):Xn.push(e)),!r.is_fork&&Rt.size>0&&!Bt&&Kt()}return t}function Kt(){Bt=!1;for(let e of Rt){e.f&1024&&$e(e,b);let t;try{t=rr(e)}catch{t=!0}t&&lr(e)}Rt.clear()}function qt(e,t=1){var n=G(e),r=t===1?n++:n--;return L(e,n),r}function Jt(e){L(e,e.v+1)}function Yt(e,t,n){var r=e.reactions;if(r!==null){var i=qe(),a=r.length;if(Wt+=a,Wt>1e5&&Ut===null&&(Ut=new Set),Ut!==null){if(Ut.has(e))return;Ut.add(e)}for(var o=0;o{if(er===d)return e();var t=U,n=er;Wn(null),tr(d);var r=e();return Wn(t),tr(n),r};return i&&r.set(`length`,I(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&Le();var i=r.get(t);return i===void 0?f(()=>{var e=I(n.value,u);return r.set(t,e),e}):L(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>I(me,u));r.set(t,e),Jt(o)}}else L(n,me),Jt(o);return!0},get(e,n,i){if(n===ne)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>I(Xt(s?e[n]:me),u)),r.set(n,o)),o!==void 0){var c=G(o);return c===me?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){this.has?.(e,t);var n=Reflect.getOwnPropertyDescriptor(e,t),i=r.get(t);if(i!==void 0){var a=G(i);if(a===me)return;if(n&&`value`in n)n.value=a;else return{enumerable:!0,configurable:!0,value:a,writable:!0}}return n},has(e,t){if(t===ne)return!0;var n=r.get(t),i=n!==void 0&&n.v!==me||Reflect.has(e,t);return(n!==void 0||W!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>I(i?Xt(e[t]):me,u)),r.set(t,n)),G(n)===me)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dI(me,u)),r.set(d+``,p)):L(p,me)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>I(void 0,u)),L(c,Xt(n)),r.set(t,c));else{l=c.v!==me;var m=f(()=>Xt(n));L(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&&L(g,_+1)}Jt(o)}return!0},ownKeys(e){G(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==me});for(var[n,i]of r)i.v!==me&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Re()}})}function Zt(e){try{if(typeof e==`object`&&e&&ne in e)return e[ne]}catch{}return e}function Qt(e,t){return Object.is(Zt(e),Zt(t))}var $t,en,tn,nn;function rn(){if($t===void 0){$t=window,en=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;tn=a(t,`firstChild`).get,nn=a(t,`nextSibling`).get,u(e)&&(e[se]=void 0,e[oe]=null,e[ce]=void 0,e.__e=void 0),u(n)&&(n[le]=void 0)}}function an(e=``){return document.createTextNode(e)}function on(e){return tn.call(e)}function sn(e){return nn.call(e)}function R(e,t){if(!A)return on(e);var n=on(j);if(n===null)n=j.appendChild(an());else if(t&&n.nodeType!==3){var r=an();return n?.before(r),xe(r),r}return t&&dn(n),xe(n),n}function z(e,t=!1){if(!A){var n=on(e);return n instanceof Comment&&n.data===``?sn(n):n}if(t){if(j?.nodeType!==3){var r=an();return j?.before(r),xe(r),r}dn(j)}return j}function B(e,t=!1){if(!A)return on(e);var n=R(e,t);return M(e),n}function V(e,t=1,n=!1){let r=A?j:e;for(var i;t--;)i=r,r=sn(r);if(!A)return r;if(n){if(r?.nodeType!==3){var a=an();return r===null?i?.after(a):r.before(a),xe(a),a}dn(r)}return xe(r),r}function cn(e){e.textContent=``}function ln(){return!1}function un(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 dn(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 fn(e){var t=W;if(t===null)return U.f|=k,e;if(!(t.f&32768)&&!(t.f&4))throw e;pn(e,t)}function pn(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 mn(e){W===null&&(U===null&&Pe(e),Ne()),Vn&&Me(e)}function hn(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function gn(e,t){var n=W;n!==null&&n.f&8192&&(e|=x);var r={ctx:N,deps:null,nodes:null,f:e|y|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};F?.register_created_effect(r);var i=r;if(e&4)Et===null?At.ensure().schedule(r):Et.push(r);else if(t!==null){try{lr(r)}catch(e){throw jn(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|=T))}if(i!==null&&(i.parent=n,n!==null&&hn(i,n),U!==null&&U.f&2&&!(e&64))){var a=U;(a.effects??=[]).push(i)}return r}function _n(){return U!==null&&!Un}function vn(e){let t=gn(8,null);return $e(t,v),t.teardown=e,t}function yn(e){mn(`$effect`);var t=W.f;if(!U&&t&32&&N!==null&&!N.i){var n=N;(n.e??=[]).push(e)}else return bn(e)}function bn(e){return gn(4|ee,e)}function xn(e){return mn(`$effect.pre`),gn(8|ee,e)}function Sn(e){At.ensure();let t=gn(64|E,e);return(e={})=>new Promise(n=>{e.outro?Pn(t,()=>{jn(t),n(void 0)}):(jn(t),n(void 0))})}function Cn(e){return gn(4,e)}function wn(e){return gn(te|E,e)}function Tn(e,t=0){return gn(8|t,e)}function H(e,t=[],n=[],r=[]){st(r,t,n,t=>{gn(8,()=>{e(...t.map(G))})})}function En(e,t=0){return gn(16|t,e)}function Dn(e){return gn(32|E,e)}function On(e){var t=e.teardown;if(t!==null){let n=Vn,r=U;Hn(!0),Wn(null);try{t.call(null)}catch(t){pn(t,e.parent)}finally{Hn(n),Wn(r)}}}function kn(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&at(()=>{e.abort(de)});var r=n.next;n.f&64?n.parent=null:jn(n,t),n=r}}function An(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||jn(t),t=n}}function jn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Mn(e.nodes.start,e.nodes.end),n=!0),e.f|=w,kn(e,t&&!n),cr(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();On(e),e.f^=w,e.f|=S;var i=e.parent;i!==null&&i.first!==null&&Nn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Mn(e,t){for(;e!==null;){var n=e===t?null:sn(e);e.remove(),e=n}}function Nn(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 Pn(e,t,n=!0){var r=[];e.f|=256,Fn(e,r,!0);var i=()=>{n&&jn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function Fn(e,t,n){if(!(e.f&8192)){e.f^=x;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);Fn(i,t,o?n:!1)}i=a}}}function In(e){e.f&=-257,Ln(e,!0)}function Ln(e,t){if(!(e.f&256)&&e.f&8192){e.f^=x,e.f&1024||($e(e,y),At.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Ln(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 Rn(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:sn(n);t.append(n),n=i}}var zn=null,Bn=!1,Vn=!1;function Hn(e){Vn=e}var U=null,Un=!1;function Wn(e){U=e}var W=null;function Gn(e){W=e}var Kn=null;function qn(e){U!==null&&(U.f&2097152||U.f&2)&&(Kn??=new Set).add(e)}var Jn=null,Yn=0,Xn=null;function Zn(e){Xn=e}var Qn=1,$n=0,er=$n;function tr(e){er=e}function nr(){return++Qn}function rr(e){var t=e.f;if(t&2048)return!0;if(t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&&St===null&&$e(e,v)}return!1}function ir(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Kn!==null&&Kn.has(e)))for(var i=0;i{e.ac.abort(de)}),e.ac=null);try{e.f|=O;var u=e.fn,d=u();e.f|=C;var f=or(e);if(qe()&&Xn!==null&&!Un&&f!==null&&!(e.f&6146))for(var p=0;p0)for(t.length=Yn+Jn.length,r=0;r{s.ac.abort(de),s.ac=null,$e(s,y)}),vt(s),cr(s,0)}}function cr(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`?(i.__removed=!1,Xe(()=>{i.__removed||t.addEventListener(e,i,r)})):t.addEventListener(e,i,r),i}function Sr(e,t,n,r,i){var a={capture:r,passive:i},o=xr(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&vn(()=>{o.__removed=!0,t.removeEventListener(e,o,a)})}function K(e,t,n){(t[vr]??={})[e]=n}function Cr(e){for(var t=0;t{Tr=!1,wr=null}));var s=0,c=wr===e&&e[vr];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[vr]=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=U,f=W;Wn(null),Gn(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[vr]?.[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[vr]=t,delete e.currentTarget,Wn(d),Gn(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=un(`template`);return t.innerHTML=Or(e.replaceAll(``,``)),t.content}function Ar(e,t){var n=W;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function q(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(A)return Ar(j,null),j;i===void 0&&(i=kr(a?e:``+e),n||(i=on(i)));var t=r||en?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=on(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(A)return Ar(j,null),j;if(!o){var e=on(kr(a));if(i)for(o=document.createDocumentFragment();on(e);)o.appendChild(on(e));else o=on(e)}var t=o.cloneNode(!0);if(i){var n=on(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(!A){var t=an(e+``);return Ar(t,t),t}var n=j;return n.nodeType===3?dn(n):(n.before(n=an()),xe(n)),Ar(n,n),n}function Pr(){if(A)return Ar(j,null),j;var e=document.createDocumentFragment(),t=document.createComment(``),n=an();return e.append(t,n),Ar(t,n),e}function J(e,t){if(A){var n=W;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=j),Se();return}e!==null&&e.before(t)}function Fr(){if(A&&j&&j.nodeType===8&&j.textContent?.startsWith(`$`)){let e=j.textContent.substring(1);return Se(),e}return(window.__svelte??={}).uid??=1,`c${window.__svelte.uid++}`}function Ir(e){let t=0,n=Vt(0),r;return()=>{_n()&&(G(n),Tn(()=>(t===0&&(r=pr(()=>e(()=>Jt(n)))),t+=1,()=>{Xe(()=>{--t,t===0&&(r?.(),r=void 0,Jt(n))})})))}}var Lr=T|E;function Rr(e,t,n,r){new zr(e,t,n,r)}var zr=class{parent;is_pending=!1;transform_error;#e;#t=A?j: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=Vt(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=W;t.b=this,t.f|=128,n(e)},this.parent=W.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=En(()=>{if(A){let e=this.#t;Se();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),A&&(this.#e=j)}#g(){try{this.#a=Dn(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Xe(r),t&&(this.#s=Dn(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){ye();return}t=!0,n&&Be(),this.#s!==null&&Pn(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){pn(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=Dn(()=>e(this.#e)),Xe(()=>{var e=this.#c=document.createDocumentFragment(),t=an(),n=!1;if(e.append(t),this.#a=this.#S(()=>{try{return Dn(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){pn(e,this.#i.parent)}return null}}),this.#a===null){this.#c=null,n&&this.#x(F);return}this.#u===0&&(this.#e.before(e),this.#c=null,Pn(this.#o,()=>{this.#o=null}),this.#x(F))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=Dn(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();Rn(this.#a,e);let t=this.#n.pending;this.#o=Dn(()=>t(this.#e))}else this.#x(F)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){tt(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=W,n=U,r=N;Gn(this.#i),Wn(this.#i),Ue(this.#i.ctx);try{return At.ensure(),e()}finally{Gn(t),Wn(n),Ue(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&&Pn(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,Xe(()=>{this.#d=!1,this.#m&&Gt(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),G(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;F?.is_fork?(this.#a&&F.skip_effect(this.#a),this.#o&&F.skip_effect(this.#o),this.#s&&F.skip_effect(this.#s),F.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(jn(this.#a),null),this.#o&&=(jn(this.#o),null),this.#s&&=(jn(this.#s),null),A&&(xe(this.#t),Ce(),xe(we()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return Dn(()=>{var r=W;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return pn(e,this.#i.parent),null}}))};Xe(()=>{var t;try{t=this.transform_error(e)}catch(e){pn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>pn(e,this.#i&&this.#i.parent)):n(t)})}};function Y(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[le]??=e.nodeValue)&&(e[le]=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}){rn();var l=void 0,u=Sn(()=>{var s=n??t.appendChild(an());Rr(s,{pending:()=>{}},t=>{We({});var n=N;if(o&&(n.c=o),a&&(i.$$events=a),A&&Ar(t,null),l=e(t,i)||Ke(),A&&(W.nodes.end=j,j===null||j.nodeType!==8||j.data!==`]`))throw _e(),pe;Ge()},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)}br.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)In(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(In(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&&(jn(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();Rn(r,t),t.append(an()),this.#n.set(e,{effect:r,fragment:t})}else jn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),Pn(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)||(jn(n.effect),this.#n.delete(e))};ensure(e,t){var n=F,r=ln();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=an();i.append(a),this.#n.set(e,{effect:Dn(()=>t(a)),fragment:i})}else this.#t.set(e,Dn(()=>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 A&&(this.anchor=j),this.#a(n)}};function X(e,t,n=!1){var r;A&&(r=j,Se());var i=new Wr(e),a=n?T:0;function o(e,t){if(A){var n=Te(r);if(e!==parseInt(n.substring(1))){var a=we();xe(a),i.anchor=a,be(!1),i.ensure(e,t),be(!0);return}}i.ensure(e,t)}En(()=>{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){A&&Se();var r=new Wr(e),i=!qe();En(()=>{var e=t();e!==e&&(e=Gr),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function qr(e,t){return t}function Jr(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;Yr(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;cn(d),d.append(u),e.items.clear()}Yr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Yr(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,Qr(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=D,ei(d,null,c)):In(d):Pn(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:En(()=>{p=G(f);var e=p.length;let t=!1;A&&Te(c)===`[!`!=(e===0)&&(c=we(),xe(c),be(!1),t=!0);for(var r=new Set,u=F,v=ln(),y=0;ys(c)):(d=Dn(()=>s(Xr??=an())),d.f|=D)),e>r.size&&je(``,``,``),A&&e>0&&xe(we()),!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&&be(!0),G(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,A&&(c=j)}function Zr(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function Qr(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=Zr(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 $r(e,t,n,r,i,a,o,s){var c=o&1?o&16?Vt(n):Ht(n,!1,!1):null,l=o&2?Vt(i):null;return{v:c,i:l,e:Dn(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function ei(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=sn(r);if(a.before(r),r===i)return;r=o}}function ti(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function ni(e,t,n){var r;A&&(r=j,Se());var i=new Wr(e);En(()=>{var e=t()??null;if(A&&Te(r)===`[`!=(e!==null)){var a=we();xe(a),i.anchor=a,be(!1),i.ensure(e,e&&(t=>n(t,e))),be(!0);return}i.ensure(e,e&&(t=>n(t,e)))},T)}var ri=[...` -\r\f\xA0\v`];function ii(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||ri.includes(r[o-1]))&&(s===r.length||ri.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function ai(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 oi(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function si(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(oi)),i&&c.push(...Object.keys(i).map(oi));var l=0,u=-1;let t=e.length;for(var d=0;d{t.every(_i)||(`__defaultValue`in e&&fi(e,!1),`__value`in e&&pi(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),vn(()=>{t.disconnect()})}function hi(e,t,n=t){var r=new WeakSet,i=!0;ot(e,`change`,t=>{var i=t?`[selected]`:`:checked`,a;if(e.multiple)a=[].map.call(e.querySelectorAll(i),gi);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&gi(o)}n(a),e.__value=a,F!==null&&r.add(F)}),Cn(()=>{var a=t();if(e===document.activeElement){var o=F;if(r.has(o))return}if(pi(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=gi(s),n(a))}e.__value=a,i=!1})}function gi(e){return`__value`in e?e.__value:e.value}function _i(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 vi=Symbol(`is custom element`),yi=Symbol(`is html`),bi=fe?`link`:`LINK`;function xi(e){if(A){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[ue]=n,Xe(n),it()}}function Si(e,t){var n=Ci(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=Ci(e);A&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===bi)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[ae]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Ti(e).has(t)?e[t]=n:e.setAttribute(t,n))}function Ci(e){return e[oe]??={[vi]:e.nodeName.includes(`-`),[yi]:e.namespaceURI===he}}var wi=new Map;function Ti(e){var t=e.getAttribute(`is`)||e.nodeName,n=wi.get(t);if(n)return n;wi.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 Ei(e,t,n=t){var r=new WeakSet;ot(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=ji(e)?Mi(a):a,n(a),F!==null&&r.add(F),await ur(),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))}}}),(A&&e.defaultValue!==e.value||pr(t)==null&&e.value)&&(n(ji(e)?Mi(e.value):e.value),F!==null&&r.add(F)),Tn(()=>{var n=t();if(e===document.activeElement){var i=F;if(r.has(i))return}ji(e)&&n===Mi(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}var Di=new Set;function Oi(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),ot(n,`change`,()=>{var e=n.__value;a&&(e=Ai(o,e,n.checked)),i(e)},()=>i(a?[]:null)),Tn(()=>{var e=r();if(A&&n.defaultChecked!==n.checked){s=!0;return}a?(e||=[],n.checked=e.includes(n.__value)):n.checked=Qt(n.__value,e)}),vn(()=>{var e=o.indexOf(n);e!==-1&&o.splice(e,1)}),Di.has(o)||(Di.add(o),Xe(()=>{o.sort((e,t)=>e.compareDocumentPosition(t)===4?-1:1),Di.delete(o)})),Xe(()=>{if(s){var e=a?Ai(o,e,n.checked):o.find(e=>e.checked)?.__value;i(e)}})}function ki(e,t,n=t){ot(e,`change`,t=>{n(t?e.defaultChecked:e.checked)}),(A&&e.defaultChecked!==e.checked||pr(t)==null)&&n(e.checked),Tn(()=>{e.checked=!!t()})}function Ai(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 Pi(e,t,n){var r=Ni.observe(e,()=>n(e[t]));Cn(()=>(pr(()=>n(e[t])),r))}function Fi(e,t){return e===t||e?.[ne]===t}function Ii(e=Ke(),t,n,r){var i=N.r,a=W;return Cn(()=>{var o,s;return Tn(()=>{o=s,s=r?.()||[],pr(()=>{Fi(n(...s),e)||(t(e,...s),o&&Fi(n(...o),e)&&t(null,...o))})}),()=>{let r=a;for(;r!==i&&r.parent!==null&&r.parent.f&33554432;)r=r.parent;let o=()=>{s&&Fi(n(...s),e)&&t(null,...s)},c=r.teardown;r.teardown=()=>{o(),c?.()}}}),e}function Li(e,t,n,r,i){var a=()=>{r(n[e])};n.addEventListener(t,a),i?Tn(()=>{n[e]=i()}):a(),(n===document.body||n===window||n===document)&&vn(()=>{n.removeEventListener(t,a)})}function Ri(e=!1){let t=N,n=t.l.u;if(!n)return;let r=()=>mr(t.s);if(e){let e=0,n={},i=dt(()=>{let r=!1,i=t.s;for(let e in i)i[e]!==n[e]&&(n[e]=i[e],r=!0);return r&&e++,e});r=()=>G(i)}n.b.length&&xn(()=>{zi(t,r),m(n.b)}),yn(()=>{let e=pr(()=>n.m.map(p));return()=>{for(let t of e)typeof t==`function`&&t()}}),n.a.length&&yn(()=>{zi(t,r),m(n.a)})}function zi(e,t){if(e.l.s)for(let t of e.l.s)G(t);t()}var Bi=!1;function Vi(e){var t=Bi;try{return Bi=!1,[e(),Bi]}finally{Bi=t}}var Hi={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===ne||t===ie)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 Ui(...e){return new Proxy({props:e},Hi)}function Wi(e,t,n,r){var i=!Ve||!!(n&2),o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=dt(r),G(u)):(l&&(l=!1,c=s?pr(r):r),c);let f;if(o){var p=ne in e||ie in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=Vi(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&Ie(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?dt:mt)(()=>(v=!1,g()));o&&G(y);var b=W;return(function(e,t){if(arguments.length>0){let n=t?G(y):i&&o?Xt(e):e;return L(y,n),v=!0,c!==void 0&&(c=n),e}return Vn&&v||b.f&16384?y.v:G(y)})}function Gi(e){N===null&&ke(`onMount`),Ve&&N.l!==null?qi(N).m.push(e):yn(()=>{let t=pr(e);if(typeof t==`function`)return t})}function Ki(e){N===null&&ke(`onDestroy`),Gi(()=>()=>pr(e))}function qi(e){var t=e.l;return t.u??={a:[],b:[],m:[]}}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);function Ji(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 Yi=new class{#e=I(Xi());get _loc(){return G(this.#e)}set _loc(e){L(this.#e,e)}#t=P(()=>this._loc.location);get _location(){return G(this.#t)}set _location(e){L(this.#t,e)}#n=P(()=>this._loc.querystring);get _querystring(){return G(this.#n)}set _querystring(e){L(this.#n,e)}#r=I(void 0);get _params(){return G(this.#r)}set _params(e){L(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=Xi()}):console.warn(`[svelte-spa-router] window 'window' is not defined, skipping initiation`)}};function Xi(){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 Qi(e,t){We(t,!0);let n=Wi(t,`routes`,19,()=>({})),r=Wi(t,`prefix`,3,``),i=Wi(t,`restoreScrollState`,3,!1),a=Wi(t,`onConditionsFailed`,3,()=>{}),o=Wi(t,`onRouteLoaded`,3,()=>{}),s=Wi(t,`onRouteLoading`,3,()=>{}),c=Wi(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=Ji(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=I(null),f=I(null),p=I({}),m=null,h=null;yn(()=>{history.scrollRestoration=i()?`manual`:`auto`}),yn(()=>{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 ur(),e(t)}yn(()=>{let e=Yi.loc,t=!1;return pr(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=z(v),b=e=>{let t=P(()=>G(d));var n=Pr(),r=z(n),i=e=>{var n=Pr();ni(z(n),()=>G(t),(e,t)=>{t(e,Ui({get params(){return G(f)},get onRouteEvent(){return c()}},()=>G(p)))}),J(e,n)},a=e=>{var n=Pr();ni(z(n),()=>G(t),(e,t)=>{t(e,Ui({get onRouteEvent(){return c()}},()=>G(p)))}),J(e,n)};X(r,e=>{G(f)?e(i):e(a,-1)}),J(e,n)};X(y,e=>{G(d)&&e(b)}),J(e,v),Ge()}var $i=[`bars`,`pace`,`zone`,`pie`,`fuel`,`resets`,`thresholds`],ea=`codexometer.web.preferences.v1`,ta={statusLine:null,tab:`quota`,view:`bars`,selected:``,defaultDetail:0,layouts:[]};function na(){try{let e=JSON.parse(localStorage.getItem(ea)||`null`);return!e||typeof e!=`object`?ta:{statusLine:Array.isArray(e.statusLine)?[...new Set(e.statusLine.filter(e=>typeof e==`string`&&e.length<64))].slice(0,32):null,tab:[`quota`,`sessions`,`usage`].includes(e.tab)?e.tab:`quota`,view:$i.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 ta}}var ra=Xt(na()),ia=Xt({open:!1});function aa(){let e=JSON.stringify(ra);try{localStorage.setItem(ea,e)}catch{}}function oa(){return ra.tab===`quota`?`/quota/`+ra.view:`/`+ra.tab}function sa(e){return ra.layouts.find(t=>t.id===e)?.level??ra.defaultDetail}function ca(e){ra.defaultDetail=e,ra.layouts=[]}function la(e,t){ra.layouts=[...ra.layouts.filter(t=>t.id!==e),{id:e,level:Math.max(0,Math.min(2,t))}].slice(-100)}var $=Xt({data:null,connected:!1,error:``}),ua=e=>e==null?`Unavailable`:e.toLocaleString(`en-GB`),da=e=>!e||String(e).startsWith(`0001-`)?`Not yet available`:new Date(typeof e==`number`?e*1e3:e).toLocaleString(`en-GB`),fa=`codexometer.web.session`,pa=class extends Error{},ma;async function ha(e,t,n){if(!ma||!$.connected||!$.data?.control||$.data.sessionsError)throw Error(`Session controls unavailable. Check the live connection.`);return await ma(e,t,n)}function ga(){let e=new AbortController,t,n=``;ma=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 pa(`Action rejected, expired or changed. Refresh and check Codex; nothing was retried.`);return a.json()};try{n=sessionStorage.getItem(fa)||``}catch{}let r=location.hash,i=r.startsWith(`#pair=`)?r.slice(6):``;(i||!r||r===`#`)&&(history.replaceState(null,``,`/#`+oa()),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(fa,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(fa)}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(),()=>{ma=void 0,e.abort(),clearTimeout(t),$.connected=!1}}He();var _a=q(`

Quota refresh failed. Policy state is based on the last successful - observation.

`),va=q(`

`),ya=q(`

The longest Codex quota window selects one active model profile. ASK - creates a per-session review; AUTO applies the profile on the next - eligible check.

`,1),ba=q(`

No threshold-based model steps were configured at launch.

`);function xa(e,t){We(t,!1),Ri();var n=Pr(),r=z(n),i=e=>{var t=ya(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,_a())};X(i,e=>{$.data.quotaError&&e(a)});var o=V(i,2),s=R(o),c=B(s),l=V(s,4);Z(l,5,()=>$.data.thresholds,qr,(e,t)=>{var n=va();let r;var i=R(n),a=B(i),o=V(i,2),s=R(o),c=B(s,!0),l=B(V(s,2));M(o);var u=V(o,2),d=B(u,!0),f=B(V(u,2));M(n),H((e,i)=>{r=ci(n,1,``,null,r,{active:G(t).state===`ACTIVE`,next:G(t).state===`NEXT`}),Y(a,`${G(t).threshold??``}%`),Y(c,G(t).model),Y(l,`${e??``} REASONING // ${i??``} - SPEED`),Y(d,G(t).mode),Y(f,`${G(t).state??``}${G(t).state===`NEXT`?` // ${G(t).remaining||0} PP TO GO`:``}`)},[()=>G(t).effort.toUpperCase(),()=>G(t).speed.toUpperCase()]),J(e,n)}),M(l),M(o),H(e=>{Y(r,`MODEL STEP POLICY // OBSERVED ${e??``}`),Y(c,`THRESHOLDS // ${$.data.thresholds.length??``} CONFIGURED`)},[()=>da($.data.quotaAt)]),J(e,t)},a=e=>{J(e,ba())};X(r,e=>{$.data?.thresholds?.length?e(i):e(a,-1)}),J(e,n),Ge()}var Sa=Mr(``),Ca=Mr(` `,1),wa=Mr(` `,1),Ta=Mr(`SAFE`),Ea=Mr(` `,1),Da=Mr(` `,1),Oa=q(`
`,1),ka=q(` `),Aa=q(`
Quota observations
Observed atPeriod elapsedConsumedTrail segment
`),ja=q(`
OBSERVATION DATA
`),Ma=q(`
QUOTA PERIOD ELAPSED
`,1);function Na(e,t){let n=Fr();We(t,!0);let r=Wi(t,`trail`,19,()=>[]),i=Wi(t,`paceView`,3,!1),a=I(!1),o=I(!0),s=I(`window`),c=[0,25,50,75,100],l={off:0,halfHour:30,hour:60,day:1440,window:0},u=P(()=>i()?[-100,-50,0,50,100]:c),d=P(()=>i()?-100:0),f=P(()=>i()?200:100),p=I(400),m=I(240),h=P(()=>G(p)-24),g=P(()=>G(m)-48),_=P(()=>Math.max(1,G(h)-48)),v=P(()=>Math.max(1,G(g)-20)),y=P(()=>48+Math.max(0,Math.min(100,t.elapsed))/100*G(_));function b(e){return G(g)-(e-G(d))/G(f)*G(v)}function x(e,t){return i()?e-t:e}let S=P(()=>b(x(t.used,t.elapsed))),C=P(()=>t.used-t.elapsed),w=P(()=>r().map((e,t)=>`${t===0||e.break?`M`:`L`}${48+e.elapsed/100*G(_)} ${b(x(e.used,e.elapsed))}`).join(` `)),T=P(()=>{let e=0;for(let t=r().length-1;t>0;t--)if(r()[t].break){e=t;break}return r().slice(e)}),E=P(()=>G(T).length<2?0:Math.max(0,Date.parse(G(T).at(-1).at)-Date.parse(G(T)[0].at)));function ee(e){if(G(E)Date.parse(e.at)>=t).length>=2}let D=P(()=>({off:!0,halfHour:ee(18e5),hour:ee(36e5),day:ee(864e5),window:Number.isFinite(t.elapsed)&&t.elapsed>0&&Number.isFinite(t.used)}));yn(()=>{G(s)!==`window`&&!G(D)[G(s)]&&L(s,`window`)});function O(e){if(e===`off`||!G(D)[e])return[];let t=l[e]*6e4,n=Date.parse(G(T).at(-1).at)-t,r=G(T).findIndex(e=>Date.parse(e.at)>=n);return r<0?[]:G(T).slice(r)}function te(e){if(e.length<2)return null;let t=e.reduce((e,t)=>e+t.elapsed,0)/e.length,n=e.reduce((e,t)=>e+t.used,0)/e.length,r=0,i=0;for(let a of e)r+=(a.elapsed-t)*(a.used-n),i+=(a.elapsed-t)**2;return i>0?Math.max(0,r/i):null}let k=P(()=>{let e=G(s)===`window`&&G(D).window?t.used/t.elapsed:te(O(G(s)));if(e===null||!t.duration)return null;let n=t.used+e*(100-t.elapsed),r=G(s)===`window`?0:t.used-e*t.elapsed,a=e-+!!i(),o=Math.max(0,t.elapsed-l[G(s)]/t.duration*100);G(s)===`window`&&(o=0);let c=100;if(a!==0){let e=(G(d)-r)/a,t=(G(d)+G(f)-r)/a;o=Math.max(o,Math.min(e,t)),c=Math.min(100,Math.max(e,t))}if(o>c)return null;let u=r+a*o,p=r+a*c,m=Math.hypot((c-o)/100*G(_),(p-u)/G(f)*G(v)),h=Math.max(3,Math.min(9,Math.floor(m/65)+2));return{path:`M${Array.from({length:h},(e,t)=>{let n=o+(c-o)*t/(h-1),r=u+(p-u)*t/(h-1);return`${48+n/100*G(_)} ${b(r)}`}).join(` L`)}`,projected:n,safe:n<=100}}),ne=P(()=>{if(G(T).length===0)return`NO OBSERVATIONS`;if(G(T).length===1)return`ONE OBSERVATION`;let e=Math.floor(G(E)/6e4);if(e<60)return`${e} MIN CONTINUOUS`;let t=Math.floor(e/60);return t<24?`${t}H CONTINUOUS`:`${Math.floor(t/24)}D ${t%24}H CONTINUOUS`});var re=Ma(),ie=z(re),ae=R(ie);let oe;var se=R(ae),ce=R(se),le=V(R(ce)),ue=e=>{J(e,Sa())};X(le,e=>{i()&&e(ue)});var de=V(le);Ce(),M(ce);var fe=V(ce);M(se);var pe=V(se),me=V(pe);Z(me,17,()=>c,qr,(e,t)=>{var n=Ca(),r=z(n),i=V(r),a=B(i);H(()=>{Q(r,`x1`,48+G(t)/100*G(_)),Q(r,`x2`,48+G(t)/100*G(_)),Q(r,`y2`,G(g)),Q(i,`x`,48+G(t)/100*G(_)),Q(i,`y`,G(g)+20),Y(a,`${G(t)??``}%`)}),J(e,n)});var he=V(me);Z(he,17,()=>G(u),qr,(e,t)=>{var n=wa(),r=z(n),a=V(r),o=B(a,!0);H((e,n,s)=>{Q(r,`y1`,e),Q(r,`x2`,G(h)),Q(r,`y2`,n),Q(a,`y`,s),Y(o,i()?`${G(t)>0?`+`:``}${G(t)}`:`${G(t)}%`)},[()=>b(G(t)),()=>b(G(t)),()=>b(G(t))+4]),J(e,n)});var ge=V(he),_e=V(ge),ve=V(_e),ye=e=>{var t=Ta();H(e=>{Q(t,`x`,G(h)-5),Q(t,`y`,e)},[()=>b(0)-6]),J(e,t)};X(ve,e=>{i()&&e(ye)});var A=V(ve),be=e=>{var t=Ea(),n=z(t),i=V(n),a=V(i),o=B(R(a));M(a),H((e,t)=>{Q(n,`d`,G(w)),Q(i,`d`,G(w)),Q(a,`cx`,48+r()[0].elapsed/100*G(_)),Q(a,`cy`,e),Y(o,`First observation: ${t??``}`)},[()=>b(x(r()[0].used,r()[0].elapsed)),()=>da(r()[0].at)]),J(e,t)};X(A,e=>{G(o)&&r().length&&e(be)});var j=V(A),xe=e=>{var t=Da(),r=z(t),i=V(r),a=B(R(i));M(i),H(e=>{Q(r,`d`,G(k).path),Q(i,`d`,G(k).path),Q(i,`marker-mid`,`url(#${n}-trend-arrow)`),Y(a,`${G(s)===`window`?`Window-average pace`:`Recent consumption trajectory`} projects ${e??``}% at reset if continued`)},[()=>G(k).projected.toFixed(1)]),J(e,t)};X(j,e=>{G(k)&&e(xe)});var Se=V(j),we=B(Se,!0),Te=V(Se),Ee=V(Te),De=V(Ee),Oe=B(R(De));M(De),M(ae),M(ie);var ke=V(ie,2),Ae=R(ke),je=R(Ae),Me=e=>{var t=Nr();H(e=>Y(t,`${G(C)>0?`+`:``}${e??``} PP FROM SAFETY`),[()=>G(C).toFixed(1)]),J(e,t)},Ne=e=>{var n=Nr();H(()=>Y(n,`${t.used??``}% - USED`)),J(e,n)};X(je,e=>{i()?e(Me):e(Ne,-1)});var Pe=V(je),Fe=V(Pe,3),Ie=B(Fe,!0),Le=V(Fe,2),Re=e=>{var t=Oa(),n=B(V(z(t)));H(e=>Y(n,`TREND // ${e??``}`),[()=>i()?`${G(k).projected-100>0?`+`:``}${(G(k).projected-100).toFixed(1)} PP AT RESET`:G(k).projected>=100?`QUOTA EXHAUSTION PROJECTED`:`${G(k).projected.toFixed(1)}% PROJECTED AT RESET`]),J(e,t)};X(Le,e=>{G(k)&&e(Re)}),M(Ae);var ze=V(Ae,2),Be=R(ze),Ve=R(Be);xi(Ve),Ce(),M(Be);var He=V(Be,2),N=V(R(He),2),Ue=R(N);Ue.value=Ue.__value=`off`;var Ke=V(Ue),qe=B(Ke);Ke.value=Ke.__value=`halfHour`;var Je=V(Ke),Ye=B(Je);Je.value=Je.__value=`hour`;var Xe=V(Je),Ze=B(Xe);Xe.value=Xe.__value=`day`;var Qe=V(Xe),$e=B(Qe);Qe.value=Qe.__value=`window`,M(N),mi(N),M(He);var et=B(V(He,2));M(ze),M(ke);var tt=V(ke,2),nt=e=>{var t=ja(),n=V(R(t),2),i=e=>{var t=Aa(),n=R(t),i=V(R(n),2);Z(i,21,r,qr,(e,t,n)=>{var r=ka(),i=R(r),a=R(i),o=B(a,!0);M(i);var s=V(i),c=B(s),l=V(s),u=B(l),d=B(V(l),!0);M(r),H((e,r)=>{Q(a,`datetime`,G(t).at),Y(o,e),Y(c,`${r??``}%`),Y(u,`${G(t).used??``}%`),Y(d,n===0?`First observation`:G(t).break?`Gap before this observation`:`Connected to previous observation`)},[()=>da(G(t).at),()=>G(t).elapsed.toFixed(1)]),J(e,r)}),M(i),M(n),M(t),J(e,t)};X(n,e=>{G(a)&&e(i)}),M(t),Li(`open`,`toggle`,t,e=>L(a,e),()=>G(a)),J(e,t)};X(tt,e=>{r().length&&e(nt)}),H((e,r,a,o,s,c,l)=>{Q(ae,`viewBox`,`0 0 ${G(p)} ${G(m)}`),Q(ae,`aria-label`,e),oe=ui(ae,``,oe,{"--trend-color":G(k)?.safe?`#115b35`:`#7f1825`}),Q(ce,`id`,n),Q(ce,`x2`,i()?`0%`:`100%`),Q(de,`stop-color`,i()?`#ae903b`:`#8c793d`),Q(fe,`id`,n+`-trend-arrow`),Q(pe,`width`,G(_)),Q(pe,`height`,G(v)),Q(pe,`fill`,`url(#${n})`),Q(ge,`d`,`M48 20 V${G(g)} H${G(h)}`),Q(_e,`y1`,r),Q(_e,`x2`,G(h)),Q(_e,`y2`,a),Y(we,i()?`DISTANCE FROM SAFETY (PP)`:`CONSUMPTION`),Q(Te,`x`,48+G(_)/2),Q(Te,`y`,G(m)-5),Q(Ee,`cx`,G(y)),Q(Ee,`cy`,G(S)),Q(De,`cx`,G(y)),Q(De,`cy`,G(S)),Y(Oe,`${t.used??``}% consumed // ${o??``}% of period elapsed${s??``}`),Y(Pe,` // ${c??``}% TIME ELAPSED`),Y(Ie,l),Ke.disabled=!G(D).halfHour,Y(qe,`LAST 30 MINUTES${G(D).halfHour?``:` — UNAVAILABLE`}`),Je.disabled=!G(D).hour,Y(Ye,`LAST HOUR${G(D).hour?``:` — UNAVAILABLE`}`),Xe.disabled=!G(D).day,Y(Ze,`LAST 24 HOURS${G(D).day?``:` — UNAVAILABLE`}`),Qe.disabled=!G(D).window,Y($e,`FROM WINDOW START${G(D).window?``:` — NO TIME ELAPSED`}`),Y(et,`HISTORY // ${G(ne)??``}`)},[()=>`${i()?`Pace zone`:`Consumption zone`}: ${t.used}% consumed, ${t.elapsed.toFixed(1)}% of quota period elapsed. ${i()?`${G(C).toFixed(1)} percentage points from safety.`:`${G(C)>0?`Above`:G(C)<0?`Below`:`On`} the steady-consumption line.`}${G(o)&&r().length?` Trace path contains ${r().length} ${r().length===1?`observation`:`observations`}; gaps are not interpolated.`:``}`,()=>b(0),()=>i()?b(0):b(100),()=>t.elapsed.toFixed(1),()=>i()?` // ${G(C).toFixed(1)} PP from safety`:``,()=>t.elapsed.toFixed(1),()=>Math.abs(G(C))<.05?`ON PACE`:G(C)>0?i()?`ABOVE SAFETY — CONSUMPTION AHEAD OF TIME`:`ABOVE THE LINE — CONSUMING FASTER THAN TIME`:i()?`BELOW SAFETY — QUOTA HEADROOM`:`BELOW THE LINE — WITHIN PACE`]),Pi(ie,`clientWidth`,e=>L(p,e)),Pi(ie,`clientHeight`,e=>L(m,e)),ki(Ve,()=>G(o),e=>L(o,e)),hi(N,()=>G(s),e=>L(s,e)),J(e,re),Ge()}var Pa=q(` `),Fa=q(`

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

`),Ia=q(`

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

`),La=q(`

`),Ra=q(`

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

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

`),za=q(` `,1),Ba=Mr(``),Va=Mr(``),Ha=q(`
`),Ua=q(`

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

`),Wa=q(`
EMPTYFULL
`),Ga=q(`

`,1),Ka=q(`
`,1),qa=q(`

`),Ja=q(`

`),Ya=q(`

No quota windows reported yet.

`),Xa=q(`
`,1),Za=q(`

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

`,1),Qa=q(` `,1);function $a(e,t){We(t,!0);let n=Wi(t,`params`,19,()=>({})),r=P(()=>$i.filter(e=>e!==`thresholds`||!!$.data?.thresholds?.length)),i=I(Xt(Date.now())),a=P(()=>G(r).includes(n().view||``)?n().view:`bars`);Gi(()=>{let e=setInterval(()=>L(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-G(i))/(e.duration*6e4))))}yn(()=>{ra.view=G(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=Qa(),l=z(c);Z(l,21,()=>G(r),qr,(e,t)=>{var n=Pa();let r;var i=B(n,!0);H(e=>{Q(n,`href`,`#/quota/`+G(t)),Q(n,`aria-current`,G(a)===G(t)?`page`:void 0),r=ci(n,1,``,null,r,{active:G(a)===G(t)}),Y(i,e)},[()=>G(t)===`fuel`?`FUEL TANK`:G(t).toUpperCase()]),J(e,n)}),M(l);var u=V(l,2),d=e=>{var t=Za(),n=z(t),r=e=>{J(e,Fa())};X(n,e=>{$.data.quotaError&&e(r)});var i=V(n,2),c=B(i),l=V(i,2),u=e=>{xa(e,{})},d=e=>{var t=Ra(),n=R(t),r=B(n),i=V(n,4),a=e=>{J(e,Ia())};X(i,e=>{$.data.credits.length||e(a)}),Z(V(i,2),17,()=>$.data.credits,qr,(e,t)=>{var n=La(),r=R(n),i=B(r),a=B(V(r,2),!0);M(n),H(e=>{Y(i,`${(G(t).title||`Quota reset`)??``} // ${G(t).status??``}`),Y(a,e)},[()=>G(t).expiryKnown?G(t).expires?`EXPIRES `+da(G(t).expires):`Does not expire`:`Expiry information unavailable`]),J(e,n)}),Ce(2),M(t),H(()=>Y(r,`RESET INVENTORY // ${$.data.creditCount??``} AVAILABLE`)),J(e,t)},f=e=>{var t=Xa(),n=z(t);let r;Z(n,21,()=>$.data.meters,qr,(e,t)=>{let n=P(()=>o(G(t)));var r=Ja(),i=R(r),c=B(i,!0),l=V(i,2),u=R(l),d=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`FREE ${100-G(t).used}%`),Y(a,`USED ${G(t).used??``}%`)}),J(e,n)},f=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`USED ${G(t).used??``}%`),Y(a,`FREE ${100-G(t).used}%`)}),J(e,n)};X(u,e=>{G(a)===`fuel`?e(d):e(f,-1)}),M(l);var p=V(l,2);let m;var h=R(p),g=e=>{var n=Ha(),r=R(n),i=V(R(r)),a=e=>{J(e,Ba())},o=e=>{var n=Va();H(e=>Q(n,`d`,e),[()=>s(G(t).used)]),J(e,n)};X(i,e=>{G(t).used>=100?e(a):G(t).used>0&&e(o,1)}),M(r),M(n),H(()=>Q(r,`aria-label`,`${G(t).used}% quota used`)),J(e,n)},_=e=>{var r=Pr(),i=z(r),o=e=>{{let r=P(()=>G(t).trail||[]),i=P(()=>G(a)===`pace`);Na(e,{get used(){return G(t).used},get elapsed(){return G(n)},get trail(){return G(r)},get duration(){return G(t).duration},get paceView(){return G(i)}})}},s=e=>{J(e,Ua())};X(i,e=>{G(n)===null?e(s,-1):e(o)}),J(e,r)},v=e=>{var r=Ka(),i=z(r),o=R(i);let s;M(i);var c=V(i,2),l=e=>{J(e,Wa())};X(c,e=>{G(a)===`fuel`&&e(l)});var u=V(c,2),d=e=>{var t=Ga(),r=z(t),i=B(r),o=V(r,2),s=R(o);let c;M(o),H(e=>{Y(i,`RESET CYCLE // ${e??``}% ELAPSED`),c=ui(s,``,c,{width:`${G(a)===`fuel`?100-G(n):G(n)}%`})},[()=>Math.floor(G(n))]),J(e,t)};X(u,e=>{G(n)!==null&&e(d)}),H(()=>{Q(i,`aria-label`,G(a)===`fuel`?`Fuel remaining`:`Quota used`),Q(i,`aria-valuenow`,G(a)===`fuel`?100-G(t).used:G(t).used),s=ui(o,``,s,{width:`${G(a)===`fuel`?100-G(t).used:G(t).used}%`})}),J(e,r)};X(h,e=>{G(a)===`pie`?e(g):G(a)===`zone`||G(a)===`pace`?e(_,1):e(v,-1)}),M(p);var y=V(p,2),b=B(y),x=V(y,2),S=e=>{var n=qa(),r=B(n,!0);H(()=>Y(r,G(t).details)),J(e,n)};X(x,e=>{G(t).details&&e(S)}),M(r),H(e=>{Y(c,G(t).name),m=ci(p,1,`meter-graphic`,null,m,{"bar-graphic":G(a)===`bars`||G(a)===`fuel`}),Y(b,`RESETS // ${e??``}`)},[()=>da(G(t).reset)]),J(e,r)}),M(n);var i=V(n,2),c=e=>{J(e,Ya())};X(i,e=>{$.data.meters.length||e(c)}),H(()=>r=ci(n,1,`quota-grid`,null,r,{radial:G(a)===`pie`,zone:G(a)===`zone`||G(a)===`pace`})),J(e,t)};X(l,e=>{G(a)===`thresholds`?e(u):G(a)===`resets`?e(d,1):e(f,-1)}),Ce(2),H(e=>Y(c,`QUOTA // OBSERVED ${e??``}`),[()=>da($.data.quotaAt)]),J(e,t)};X(u,e=>{$.data&&e(d)}),J(e,c),Ge()}var eo=q(`
`),to=q(`

`,1);function no(e,t){We(t,!0);let n=Wi(t,`values`,19,()=>[]),r=Wi(t,`label`,3,`Token activity`),i=Wi(t,`capacity`,3,0),a=P(()=>Math.max(0,...n())),o=P(()=>i()>n().length?[...Array(i()-n().length).fill(0),...n()]:n());var s=to(),c=z(s),l=B(c),u=V(c,2);Z(u,21,()=>G(o),qr,(e,t)=>{var n=eo();let r;H((e,t)=>{Q(n,`title`,e),r=ui(n,``,r,{height:t})},[()=>G(t).toLocaleString(`en-GB`)+` tokens`,()=>`${100*G(t)/Math.max(1,G(a))}%`]),J(e,n)}),M(u),H((e,t)=>{Y(l,`SCALE // 0 — ${e??``} TOKENS`),Q(u,`aria-label`,t)},[()=>G(a).toLocaleString(`en-GB`),()=>`${r()}. Peak ${G(a).toLocaleString(`en-GB`)} tokens.`]),J(e,s),Ge()}var ro=q(`

`),io=q(`

`,1),ao=q(`

`),oo=q(`

Loading / sending…

`),so=q(`
`),co=q(`

Confirmation expired. Reopen the option.

`),lo=q(`

`,1),uo=q(`

 
`,1),fo=q(` `),po=q(``),mo=q(`

No available matching commands.

`),ho=q(`

↑/↓ select · Tab complete · Enter options · Escape dismiss

`),go=q(`
`,1),_o=q(` `,1),vo=q(`
`),yo=q(`
`);function bo(e,t){We(t,!0);let n=Wi(t,`query`,3,``),r=Wi(t,`onchange`,3,()=>{}),i=Wi(t,`oncomplete`,3,e=>{}),a=I(!1),o=I(!1),s=I(``),c=I(null),l=I(null),u=I(``),d=I(0),f=I(Xt(Date.now())),p=I(``),m=0,h=I(0),g=I(null),_=I(void 0),v=setInterval(()=>{L(f,Date.now(),!0)},1e3);Ki(()=>{clearInterval(v),m++});let y=P(()=>n().trim().startsWith(`/`)&&!n().trim().startsWith(`//`)),b=P(()=>G(c)?.path===``&&G(y)?n().trim().slice(1).toLowerCase():``),x=P(()=>(G(c)?.choices||[]).filter(e=>!G(b)||e.label.toLowerCase().startsWith(`/`+G(b)))),S=P(()=>!$.connected||!!$.data?.sessionsError),C=P(()=>G(a)&&G(y)&&(!G(c)||G(c).path===``)&&!G(l));yn(()=>{n(),L(h,0)}),yn(()=>{let e=G(h);G(x),G(C)&&ur().then(()=>{let t=G(_)?.children[e];if(!t||!G(_))return;let n=G(_).getBoundingClientRect(),r=t.getBoundingClientRect();r.topn.bottom&&(G(_).scrollTop+=r.bottom-n.bottom)})});function w(e){if(!G(y)||!G(a)||G(c)&&G(c).path!==``||G(l)||G(S)||e.isComposing||e.ctrlKey||e.metaKey||e.altKey||![`ArrowUp`,`ArrowDown`,`Tab`,`Enter`,`Escape`].includes(e.key)||e.key===`Tab`&&e.shiftKey)return;if(e.preventDefault(),e.key===`Escape`){L(a,!1),L(g,n()),L(u,``);return}if(e.key===`ArrowUp`||e.key===`ArrowDown`){L(h,Math.min(Math.max(G(h)+(e.key===`ArrowUp`?-1:1),0),Math.max(G(x).length-1,0)),!0);return}let t=G(x)[G(h)];t&&!G(o)&&(e.key===`Tab`?i()(t.label):E(t))}yn(()=>{G(S)&&(m++,L(o,!1),L(u,``),G(a)&&(L(a,!1),L(g,n())),L(c,null),L(l,null))}),yn(()=>{G(y)&&!G(a)&&n()!==G(g)&&!G(S)&&(L(a,!0),T(``))});async function T(e){let n=++m;L(o,!0),L(l,null),L(u,``),L(s,``);try{let r=await ha(`commands`,{session:t.session,command:{mode:`list`,path:e}});n===m&&((e===``||e===`help`)&&r.choices.push({id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}),L(c,r,!0),L(p,r.value||``,!0),(r.path.startsWith(`rename/`)||r.path.startsWith(`cd/`))&&r.choices.length===1&&E(r.choices[0]))}catch{n===m&&(L(s,`Command catalogue unavailable. Use Codex.`),(e===``||e===`help`)&&L(c,{title:`/ COMMANDS`,help:`Local display settings remain available.`,path:``,revision:``,choices:[{id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}]},!0))}finally{n===m&&L(o,!1)}}async function E(e){if(e.next===`statusline`){ia.open=!0,L(a,!1),L(g,n());return}if(e.next){await T(e.next);return}if(L(l,e,!0),L(u,``),L(s,``),!e.action||!G(c))return;let r=++m;L(o,!0);try{let n=await ha(`commands`,{session:t.session,command:{mode:`prepare`,path:G(c).path,revision:G(c).revision,choice:e.id}});r===m&&(L(u,n.confirmation,!0),L(d,Date.parse(n.expires),!0))}catch{r===m&&L(s,`Option changed or unavailable. Refresh before retrying.`)}finally{r===m&&L(o,!1)}}async function ee(){if(!G(u)||G(S)||G(o)||G(f)>=G(d)||!G(c))return;let e=G(u);L(u,``),L(o,!0);let n=++m;try{let i=await ha(`commands`,{session:t.session,confirmation:e,command:{mode:`commit`,path:G(c).path}});n===m&&(L(s,i.message,!0),L(a,!1),L(c,null),L(l,null),L(d,0),L(g,null),r()())}catch{n===m&&L(s,`Change unconfirmed. Check Codex before retrying.`)}finally{n===m&&L(o,!1)}}var D={handleKey:w},O=yo(),te=R(O),k=V(te,2),ne=e=>{var t=ro(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(k,e=>{G(s)&&!G(a)&&e(ne)});var re=V(k,2),ie=e=>{var n=vo();let r;var i=R(n),a=e=>{var t=io(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(c)?.title||`/ COMMANDS`),Y(i,G(c)?.help||`Loading live options…`)}),J(e,t)};X(i,e=>{G(C)||e(a)});var m=V(i,2),g=e=>{var t=ao(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(m,e=>{G(s)&&e(g)});var v=V(m,2),b=e=>{J(e,oo())};X(v,e=>{G(o)&&e(b)});var w=V(v,2),D=e=>{var t=so(),n=R(t),r=R(n),i=V(r);xi(i),M(n);var a=V(n,2),s=B(a);M(t),H((e,t)=>{Y(r,`${e??``} `),Q(i,`aria-label`,G(c).inputLabel||`Session name`),Q(i,`maxlength`,G(c).inputLimit||512),i.disabled=G(o)||G(S),a.disabled=t,Y(s,`REVIEW ${G(c).path===`cd`?`DIRECTORY`:`RENAME`}`)},[()=>(G(c).inputLabel||`Session name`).toUpperCase(),()=>G(o)||G(S)||!G(p).trim()]),Sr(`submit`,t,e=>{e.preventDefault(),G(c)&&G(p).trim()&&!G(o)&&!G(S)&&T(G(c).path+`/`+encodeURIComponent(G(p).trim()))}),Ei(i,()=>G(p),e=>L(p,e)),J(e,t)},O=e=>{var n=uo(),r=z(n),i=B(r,!0),a=V(r,2),s=B(a,!0),p=V(a,2),m=e=>{var n=lo(),r=z(n),i=R(r),a=V(i),s=e=>{J(e,Nr(`Only this session's saved name - changes.`))},l=P(()=>G(c)?.path.startsWith(`rename/`)),p=e=>{J(e,Nr(`Only this session’s directory - changes; project configuration is not reloaded.`))},m=P(()=>G(c)?.path.startsWith(`cd/`)),h=e=>{J(e,Nr(`Changes affect subsequent turns of this session, not global - defaults. Automatic quota thresholds may later supersede model - settings.`))};X(a,e=>{G(l)?e(s):G(m)?e(p,1):e(h,-1)}),M(r);var g=V(r,2),_=V(g,2),v=e=>{J(e,co())};X(_,e=>{G(u)&&G(f)>=G(d)&&e(v)}),H(()=>{Y(i,`TARGET // ${t.session??``}. `),g.disabled=G(o)||G(S)||!G(u)||G(f)>=G(d)}),K(`click`,g,ee),J(e,n)};X(p,e=>{G(l).action&&e(m)});var h=V(p,2);H(()=>{Y(i,G(l).label),Y(s,G(l).help||`No additional help supplied by Codex.`),h.disabled=G(o)}),K(`click`,h,()=>{L(l,null),L(u,``)}),J(e,n)},te=e=>{var t=go(),n=z(t);let r;Z(n,23,()=>G(x),e=>e.id,(e,t,n)=>{var r=po();let i;var a=R(r),s=B(a,!0),l=V(a),u=B(l,!0),d=V(l),f=e=>{var n=fo(),r=B(n,!0);H(()=>Y(r,G(t).help)),J(e,n)};X(d,e=>{G(y)&&G(c)?.path===``&&e(f)}),M(r),H(()=>{r.disabled=G(o)||G(S),Q(r,`title`,G(t).help),Q(r,`aria-label`,G(t).label+(G(t).next?` →`:G(t).action?``:` // HELP`)),i=ci(r,1,`svelte-7bfwr9`,null,i,{suggested:G(y)&&G(c)?.path===``&&G(h)===G(n)}),Y(s,G(t).label),Y(u,G(t).next?` →`:G(t).action?``:` // HELP`)}),K(`click`,r,()=>E(G(t))),J(e,r)}),M(n),Ii(n,e=>L(_,e),()=>G(_));var i=V(n,2),a=e=>{J(e,mo())};X(i,e=>{!G(o)&&!G(x).length&&e(a)});var s=V(i,2),l=e=>{J(e,ho())};X(s,e=>{G(y)&&G(c)?.path===``&&e(l)}),H(()=>r=ci(n,1,`command-options svelte-7bfwr9`,null,r,{vertical:G(C)})),J(e,t)};X(w,e=>{G(c)?.input?e(D):G(l)?e(O,1):e(te,-1)});var k=V(w,2),ne=e=>{var t=_o(),n=z(t),r=V(n,2);H(()=>{n.disabled=G(o),r.disabled=G(o)}),K(`click`,n,()=>T(``)),K(`click`,r,()=>T(G(c)?.path||``)),J(e,t)};X(k,e=>{G(C)||e(ne)}),M(n),H(()=>{Q(n,`aria-label`,G(C)?`Slash command suggestions`:void 0),r=ci(n,1,`svelte-7bfwr9`,null,r,{"command-popup":G(C)})}),J(e,n)};return X(re,e=>{G(a)&&e(ie)}),M(O),H(()=>te.disabled=G(S)||G(o)),K(`click`,te,()=>{L(a,!G(a)),L(g,G(a)?null:n(),!0),L(u,``),G(a)&&T(``)}),J(e,O),Ge(D)}Cr([`click`]);var xo=q(` `,1),So=q(`
`),Co=q(`
/
`);function wo(e,t){We(t,!0);let n=P(()=>t.lines.filter(e=>e.kind===`addition`).length),r=P(()=>t.lines.filter(e=>e.kind===`removal`).length);var i=Co(),a=R(i),o=R(a),s=B(o),c=B(V(o,2));M(a),Z(V(a,2),17,()=>t.lines,qr,(e,t)=>{var n=So();let r;var i=R(n),a=e=>{var n=xo(),r=z(n),i=B(r,!0),a=B(V(r),!0);H(()=>{Y(i,G(t).old||``),Y(a,G(t).new||``)}),J(e,n)};X(i,e=>{G(t).kind!==`heading`&&G(t).kind!==`metadata`&&e(a)});var o=B(V(i),!0);M(n),H(()=>{r=ci(n,1,`diff-line svelte-x4gtb6`,null,r,{added:G(t).kind===`addition`,removed:G(t).kind===`removal`,heading:G(t).kind===`heading`}),Y(o,G(t).text)}),J(e,n)}),M(i),H(()=>{Q(a,`aria-label`,`${G(n)} lines added, ${G(r)} lines removed`),Y(s,`+${G(n)??``}`),Y(c,`−${G(r)??``}`)}),J(e,i),Ge()}var To=q(`

`),Eo=q(`

Send this saved prompt now? This starts Codex work and consumes quota.

`,1),Do=q(``),Oo=q(`

 

In memory only. Follows session model, reasoning and speed. Closing - Codexometer cancels pending work.

`),ko=q(`

CURRENT PROFILE

MODEL / REASONING LEVEL / SPEED

 

PROPOSED PROFILE

MODEL / REASONING LEVEL / SPEED

 

Applied settings remain after Codexometer closes.

`,1),Ao=q(`

`),jo=q(`

 
`,1),Mo=q(`

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

`),No=q(`

Session controls temporarily unavailable. Check Codex for current state.

`),Po=q(`

Checking session controls…

`),Fo=q(`

`),Io=q(`
About browser controls

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

`),Lo=q(` `,1),Ro=q(` `),zo=q(`Grants permission beyond this one action. Check the scope - carefully.`),Bo=q(``),Vo=q(``),Ho=q(``),Uo=q(``),Wo=q(`

Not before this time; when quota and idle allow.

`),Go=q(`

`,1),Ko=q(`

The existing trigger remains active until saved or deleted. If - it changes or sends while you edit, saving is blocked.

`),qo=q(` `,1),Jo=q(``),Yo=q(``),Xo=q(``),Zo=q(` `,1),Qo=q(`
  • `),$o=q(`
    View fixed choices

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

      `),es=q(` `,1),ts=q(`

      `),ns=q(`

      `,1),rs=q(` `,1),is=q(``),as=q(`

      `,1),os=q(`

      `);function ss(e,t){We(t,!0);let n=[],r=Wi(t,`observedCommand`,3,``),i=Wi(t,`observedFileChanges`,19,()=>[]),a=Wi(t,`review`,3,``),o=Wi(t,`suspended`,3,!1),s=Wi(t,`openScheduler`,3,!1),c=Wi(t,`onProtectedChange`,3,e=>{}),l=I(null),u=I(Xt([])),d=I(null),f=I(``),p=I(0),m=I(Xt(Date.now())),h=I(!1),g=I(``),_=I(!1),v=I(!1),y=I(``),b=I(!1),x=I(``),S=I(!1),C=I(``),w=I(`now`),T=I(60),E=I(``),ee=I(!1),D=I(``),O=I(Xt([])),te=P(()=>G(O).find(e=>e.status!==`sent`)),k=I(void 0),ne=I(void 0);function re(e){if(G(b)){ur().then(()=>G(k)?.focus());return}if(e.status!==`pending`||G(h)||!G(l)?.id||G(l).kind!==`prompt`||G(l).questions?.length)return;L(b,!0),L(x,e.id,!0),ur().then(()=>G(k)?.focus()),L(u,[e.text],!0),L(w,e.trigger===`quota`?`quota`:`at`,!0),L(f,``),L(C,``);let t=new Date(e.at);e.trigger!==`quota`&&L(E,new Date(t.getTime()-t.getTimezoneOffset()*6e4).toISOString().slice(0,16),!0)}yn(()=>{s()&&G(te)&&!G(S)&&G(l)?.id&&G(l).kind===`prompt`&&!G(l).questions?.length&&(L(S,!0),re(G(te)))});async function ie(){if(!a())try{L(O,await ha(`schedules`,{session:t.session},ye.signal),!0),G(b)&&!G(O).some(e=>e.id===G(x)&&e.status===`pending`)&&L(f,``),G(C)&&!G(O).some(e=>e.id===G(C)&&e.status===`pending`)&&(L(f,``),L(C,``))}catch{}}async function ae(e){try{L(O,await ha(`schedules`,{session:t.session,cancelId:e},ye.signal),!0),L(b,!1),L(f,``),L(C,``),L(u,[],!0)}catch(e){L(g,e instanceof Error?e.message:`Unable to cancel trigger.`,!0)}}yn(()=>(c()(G(h)||G(u).some(e=>e.length>0)),()=>c()(!1)));let oe=P(()=>$.data?.sessions.find(e=>e.id===t.session)?.status),se=P(()=>!$.connected||!!$.data?.sessionsError),ce=P(()=>a()!==`profile`&&G(l)?.kind===`prompt`&&!G(l).questions?.length&&!!$.data?.profiles?.some(e=>e.session===t.session&&e.pending)),le=P(()=>!G(se)&&!G(v)&&!!G(l)?.id&&G(l).kind===`approval`&&G(y)!==G(l).id),ue=P(()=>G(le)?G(l).command:r()),de=P(()=>!!G(f)&&G(m)G(l)?.questions?.length?G(l).questions:[{text:`Follow-up message`,secret:!1,freeText:!0,options:[]}]),pe=P(()=>G(l)?.kind===`approval`||G(l)?.kind===`profile`?G(d)!==null:G(u).length===G(fe).length&&G(u).every((e,t)=>e.trim().length>0&&(G(fe)[t].freeText||G(fe)[t].options?.includes(e)))),me=P(()=>G(l)?.kind===`prompt`&&!G(l).questions?.length&&G(w)!==`now`),he=P(()=>G(w)===`delay`?G(m)+G(T)*6e4:Date.parse(G(E))),ge=P(()=>{if(!G(me))return``;if(G(b)&&!G(O).some(e=>e.id===G(x)&&e.status===`pending`))return`Trigger changed, removed or already sent. Go back and reopen it; your draft has not been saved.`;if(!G(u)[0]?.trim())return`Enter a message to schedule.`;if(G(w)===`quota`)return``;if(!Number.isFinite(G(he))||G(he)<=G(m))return`Choose a future date/time or a delay greater than zero.`;let e=new Date(G(m));return e.setFullYear(e.getFullYear()+1),G(he)>=e.getTime()?`Choose a time within one year.`:``});function _e(e){return new Date(e).toLocaleString([],{timeZoneName:`short`})}function ve(e){if(e.status!==`pending`)return e.status;if(e.trigger===`at`&&Date.parse(e.at)>G(m))return`Due in `+Math.ceil((Date.parse(e.at)-G(m))/6e4)+` min`;let t=G(se)?`waiting for a fresh connection`:e.waitingReason||(e.canSend?`ready; awaiting dispatch`:`waiting for quota and an eligible idle session`);return(e.trigger===`at`?`Time reached — `:``)+t}yn(()=>{(G(se)||o()||G(ce)||G(m)>=G(p))&&L(f,``)});let ye=new AbortController;Gi(()=>{let e=e=>{e.ctrlKey&&e.key.toLowerCase()===`s`&&!a()&&G(te)&&(e.preventDefault(),re(G(te)))};window.addEventListener(`keydown`,e);let n,r=setInterval(()=>{L(m,Date.now(),!0)},1e3);async function i(){await ie();try{let e=await ha(`offer`,{session:t.session,...a()?{review:a()}:{}},ye.signal);if(ye.signal.aborted)return;L(v,!1),G(l)?.id!==e.id&&(L(f,``),L(d,null),L(u,Array(Math.max(1,e.questions?.length||0)).fill(``),!0)),L(l,e,!0),G(_)&&e.id&&e.id!==G(y)&&(L(g,``),L(_,!1))}catch{ye.signal.aborted||(L(l,null),L(v,!0),L(f,``))}finally{ye.signal.aborted||(n=setTimeout(i,2e3))}}return i(),()=>{window.removeEventListener(`keydown`,e),ye.abort(),clearTimeout(n),clearInterval(r)}});async function A(e){if(!e&&G(l)?.kind===`prompt`&&!G(l).questions?.length&&G(u)[0]?.trim().startsWith(`/`)&&!G(u)[0]?.trim().startsWith(`//`)){L(g,`Choose a slash command from COMMANDS; use // for literal slash text.`);return}if(!G(l)?.id||G(h)||G(se)||o()||G(ce)||(e?!e.canSend:!G(pe)||G(ge)))return;let n=G(l).id;L(h,!0),L(g,``),L(_,!1),L(f,``),L(C,e?.id||``,!0);try{let r=!e&&G(l).kind===`prompt`&&!G(l).questions?.length&&G(w)!==`now`?{trigger:G(w)===`quota`?`quota`:`at`,zone:Intl.DateTimeFormat().resolvedOptions().timeZone,...G(w)===`quota`?{}:{at:(G(w)===`delay`?new Date(Date.now()+G(T)*6e4):new Date(G(E))).toISOString()}}:void 0;L(ee,!!r),L(D,r?r.trigger===`quota`?`After fresh quota becomes available, when the session is idle`:_e(r.at)+` — not before this time; when quota and idle allow`:``,!0);let i=await ha(`prepare`,{session:t.session,...a()?{review:a()}:{},offer:n,...e?{sendId:e.id}:{},...r?{schedule:r}:{},...r&&G(b)?{editId:G(x)}:{},...G(l).kind===`approval`||G(l).kind===`profile`?{choice:G(d)}:{answers:e?[e.text]:[...G(u)]}},ye.signal);G(l)?.id===n&&!ye.signal.aborted&&!G(se)&&!o()&&!G(ce)&&(L(f,i.confirmation,!0),L(p,Date.parse(i.expires),!0))}catch(e){ye.signal.aborted||L(g,e instanceof Error?e.message:`Unable to prepare action.`,!0)}finally{L(h,!1)}}async function be(){if(!G(l)?.id||G(h)||o()||G(ce)||!G(de))return;let e=G(l).id,n=G(l).kind,r=G(f);L(f,``),L(h,!0),L(y,e,!0);try{await ha(`commit`,{session:t.session,...a()?{review:a()}:{},offer:e,confirmation:r},ye.signal),L(_,!0),L(b,!1),G(ee)&&(L(y,``),await ie()),L(g,G(ee)?`Trigger set. Closing Codexometer cancels it.`:n===`profile`?`Profile decision completed.`:n===`approval`?`Decision sent.`:`Text sent.`,!0)}catch(e){L(g,e instanceof pa?e.message:`Outcome uncertain. Check Codex before taking another action; nothing was retried.`,!0)}finally{L(h,!1),L(C,``),await ie(),L(u,[],!0),L(d,null)}}var j=Lo(),xe=z(j),Se=e=>{var t=Pr();Z(z(t),17,()=>G(O).filter(e=>e.status!==`sent`),e=>e.id,(e,t)=>{var n=Oo(),r=R(n),i=B(r,!0),a=V(r,2),s=B(a),c=V(a,2),u=B(c,!0),d=V(c,2),p=B(d,!0),m=V(d,2),_=B(m,!0),v=V(m,2),y=e=>{var t=To(),n=B(t,!0);H(()=>Y(n,G(g))),J(e,t)};X(v,e=>{G(g)&&e(y)});var b=V(v,4),x=V(b,2),S=V(x,2),w=e=>{var n=Eo(),r=V(z(n),2),i=V(r,2);H(()=>r.disabled=G(h)||G(se)||!G(t).canSend),K(`click`,r,be),K(`click`,i,()=>{L(f,``),L(C,``)}),J(e,n)},T=e=>{var n=Do();H(()=>n.disabled=G(h)||G(se)||!G(t).canSend||o()),K(`click`,n,()=>A(G(t))),J(e,n)};X(S,e=>{G(de)&&G(C)===G(t).id?e(w):e(T,-1)}),M(n),H((e,n)=>{Y(i,G(t).status===`uncertain`?`CHECK TRIGGER — outcome uncertain; not retried`:`SCHEDULED FOLLOW-UP`),Y(s,`TARGET // ${G(t).session??``}`),Y(u,e),Y(p,n),Y(_,G(t).text),b.disabled=G(h)||!G(l)?.id||G(l).kind!==`prompt`||!!G(l).questions?.length||G(t).status!==`pending`,x.disabled=G(h)||G(t).status===`sending`},[()=>G(t).trigger===`quota`?`After confirmed quota recovery, when idle`:`Not before ${_e(G(t).at)}`,()=>ve(G(t))]),K(`click`,b,()=>re(G(t))),K(`click`,x,()=>ae(G(t).id)),J(e,n)}),J(e,t)},we=P(()=>!a()&&G(l)?.kind!==`approval`&&!G(l)?.questions?.length&&![`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(oe)||``));X(xe,e=>{G(we)&&e(Se)});var Te=V(xe,2),Ee=e=>{var r=os(),o=R(r),s=B(o,!0),c=V(o,2),x=e=>{var t=ko(),n=z(t),r=B(n),i=V(n,6),a=B(i,!0),o=B(V(i,6),!0);Ce(2),H(()=>{Y(r,`Your ${G(l).profile.threshold??``}% quota threshold has been reached. Review - the profile for subsequent turns.`),Y(a,G(l).profile.current),Y(o,G(l).profile.proposed)}),J(e,t)};X(c,e=>{G(l)?.profile&&!G(se)&&!G(v)&&e(x)});var S=V(c,2),C=e=>{var t=Ao();let n;var r=B(t,!0);H(()=>{n=ci(t,1,`svelte-1oupzfc`,null,n,{notice:!G(_),sent:G(_)}),Y(r,G(g))}),J(e,t)};X(S,e=>{G(g)&&e(C)});var O=V(S,2),te=e=>{wo(e,{get lines(){return G(l).fileChanges}})},re=e=>{wo(e,{get lines(){return i()}})},ie=e=>{var t=jo(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(le)?`EXACT COMMAND`:`LAST OBSERVED COMMAND`),Y(i,G(ue))}),J(e,t)},ae=e=>{J(e,Mo())};X(O,e=>{G(l)?.fileChanges?.length&&!G(se)&&!G(v)?e(te):i().length?e(re,1):G(ue)?e(ie,2):a()!==`profile`&&G(oe)===`APPROVAL NEEDED`&&!G(_)&&e(ae,3)});var ce=V(O,2),me=e=>{J(e,No())},ve=e=>{J(e,Po())},ye=e=>{var t=Lo(),n=z(t),r=e=>{var t=Fo(),n=B(t,!0);H(e=>Y(n,e),[()=>G(oe)===`WORKING`?`Codex is working — nothing to respond to.`:[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(oe)||``)?`Respond in Codex for this request.`:`Nothing needs a response right now.`]),J(e,t)};X(n,e=>{(G(oe)===`WORKING`||!G(_)&&!G(h))&&e(r)});var i=V(n,2),a=e=>{J(e,Io())},o=P(()=>[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(oe)||``)&&!G(_));X(i,e=>{G(o)&&e(a)}),J(e,t)},j=e=>{var r=as(),i=z(r),o=B(i),s=V(i,2),c=R(s),g=B(c,!0),_=V(c,2),v=e=>{var r=Pr();Z(z(r),17,()=>G(l).choices||[],qr,(e,r,i)=>{var o=Bo(),s=R(o);xi(s),s.value=s.__value=i;var c=V(s),l=V(c),u=e=>{var t=Ro(),n=B(t,!0);H(()=>Y(n,G(r).detail)),J(e,t)};X(l,e=>{G(r).detail&&e(u)});var f=V(l,2),p=e=>{J(e,zo())};X(f,e=>{G(r).persistent&&e(p)}),M(o),H(()=>{Q(s,`name`,`decision-`+t.session+`-`+a()),Y(c,` ${G(r).label??``} `)}),Oi(n,[],s,()=>G(d),e=>L(d,e)),J(e,o)}),J(e,r)},y=e=>{var n=Lo(),r=z(n),i=e=>{var t=qo(),n=z(t),r=V(R(n)),i=R(r),a=e=>{var t=Vo();t.value=t.__value=`now`,J(e,t)};X(i,e=>{G(b)||e(a)});var o=V(i);o.value=o.__value=`quota`;var s=V(o);s.value=s.__value=`delay`;var c=V(s);c.value=c.__value=`at`,M(r),mi(r),M(n);var l=V(n,2),u=e=>{var t=Ho(),n=V(R(t));xi(n),M(t),Ei(n,()=>G(T),e=>L(T,e)),J(e,t)};X(l,e=>{G(w)===`delay`&&e(u)});var d=V(l,2),f=e=>{var t=Uo(),n=V(R(t));xi(n),M(t),Ei(n,()=>G(E),e=>L(E,e)),J(e,t)};X(d,e=>{G(w)===`at`&&e(f)});var p=V(d,2),m=e=>{var t=Go(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,Wo())};X(i,e=>{G(w)!==`quota`&&e(a)});var o=V(i,2);o.textContent=`Timezone: ${Intl.DateTimeFormat().resolvedOptions().timeZone??``}. - One pending request per session; saving replaces it. Memory - only; Codexometer must stay running. Uses session model, - reasoning and speed.`,H(e=>Y(r,`Will send: ${e??``}`),[()=>G(w)===`quota`?`when quota is available and this session is idle`:Number.isFinite(G(he))?_e(G(he)):`choose a date and time`]),J(e,t)};X(p,e=>{G(w)!==`now`&&e(m)});var h=V(p,2),g=e=>{J(e,Ko())};X(h,e=>{G(b)&&e(g)}),hi(r,()=>G(w),e=>L(w,e)),J(e,t)};X(r,e=>{G(l).questions?.length||e(i)}),Z(V(r,2),17,()=>G(fe),qr,(e,n,r)=>{var i=es(),o=z(i),s=e=>{{let n=P(()=>G(u)[0]||``);Ii(bo(e,{get session(){return t.session},get query(){return G(n)},oncomplete:e=>{L(u,[e],!0),ur().then(()=>G(k)?.focus())},onchange:()=>{L(u,[``],!0),ur().then(()=>G(k)?.focus())}}),e=>L(ne,e,!0),()=>G(ne))}};X(o,e=>{r===0&&a()!==`profile`&&G(l).kind===`prompt`&&!G(l).questions?.length&&e(s)});var c=V(o,2),d=R(c),f=V(d),p=e=>{var t=Jo();xi(t),Ei(t,()=>G(u)[r],e=>G(u)[r]=e),J(e,t)},m=e=>{var t=Xo(),i=R(t);i.value=i.__value=``,Z(V(i),17,()=>G(n).options||[],qr,(e,t)=>{var n=Yo(),r=B(n,!0),i={};H(()=>{Y(r,G(t)),i!==(i=G(t))&&(n.value=(n.__value=i)??``)}),J(e,n)}),M(t),mi(t),hi(t,()=>G(u)[r],e=>G(u)[r]=e),J(e,t)},h=e=>{var t=Zo(),i=z(t);nt(i),Ii(i,e=>L(k,e),()=>G(k));var a=V(i,2),o=e=>{var t=Fo(),r=B(t);H(e=>Y(r,`Suggested answers: ${e??``}`),[()=>G(n).options.join(` · `)]),J(e,t)};X(a,e=>{G(n).options?.length&&e(o)}),K(`keydown`,i,e=>{G(l)?.kind===`prompt`&&!G(l).questions?.length&&G(ne)?.handleKey(e)}),Ei(i,()=>G(u)[r],e=>G(u)[r]=e),J(e,t)};X(f,e=>{G(n).secret?e(p):G(n).freeText?e(h,-1):e(m,1)}),M(c);var g=V(c,2),_=e=>{var t=$o(),r=V(R(t),4);Z(r,21,()=>G(n).options||[],qr,(e,t)=>{var n=Qo(),r=B(n,!0);H(()=>Y(r,G(t))),J(e,n)}),M(r),M(t),J(e,t)};X(g,e=>{G(n).secret&&!G(n).freeText&&e(_)}),H(()=>Y(d,`${G(n).text??``} `)),J(e,i)}),J(e,n)};X(_,e=>{G(l).kind===`approval`||G(l).kind===`profile`?e(v):e(y,-1)}),M(s);var x=V(s,2),S=e=>{var t=ns(),n=z(t),r=e=>{var t=ts(),n=B(t);H(()=>Y(n,`TRIGGER // ${G(D)??``}`)),J(e,t)};X(n,e=>{G(ee)&&e(r)});var i=V(n,2),a=B(i),o=V(i,2),s=B(o),c=V(o,2);H(e=>{Y(a,`Check the target and ${G(l).kind===`profile`?`profile above`:G(l).kind===`approval`?G(l).fileChanges?.length?`proposed file changes above`:`exact command and permission scope`:`message above`}. ${G(ee)?`This schedules a follow-up that will send automatically when eligible`:`This will send to Codex`}; it may start work using your quota. - Confirmation expires in ${e??``}s.`),o.disabled=G(h)||G(se),Y(s,`CONFIRM ${(G(l).kind===`approval`||G(l).kind===`profile`?G(l).choices?.[G(d)]?.label:G(ee)?G(b)?`SAVE CHANGES`:`SCHEDULE`:`SEND`)??``}`)},[()=>Math.max(0,Math.ceil((G(p)-G(m))/1e3))]),K(`click`,o,be),K(`click`,c,()=>{L(f,``)}),J(e,t)},C=e=>{var t=rs(),n=z(t),r=e=>{var t=To(),n=B(t,!0);H(()=>Y(n,G(ge))),J(e,t)};X(n,e=>{G(ge)&&e(r)});var i=V(n,2),a=B(i,!0);H(()=>{i.disabled=G(h)||G(se)||!G(pe)||!!G(ge),Y(a,G(h)?`SENDING…`:G(b)?`REVIEW CHANGES`:`REVIEW BEFORE SENDING`)}),K(`click`,i,()=>A()),J(e,t)};X(x,e=>{G(de)?e(S):e(C,-1)});var O=V(x,2),te=e=>{var t=is();K(`click`,t,()=>{L(b,!1),L(f,``),L(u,[],!0)}),J(e,t)};X(O,e=>{G(b)&&e(te)}),H(()=>{Y(o,`TARGET // ${G(l).thread??``} // ${(G(l).directory||`Directory unavailable`)??``}`),s.disabled=G(h)||G(de)||G(se),Y(g,G(l).kind===`approval`||G(l).kind===`profile`?`Choose a decision`:G(b)?`EDIT SCHEDULED FOLLOW-UP`:`Reply to this session`)}),J(e,r)};X(ce,e=>{G(se)||G(v)?e(me):G(l)?G(l).id?G(y)!==G(l).id&&e(j,3):e(ye,2):e(ve,1)}),M(r),H(()=>Y(s,a()===`profile`?`QUOTA THRESHOLD`:`SESSION CONTROL // EXPERIMENTAL`)),J(e,r)};X(Te,e=>{!G(ce)&&(!G(te)||G(b)||a()||G(l)?.kind!==`prompt`||G(l).questions?.length)&&e(Ee)}),J(e,j),Ge()}Cr([`click`,`keydown`]);var cs=q(` `,1),ls=q(`
      `),us=q(`

      STATUS LINE // CODEXOMETER

      Choose multiple fields and their order. These display preferences do not - change Codex CLI configuration. Missing values are omitted.

      `),ds=q(`

      `,1);function fs(e,t){We(t,!0);let n=Wi(t,`stale`,3,!1),r=I(Xt([])),i=I(!1),a=P(()=>$.data?.statusLineFields||[]),o=e=>[...new Set(e??G(a).filter(e=>e.default).map(e=>e.id))].filter(e=>G(a).some(t=>t.id===e)),s=e=>o(e).map(e=>e===`run-state`&&(n()||!$.connected||$.data?.sessionsError)?`STALE`:t.session.statusLine?.[e]).filter(Boolean).join(` · `),c=P(()=>[...G(r).map(e=>G(a).find(t=>t.id===e)).filter(Boolean),...G(a).filter(e=>!G(r).includes(e.id))]);yn(()=>{ia.open&&!G(i)?(L(r,o(ra.statusLine),!0),L(i,!0)):ia.open||L(i,!1)});function l(e,t){L(r,t?[...G(r),e]:G(r).filter(t=>t!==e),!0)}function u(e,t){let n=G(r).indexOf(e),i=n+t;if(n<0||i<0||i>=G(r).length)return;let a=[...G(r)];[a[n],a[i]]=[a[i],a[n]],L(r,a,!0)}var d=ds(),f=z(d),p=e=>{var t=us(),n=V(R(t),4);Z(n,21,()=>G(c),e=>e.id,(e,t)=>{var n=ls(),i=R(n),a=R(i);xi(a);var o=V(a,1,!0),s=B(V(o),!0);M(i);var c=V(i,2),d=e=>{var n=cs(),i=z(n),a=V(i,2);H((e,n)=>{Q(i,`aria-label`,`Move `+G(t).label+` earlier`),i.disabled=e,Q(a,`aria-label`,`Move `+G(t).label+` later`),a.disabled=n},[()=>G(r).indexOf(G(t).id)===0,()=>G(r).indexOf(G(t).id)===G(r).length-1]),K(`click`,i,()=>u(G(t).id,-1)),K(`click`,a,()=>u(G(t).id,1)),J(e,n)},f=P(()=>G(r).includes(G(t).id));X(c,e=>{G(f)&&e(d)}),M(n),H(e=>{Q(i,`title`,G(t).help),Si(a,e),Y(o,G(t).label),Y(s,G(t).help)},[()=>G(r).includes(G(t).id)]),K(`change`,a,e=>l(G(t).id,e.currentTarget.checked)),J(e,n)}),M(n);var i=V(n,2),a=B(i),o=V(i,2),d=V(o,2);M(t),H(e=>Y(a,`Preview // ${e??``}`),[()=>s(G(r))||`—`]),K(`click`,o,()=>{ra.statusLine=[...G(r)],aa(),ia.open=!1}),K(`click`,d,()=>{ia.open=!1}),J(e,t)};X(f,e=>{ia.open&&e(p)});var m=V(f,2),h=R(m),g=B(h,!0),_=V(h,2);M(m),H((e,t)=>{Q(h,`title`,e),Y(g,t)},[()=>s(ra.statusLine),()=>s(ra.statusLine)]),K(`click`,_,()=>{ia.open=!ia.open}),J(e,d),Ge()}Cr([`change`,`click`]);var ps=q(`
      `);function ms(e,t){We(t,!0);let n=Wi(t,`active`,3,!1),r=P(()=>t.session.text||t.session.contextKind===`LAST ACTIVITY`&&t.session.workingCommand||``),i=P(()=>[`LAST REPLY`,`LAST ACTIVITY`].includes(t.session.contextKind)&&!!G(r).trim()),a=I(!1),o=I(``),s=I(!1);yn(()=>{if(!G(s))return;let e=setTimeout(()=>{L(s,!1)},150);return()=>clearTimeout(e)}),yn(()=>{G(r),t.session.status,L(o,``)});async function c(){if(!G(i)||G(a))return;let e=G(r);L(a,!0),L(s,!0),L(o,``);try{await navigator.clipboard.writeText(e),G(r)===e&&L(o,`Copied.`)}catch{G(r)===e&&L(o,`Clipboard unavailable. Select the visible text and copy it manually.`)}finally{L(a,!1)}}function l(e){!n()||!G(i)||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(),c())}var u=Pr();Sr(`keydown`,$t,l);var d=z(u),f=e=>{var t=ps(),n=R(t),r=B(n,!0),i=V(n,2);let l;M(t),H(()=>{Y(r,G(o)),i.disabled=G(a),l=ci(i,1,`svelte-543j00`,null,l,{flashed:G(s)})}),K(`click`,i,c),J(e,t)};X(d,e=>{G(i)&&e(f)}),J(e,u),Ge()}Cr([`click`]);var hs=q(`

       
      `,1),gs=q(`

      LATEST GUIDANCE

       
      `,1),_s=q(`

      CONTEXT

       

      `,1),vs=q(`

      `),ys=q(`

      `),bs=q(`
       
      `),xs=q(`

       
      `,1),Ss=q(`
       
      `),Cs=q(`

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

      `),ws=q(`

      `,1),Ts=q(`

      `),Es=q(` `,1),Ds=q(`
      `),Os=q(`

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

      `),ks=q(`

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

      `),As=q(` `),js=q(` `),Ms=q(` `),Ns=q(``),Ps=q(`

      Read only — reply or approve in Codex.

      `),Fs=q(`

      `),Is=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),Ls=q(`
      `),Rs=q(`
      `),zs=q(`

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

      `),Bs=q(`

      `),Vs=q(``),Hs=q(`

      `),Us=q(` `),Ws=q(`

      `),Gs=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),Ks=q(` `,1),qs=q(`

      `),Js=q(`

      TOKEN ACTIVITY // 30 SECOND SAMPLES

      `),Ys=q(`

      TOKENS

      FULL DETAIL →
      `),Xs=q(`

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

      `),Zs=q(`

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

      `,1),Qs=q(`

      SESSION TOTALS

      `,1);function $s(e,t){We(t,!0);let n=(e,t=f,n,r)=>{let i=mt(()=>g(n?.(),!0)),a=mt(()=>g(r?.(),!1));var o=Es(),s=z(o),c=e=>{var n=hs(),r=z(n),i=B(r,!0),a=B(V(r,2),!0);H(()=>{Y(i,t().contextKind===`LAST REPLY`&&!t().streaming?`TASK`:`CURRENT TASK`),Y(a,t().currentTask)}),J(e,n)};X(s,e=>{t().currentTask&&e(c)});var l=V(s,2),u=e=>{var n=gs(),r=B(V(z(n),2),!0);H(()=>Y(r,t().latestGuidance)),J(e,n)};X(l,e=>{t().latestGuidance&&e(u)});var d=V(l,2),p=e=>{var n=_s(),r=B(V(z(n),2),!0);Ce(2),H(()=>Y(r,t().approvalContext)),J(e,n)};X(d,e=>{G(a)&&t().contextKind===`APPROVAL REQUEST`&&t().approvalContext&&e(p)});var m=V(d,2),_=e=>{var n=vs();let r;var i=B(n,!0);H(e=>{r=ci(n,1,`attention-note`,null,r,{inferred:t().status===`CHECK SESSION`}),Y(i,e)},[()=>C(t())]),J(e,n)},v=P(()=>C(t())&&(!G(a)||G(h)||t().status===`CHECK SESSION`));X(m,e=>{G(v)&&e(_)});var y=V(m,2),b=e=>{var n=ys(),r=B(n,!0);H(e=>Y(r,e),[()=>w(t())]),J(e,n)};X(y,e=>{G(i)&&e(b)});var x=V(y,2),S=e=>{var n=bs(),r=B(n,!0);H(()=>Y(r,t().text||`No session context available.`)),J(e,n)};X(x,e=>{(t().text||!t().workingCommand)&&e(S)});var T=V(x,2),E=e=>{var n=xs(),r=V(z(n),2),i=R(r),a=V(i),o=e=>{var n=Nr();H(()=>Y(n,`// +${(t().runningCommands||0)-+(t().commandStatus===`running`)} RUNNING`)),J(e,n)};X(a,e=>{!G(h)&&(t().runningCommands||0)>+(t().commandStatus===`running`)&&e(o)});var s=V(a,2),c=e=>{J(e,Nr(`+`))};X(s,e=>{t().runningLimited&&e(c)}),M(r);var l=B(V(r,2),!0);H(e=>{Y(i,`COMMAND // ${e??``} `),Y(l,t().workingCommand)},[()=>G(h)?`UNKNOWN`:(t().commandStatus||`unknown`).toUpperCase()]),J(e,n)};X(T,e=>{t().workingCommand&&e(E)});var ee=V(T,2),D=e=>{wo(e,{get lines(){return t().fileChanges}})},O=e=>{var n=ws(),r=V(z(n),2),i=B(r,!0),a=V(r,2),o=e=>{var n=Ss(),r=B(n,!0);H(()=>Y(r,t().command)),J(e,n)},s=e=>{J(e,Cs())};X(a,e=>{t().command?e(o):e(s,-1)}),H(()=>Y(i,G(h)||t().status!==`APPROVAL NEEDED`?`LAST OBSERVED COMMAND`:$.data?.control?`COMMAND REQUEST`:`COMMAND TO APPROVE IN CODEX`)),J(e,n)};X(ee,e=>{(!G(a)||!$.data?.control)&&t().fileChanges?.length?e(D):(!G(a)||!$.data?.control)&&(t().command||t().status===`APPROVAL NEEDED`)&&e(O,1)});var te=V(ee,2),k=e=>{var n=Ts(),r=B(n);H(()=>Y(r,`CONTEXT SOURCE // ${(t().source||`LOCAL`)??``} // OBSERVATION`)),J(e,n)};X(te,e=>{G(a)||e(k)}),J(e,o)},r=Wi(t,`params`,19,()=>({})),i=P(()=>$.data?.sessions||[]),a=P(()=>$.data?.control&&$.data.profiles||[]),o=P(()=>($.data?.triggers||[]).filter(e=>G(i).some(t=>t.id===e.session)));function s(e,t){if(r().id&&r().id!==t&&G(l)){e.preventDefault();return}b(t)}function c(e){return[`TURN COMPLETE`,`IDLE`,`ACTIVE`].includes(e.status)&&G(o).some(t=>t.session===e.id)?`TRIGGER SET`:e.status}let l=I(!1);function u(e,t){if(r().id&&r().id!==t&&G(l)){e.preventDefault();return}b(t)}yn(()=>{let e=r().id;e&&pr(()=>{ra.selected=e,la(e,2)})});let d=P(()=>G(i).find(e=>e.id===r().id)),p=P(()=>new URLSearchParams(Yi.querystring).get(`review`)===`profile`&&G(a).some(e=>e.session===r().id&&e.pending)),m=P(()=>G(i).some(e=>e.id===ra.selected)?ra.selected:G(i)[0]?.id),h=P(()=>!$.connected||!!$.data?.sessionsError),v=P(()=>[[`OBSERVED TOKENS`,ua(G(i).reduce((e,t)=>e+t.tokens,0))],[`LISTED SESSIONS`,ua(G(i).length)],...[[`WORKING`,`WORKING`],[`AWAITING APPROVAL`,`APPROVAL NEEDED`],[`AWAITING INPUT`,`INPUT NEEDED`],[`CHECK · INFERRED`,`CHECK SESSION`]].map(([e,t])=>[e,G(h)?`—`:ua(G(i).filter(e=>e.status===t).length)])]),y=P(()=>G(i).filter(e=>[`INPUT NEEDED`,`APPROVAL NEEDED`,`CHECK SESSION`].includes(e.status)));function b(e){ra.selected=e,ur().then(()=>document.querySelector(`.session-row.selected`)?.scrollIntoView({block:`nearest`}))}function x(e,t){if(b(e),r().id){t<0&&(la(e,2),location.hash=`/sessions`);return}let n=sa(e)+t;n>2?location.hash=`/sessions/`+encodeURIComponent(e):la(e,n)}function S(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(),x(r().id,-1);else if([`ArrowLeft`,`ArrowRight`].includes(e.key)&&(r().id||G(m)))e.preventDefault(),x(r().id||G(m),e.key===`ArrowLeft`?-1:1);else if(!r().id&&[`ArrowUp`,`ArrowDown`].includes(e.key)&&G(i).length){e.preventDefault();let t=G(i).findIndex(e=>e.id===G(m));b(G(i)[Math.max(0,Math.min(G(i).length-1,t+(e.key===`ArrowUp`?-1:1)))].id)}}}function C(e){return G(h)?`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.`:``}function w(e){return e.streaming&&e.contextKind===`LAST REPLY`?`REPLY // STREAMING`:e.contextKind||`LAST ACTIVITY`}var T=Qs();Sr(`keydown`,$t,S);var E=z(T),ee=B(V(R(E),2));M(E);var D=V(E,2);let O;Z(D,21,()=>G(v),qr,(e,t)=>{var n=P(()=>_(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Ds(),o=R(a),s=B(o,!0),c=B(V(o,2),!0);M(a),H(()=>{Y(s,r()),Y(c,i())}),J(e,a)}),M(D);var te=V(D,2),k=B(te),ne=V(te,2),re=e=>{J(e,Os())};X(ne,e=>{G(h)&&e(re)});var ie=V(ne,2),ae=e=>{J(e,ks())};X(ie,e=>{$.data?.profileError&&e(ae)});var oe=V(ie,2),se=e=>{var t=Ns(),n=R(t);Z(n,17,()=>G(y),qr,(e,t)=>{var n=As();let r;var i=B(n);H((e,a)=>{r=ci(n,1,`button`,null,r,{approval:G(t).status===`APPROVAL NEEDED`}),Q(n,`href`,e),Y(i,`${G(t).status??``} - ${a??``} // ${(G(t).name||G(t).directory||G(t).id)??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,n,()=>b(G(t).id)),J(e,n)});var c=V(n,2);Z(c,17,()=>G(a).filter(e=>e.pending&&G(i).some(t=>t.id===e.session)),qr,(e,t)=>{var n=js(),a=B(n);H((e,i,o)=>{Q(n,`title`,r().id&&r().id!==G(t).session&&G(l)?`Finish sending or clear your current draft before switching sessions.`:`Review this session’s quota threshold`),Q(n,`href`,e),Y(a,`QUOTA THRESHOLD ${i??``} // ${o??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).session)+`?review=profile`,()=>Array.from(G(t).session).slice(-5).join(``).toUpperCase(),()=>G(i).find(e=>e.id===G(t).session)?.name||G(i).find(e=>e.id===G(t).session)?.directory||G(t).session]),K(`click`,n,e=>u(e,G(t).session)),J(e,n)}),Z(V(c,2),17,()=>G(o),qr,(e,t)=>{var n=Ms(),r=B(n);H((e,t,i)=>{Q(n,`href`,e),Y(r,`TRIGGER SET ${t??``} // ${i??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).session),()=>Array.from(G(t).session).slice(-5).join(``).toUpperCase(),()=>G(i).find(e=>e.id===G(t).session)?.name||G(i).find(e=>e.id===G(t).session)?.directory]),K(`click`,n,e=>s(e,G(t).session)),J(e,n)}),M(t),J(e,t)},ce=P(()=>(G(y).length||G(a).some(e=>e.pending)||G(o).length)&&!G(h));X(oe,e=>{G(ce)&&e(se)});var le=V(oe,2),ue=e=>{var t=Pr(),i=z(t),o=e=>{var t=Rs(),i=R(t),o=R(i),s=R(o);let u;var f=V(s);M(o);var m=V(o,2);M(i);var g=V(i,2),_=e=>{var t=Ts(),n=B(t,!0);H(()=>Y(n,G(d).directory)),J(e,t)};X(g,e=>{G(d).name&&G(d).directory&&e(_)});var v=V(g,2),y=B(v),x=V(v,2);let S;var C=R(x),w=R(C);n(w,()=>G(d),()=>!0,()=>!0),M(C);var T=V(C,2),E=e=>{var t=Pr();Kr(z(t),()=>G(d).id,e=>{{let t=P(()=>new URLSearchParams(Yi.querystring).get(`schedule`)===`edit`),n=P(()=>G(d).fileChanges||[]);ss(e,{get session(){return G(d).id},get openScheduler(){return G(t)},get observedCommand(){return G(d).command},get observedFileChanges(){return G(n)},get suspended(){return G(p)},onProtectedChange:e=>{L(l,e,!0)}})}}),J(e,t)},ee=e=>{J(e,Ps())};X(T,e=>{$.data?.control?e(E):e(ee,-1)}),M(x);var D=V(x,2);Z(D,17,()=>G(a).filter(e=>e.session===G(d).id),e=>e.session,(e,t)=>{var n=Ls(),r=R(n),i=e=>{var n=Fs(),r=B(n,!0);H(()=>Y(r,G(t).notice)),J(e,n)};X(r,e=>{G(t).notice&&e(i)});var a=V(r,2),o=e=>{ss(e,{get session(){return G(d).id},review:`profile`})},s=e=>{var t=Is();H(e=>Q(t,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(d).id)+`?review=profile`]),J(e,t)};X(a,e=>{G(t).pending&&G(p)?e(o):G(t).pending&&e(s,1)}),M(n),H(()=>Q(n,`id`,`quota-profile-`+G(d).id)),J(e,n)});var O=V(D,2),te=e=>{var t=Pr();Kr(z(t),()=>G(d).id,e=>{ms(e,{get session(){return G(d)},active:!0})}),J(e,t)};X(O,e=>{G(p)||e(te)}),Kr(V(O,2),()=>G(d).id,e=>{fs(e,{get session(){return G(d)},get stale(){return G(h)}})}),M(t),H((e,t)=>{u=ci(s,1,`lamp lit`,null,u,{working:G(d).status===`WORKING`&&!G(h)}),Y(f,`${e??``} // ${(G(d).name||G(d).directory)??``}`),Y(y,`${t??``} TOKENS // ${G(d).id??``} // CONTEXT SOURCE // ${(G(d).source||`LOCAL`)??``}`),S=ui(x,``,S,{display:G(p)?`none`:void 0})},[()=>G(h)?`STALE`:G(p)?`QUOTA THRESHOLD`:c(G(d)),()=>ua(G(d).tokens)]),K(`click`,m,()=>{b(r().id),la(r().id,2)}),J(e,t)},s=e=>{J(e,zs())};X(i,e=>{G(d)?e(o):e(s,-1)}),J(e,t)},de=e=>{var t=Zs(),r=z(t),o=V(R(r),2),s=R(o),l=V(s,2);M(o),M(r);var d=V(r,2);Z(d,17,()=>G(i),e=>e.id,(e,t)=>{let r=P(()=>sa(G(t).id));var i=Ys();let o;var s=R(i),l=R(s),d=e=>{var n=Bs(),r=R(n),i=B(r);M(n),H(e=>{Q(r,`aria-pressed`,G(m)===G(t).id),Y(i,`${e??``} // ${G(t).name??``}`)},[()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,r,()=>b(G(t).id)),J(e,n)};X(l,e=>{G(t).name&&e(d)});var f=V(l,2),p=R(f),g=R(p);let _;var v=V(g,1,!0);M(p),M(f);var y=V(f,2),S=e=>{var n=Vs(),r=B(n,!0);H(()=>{Q(n,`aria-pressed`,G(m)===G(t).id),Y(r,G(t).directory||G(t).id)}),K(`click`,n,()=>b(G(t).id)),J(e,n)};X(y,e=>{G(t).name||e(S)});var C=V(y,2),T=R(C);Ce(),M(C);var E=V(C,2),ee=e=>{var n=Ts(),r=B(n,!0);H(()=>Y(r,G(t).directory)),J(e,n)};X(E,e=>{G(t).name&&G(t).directory&&e(ee)});var D=V(E,2),O=B(D),te=V(D,2),k=B(te),ne=V(te,2),re=R(ne),ie=V(re,2),ae=B(ie,!0),oe=V(ie,2);M(ne);var se=V(ne,2),ce=V(se,2),le=e=>{var n=Hs(),r=B(n,!0);H(()=>Y(r,G(t).status===`CHECK SESSION`?`INFERRED INACTIVITY`:$.data?.control?`OPEN FULL DETAIL OR REPLY IN CODEX`:G(t).status===`APPROVAL NEEDED`?`APPROVE OR DECLINE IN CODEX`:`REPLY IN CODEX`)),J(e,n)},ue=P(()=>!G(h)&&[`APPROVAL NEEDED`,`INPUT NEEDED`,`CHECK SESSION`].includes(G(t).status));X(ce,e=>{G(ue)&&e(le)}),M(s);var de=V(s,2),fe=e=>{var r=qs(),i=R(r),o=R(i),s=B(o,!0),c=V(o,2),l=e=>{var n=Us(),r=B(n,!0);H(e=>{Q(n,`href`,e),Y(r,$.data?.control?`REVIEW IN FULL DETAIL ↗`:`APPROVAL IN CODEX ↗`)},[()=>`#/sessions/`+encodeURIComponent(G(t).id)]),J(e,n)};X(c,e=>{!G(h)&&G(t).status===`APPROVAL NEEDED`&&e(l)}),M(i);var d=V(i,2);n(d,()=>G(t),()=>!1);var f=V(d,2);Z(f,17,()=>G(a).filter(e=>e.session===G(t).id),qr,(e,n)=>{var r=Ks(),i=z(r),a=e=>{var t=Ws(),r=B(t,!0);H(()=>Y(r,G(n).notice)),J(e,t)};X(i,e=>{G(n).notice&&e(a)});var o=V(i,2),s=e=>{var n=Gs();H(e=>Q(n,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(t).id)+`?review=profile`]),K(`click`,n,e=>u(e,G(t).id)),J(e,n)};X(o,e=>{G(n).pending&&e(s)}),J(e,r)});var p=V(f,2);{let e=P(()=>G(m)===G(t).id);ms(p,{get session(){return G(t)},get active(){return G(e)}})}M(r),H(e=>Y(s,e),[()=>w(G(t))]),J(e,r)};X(de,e=>{G(r)>0&&e(fe)});var pe=V(de,2),me=e=>{var n=Js(),r=V(R(n),2);{let e=P(()=>(G(t).samples||[]).map(e=>e.tokens));no(r,{get values(){return G(e)},capacity:120})}var i=B(V(r,2));M(n),H(()=>Y(i,`LAST ${(G(t).samples?.length||0)??``} SAMPLES // AUTO SCALE`)),J(e,n)};X(pe,e=>{G(r)<2&&e(me)}),M(i),H((e,n,a,s,c)=>{o=ci(i,1,`session-row`,null,o,{selected:G(m)===G(t).id,wide:G(r)===2,split:G(r)===1}),Q(i,`aria-label`,`Session `+(G(t).name||G(t).directory||G(t).id)),Q(p,`href`,e),_=ci(g,1,`lamp lit`,null,_,{working:G(t).status===`WORKING`&&!G(h)}),Y(v,n),Y(T,`${a??``} `),Y(O,`${G(t).agents??``} LINKED AGENTS`),Y(k,`ACTIVE // ${s??``}`),re.disabled=G(r)===0,Q(ie,`aria-expanded`,G(r)>0),Y(ae,G(r)?`HIDE DETAIL`:`SHOW DETAIL`),Q(se,`href`,c)},[()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>G(h)?`STALE`:c(G(t)),()=>ua(G(t).tokens),()=>da(G(t).activity),()=>`#/sessions/`+encodeURIComponent(G(t).id)]),K(`click`,p,()=>b(G(t).id)),K(`click`,re,()=>x(G(t).id,-1)),K(`click`,ie,()=>{b(G(t).id),la(G(t).id,+!G(r))}),K(`click`,oe,()=>x(G(t).id,1)),K(`click`,se,()=>b(G(t).id)),J(e,i)});var f=V(d,2),p=e=>{J(e,Xs())};X(f,e=>{G(i).length||e(p)}),K(`click`,s,()=>ca(1)),K(`click`,l,()=>ca(0)),J(e,t)};X(le,e=>{r().id?e(ue):e(de,-1)}),H(e=>{Y(ee,`OBSERVED ${e??``}`),O=ci(D,1,`session-totals`,null,O,{stale:G(h)}),Y(k,`${G(h)?`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.`)},[()=>da($.data?.sessionsAt)]),J(e,T),Ge()}Cr([`click`]);var ec=q(`

      `),tc=q(`

      Relative usage/credits are not tokens or quota percentages. Groupings - describe the same usage, not additional consumption.

      `,1),nc=q(`// APPROXIMATE`),rc=q(`

      Partial accounting: totals may still change.

      `),ic=q(`

      Percentage of this period's historical allowance, not today's limit. May - exceed 100%. This is not a manual/automatic reset log.

      `,1),ac=q(`

      `,1),oc=q(`

      This optional account report is unavailable. Token history remains - available; missing data does not mean zero usage.

      `),sc=q(`
      `),cc=q(`
      `),lc=q(`

      No usage reported for this day.

      `),uc=q(`

      Selected breakdown unavailable; missing does not mean zero.

      `),dc=q(`

      `,1);function fc(e,t){We(t,!0);let n=I(`surface`),r=I(0),i=P(()=>t.reports?.daily),a=P(()=>t.reports?.plan),o=P(()=>t.mode===`breakdown`?G(i)?.days.length||0:G(a)?.periods.length||0),s=P(()=>Math.min(G(r),Math.max(0,G(o)-1))),c=P(()=>G(i)?.days[(G(i)?.days.length||0)-1-G(s)]),l=P(()=>G(a)?.periods[G(s)]),u=P(()=>t.mode===`breakdown`?G(i)?.units||``:`%`),d=P(()=>{let e=Object.create(null);if(t.mode===`breakdown`)e=G(c)?.groups[G(n)]||{};else{let t=G(n)===`feature`?`thread_source`:G(n)===`task start`?`turn_trigger`:G(n);for(let n of G(l)?.breakdowns||[])if(n.dimension===t)for(let t of n.rows)e[t.key]=(e[t.key]||0)+t.basis_points/100}return Object.entries(e).sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0]))}),f=P(()=>t.mode===`breakdown`?G(c)?.total:G(l)?.used_basis_points==null?null:G(l).used_basis_points/100),p=P(()=>Math.max(1,G(f)||0,...G(d).map(([,e])=>e))),m=e=>e==null?`UNKNOWN`:e.toLocaleString(`en-GB`,{maximumFractionDigits:2});var h=dc(),g=z(h),v=R(g),y=V(R(v)),b=R(y);b.value=b.__value=`surface`;var x=V(b);x.value=x.__value=`model`;var S=V(x);S.value=S.__value=`feature`;var C=V(S);C.value=C.__value=`task start`,M(y),mi(y),M(v);var w=V(v,2),T=V(w,2),E=B(V(T,2),!0);M(g);var ee=V(g,2),D=R(ee),O=B(D,!0),te=V(D,2),k=B(te),ne=V(te,2),re=e=>{var t=tc(),n=z(t),r=B(n),a=V(n,2),o=e=>{var t=ec(),n=B(t);H(()=>Y(n,`Data as of ${G(i).dataAsOf??``}`)),J(e,t)};X(a,e=>{G(i).dataAsOf&&e(o)});var s=B(V(a,2));Ce(2),H((e,t)=>{Y(r,`Latest fetch ${e??``} // queried ${G(i).from??``} → ${G(i).through??``}. - Reports are fetched from OpenAI and are not saved between runs.`),Y(s,`${(G(c)?.date||`No daily buckets reported`)??``} // ${t??``} - ${G(u)??``}`)},[()=>da(G(i).fetchedAt),()=>m(G(f))]),J(e,t)},ie=e=>{var t=ac(),n=z(t),r=R(n);let i;var o=B(r,!0),s=V(r),c=e=>{J(e,nc())};X(s,e=>{G(a).approximate&&e(c)});var u=V(s);M(n);var d=V(n,2),p=R(d),h=V(p),g=e=>{var t=Nr();H(()=>Y(t,`// Boundary tolerance ${G(a).boundary_tolerance_seconds??``}s`)),J(e,t)};X(h,e=>{G(a).boundary_tolerance_seconds!=null&&e(g)}),M(d);var _=V(d,2),v=e=>{var t=ic(),n=z(t),r=R(n),i=V(r);let a;var o=B(i);M(n);var s=V(n,2),c=B(s),u=V(s,2),d=e=>{J(e,rc())};X(u,e=>{G(l).accounting_complete||e(d)}),Ce(2),H(e=>{Y(r,`${G(l).window_minutes??``} MIN // ${G(l).plan_type??``} // `),a=ci(i,1,`svelte-1fbui7h`,null,a,{muted:G(f)==null,"quota-near":G(f)!=null&&G(f)>=80&&G(f)<100,"quota-full":G(f)!=null&&G(f)>=100}),Y(o,`USED ${e??``}${G(f)==null?``:`%`}`),Y(c,`${G(l).starts_at??``} → ${G(l).ends_at??``}`)},[()=>m(G(f))]),J(e,t)};X(_,e=>{G(l)&&e(v)}),H(e=>{i=ci(r,1,`svelte-1fbui7h`,null,i,{"quality-warning":!G(a).coverage_complete}),Y(o,G(a).coverage_complete?`Reported range complete`:`Partial coverage`),Y(u,` // Latest fetch ${e??``}`),Y(p,`Coverage starts ${(G(a).coverage_start||`unknown`)??``} // Data as of ${(G(a).data_as_of||`unknown`)??``}`)},[()=>da(G(a).fetchedAt)]),J(e,t)},ae=e=>{J(e,oc())};X(ne,e=>{t.mode===`breakdown`&&G(i)?e(re):t.mode===`periods`&&G(a)?e(ie,1):e(ae,-1)});var oe=V(ne,2),se=e=>{var n=cc(),r=R(n),i=B(V(R(r),2),!0);M(r),Z(V(r,2),17,()=>G(d),qr,(e,n,r)=>{var i=P(()=>_(G(n),2));let a=()=>G(i)[0],o=()=>G(i)[1];var s=sc();let c;var l=R(s),u=B(l,!0),d=V(l,2),f=R(d);let h;M(d);var g=B(V(d,2));M(s),H((e,n,i)=>{c=ci(s,1,`report-row svelte-1fbui7h`,null,c,{unknown:e,alternate:r%2==1}),Q(l,`title`,a()),Y(u,a()),h=ui(f,``,h,{width:n}),Y(g,`${i??``}${t.mode===`periods`?`%`:``}`)},[()=>a().trim().toLowerCase()===`unknown`,()=>`${Math.max(0,100*o()/G(p))}%`,()=>m(o())]),J(e,s)}),M(n),H(()=>Y(i,t.mode===`breakdown`?G(u):`QUOTA USED`)),J(e,n)},ce=e=>{J(e,lc())},le=e=>{J(e,uc())};X(oe,e=>{G(d).length?e(se):t.mode===`breakdown`&&G(c)?.total===0&&G(c)?.groups[G(n)]!=null?e(ce,1):(G(i)&&t.mode===`breakdown`||G(a)&&t.mode===`periods`)&&e(le,2)}),M(ee),H(()=>{w.disabled=G(s)>=G(o)-1,T.disabled=G(s)===0,Y(E,G(o)?`${G(s)+1} / ${G(o)}`:`NO DATA`),Y(O,t.mode===`breakdown`?`DAILY BREAKDOWN`:`QUOTA WINDOWS`),Y(k,`${(t.mode===`breakdown`?t.reports?.dailyStatus||`UNAVAILABLE`:t.reports?.planStatus||`UNAVAILABLE`)??``} // UTC`)}),hi(y,()=>G(n),e=>L(n,e)),K(`click`,w,()=>L(r,G(s)+1)),K(`click`,T,()=>L(r,G(s)-1)),J(e,h),Ge()}Cr([`click`]);var pc=864e5;function mc(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 hc(e,t,n){let r=new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()));for(let e=0;;e++){let i=mc(r,-t),a=new Date(i.getTime()+pc);if(e===n)return{start:a,end:r};r=i}}var gc=q(``),_c=q(``,1),vc=q(`

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

      `),yc=q(`

      Token history unavailable; other reports may still be available.

      `),bc=q(``),xc=q(`
      `),Sc=q(`

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

      `,1),Cc=q(`
      `,1),wc=q(` `),Tc=q(`

      LIFETIME TOKENS

      PEAK DAY

      CURRENT STREAK

      DAYS

      LONGEST TURN

      SECONDS

      LONGEST STREAK

      DAYS

      OPENAI // UTC

      Accessible data table
      Date (UTC)Tokens

      `,1),Ec=q(`

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

      `),Dc=q(`

      USAGE // ACCOUNT HISTORY

      Account-wide history reported by Codex, not the local Sessions counter. Dates - use UTC. Allowance history is approximate where indicated; reset causes are - not provided.

      `,1);function Oc(e,t){We(t,!0);let n=I(`daily`),r=I(12),i=I(0),a=P(()=>{let e=$.data?.usage?.dailyUsageBuckets;if(!e)return[];let{start:t,end:n}=hc(new Date,G(r),G(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=P(()=>Math.max(1,...G(a).map(e=>e.tokens))),s=P(()=>G(a).length?new Date(G(a)[0].date+`T00:00:00Z`).getUTCDay():0),c=P(()=>{if(G(n)===`monthly`){let e=new Map;for(let t of G(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 G(a).map(t=>({date:t.date,tokens:e+=t.tokens}))});var l=Dc(),u=V(z(l),4);Z(u,20,()=>[[`daily`,`Daily`],[`monthly`,`Monthly`],[`cumulative`,`Cumulative`],[`breakdown`,`Breakdown`],[`periods`,`Windows`]],qr,(e,t)=>{var r=P(()=>_(t,2));let a=()=>G(r)[0],o=()=>G(r)[1];var s=gc();let c;var l=B(s,!0);H(()=>{Q(s,`aria-pressed`,G(n)===a()),c=ci(s,1,``,null,c,{active:G(n)===a()}),Y(l,o())}),K(`click`,s,()=>{L(n,a(),!0),L(i,0)}),J(e,s)}),M(u);var d=V(u,2),f=R(d),p=e=>{var t=_c(),n=z(t),a=V(R(n)),o=R(a);o.value=o.__value=6;var s=V(o);s.value=s.__value=12,M(a),mi(a),M(n);var c=V(n),l=V(c);H(()=>l.disabled=G(i)===0),K(`change`,a,()=>L(i,0)),hi(a,()=>G(r),e=>L(r,e)),K(`click`,c,()=>qt(i)),K(`click`,l,()=>qt(i,-1)),J(e,t)};X(f,e=>{G(n)!==`breakdown`&&G(n)!==`periods`&&e(p)}),M(d);var m=V(d,2),h=e=>{J(e,vc())};X(m,e=>{$.data?.usageError&&e(h)});var g=V(m,2),v=e=>{J(e,yc())};X(g,e=>{$.data?.usage?.tokenStatus===`UNAVAILABLE`&&G(n)!==`breakdown`&&G(n)!==`periods`&&e(v)});var y=V(g,2),b=e=>{var t=Pr();Kr(z(t),()=>G(n),e=>{{let t=P(()=>$.data?.usage?.reports);fc(e,{get reports(){return G(t)},get mode(){return G(n)}})}}),J(e,t)},x=e=>{var t=Tc(),r=z(t),i=R(r),l=B(V(R(i),2),!0);M(i);var u=V(i,2),d=B(V(R(u),2),!0);M(u);var f=V(u,2),p=V(R(f),2),m=R(p);Ce(),M(p),M(f);var h=V(f,2),g=V(R(h),2),_=R(g);Ce(),M(g),M(h);var v=V(h,2),y=V(R(v),2),b=R(y);Ce(),M(y),M(v),M(r);var x=V(r,4),S=R(x),C=B(S),w=V(S,2),T=e=>{var t=Sc(),n=z(t),r=R(n),i=R(r);Z(i,17,()=>Array(G(s)),qr,(e,t)=>{J(e,bc())}),Z(V(i,2),17,()=>G(a),qr,(e,t)=>{var n=xc();let r,i;H(e=>{r=ci(n,1,`heat-cell`,null,r,{zero:G(t).tokens===0}),Q(n,`title`,e),i=ui(n,``,i,{opacity:G(t).tokens?.25+.75*G(t).tokens/G(o):1})},[()=>`${G(t).date}: ${ua(G(t).tokens)} tokens`]),J(e,n)}),M(r),M(n),Ce(2),J(e,t)},E=e=>{var t=Cc(),r=z(t);{let e=P(()=>G(c).map(e=>e.tokens)),t=P(()=>G(n)+` usage`);no(r,{get values(){return G(e)},get label(){return G(t)}})}var i=V(r,2),a=R(i),o=B(a,!0),s=B(V(a),!0);M(i),H(e=>{Y(o,G(c)[0]?.date),Y(s,e)},[()=>G(c).at(-1)?.date]),J(e,t)};X(w,e=>{G(n)===`daily`?e(T):e(E,-1)});var ee=V(w,2),D=V(R(ee),2),O=R(D),te=V(R(O));Z(te,21,()=>G(n)===`daily`?G(a):G(c),qr,(e,t)=>{var n=wc(),r=R(n),i=B(r,!0),a=B(V(r),!0);M(n),H(e=>{Y(i,G(t).date),Y(a,e)},[()=>ua(G(t).tokens)]),J(e,n)}),M(te),M(O),M(D),M(ee),M(x);var k=B(V(x,2));H((e,t,n,r,i,o,s)=>{Y(l,e),Y(d,t),Y(m,`${n??``} `),Y(_,`${r??``} `),Y(b,`${i??``} `),Y(C,`${G(a)[0]?.date??``} — ${o??``}`),Y(k,`OBSERVED ${s??``} // CUMULATIVE IS FOR THE SELECTED PERIOD`)},[()=>ua($.data.usage.summary.lifetimeTokens),()=>ua($.data.usage.summary.peakDailyTokens),()=>ua($.data.usage.summary.currentStreakDays),()=>ua($.data.usage.summary.longestRunningTurnSec),()=>ua($.data.usage.summary.longestStreakDays),()=>G(a).at(-1)?.date,()=>da($.data.usageAt)]),J(e,t)},S=e=>{J(e,Ec())};X(y,e=>{G(n)===`breakdown`||G(n)===`periods`?e(b):$.data?.usage&&$.data.usage.dailyUsageBuckets!==null?e(x,1):e(S,-1)}),J(e,l),Ge()}Cr([`click`,`change`]);var kc=q(`

      Page not found

      Return to Quota

      `,1);function Ac(e){var t=kc();Ce(2),J(e,t)}var jc=q(` `),Mc=q(`

      `),Nc=q(`

      Connecting to your local Codexometer…

      `),Pc=q(``),Fc=q(`
      CODEXOMETER

      Your quota. Your sessions. Your command centre.

      `);function Ic(e,t){We(t,!0);let n={"/":$a,"/quota/:view?":$a,"/sessions/:id?":$s,"/usage":Oc,"*":Ac},r={quota:/^(?:\/|\/quota(?:\/[^/]+)?\/?)$/,sessions:/^\/sessions(?:\/[^/]+)?\/?$/,usage:/^\/usage\/?$/},i=I(`hacker`),a=[`hacker`,`rust`,`blue-steel`,`ultraviolet`,`nightshade`];yn(()=>{aa()}),yn(()=>{if($.data)for(let[e,t]of Object.entries(r))t.test(Yi.location)&&(ra.tab=e)}),Gi(()=>{try{let e=localStorage.getItem(`codexometer.web.theme`);e&&a.includes(e)&&L(i,e,!0)}catch{}return ga()});function o(){try{localStorage.setItem(`codexometer.web.theme`,G(i))}catch{}}var s=Fc(),c=R(s),l=V(R(c),2),u=R(l);let d;var f=V(u,1,!0),p=B(V(f));M(l),M(c);var m=V(c,2);Z(m,21,()=>Object.entries(r),qr,(e,t)=>{var n=P(()=>_(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1],a=P(()=>i().test(Yi.location));var o=jc();let s;var c=B(o,!0);H(e=>{Q(o,`href`,r()===`quota`?`#/quota/`+ra.view:`#/`+r()),Q(o,`aria-current`,G(a)?`page`:void 0),s=ci(o,1,``,null,s,{active:G(a)}),Y(c,e)},[()=>r().toUpperCase()]),J(e,o)}),M(m);var h=V(m,2),g=R(h),v=e=>{var t=Mc(),n=B(t,!0);H(()=>Y(n,$.error)),J(e,t)};X(g,e=>{$.error&&e(v)});var y=V(g,2),b=e=>{Qi(e,{get routes(){return n}})},x=e=>{J(e,Nc())};X(y,e=>{$.data?e(b):$.error||e(x,1)}),M(h);var S=V(h,2),C=R(S),w=B(C),T=V(C,2),E=B(T,!0),ee=V(T,2),D=V(R(ee));Z(D,21,()=>a,qr,(e,t)=>{var n=Pc(),r=B(n,!0),i={};H(e=>{Y(r,e),i!==(i=G(t))&&(n.value=(n.__value=i)??``)},[()=>G(t).replace(`-`,` `).toUpperCase()]),J(e,n)}),M(D),mi(D),M(ee),M(S),M(s),H(()=>{Q(s,`data-theme`,G(i)),d=ci(u,1,`lamp`,null,d,{lit:$.connected}),Y(f,$.connected?`CONNECTED`:`OFFLINE`),Y(p,`EXPERIMENTAL // ${$.data?.control?`SESSION CONTROL`:`READ ONLY`}`),Y(w,`v${($.data?.version||`…`)??``} // LOCAL ONLY`),Y(E,$.data?.control?`Session control enabled. Stop the server to revoke access.`:`No actions can be sent from this preview.`)}),K(`change`,D,o),hi(D,()=>G(i),e=>L(i,e)),J(e,s),Ge()}Cr([`change`]),Br(Ic,{target:document.getElementById(`app`)}); \ No newline at end of file diff --git a/internal/web/dist/assets/index-ED7GoxW0.css b/internal/web/dist/assets/index-ED7GoxW0.css new file mode 100644 index 0000000..b31a55d --- /dev/null +++ b/internal/web/dist/assets/index-ED7GoxW0.css @@ -0,0 +1 @@ +.observation-details.svelte-1vgdi83{font-size:12px}summary.svelte-1vgdi83{cursor:pointer;color:var(--accent)}.observation-table.svelte-1vgdi83{max-height:240px;overflow:auto}.zone-canvas.svelte-1vgdi83{flex:1;min-height:170px;margin-top:6px;position:relative}svg.svelte-1vgdi83{width:100%;height:100%;display:block;position:absolute;inset:0}text.svelte-1vgdi83{fill:var(--ink);font:14px Cascadia Code,Consolas,monospace}.axis-title.svelte-1vgdi83{letter-spacing:.04em;font-size:12px}.grid.svelte-1vgdi83{stroke:#fff;stroke-opacity:.14;stroke-width:1px}.axes.svelte-1vgdi83{stroke:var(--ink);stroke-width:1.5px;fill:none}.pace-line.svelte-1vgdi83{stroke:#fff;stroke-width:2px;stroke-dasharray:6 4}.position-halo.svelte-1vgdi83{fill:#101820;stroke:#fff;stroke-width:1.5px}.position-dot.svelte-1vgdi83{fill:#fff}.observation-trail.svelte-1vgdi83{fill:none;stroke:#101820;stroke-width:2.5px;stroke-linejoin:round}.observation-trail-casing.svelte-1vgdi83{fill:none;stroke:#ffffff73;stroke-width:4.5px;stroke-linejoin:round}.trail-start.svelte-1vgdi83{fill:#101820;stroke:#ffffffb3;stroke-width:2px}.trend-line.svelte-1vgdi83{fill:none;stroke:var(--trend-color);stroke-width:2px;stroke-dasharray:3 6}.trend-arrow.svelte-1vgdi83{fill:var(--trend-color);stroke:#ffffff73;stroke-width:.5px}.trend-casing.svelte-1vgdi83{fill:none;stroke:#ffffff73;stroke-width:4px;stroke-dasharray:3 6}.zone-caption.svelte-1vgdi83{min-width:0;color:var(--accent);flex:auto;margin:0}.trend-summary.svelte-1vgdi83{color:var(--ink)}.zone-footer.svelte-1vgdi83{justify-content:space-between;align-items:flex-start;gap:12px;margin-top:4px;display:flex}.zone-controls.svelte-1vgdi83{color:var(--muted);text-align:right;flex-direction:column;align-items:flex-end;gap:5px;font-size:11px;display:flex}.trace-control.svelte-1vgdi83,.trend-control.svelte-1vgdi83{cursor:pointer;white-space:nowrap}.trace-control.svelte-1vgdi83 input:where(.svelte-1vgdi83){accent-color:var(--accent)}.trend-control.svelte-1vgdi83 select:where(.svelte-1vgdi83){border:1px solid var(--edge);background:var(--panel);max-width:min(230px,45vw);color:var(--ink);font:inherit}.trend-control.svelte-1vgdi83 option:where(.svelte-1vgdi83):disabled{color:var(--muted)}.zone-controls.svelte-1vgdi83 small:where(.svelte-1vgdi83){font-size:10px}@container (width<=560px){.zone-footer.svelte-1vgdi83{flex-direction:column}.zone-controls.svelte-1vgdi83{align-self:stretch;align-items:flex-end}}.slash-commands.svelte-7bfwr9{margin:.4rem 0;position:relative}.command-popup.svelte-7bfwr9{z-index:5;box-sizing:border-box;border:1px solid var(--accent);background:var(--panel);width:min(40rem,100%);padding:.35rem;position:absolute;bottom:100%;left:0;box-shadow:0 .3rem 1rem #0006}.command-popup.svelte-7bfwr9 p:where(.svelte-7bfwr9){margin:.3rem 0;font-size:.8em}.command-options.vertical.svelte-7bfwr9{flex-flow:column;gap:.15rem;display:flex}.vertical.svelte-7bfwr9 button:where(.svelte-7bfwr9){text-align:left;white-space:nowrap;width:100%;min-width:0;color:var(--muted);background:var(--panel);border-color:#0000;flex:none;align-items:baseline;gap:.4rem;display:flex}.vertical.svelte-7bfwr9 .command-name:where(.svelte-7bfwr9),.vertical.svelte-7bfwr9 .command-tail:where(.svelte-7bfwr9){flex:none}.vertical.svelte-7bfwr9 .command-name:where(.svelte-7bfwr9){text-overflow:ellipsis;max-width:100%;overflow:hidden}.vertical.svelte-7bfwr9 button.suggested:where(.svelte-7bfwr9){outline:none}.vertical.svelte-7bfwr9 button.suggested:where(.svelte-7bfwr9) .command-name:where(.svelte-7bfwr9),.vertical.svelte-7bfwr9 button:where(.svelte-7bfwr9):hover .command-name:where(.svelte-7bfwr9){background:var(--accent);color:var(--bg)}.vertical.svelte-7bfwr9 .command-help:where(.svelte-7bfwr9){min-width:0;max-width:none;color:var(--muted);flex:1}.command-options.svelte-7bfwr9{flex-wrap:wrap;gap:.35rem;max-height:35vh;display:flex;overflow:auto}.command-options.svelte-7bfwr9 .suggested:where(.svelte-7bfwr9){outline:1px solid var(--accent)}.command-help.svelte-7bfwr9{text-overflow:ellipsis;white-space:nowrap;opacity:.75;max-width:32ch;font-size:.8em;display:block;overflow:hidden}pre.svelte-7bfwr9{white-space:pre-wrap;overflow-wrap:anywhere;max-height:35vh;overflow:auto}.file-diff.svelte-x4gtb6{border:1px solid var(--muted);max-height:60vh;padding:.5rem;font-family:monospace;overflow:auto}.diff-line.svelte-x4gtb6{white-space:pre;min-height:1.3em;display:flex}.line-number.svelte-x4gtb6{text-align:right;opacity:.75;-webkit-user-select:none;user-select:none;flex:0 0 5ch;padding-right:1ch;display:inline-block}.added.svelte-x4gtb6{color:#67d391;background:#67d39112}.removed.svelte-x4gtb6{color:#ff6b83;background:#ff6b8312}.heading.svelte-x4gtb6{padding:.5rem 0;font-weight:700}.saved-prompt.svelte-1oupzfc{white-space:pre-wrap;overflow-wrap:anywhere}fieldset.svelte-1oupzfc{border:1px solid;margin:.5rem 0;padding:.35rem .6rem}.decision.svelte-1oupzfc,.answer.svelte-1oupzfc{margin:.3rem 0;display:block}.decision.svelte-1oupzfc code:where(.svelte-1oupzfc),.decision.svelte-1oupzfc span:where(.svelte-1oupzfc){overflow-wrap:anywhere;margin:.3rem 0 .3rem 1.5rem;display:block}textarea.svelte-1oupzfc,.answer.svelte-1oupzfc input:where(.svelte-1oupzfc),.answer.svelte-1oupzfc select:where(.svelte-1oupzfc){box-sizing:border-box;background:var(--bg);width:100%;color:inherit;font:inherit;border:1px solid;margin-top:.4rem;padding:.5rem;display:block}textarea.svelte-1oupzfc{resize:vertical;background:color-mix(in srgb, currentColor 8%, var(--bg))}button.svelte-1oupzfc{margin:.3rem .5rem .3rem 0}h3.svelte-1oupzfc,p.svelte-1oupzfc{margin-block:.4rem}.sent.svelte-1oupzfc{color:var(--accent)}.status-line.svelte-gprptn{align-items:center;gap:.5rem;min-width:0;margin-top:.5rem;display:flex}.status-line.svelte-gprptn p:where(.svelte-gprptn){white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;margin:0;font-size:.8rem;overflow:hidden}.configure.svelte-gprptn{padding:.15rem .35rem;font-size:.75rem}.status-picker.svelte-gprptn{border:1px solid var(--edge);margin:.5rem 0;padding:.6rem}.fields.svelte-gprptn{max-height:35vh;overflow:auto}.field.svelte-gprptn{align-items:center;gap:.35rem;display:flex}.field.svelte-gprptn label:where(.svelte-gprptn){flex:1;align-items:center;gap:.4rem;display:flex}.field.svelte-gprptn label:where(.svelte-gprptn) span:where(.svelte-gprptn){font-size:.75rem}.field.svelte-gprptn button:where(.svelte-gprptn){padding:.1rem .35rem}.session-copy.svelte-543j00{justify-content:flex-end;align-items:center;gap:8px;margin-top:auto;padding-top:6px;display:flex}span.svelte-543j00{color:var(--muted);overflow-wrap:anywhere;font-size:12px}button.svelte-543j00{color:var(--accent);flex-shrink:0;padding:3px 7px}button.svelte-543j00:hover,button.flashed.svelte-543j00{color:var(--bg);background:var(--accent)}h3.svelte-1fbui7h,.window-dates.svelte-1fbui7h,.report-value.svelte-1fbui7h{color:var(--accent);font-weight:700}.quality-warning.svelte-1fbui7h,.quota-near.svelte-1fbui7h{color:var(--approval)}.quota-full.svelte-1fbui7h{color:#ff6680}.alternate.svelte-1fbui7h .report-fill:where(.svelte-1fbui7h){background:radial-gradient(circle, var(--panel) .7px, transparent .9px) 0 0 / 3px 3px, var(--accent)}.unknown.svelte-1fbui7h,.unknown.svelte-1fbui7h .report-value:where(.svelte-1fbui7h){color:var(--muted)}.unknown.svelte-1fbui7h .report-fill:where(.svelte-1fbui7h){background:var(--muted);opacity:1}.report-bars.svelte-1fbui7h{grid-template-columns:minmax(5rem,1fr) minmax(2rem,3fr) auto;gap:.6rem;display:grid}.report-row.svelte-1fbui7h,.report-head.svelte-1fbui7h{grid-column:1/-1;grid-template-columns:subgrid;align-items:center;gap:.6rem;display:grid}.report-head.svelte-1fbui7h{color:var(--muted);font-size:.85rem}.report-head.svelte-1fbui7h>span:where(.svelte-1fbui7h):last-child,.report-value.svelte-1fbui7h{text-align:right}.report-row.svelte-1fbui7h>span:where(.svelte-1fbui7h):first-child{overflow-wrap:anywhere}.report-track.svelte-1fbui7h{background:var(--panel);height:1rem}.report-fill.svelte-1fbui7h{background:var(--accent);height:100%}:root{font-synthesis:none;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;background:#080e0c;font-family:Cascadia Code,SFMono-Regular,Consolas,monospace}*{box-sizing:border-box}body{margin:0}.shell{--accent:#80edac;--approval:#ffca58;--muted:#98aaa0;--edge:#31473a;--panel:#101c16;--bg:#080e0c;--ink:#e2eee5;background:var(--bg);height:100dvh;color:var(--ink);grid-template-rows:auto auto minmax(0,1fr) auto;padding:clamp(10px,1.2vw,20px);display:grid}.shell[data-theme=rust]{--approval:#ff8a3d;--accent:#ffbc75;--muted:#bfac95;--edge:#59412c;--panel:#261b14;--bg:#140e0a}.shell[data-theme=blue-steel]{--approval:#e8c46a;--accent:#85c8ff;--muted:#9cacc4;--edge:#334d69;--panel:#142235;--bg:#0b1421}.shell[data-theme=ultraviolet]{--approval:#f9a8d4;--accent:#c5adff;--muted:#b3a6c9;--edge:#4b3c68;--panel:#241a35;--bg:#140d22}.shell[data-theme=nightshade]{--approval:#8f7cff;--accent:#e59bff;--muted:#c6a7cf;--edge:#673976;--panel:#301739;--bg:#1c0b24}header,.spread,footer,.controls{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:10px;display:flex}header{margin-bottom:10px}.brand{letter-spacing:.08em;color:var(--accent);text-shadow:0 0 22px color-mix(in srgb, var(--accent) 20%, transparent);font-size:clamp(22px,2.5vw,32px);font-weight:800;text-decoration:none}header p{color:var(--muted);margin:3px 0 0;font-size:13px}.connection{color:var(--accent);text-align:right}small,.eyebrow{letter-spacing:.04em;font-size:12px}.connection small{color:var(--muted);margin-top:4px;display:block}.lamp{background:var(--muted);border-radius:50%;width:9px;height:9px;margin-right:9px;display:inline-block}.lamp.lit{background:var(--accent);box-shadow:0 0 8px color-mix(in srgb, var(--accent) 40%, transparent)}.working{animation:1.5s ease-in-out infinite pulse}@keyframes pulse{50%{opacity:.3}}nav{flex-wrap:wrap;gap:6px;margin-bottom:10px;display:flex}nav a,button,.button,select{font:inherit;color:var(--accent);border:1px solid var(--edge);background:var(--panel);cursor:pointer;border-radius:3px;padding:7px 11px;font-size:13px;text-decoration:none}button:hover,.button:hover,nav a:hover{border-color:var(--accent)}nav a.active,nav button.active{background:var(--accent);color:var(--bg);border-color:var(--accent)}:focus-visible{outline:2px solid var(--accent);outline-offset:4px}.secondary{margin-bottom:8px}.secondary a,.secondary button{padding:6px 10px;font-size:12px}main{scrollbar-gutter:stable;flex-direction:column;min-width:0;min-height:0;display:flex;overflow:auto}main>*{flex-shrink:0}.panel{border:1px solid var(--edge);border-top:2px solid var(--accent);background:var(--panel);border-radius:4px;min-width:0;padding:clamp(10px,1vw,16px)}h1{color:var(--accent);font-size:20px}h2{letter-spacing:.04em;color:var(--accent);overflow-wrap:anywhere;margin:0 0 10px;font-size:13px}h3{overflow-wrap:anywhere;font-size:13px}p{margin:6px 0;font-size:13px;line-height:1.45}a{color:var(--accent)}.muted,.eyebrow{color:var(--muted)}.notice{color:#ffe0aa;background:#332611;border-left:3px solid #ffc26e;padding:12px 16px}.empty{color:var(--muted);padding:35px 0}.quota-grid{flex:1 0 auto;grid-auto-rows:minmax(220px,1fr);gap:10px;display:grid}.quota-card{flex-direction:column;min-height:0;display:flex;container-type:inline-size}.quota-card>:not(.meter-graphic){flex-shrink:0}.meter-graphic{flex-direction:column;flex:1;min-height:100px;display:flex}.bar-graphic{min-height:65px}.quota-card .gauge{flex:2;height:auto;min-height:16px;margin:7px 0}.quota-card .timeline{flex:1;min-height:8px}.quota-grid.zone{grid-template-columns:repeat(auto-fit,minmax(min(100%,420px),1fr));grid-auto-rows:minmax(330px,1fr)}.quota-grid.radial{grid-template-columns:repeat(auto-fit,minmax(min(100%,300px),1fr));grid-auto-rows:minmax(260px,1fr)}.gauge{background:var(--edge);height:35px;margin:15px 0;overflow:hidden}.gauge>div{background:repeating-linear-gradient(90deg, var(--accent) 0, var(--accent) 9px, transparent 9px, transparent 12px);height:100%;transition:width .5s}.gauge.timeline{height:14px}.pie-wrap{flex:1;min-height:100px;margin:6px 0;position:relative}.pie-wrap svg{width:100%;height:100%;position:absolute;inset:0}.pie-base{fill:var(--edge);stroke:var(--accent);stroke-width:1px}.pie-fill{fill:var(--accent)}.readout{overflow-wrap:anywhere;color:var(--accent);margin:18px 0;font-size:clamp(22px,3vw,34px)}.credit+.credit{border-top:1px solid var(--edge);padding-top:20px}.credit{margin-top:24px}.session-row{grid-template-columns:minmax(210px,1.1fr) minmax(0,1.2fr) minmax(0,1.5fr);align-items:stretch;gap:14px;margin:18px 0;display:grid}.session-totals{grid-template-columns:repeat(auto-fit,minmax(min(145px,100%),1fr));gap:8px;margin:8px 0;display:grid}.session-totals>div{border:1px solid var(--edge);min-width:0;padding:10px}.session-totals dt{color:var(--muted);font-size:11px}.session-totals dd{color:var(--accent);overflow-wrap:anywhere;margin:6px 0 0;font-size:24px}.session-totals.stale dd{color:var(--muted)}.session-row.selected{outline:1px solid var(--accent);outline-offset:4px}.session-row.wide .context{grid-column:2/-1}.detail-controls{flex-wrap:wrap;gap:6px;display:flex}.attention-summary{flex-wrap:wrap;gap:8px;margin-block:8px;display:flex}.attention-summary .approval{color:var(--approval);border-color:var(--approval)}.attention-summary .approval:hover{background:color-mix(in srgb, var(--approval) 12%, var(--panel))}.attention-summary .approval:focus-visible{outline-color:var(--approval)}.attention-note,.attention-badge{color:var(--accent);border-left:3px solid;padding-left:8px}.attention-note.inferred{color:var(--muted)}.attention-badge{font-size:12px}.session-select{text-align:left;overflow-wrap:anywhere;max-width:100%}.status-detail{color:inherit;text-decoration:none}.status-detail:hover{text-decoration:underline}button:disabled{opacity:.4;cursor:default}.session-row .graph-panel{flex-direction:column;grid-column:2/-1;display:flex}.session-row.split .graph-panel{grid-column:auto}.session-row .button,.session-row button{margin-top:8px;display:inline-block}.context pre{max-height:230px;overflow:auto}.session-row .context{flex-direction:column;display:flex}pre{font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:1.7}.full-detail{margin-top:6px}.detail-heading{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;display:flex}.detail-heading h2{flex:250px;min-width:0;margin:0}.detail-metadata{overflow-wrap:anywhere}.detail-workspace{border-top:1px solid var(--edge);flex-direction:column;gap:10px;margin-top:8px;padding-top:4px;display:flex}.detail-context,.detail-workspace .session-actions{min-width:0}.detail-workspace .session-actions{border-top:1px solid var(--edge);padding-top:6px}.full-detail h3{margin-block:8px}.full-detail pre{margin-block:8px;line-height:1.5}.full-detail hr{margin-block:12px}.full-detail .command,.full-detail .notice{padding:8px 10px}.command{background:var(--bg);border-left:3px solid var(--accent);padding:16px}hr{border:0;border-top:1px solid var(--edge);margin:24px 0}.chart{border-bottom:1px solid var(--muted);align-items:flex-end;gap:2px;height:clamp(120px,22vh,320px);margin-top:18px;display:flex}.chart-bar{background:var(--accent);flex:1;min-width:0;max-height:100%}.controls{justify-content:flex-start;margin:20px 0}.summary-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:16px;margin:20px 0;display:grid}.thresholds-panel{padding:clamp(14px,2vw,22px)}.thresholds-panel h1{margin-top:0}.threshold-list{gap:8px;margin-top:16px;display:grid}.threshold-list article{border:1px solid var(--edge);grid-template-columns:minmax(64px,.5fr) minmax(220px,3fr) minmax(64px,.6fr) minmax(120px,1.2fr);align-items:center;gap:12px;padding:10px 12px;display:grid}.threshold-list article.active{border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}.threshold-list article.next{border-color:var(--approval);box-shadow:inset 3px 0 0 var(--approval)}.threshold-list p{color:var(--muted);margin:3px 0 0;font-size:12px}.threshold-trigger{color:var(--accent);font-size:22px;font-weight:800}.threshold-mode,.threshold-state{color:var(--muted);font-size:12px;font-weight:700}.threshold-list article.active .threshold-state{color:var(--accent)}.threshold-list article.next .threshold-state{color:var(--approval)}.heat-scroll{overflow-x:auto}.heatmap{grid-template-rows:repeat(7,13px);grid-auto-columns:minmax(9px,1fr);grid-auto-flow:column;gap:4px;min-width:620px;margin:25px 0;display:grid}.heat-cell{background:var(--accent);border-radius:2px}.heat-cell.zero{background:var(--edge)}.table-scroll{max-height:280px;overflow:auto}table{border-collapse:collapse;width:100%;margin-top:15px}th,td{text-align:left;border-bottom:1px solid var(--edge);padding:8px}summary{cursor:pointer;color:var(--accent);padding-top:14px}footer{border-top:1px solid var(--edge);color:var(--muted);margin-top:8px;padding-top:8px;font-size:11px}footer select{padding:6px}@media (width<=850px){.session-row{grid-template-columns:minmax(0,1fr)}.session-row.wide .context,.session-row .graph-panel{grid-column:auto}.connection{text-align:left}.threshold-list article{grid-template-columns:64px minmax(0,1fr)}.threshold-mode,.threshold-state{grid-column:2}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none!important;animation:none!important}} diff --git a/internal/web/dist/assets/index-KFu7j0xL.js b/internal/web/dist/assets/index-KFu7j0xL.js new file mode 100644 index 0000000..0173a34 --- /dev/null +++ b/internal/web/dist/assets/index-KFu7j0xL.js @@ -0,0 +1,44 @@ +(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){return e()}function m(e){for(var t=0;t{e=n,t=r}),resolve:e,reject:t}}function g(e,t,n=!1){return e===void 0?n?t():t:e}function _(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 v=1024,y=2048,b=4096,x=8192,S=16384,C=32768,w=1<<25,T=65536,E=1<<19,ee=1<<20,D=1<<25,O=1<<21,k=1<<22,te=1<<23,A=Symbol(`$state`),ne=Symbol(`component`),re=Symbol(`legacy props`),ie=Symbol(``),ae=Symbol(`attributes`),oe=Symbol(`class`),se=Symbol(`style`),ce=Symbol(`text`),le=Symbol(`form reset`),ue=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},de=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),fe={},pe=Symbol(`uninitialized`),me=`http://www.w3.org/1999/xhtml`;function he(){console.warn(`https://svelte.dev/e/derived_inert`)}function ge(e){console.warn(`https://svelte.dev/e/hydration_mismatch`)}function _e(){console.warn(`https://svelte.dev/e/select_multiple_invalid_value`)}function ve(){console.warn(`https://svelte.dev/e/svelte_boundary_reset_noop`)}var j=!1;function ye(e){j=e}var M;function be(e){if(e===null)throw ge(),fe;return M=e}function xe(){return be(sn(M))}function N(e){if(j){if(sn(M)!==null)throw ge(),fe;M=e}}function Se(e=1){if(j){for(var t=e,n=M;t--;)n=sn(n);M=n}}function Ce(e=!0){for(var t=0,n=M;;){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=sn(n);e&&n.remove(),n=i}}function we(e){if(!e||e.nodeType!==8)throw ge(),fe;return e.data}function Te(e){return e===this.v}function Ee(e,t){return e==e?e!==t||typeof e==`object`&&!!e||typeof e==`function`:t==t}function De(e){return!Ee(e,this.v)}function Oe(e){throw Error(`https://svelte.dev/e/lifecycle_outside_component`)}function ke(){throw Error(`https://svelte.dev/e/async_derived_orphan`)}function Ae(e,t,n){throw Error(`https://svelte.dev/e/each_key_duplicate`)}function je(e){throw Error(`https://svelte.dev/e/effect_in_teardown`)}function Me(){throw Error(`https://svelte.dev/e/effect_in_unowned_derived`)}function Ne(e){throw Error(`https://svelte.dev/e/effect_orphan`)}function Pe(){throw Error(`https://svelte.dev/e/effect_update_depth_exceeded`)}function Fe(e){throw Error(`https://svelte.dev/e/props_invalid_value`)}function Ie(){throw Error(`https://svelte.dev/e/state_descriptors_fixed`)}function Le(){throw Error(`https://svelte.dev/e/state_prototype_fixed`)}function Re(){throw Error(`https://svelte.dev/e/state_unsafe_mutation`)}function ze(){throw Error(`https://svelte.dev/e/svelte_boundary_reset_onerror`)}var Be=!1;function Ve(){Be=!0}var He=null;function Ue(e){He=e}function We(e,t=!1,n){He={p:He,i:!1,c:null,e:null,s:e,x:null,r:W,l:Be&&!t?{s:null,u:null,$:[]}:null}}function Ge(e){var t=He,n=t.e;if(n!==null){t.e=null;for(var r of n)bn(r)}return e!==void 0&&(t.x=e),t.i=!0,He=t.p,Ke(e)}function Ke(e={}){return i(e,ne,{value:!0}),e}function qe(){return!Be||He!==null&&He.l===null}var Je=[];function Ye(){var e=Je;Je=[],m(e)}function Xe(e){if(Je.length===0&&!wt){var t=Je;queueMicrotask(()=>{t===Je&&Ye()})}Je.push(e)}function Ze(){for(;Je.length>0;)Ye()}var Qe=~(y|b|v);function $e(e,t){e.f=e.f&Qe|t}function et(e){e.f&512||e.deps===null?$e(e,v):$e(e,b)}function tt(e,t,n){e.f&2048?t.add(e):e.f&4096&&n.add(e),$e(e,v)}function nt(e){j&&on(e)!==null&&cn(e)}var rt=!1;function it(){rt||(rt=!0,document.addEventListener(`reset`,e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[le]?.()})},{capture:!0}))}function at(e){var t=U,n=W;Wn(null),Gn(null);try{return e()}finally{Wn(t),Gn(n)}}function ot(e,t,n,r=n){e.addEventListener(t,()=>at(n));let i=e[le];e[le]=i?()=>{i(),r(!0)}:()=>r(!0),it()}function st(e,t,n,r){let i=qe()?dt:mt;var a=e.filter(e=>!e.settled),o=t.map(i);if(n.length===0&&a.length===0){r(o);return}var s=W,c=ct(),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){pn(e,s)}lt()}}var d=ut();if(n.length===0){l.then(()=>u([])).finally(d);return}function f(){Promise.all(n.map(e=>pt(e))).then(u).catch(e=>pn(e,s)).finally(d)}l?l.then(()=>{c(),f(),lt()}):f()}function ct(){var e=W,t=U,n=He,r=F;return function(i=!0){Gn(e),Wn(t),Ue(n),i&&!(e.f&16384)&&(r?.activate(),r?.apply())}}function lt(e=!0){Gn(null),Wn(null),Ue(null),e&&F?.deactivate()}function ut(){var e=W,t=e.b,n=F,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 dt(e){var t=2|y;return W!==null&&(W.f|=E),{ctx:He,deps:null,effects:null,equals:Te,f:t,fn:e,reactions:null,rv:0,v:pe,wv:0,parent:W,ac:null}}var ft=Symbol(`obsolete`);function pt(e,t,n){let r=W;r===null&&ke();var i=void 0,a=Vt(pe),o=!U,s=new Set;return wn(()=>{var t=W,n=h();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==ue&&n.reject(e)}).finally(lt)}catch(e){n.reject(e),lt()}var c=F;if(o){if(t.f&32768)var l=ut();if(r.b?.is_rendered())c.async_deriveds.get(t)?.reject(ft);else for(let e of s.values())e.reject(ft);s.add(n),c.async_deriveds.set(t,n)}let u=(e,t=void 0)=>{l?.(),s.delete(n),t!==ft&&(c.activate(),t?(a.f|=te,Gt(a,t)):(a.f&8388608&&(a.f^=te),Gt(a,e)),c.deactivate())};n.promise.then(u,e=>u(null,e||`unknown`))}),vn(()=>{for(let e of s)e.reject(ft)}),new Promise(e=>{function t(n){function r(){n===i?e(a):t(i)}n.then(r,r)}t(i)})}function P(e){let t=dt(e);return qn(t),t}function mt(e){let t=dt(e);return t.equals=De,t}function ht(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n{t.ac.abort(ue),t.ac=null}),t.fn!==null&&(t.teardown=f),cr(t,0),kn(t))}function yt(e){if(e.effects!==null)for(let t of e.effects)t.teardown&&t.fn!==null&&lr(t)}var bt=null,F=null,xt=null,St=null,Ct=null,wt=!1,Tt=!1,Et=null,Dt=null,Ot=0,kt=1,At=class e{id=kt++;#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(){bt===null?bt=this:(bt.#n=this,this.#t=bt),bt=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)$e(r,y),t(r);for(r of n.m)$e(r,b),t(r)}this.#p.add(e)}#g(){var e=[];for(let i of this.#c)if(!(i.f&16384||!(i.f&6144))){for(var t=i,n=!1;t.parent!==null;){t=t.parent;var r=t.f;if(r&96){if(!(r&1024)){n=!0;break}t.f^=v}}n||e.push(t)}return this.#c=[],e}#_(){this.#e=!0;for(let e of this.#u)this.#d.delete(e),$e(e,y),this.schedule(e);for(let e of this.#d)$e(e,b),this.schedule(e);this.apply();for(var t=Et=[],n=[],r=Dt=[];this.#c.length>0;){Ot++>1e3&&(this.#S(),Mt());for(let e of this.#g())try{this.#v(e,t,n)}catch(t){throw Lt(e),this.#h()||this.discard(),t}}if(F=null,r.length>0){var i=e.ensure();for(let e of r)i.schedule(e)}if(Et=null,Dt=null,this.#h()){this.#x(n),this.#x(t);for(let[e,t]of this.#f)It(e,t);r.length>0&&F.#_();return}let a=this.#y();if(a){this.#x(n),this.#x(t),a.#b(this);return}this.#u.clear(),this.#d.clear();for(let e of this.#r)e(this);this.#r.clear(),xt=this,Pt(n),Pt(t),xt=null,this.#s?.resolve();var o=F;if(this.#a===0&&(this.#c.length===0||o!==null)&&this.#S(),this.#c.length>0){if(o!==null){for(let e of this.#c)o.#c.push(e);this.#c=[]}else o=this}o!==null&&(zt.clear(),o.#_())}#v(e,t,n){e.f^=v;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^=v:i&4?t.push(r):rr(r)&&(i&16&&this.#d.add(r),lr(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}}}#y(){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}#b(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),$e(i,y),this.schedule(i))}}};for(let e of this.current.keys())t(e);this.oncommit(()=>e.discard()),e.#S(),F=this,this.#_()}#x(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??=h()).promise}static ensure(){if(F===null){let t=F=new e;!Tt&&!wt&&Xe(()=>{t.#e||t.flush()})}return F}apply(){St=null}schedule(e){if(Ct=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)){e.b.defer_effect(e);return}this.#c.push(e)}#S(){if(this.linked){var e=this.#t,t=this.#n;e===null||(e.#n=t),t===null?bt=e:t.#t=e,this.linked=!1}}};function jt(e){var t=wt;wt=!0;try{var n;for(e&&(F!==null&&!F.is_fork&&F.flush(),n=e());;){if(Ze(),F===null)return n;F.flush()}}finally{wt=t}}function Mt(){try{Pe()}catch(e){pn(e,Ct)}}var Nt=null;function Pt(e){var t=e.length;if(t!==0){for(var n=0;n0)){zt.clear();for(let e of Nt){if(e.f&24576)continue;let t=[e],n=e.parent;for(;n!==null;)Nt.has(n)&&(Nt.delete(n),t.push(n)),n=n.parent;for(let e=t.length-1;e>=0;e--){let n=t[e];n.f&24576||lr(n)}}Nt.clear()}}Nt=null}}function Ft(e){F.schedule(e)}function It(e,t){if(!(e.f&32&&e.f&1024)){e.f&2048?t.d.push(e):e.f&4096&&t.m.push(e),$e(e,v);for(var n=e.first;n!==null;)It(n,t),n=n.next}}function Lt(e){$e(e,v);for(var t=e.first;t!==null;)Lt(t),t=t.next}var Rt=new Set,zt=new Map,Bt=!1;function Vt(e,t){return{f:0,v:e,reactions:null,equals:Te,rv:0,wv:0}}function I(e,t){let n=Vt(e,t);return qn(n),n}function Ht(e,t=!1,n=!0){let r=Vt(e);return t||(r.equals=De),Be&&n&&He!==null&&He.l!==null&&(He.l.s??=[]).push(r),r}function L(e,t,n=!1){return U!==null&&(!Un||U.f&131072)&&qe()&&U.f&4325394&&(Kn===null||!Kn.has(e))&&Re(),Gt(e,n?Xt(t):t,Dt)}var Ut=null,Wt=0;function Gt(e,t,n=null){if(!e.equals(t)){Vn?zt.set(e,t):zt.has(e)||zt.set(e,e.v);var r=At.ensure();if(r.capture(e,t),e.f&2){let t=e;e.f&2048&>(t),St===null&&et(t)}e.wv=nr(),Ut=null,Wt=0,Yt(e,y,n),Ut=null,qe()&&W!==null&&W.f&1024&&!(W.f&96)&&(Xn===null?Zn([e]):Xn.push(e)),!r.is_fork&&Rt.size>0&&!Bt&&Kt()}return t}function Kt(){Bt=!1;for(let e of Rt){e.f&1024&&$e(e,b);let t;try{t=rr(e)}catch{t=!0}t&&lr(e)}Rt.clear()}function qt(e,t=1){var n=G(e),r=t===1?n++:n--;return L(e,n),r}function Jt(e){L(e,e.v+1)}function Yt(e,t,n){var r=e.reactions;if(r!==null){var i=qe(),a=r.length;if(Wt+=a,Wt>1e5&&Ut===null&&(Ut=new Set),Ut!==null){if(Ut.has(e))return;Ut.add(e)}for(var o=0;o{if(er===d)return e();var t=U,n=er;Wn(null),tr(d);var r=e();return Wn(t),tr(n),r};return i&&r.set(`length`,I(t.length,u)),new Proxy(t,{defineProperty(e,t,n){(!(`value`in n)||n.configurable===!1||n.enumerable===!1||n.writable===!1)&&Ie();var i=r.get(t);return i===void 0?f(()=>{var e=I(n.value,u);return r.set(t,e),e}):L(i,n.value,!0),!0},deleteProperty(e,t){var n=r.get(t);if(n===void 0){if(t in e){let e=f(()=>I(pe,u));r.set(t,e),Jt(o)}}else L(n,pe),Jt(o);return!0},get(e,n,i){if(n===A)return t;var o=r.get(n),s=n in e;if(o===void 0&&(!s||a(e,n)?.writable)&&(o=f(()=>I(Xt(s?e[n]:pe),u)),r.set(n,o)),o!==void 0){var c=G(o);return c===pe?void 0:c}return Reflect.get(e,n,i)},getOwnPropertyDescriptor(e,t){this.has?.(e,t);var n=Reflect.getOwnPropertyDescriptor(e,t),i=r.get(t);if(i!==void 0){var a=G(i);if(a===pe)return;if(n&&`value`in n)n.value=a;else return{enumerable:!0,configurable:!0,value:a,writable:!0}}return n},has(e,t){if(t===A)return!0;var n=r.get(t),i=n!==void 0&&n.v!==pe||Reflect.has(e,t);return(n!==void 0||W!==null&&(!i||a(e,t)?.writable))&&(n===void 0&&(n=f(()=>I(i?Xt(e[t]):pe,u)),r.set(t,n)),G(n)===pe)?!1:i},set(e,t,n,s){var c=r.get(t),l=t in e;if(i&&t===`length`)for(var d=n;dI(pe,u)),r.set(d+``,p)):L(p,pe)}if(c===void 0)(!l||a(e,t)?.writable)&&(c=f(()=>I(void 0,u)),L(c,Xt(n)),r.set(t,c));else{l=c.v!==pe;var m=f(()=>Xt(n));L(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&&L(g,_+1)}Jt(o)}return!0},ownKeys(e){G(o);var t=Reflect.ownKeys(e).filter(e=>{var t=r.get(e);return t===void 0||t.v!==pe});for(var[n,i]of r)i.v!==pe&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Le()}})}function Zt(e){try{if(typeof e==`object`&&e&&A in e)return e[A]}catch{}return e}function Qt(e,t){return Object.is(Zt(e),Zt(t))}var $t,en,tn,nn;function rn(){if($t===void 0){$t=window,en=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;tn=a(t,`firstChild`).get,nn=a(t,`nextSibling`).get,u(e)&&(e[oe]=void 0,e[ae]=null,e[se]=void 0,e.__e=void 0),u(n)&&(n[ce]=void 0)}}function an(e=``){return document.createTextNode(e)}function on(e){return tn.call(e)}function sn(e){return nn.call(e)}function R(e,t){if(!j)return on(e);var n=on(M);if(n===null)n=M.appendChild(an());else if(t&&n.nodeType!==3){var r=an();return n?.before(r),be(r),r}return t&&dn(n),be(n),n}function z(e,t=!1){if(!j){var n=on(e);return n instanceof Comment&&n.data===``?sn(n):n}if(t){if(M?.nodeType!==3){var r=an();return M?.before(r),be(r),r}dn(M)}return M}function B(e,t=!1){if(!j)return on(e);var n=R(e,t);return N(e),n}function V(e,t=1,n=!1){let r=j?M:e;for(var i;t--;)i=r,r=sn(r);if(!j)return r;if(n){if(r?.nodeType!==3){var a=an();return r===null?i?.after(a):r.before(a),be(a),a}dn(r)}return be(r),r}function cn(e){e.textContent=``}function ln(){return!1}function un(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 dn(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 fn(e){var t=W;if(t===null)return U.f|=te,e;if(!(t.f&32768)&&!(t.f&4))throw e;pn(e,t)}function pn(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 mn(e){W===null&&(U===null&&Ne(e),Me()),Vn&&je(e)}function hn(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function gn(e,t){var n=W;n!==null&&n.f&8192&&(e|=x);var r={ctx:He,deps:null,nodes:null,f:e|y|512,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};F?.register_created_effect(r);var i=r;if(e&4)Et===null?At.ensure().schedule(r):Et.push(r);else if(t!==null){try{lr(r)}catch(e){throw jn(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|=T))}if(i!==null&&(i.parent=n,n!==null&&hn(i,n),U!==null&&U.f&2&&!(e&64))){var a=U;(a.effects??=[]).push(i)}return r}function _n(){return U!==null&&!Un}function vn(e){let t=gn(8,null);return $e(t,v),t.teardown=e,t}function yn(e){mn(`$effect`);var t=W.f;if(!U&&t&32&&He!==null&&!He.i){var n=He;(n.e??=[]).push(e)}else return bn(e)}function bn(e){return gn(4|ee,e)}function xn(e){return mn(`$effect.pre`),gn(8|ee,e)}function Sn(e){At.ensure();let t=gn(64|E,e);return(e={})=>new Promise(n=>{e.outro?Pn(t,()=>{jn(t),n(void 0)}):(jn(t),n(void 0))})}function Cn(e){return gn(4,e)}function wn(e){return gn(k|E,e)}function Tn(e,t=0){return gn(8|t,e)}function H(e,t=[],n=[],r=[]){st(r,t,n,t=>{gn(8,()=>{e(...t.map(G))})})}function En(e,t=0){return gn(16|t,e)}function Dn(e){return gn(32|E,e)}function On(e){var t=e.teardown;if(t!==null){let n=Vn,r=U;Hn(!0),Wn(null);try{t.call(null)}catch(t){pn(t,e.parent)}finally{Hn(n),Wn(r)}}}function kn(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){let e=n.ac;e!==null&&at(()=>{e.abort(ue)});var r=n.next;n.f&64?n.parent=null:jn(n,t),n=r}}function An(e){for(var t=e.first;t!==null;){var n=t.next;t.f&32||jn(t),t=n}}function jn(e,t=!0){var n=!1;(t||e.f&262144)&&e.nodes!==null&&e.nodes.end!==null&&(Mn(e.nodes.start,e.nodes.end),n=!0),e.f|=w,kn(e,t&&!n),cr(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(let e of r)e.stop();On(e),e.f^=w,e.f|=S;var i=e.parent;i!==null&&i.first!==null&&Nn(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Mn(e,t){for(;e!==null;){var n=e===t?null:sn(e);e.remove(),e=n}}function Nn(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 Pn(e,t,n=!0){var r=[];e.f|=256,Fn(e,r,!0);var i=()=>{n&&jn(e),t&&t()},a=r.length;if(a>0){var o=()=>--a||i();for(var s of r)s.out(o)}else i()}function Fn(e,t,n){if(!(e.f&8192)){e.f^=x;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);Fn(i,t,o?n:!1)}i=a}}}function In(e){e.f&=-257,Ln(e,!0)}function Ln(e,t){if(!(e.f&256)&&e.f&8192){e.f^=x,e.f&1024||($e(e,y),At.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=!!(n.f&65536)||!!(n.f&32);Ln(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 Rn(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:sn(n);t.append(n),n=i}}var zn=null,Bn=!1,Vn=!1;function Hn(e){Vn=e}var U=null,Un=!1;function Wn(e){U=e}var W=null;function Gn(e){W=e}var Kn=null;function qn(e){U!==null&&(U.f&2097152||U.f&2)&&(Kn??=new Set).add(e)}var Jn=null,Yn=0,Xn=null;function Zn(e){Xn=e}var Qn=1,$n=0,er=$n;function tr(e){er=e}function nr(){return++Qn}function rr(e){var t=e.f;if(t&2048)return!0;if(t&4096){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}t&512&&St===null&&$e(e,v)}return!1}function ir(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Kn!==null&&Kn.has(e)))for(var i=0;i{e.ac.abort(ue)}),e.ac=null);try{e.f|=O;var u=e.fn,d=u();e.f|=C;var f=or(e);if(qe()&&Xn!==null&&!Un&&f!==null&&!(e.f&6146))for(var p=0;p0)for(t.length=Yn+Jn.length,r=0;r{s.ac.abort(ue),s.ac=null,$e(s,y)}),vt(s),cr(s,0)}}function cr(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`?(i.__removed=!1,Xe(()=>{i.__removed||t.addEventListener(e,i,r)})):t.addEventListener(e,i,r),i}function Sr(e,t,n,r,i){var a={capture:r,passive:i},o=xr(e,t,n,a);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&vn(()=>{o.__removed=!0,t.removeEventListener(e,o,a)})}function K(e,t,n){(t[vr]??={})[e]=n}function Cr(e){for(var t=0;t{Tr=!1,wr=null}));var s=0,c=wr===e&&e[vr];if(c){var l=a.indexOf(c);if(l!==-1&&(t===document||t===window)){e[vr]=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=U,f=W;Wn(null),Gn(null);try{for(var p,m=[];o!==null&&o!==t;){try{var h=o[vr]?.[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[vr]=t,delete e.currentTarget,Wn(d),Gn(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=un(`template`);return t.innerHTML=Or(e.replaceAll(``,``)),t.content}function Ar(e,t){var n=W;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function q(e,t){var n=!!(t&1),r=!!(t&2),i,a=!e.startsWith(``);return()=>{if(j)return Ar(M,null),M;i===void 0&&(i=kr(a?e:``+e),n||(i=on(i)));var t=r||en?document.importNode(i,!0):i.cloneNode(!0);if(n){var o=on(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(j)return Ar(M,null),M;if(!o){var e=on(kr(a));if(i)for(o=document.createDocumentFragment();on(e);)o.appendChild(on(e));else o=on(e)}var t=o.cloneNode(!0);if(i){var n=on(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(!j){var t=an(e+``);return Ar(t,t),t}var n=M;return n.nodeType===3?dn(n):(n.before(n=an()),be(n)),Ar(n,n),n}function Pr(){if(j)return Ar(M,null),M;var e=document.createDocumentFragment(),t=document.createComment(``),n=an();return e.append(t,n),Ar(t,n),e}function J(e,t){if(j){var n=W;(!(n.f&32768)||n.nodes.end===null)&&(n.nodes.end=M),xe();return}e!==null&&e.before(t)}function Fr(){if(j&&M&&M.nodeType===8&&M.textContent?.startsWith(`$`)){let e=M.textContent.substring(1);return xe(),e}return(window.__svelte??={}).uid??=1,`c${window.__svelte.uid++}`}function Ir(e){let t=0,n=Vt(0),r;return()=>{_n()&&(G(n),Tn(()=>(t===0&&(r=pr(()=>e(()=>Jt(n)))),t+=1,()=>{Xe(()=>{--t,t===0&&(r?.(),r=void 0,Jt(n))})})))}}var Lr=T|E;function Rr(e,t,n,r){new zr(e,t,n,r)}var zr=class{parent;is_pending=!1;transform_error;#e;#t=j?M: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=Vt(this.#l),()=>{this.#m=null}));constructor(e,t,n,r){this.#e=e,this.#n=t,this.#r=e=>{var t=W;t.b=this,t.f|=128,n(e)},this.parent=W.b,this.transform_error=r??this.parent?.transform_error??(e=>e),this.#i=En(()=>{if(j){let e=this.#t;xe();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),j&&(this.#e=M)}#g(){try{this.#a=Dn(()=>this.#r(this.#e))}catch(e){this.error(e)}}#_(e){let t=this.#n.failed,{reset:n,invoke_onerror:r}=this.#v(e);Xe(r),t&&(this.#s=Dn(()=>{t(this.#e,()=>e,()=>n)}))}#v(e){var t=!1,n=!1;let r=()=>{if(t){ve();return}t=!0,n&&ze(),this.#s!==null&&Pn(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){pn(e,this.#i&&this.#i.parent)}}}}#y(){let e=this.#n.pending;e&&(this.is_pending=!0,this.#o=Dn(()=>e(this.#e)),Xe(()=>{var e=this.#c=document.createDocumentFragment(),t=an(),n=!1;if(e.append(t),this.#a=this.#S(()=>{try{return Dn(()=>this.#r(t))}catch(e){try{this.error(e),n=!0}catch(e){pn(e,this.#i.parent)}return null}}),this.#a===null){this.#c=null,n&&this.#x(F);return}this.#u===0&&(this.#e.before(e),this.#c=null,Pn(this.#o,()=>{this.#o=null}),this.#x(F))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#u=0,this.#l=0,this.#a=Dn(()=>{this.#r(this.#e)}),this.#u>0){var e=this.#c=document.createDocumentFragment();Rn(this.#a,e);let t=this.#n.pending;this.#o=Dn(()=>t(this.#e))}else this.#x(F)}catch(e){this.error(e)}}#x(e){this.is_pending=!1,e.transfer_effects(this.#f,this.#p)}defer_effect(e){tt(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=W,n=U,r=He;Gn(this.#i),Wn(this.#i),Ue(this.#i.ctx);try{return At.ensure(),e()}finally{Gn(t),Wn(n),Ue(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&&Pn(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,Xe(()=>{this.#d=!1,this.#m&&Gt(this.#m,this.#l)}))}get_effect_pending(){return this.#h(),G(this.#m)}error(e){if(!this.#n.onerror&&!this.#n.failed)throw e;F?.is_fork?(this.#a&&F.skip_effect(this.#a),this.#o&&F.skip_effect(this.#o),this.#s&&F.skip_effect(this.#s),F.oncommit(()=>{this.#w(e)})):this.#w(e)}#w(e){this.#a&&=(jn(this.#a),null),this.#o&&=(jn(this.#o),null),this.#s&&=(jn(this.#s),null),j&&(be(this.#t),Se(),be(Ce()));let t=this.#n.failed,n=e=>{let{reset:n,invoke_onerror:r}=this.#v(e);r(),t&&(this.#s=this.#S(()=>{try{return Dn(()=>{var r=W;r.b=this,r.f|=128,t(this.#e,()=>e,()=>n)})}catch(e){return pn(e,this.#i.parent),null}}))};Xe(()=>{var t;try{t=this.transform_error(e)}catch(e){pn(e,this.#i&&this.#i.parent);return}typeof t==`object`&&t&&typeof t.then==`function`?t.then(n,e=>pn(e,this.#i&&this.#i.parent)):n(t)})}};function Y(e,t){var n=t==null?``:typeof t==`object`?`${t}`:t;n!==(e[ce]??=e.nodeValue)&&(e[ce]=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}){rn();var l=void 0,u=Sn(()=>{var s=n??t.appendChild(an());Rr(s,{pending:()=>{}},t=>{We({});var n=He;if(o&&(n.c=o),a&&(i.$$events=a),j&&Ar(t,null),l=e(t,i)||Ke(),j&&(W.nodes.end=M,M===null||M.nodeType!==8||M.data!==`]`))throw ge(),fe;Ge()},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)}br.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)In(n),this.#r.delete(t);else{var r=this.#n.get(t);r&&(In(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&&(jn(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();Rn(r,t),t.append(an()),this.#n.set(e,{effect:r,fragment:t})}else jn(r);this.#r.delete(e),this.#t.delete(e)};this.#i||!n?(this.#r.add(e),Pn(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)||(jn(n.effect),this.#n.delete(e))};ensure(e,t){var n=F,r=ln();if(t&&!this.#t.has(e)&&!this.#n.has(e)){if(r){var i=document.createDocumentFragment(),a=an();i.append(a),this.#n.set(e,{effect:Dn(()=>t(a)),fragment:i})}else this.#t.set(e,Dn(()=>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 j&&(this.anchor=M),this.#a(n)}};function X(e,t,n=!1){var r;j&&(r=M,xe());var i=new Wr(e),a=n?T:0;function o(e,t){if(j){var n=we(r);if(e!==parseInt(n.substring(1))){var a=Ce();be(a),i.anchor=a,ye(!1),i.ensure(e,t),ye(!0);return}}i.ensure(e,t)}En(()=>{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){j&&xe();var r=new Wr(e),i=!qe();En(()=>{var e=t();e!==e&&(e=Gr),i&&typeof e==`object`&&e&&(e={}),r.ensure(e,n)})}function qr(e,t){return t}function Jr(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;Yr(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;cn(d),d.append(u),e.items.clear()}Yr(e,t,!l)}else o={pending:new Set(t),done:new Set},(e.outrogroups??=new Set).add(o)}function Yr(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,Qr(v,p,c,n,a),d!==null&&(p.length===0?d.f&33554432?(d.f^=D,ei(d,null,c)):In(d):Pn(d,()=>{d=null})))}function _(e){v.pending.delete(e)}var v={effect:En(()=>{p=G(f);var e=p.length;let t=!1;j&&we(c)===`[!`!=(e===0)&&(c=Ce(),be(c),ye(!1),t=!0);for(var r=new Set,u=F,v=ln(),y=0;ys(c)):(d=Dn(()=>s(Xr??=an())),d.f|=D)),e>r.size&&Ae(``,``,``),j&&e>0&&be(Ce()),!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&&ye(!0),G(f)}),flags:n,items:l,pending:m,outrogroups:null,fallback:d};h=!1,j&&(c=M)}function Zr(e){for(;e!==null&&!(e.f&32);)e=e.next;return e}function Qr(e,t,n,i,a){var o=!!(i&8),s=t.length,c=e.items,l=Zr(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 $r(e,t,n,r,i,a,o,s){var c=o&1?o&16?Vt(n):Ht(n,!1,!1):null,l=o&2?Vt(i):null;return{v:c,i:l,e:Dn(()=>(a(t,c??n,l??i,s),()=>{e.delete(r)}))}}function ei(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=sn(r);if(a.before(r),r===i)return;r=o}}function ti(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function ni(e,t,n){var r;j&&(r=M,xe());var i=new Wr(e);En(()=>{var e=t()??null;if(j&&we(r)===`[`!=(e!==null)){var a=Ce();be(a),i.anchor=a,ye(!1),i.ensure(e,e&&(t=>n(t,e))),ye(!0);return}i.ensure(e,e&&(t=>n(t,e)))},T)}var ri=[...` +\r\f\xA0\v`];function ii(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||ri.includes(r[o-1]))&&(s===r.length||ri.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function ai(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 oi(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function si(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(oi)),i&&c.push(...Object.keys(i).map(oi));var l=0,u=-1;let t=e.length;for(var d=0;d{t.every(_i)||(`__defaultValue`in e&&fi(e,!1),`__value`in e&&pi(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),vn(()=>{t.disconnect()})}function hi(e,t,n=t){var r=new WeakSet,i=!0;ot(e,`change`,t=>{var i=t?`[selected]`:`:checked`,a;if(e.multiple)a=[].map.call(e.querySelectorAll(i),gi);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&gi(o)}n(a),e.__value=a,F!==null&&r.add(F)}),Cn(()=>{var a=t();if(e===document.activeElement){var o=F;if(r.has(o))return}if(pi(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=gi(s),n(a))}e.__value=a,i=!1})}function gi(e){return`__value`in e?e.__value:e.value}function _i(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 vi=Symbol(`is custom element`),yi=Symbol(`is html`),bi=de?`link`:`LINK`;function xi(e){if(j){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[le]=n,Xe(n),it()}}function Si(e,t){var n=Ci(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=Ci(e);j&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===bi)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[ie]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Ti(e).has(t)?e[t]=n:e.setAttribute(t,n))}function Ci(e){return e[ae]??={[vi]:e.nodeName.includes(`-`),[yi]:e.namespaceURI===me}}var wi=new Map;function Ti(e){var t=e.getAttribute(`is`)||e.nodeName,n=wi.get(t);if(n)return n;wi.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 Ei(e,t,n=t){var r=new WeakSet;ot(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=ji(e)?Mi(a):a,n(a),F!==null&&r.add(F),await ur(),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))}}}),(j&&e.defaultValue!==e.value||pr(t)==null&&e.value)&&(n(ji(e)?Mi(e.value):e.value),F!==null&&r.add(F)),Tn(()=>{var n=t();if(e===document.activeElement){var i=F;if(r.has(i))return}ji(e)&&n===Mi(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}var Di=new Set;function Oi(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),ot(n,`change`,()=>{var e=n.__value;a&&(e=Ai(o,e,n.checked)),i(e)},()=>i(a?[]:null)),Tn(()=>{var e=r();if(j&&n.defaultChecked!==n.checked){s=!0;return}a?(e||=[],n.checked=e.includes(n.__value)):n.checked=Qt(n.__value,e)}),vn(()=>{var e=o.indexOf(n);e!==-1&&o.splice(e,1)}),Di.has(o)||(Di.add(o),Xe(()=>{o.sort((e,t)=>e.compareDocumentPosition(t)===4?-1:1),Di.delete(o)})),Xe(()=>{if(s){var e=a?Ai(o,e,n.checked):o.find(e=>e.checked)?.__value;i(e)}})}function ki(e,t,n=t){ot(e,`change`,t=>{n(t?e.defaultChecked:e.checked)}),(j&&e.defaultChecked!==e.checked||pr(t)==null)&&n(e.checked),Tn(()=>{e.checked=!!t()})}function Ai(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 Pi(e,t,n){var r=Ni.observe(e,()=>n(e[t]));Cn(()=>(pr(()=>n(e[t])),r))}function Fi(e,t){return e===t||e?.[A]===t}function Ii(e=Ke(),t,n,r){var i=He.r,a=W;return Cn(()=>{var o,s;return Tn(()=>{o=s,s=r?.()||[],pr(()=>{Fi(n(...s),e)||(t(e,...s),o&&Fi(n(...o),e)&&t(null,...o))})}),()=>{let r=a;for(;r!==i&&r.parent!==null&&r.parent.f&33554432;)r=r.parent;let o=()=>{s&&Fi(n(...s),e)&&t(null,...s)},c=r.teardown;r.teardown=()=>{o(),c?.()}}}),e}function Li(e,t,n,r,i){var a=()=>{r(n[e])};n.addEventListener(t,a),i?Tn(()=>{n[e]=i()}):a(),(n===document.body||n===window||n===document)&&vn(()=>{n.removeEventListener(t,a)})}function Ri(e=!1){let t=He,n=t.l.u;if(!n)return;let r=()=>mr(t.s);if(e){let e=0,n={},i=dt(()=>{let r=!1,i=t.s;for(let e in i)i[e]!==n[e]&&(n[e]=i[e],r=!0);return r&&e++,e});r=()=>G(i)}n.b.length&&xn(()=>{zi(t,r),m(n.b)}),yn(()=>{let e=pr(()=>n.m.map(p));return()=>{for(let t of e)typeof t==`function`&&t()}}),n.a.length&&yn(()=>{zi(t,r),m(n.a)})}function zi(e,t){if(e.l.s)for(let t of e.l.s)G(t);t()}var Bi=!1;function Vi(e){var t=Bi;try{return Bi=!1,[e(),Bi]}finally{Bi=t}}var Hi={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===A||t===re)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 Ui(...e){return new Proxy({props:e},Hi)}function Wi(e,t,n,r){var i=!Be||!!(n&2),o=!!(n&8),s=!!(n&16),c=r,l=!0,u=void 0,d=()=>s&&i?(u??=dt(r),G(u)):(l&&(l=!1,c=s?pr(r):r),c);let f;if(o){var p=A in e||re in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=Vi(()=>e[t]):m=e[t],m===void 0&&r!==void 0&&(m=d(),f&&(i&&Fe(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?dt:mt)(()=>(v=!1,g()));o&&G(y);var b=W;return(function(e,t){if(arguments.length>0){let n=t?G(y):i&&o?Xt(e):e;return L(y,n),v=!0,c!==void 0&&(c=n),e}return Vn&&v||b.f&16384?y.v:G(y)})}function Gi(e){He===null&&Oe(`onMount`),Be&&He.l!==null?qi(He).m.push(e):yn(()=>{let t=pr(e);if(typeof t==`function`)return t})}function Ki(e){He===null&&Oe(`onDestroy`),Gi(()=>()=>pr(e))}function qi(e){var t=e.l;return t.u??={a:[],b:[],m:[]}}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);function Ji(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 Yi=new class{#e=I(Xi());get _loc(){return G(this.#e)}set _loc(e){L(this.#e,e)}#t=P(()=>this._loc.location);get _location(){return G(this.#t)}set _location(e){L(this.#t,e)}#n=P(()=>this._loc.querystring);get _querystring(){return G(this.#n)}set _querystring(e){L(this.#n,e)}#r=I(void 0);get _params(){return G(this.#r)}set _params(e){L(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=Xi()}):console.warn(`[svelte-spa-router] window 'window' is not defined, skipping initiation`)}};function Xi(){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}}async function Zi(e){if(!e||e.length<1||e.charAt(0)!=`/`&&e.indexOf(`#/`)!==0)throw Error(`Invalid parameter location`);await ur();let t=(e.charAt(0)==`#`?``:`#`)+e;try{let e={...history.state};delete e.__svelte_spa_router_scrollX,delete e.__svelte_spa_router_scrollY,window.history.replaceState(e,``,t)}catch{console.warn("Caught exception while replacing the current page. If you're running this in the Svelte REPL, please note that the `replace` method might not work in this environment.")}window.dispatchEvent(new Event(`hashchange`))}function Qi(e){e?window.scrollTo(e.__svelte_spa_router_scrollX||0,e.__svelte_spa_router_scrollY||0):window.scrollTo(0,0)}function $i(e,t){We(t,!0);let n=Wi(t,`routes`,19,()=>({})),r=Wi(t,`prefix`,3,``),i=Wi(t,`restoreScrollState`,3,!1),a=Wi(t,`onConditionsFailed`,3,()=>{}),o=Wi(t,`onRouteLoaded`,3,()=>{}),s=Wi(t,`onRouteLoading`,3,()=>{}),c=Wi(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=Ji(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=I(null),f=I(null),p=I({}),m=null,h=null;yn(()=>{history.scrollRestoration=i()?`manual`:`auto`}),yn(()=>{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 ur(),e(t)}yn(()=>{let e=Yi.loc,t=!1;return pr(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=z(v),b=e=>{let t=P(()=>G(d));var n=Pr(),r=z(n),i=e=>{var n=Pr();ni(z(n),()=>G(t),(e,t)=>{t(e,Ui({get params(){return G(f)},get onRouteEvent(){return c()}},()=>G(p)))}),J(e,n)},a=e=>{var n=Pr();ni(z(n),()=>G(t),(e,t)=>{t(e,Ui({get onRouteEvent(){return c()}},()=>G(p)))}),J(e,n)};X(r,e=>{G(f)?e(i):e(a,-1)}),J(e,n)};X(y,e=>{G(d)&&e(b)}),J(e,v),Ge()}var ea=[`bars`,`pace`,`pie`,`fuel`,`resets`,`thresholds`];function ta(e){return e===`zone`||e===`consumption-pace`?`pace`:typeof e==`string`&&ea.includes(e)?e:`bars`}var na=`codexometer.web.preferences.v1`,ra={statusLine:null,tab:`quota`,view:`bars`,selected:``,defaultDetail:0,layouts:[]};function ia(){try{let e=JSON.parse(localStorage.getItem(na)||`null`);return!e||typeof e!=`object`?ra:{statusLine:Array.isArray(e.statusLine)?[...new Set(e.statusLine.filter(e=>typeof e==`string`&&e.length<64))].slice(0,32):null,tab:[`quota`,`sessions`,`usage`].includes(e.tab)?e.tab:`quota`,view:ta(e.view),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 ra}}var aa=Xt(ia()),oa=Xt({open:!1});function sa(){let e=JSON.stringify(aa);try{localStorage.setItem(na,e)}catch{}}function ca(){return aa.tab===`quota`?`/quota/`+aa.view:`/`+aa.tab}function la(e){return aa.layouts.find(t=>t.id===e)?.level??aa.defaultDetail}function ua(e){aa.defaultDetail=e,aa.layouts=[]}function da(e,t){aa.layouts=[...aa.layouts.filter(t=>t.id!==e),{id:e,level:Math.max(0,Math.min(2,t))}].slice(-100)}var $=Xt({data:null,connected:!1,error:``}),fa=e=>e==null?`Unavailable`:e.toLocaleString(`en-GB`),pa=e=>!e||String(e).startsWith(`0001-`)?`Not yet available`:new Date(typeof e==`number`?e*1e3:e).toLocaleString(`en-GB`),ma=`codexometer.web.session`,ha=class extends Error{},ga;async function _a(e,t,n){if(!ga||!$.connected||!$.data?.control||$.data.sessionsError)throw Error(`Session controls unavailable. Check the live connection.`);return await ga(e,t,n)}function va(){let e=new AbortController,t,n=``;ga=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 ha(`Action rejected, expired or changed. Refresh and check Codex; nothing was retried.`);return a.json()};try{n=sessionStorage.getItem(ma)||``}catch{}let r=location.hash,i=r.startsWith(`#pair=`)?r.slice(6):``;(i||!r||r===`#`)&&(history.replaceState(null,``,`/#`+ca()),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(ma,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(ma)}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(),()=>{ga=void 0,e.abort(),clearTimeout(t),$.connected=!1}}Ve();var ya=q(`

      Quota refresh failed. Policy state is based on the last successful + observation.

      `),ba=q(`

      `),xa=q(`

      The longest Codex quota window selects one active model profile. ASK + creates a per-session review; AUTO applies the profile on the next + eligible check.

      `,1),Sa=q(`

      No threshold-based model steps were configured at launch.

      `);function Ca(e,t){We(t,!1),Ri();var n=Pr(),r=z(n),i=e=>{var t=xa(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,ya())};X(i,e=>{$.data.quotaError&&e(a)});var o=V(i,2),s=R(o),c=B(s),l=V(s,4);Z(l,5,()=>$.data.thresholds,qr,(e,t)=>{var n=ba();let r;var i=R(n),a=B(i),o=V(i,2),s=R(o),c=B(s,!0),l=B(V(s,2));N(o);var u=V(o,2),d=B(u,!0),f=B(V(u,2));N(n),H((e,i)=>{r=ci(n,1,``,null,r,{active:G(t).state===`ACTIVE`,next:G(t).state===`NEXT`}),Y(a,`${G(t).threshold??``}%`),Y(c,G(t).model),Y(l,`${e??``} REASONING // ${i??``} + SPEED`),Y(d,G(t).mode),Y(f,`${G(t).state??``}${G(t).state===`NEXT`?` // ${G(t).remaining||0} PP TO GO`:``}`)},[()=>G(t).effort.toUpperCase(),()=>G(t).speed.toUpperCase()]),J(e,n)}),N(l),N(o),H(e=>{Y(r,`MODEL STEP POLICY // OBSERVED ${e??``}`),Y(c,`THRESHOLDS // ${$.data.thresholds.length??``} CONFIGURED`)},[()=>pa($.data.quotaAt)]),J(e,t)},a=e=>{J(e,Sa())};X(r,e=>{$.data?.thresholds?.length?e(i):e(a,-1)}),J(e,n),Ge()}var wa=Mr(` `,1),Ta=Mr(` `,1),Ea=Mr(` `,1),Da=Mr(` `,1),Oa=q(`
      `,1),ka=q(` `),Aa=q(`
      Quota observations
      Observed atPeriod elapsedConsumedTrail segment
      `),ja=q(`
      OBSERVATION DATA
      `),Ma=q(`
      CONSUMPTIONQUOTA PERIOD ELAPSED
      `,1);function Na(e,t){let n=Fr();We(t,!0);let r=Wi(t,`trail`,19,()=>[]),i=I(!1),a=I(!0),o=I(`window`),s=[0,25,50,75,100],c={off:0,halfHour:30,hour:60,day:1440,window:0},l=I(400),u=I(240),d=P(()=>G(l)-24),f=P(()=>G(u)-48),p=P(()=>Math.max(1,G(d)-48)),m=P(()=>Math.max(1,G(f)-20)),h=P(()=>48+Math.max(0,Math.min(100,t.elapsed))/100*G(p));function g(e){return G(f)-(e-0)/100*G(m)}let _=P(()=>g(t.used)),v=P(()=>t.used-t.elapsed),y=P(()=>r().map((e,t)=>`${t===0||e.break?`M`:`L`}${48+e.elapsed/100*G(p)} ${g(e.used)}`).join(` `)),b=P(()=>{let e=0;for(let t=r().length-1;t>0;t--)if(r()[t].break){e=t;break}return r().slice(e)}),x=P(()=>G(b).length<2?0:Math.max(0,Date.parse(G(b).at(-1).at)-Date.parse(G(b)[0].at)));function S(e){if(G(x)Date.parse(e.at)>=t).length>=2}let C=P(()=>({off:!0,halfHour:S(18e5),hour:S(36e5),day:S(864e5),window:Number.isFinite(t.elapsed)&&t.elapsed>0&&Number.isFinite(t.used)}));yn(()=>{G(o)!==`window`&&!G(C)[G(o)]&&L(o,`window`)});function w(e){if(e===`off`||!G(C)[e])return[];let t=c[e]*6e4,n=Date.parse(G(b).at(-1).at)-t,r=G(b).findIndex(e=>Date.parse(e.at)>=n);return r<0?[]:G(b).slice(r)}function T(e){if(e.length<2)return null;let t=e.reduce((e,t)=>e+t.elapsed,0)/e.length,n=e.reduce((e,t)=>e+t.used,0)/e.length,r=0,i=0;for(let a of e)r+=(a.elapsed-t)*(a.used-n),i+=(a.elapsed-t)**2;return i>0?Math.max(0,r/i):null}let E=P(()=>{let e=G(o)===`window`&&G(C).window?t.used/t.elapsed:T(w(G(o)));if(e===null||!t.duration)return null;let n=t.used+e*(100-t.elapsed),r=G(o)===`window`?0:t.used-e*t.elapsed,i=e,a=Math.max(0,t.elapsed-c[G(o)]/t.duration*100);G(o)===`window`&&(a=0);let s=100;if(i!==0){let e=(0-r)/i,t=(100-r)/i;a=Math.max(a,Math.min(e,t)),s=Math.min(100,Math.max(e,t))}if(a>s)return null;let l=r+i*a,u=r+i*s,d=Math.hypot((s-a)/100*G(p),(u-l)/100*G(m)),f=Math.max(3,Math.min(9,Math.floor(d/65)+2));return{path:`M${Array.from({length:f},(e,t)=>{let n=a+(s-a)*t/(f-1),r=l+(u-l)*t/(f-1);return`${48+n/100*G(p)} ${g(r)}`}).join(` L`)}`,projected:n,safe:n<=100}}),ee=P(()=>{if(G(b).length===0)return`NO OBSERVATIONS`;if(G(b).length===1)return`ONE OBSERVATION`;let e=Math.floor(G(x)/6e4);if(e<60)return`${e} MIN CONTINUOUS`;let t=Math.floor(e/60);return t<24?`${t}H CONTINUOUS`:`${Math.floor(t/24)}D ${t%24}H CONTINUOUS`});var D=Ma(),O=z(D),k=R(O);let te;var A=R(k),ne=R(A),re=V(ne);N(A);var ie=V(A),ae=V(ie);Z(ae,17,()=>s,qr,(e,t)=>{var n=wa(),r=z(n),i=V(r),a=B(i);H(()=>{Q(r,`x1`,48+G(t)/100*G(p)),Q(r,`x2`,48+G(t)/100*G(p)),Q(r,`y2`,G(f)),Q(i,`x`,48+G(t)/100*G(p)),Q(i,`y`,G(f)+20),Y(a,`${G(t)??``}%`)}),J(e,n)});var oe=V(ae);Z(oe,17,()=>s,qr,(e,t)=>{var n=Ta(),r=z(n),i=V(r),a=B(i);H((e,n,o)=>{Q(r,`y1`,e),Q(r,`x2`,G(d)),Q(r,`y2`,n),Q(i,`y`,o),Y(a,`${G(t)??``}%`)},[()=>g(G(t)),()=>g(G(t)),()=>g(G(t))+4]),J(e,n)});var se=V(oe),ce=V(se),le=V(ce),ue=e=>{var t=Ea(),n=z(t),i=V(n),a=V(i),o=B(R(a));N(a),H((e,t)=>{Q(n,`d`,G(y)),Q(i,`d`,G(y)),Q(a,`cx`,48+r()[0].elapsed/100*G(p)),Q(a,`cy`,e),Y(o,`First observation: ${t??``}`)},[()=>g(r()[0].used),()=>pa(r()[0].at)]),J(e,t)};X(le,e=>{G(a)&&r().length&&e(ue)});var de=V(le),fe=e=>{var t=Da(),r=z(t),i=V(r),a=B(R(i));N(i),H(e=>{Q(r,`d`,G(E).path),Q(i,`d`,G(E).path),Q(i,`marker-mid`,`url(#${n}-trend-arrow)`),Y(a,`${G(o)===`window`?`Window-average pace`:`Recent consumption trajectory`} projects ${e??``}% at reset if continued`)},[()=>G(E).projected.toFixed(1)]),J(e,t)};X(de,e=>{G(E)&&e(fe)});var pe=V(de,2),me=V(pe),he=V(me),ge=B(R(he));N(he),N(k),N(O);var _e=V(O,2),ve=R(_e),j=R(ve),ye=V(j,3),M=B(ye,!0),be=V(ye,2),xe=e=>{var t=Oa(),n=B(V(z(t)));H(e=>Y(n,`TREND // ${e??``}`),[()=>G(E).projected>=100?`QUOTA EXHAUSTION PROJECTED`:`${G(E).projected.toFixed(1)}% PROJECTED AT RESET`]),J(e,t)};X(be,e=>{G(E)&&e(xe)}),N(ve);var Ce=V(ve,2),we=R(Ce),Te=R(we);xi(Te),Se(),N(we);var Ee=V(we,2),De=V(R(Ee),2),Oe=R(De);Oe.value=Oe.__value=`off`;var ke=V(Oe),Ae=B(ke);ke.value=ke.__value=`halfHour`;var je=V(ke),Me=B(je);je.value=je.__value=`hour`;var Ne=V(je),Pe=B(Ne);Ne.value=Ne.__value=`day`;var Fe=V(Ne),Ie=B(Fe);Fe.value=Fe.__value=`window`,N(De),mi(De),N(Ee);var Le=B(V(Ee,2));N(Ce),N(_e);var Re=V(_e,2),ze=e=>{var t=ja(),n=V(R(t),2),a=e=>{var t=Aa(),n=R(t),i=V(R(n),2);Z(i,21,r,qr,(e,t,n)=>{var r=ka(),i=R(r),a=R(i),o=B(a,!0);N(i);var s=V(i),c=B(s),l=V(s),u=B(l),d=B(V(l),!0);N(r),H((e,r)=>{Q(a,`datetime`,G(t).at),Y(o,e),Y(c,`${r??``}%`),Y(u,`${G(t).used??``}%`),Y(d,n===0?`First observation`:G(t).break?`Gap before this observation`:`Connected to previous observation`)},[()=>pa(G(t).at),()=>G(t).elapsed.toFixed(1)]),J(e,r)}),N(i),N(n),N(t),J(e,t)};X(n,e=>{G(i)&&e(a)}),N(t),Li(`open`,`toggle`,t,e=>L(i,e),()=>G(i)),J(e,t)};X(Re,e=>{r().length&&e(ze)}),H((e,r,i,a,o,s)=>{Q(k,`viewBox`,`0 0 ${G(l)} ${G(u)}`),Q(k,`aria-label`,e),te=ui(k,``,te,{"--trend-color":G(E)?.safe?`#115b35`:`#7f1825`}),Q(ne,`id`,n),Q(re,`id`,n+`-trend-arrow`),Q(ie,`width`,G(p)),Q(ie,`height`,G(m)),Q(ie,`fill`,`url(#${n})`),Q(se,`d`,`M48 20 V${G(f)} H${G(d)}`),Q(ce,`y1`,r),Q(ce,`x2`,G(d)),Q(ce,`y2`,i),Q(pe,`x`,48+G(p)/2),Q(pe,`y`,G(u)-5),Q(me,`cx`,G(h)),Q(me,`cy`,G(_)),Q(he,`cx`,G(h)),Q(he,`cy`,G(_)),Y(ge,`${t.used??``}% consumed // ${a??``}% of period elapsed`),Y(j,`${t.used??``}% USED // ${o??``}% TIME ELAPSED`),Y(M,s),ke.disabled=!G(C).halfHour,Y(Ae,`LAST 30 MINUTES${G(C).halfHour?``:` — UNAVAILABLE`}`),je.disabled=!G(C).hour,Y(Me,`LAST HOUR${G(C).hour?``:` — UNAVAILABLE`}`),Ne.disabled=!G(C).day,Y(Pe,`LAST 24 HOURS${G(C).day?``:` — UNAVAILABLE`}`),Fe.disabled=!G(C).window,Y(Ie,`FROM WINDOW START${G(C).window?``:` — NO TIME ELAPSED`}`),Y(Le,`HISTORY // ${G(ee)??``}`)},[()=>`Pace: ${t.used}% consumed, ${t.elapsed.toFixed(1)}% of quota period elapsed. ${G(v)>0?`Above`:G(v)<0?`Below`:`On`} the steady-consumption line.${G(a)&&r().length?` Trace path contains ${r().length} ${r().length===1?`observation`:`observations`}; gaps are not interpolated.`:``}`,()=>g(0),()=>g(100),()=>t.elapsed.toFixed(1),()=>t.elapsed.toFixed(1),()=>Math.abs(G(v))<.05?`ON PACE`:G(v)>0?`ABOVE THE LINE — CONSUMING FASTER THAN TIME`:`BELOW THE LINE — WITHIN PACE`]),Pi(O,`clientWidth`,e=>L(l,e)),Pi(O,`clientHeight`,e=>L(u,e)),ki(Te,()=>G(a),e=>L(a,e)),hi(De,()=>G(o),e=>L(o,e)),J(e,D),Ge()}var Pa=q(` `),Fa=q(`

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

      `),Ia=q(`

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

      `),La=q(`

      `),Ra=q(`

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

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

      `),za=q(` `,1),Ba=Mr(``),Va=Mr(``),Ha=q(`
      `),Ua=q(`

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

      `),Wa=q(`
      EMPTYFULL
      `),Ga=q(`

      `,1),Ka=q(`
      `,1),qa=q(`

      `),Ja=q(`

      `),Ya=q(`

      No quota windows reported yet.

      `),Xa=q(`
      `,1),Za=q(`

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

      `,1),Qa=q(` `,1);function $a(e,t){We(t,!0);let n=Wi(t,`params`,19,()=>({})),r=P(()=>ea.filter(e=>e!==`thresholds`||!!$.data?.thresholds?.length)),i=I(Xt(Date.now())),a=P(()=>G(r).includes(ta(n().view))?ta(n().view):`bars`);Gi(()=>{let e=setInterval(()=>L(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-G(i))/(e.duration*6e4))))}yn(()=>{aa.view=G(a),(n().view===`zone`||n().view===`consumption-pace`)&&Zi(`/quota/pace`)});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=Qa(),l=z(c);Z(l,21,()=>G(r),qr,(e,t)=>{var n=Pa();let r;var i=B(n,!0);H(e=>{Q(n,`href`,`#/quota/`+G(t)),Q(n,`aria-current`,G(a)===G(t)?`page`:void 0),r=ci(n,1,``,null,r,{active:G(a)===G(t)}),Y(i,e)},[()=>G(t)===`fuel`?`FUEL TANK`:G(t).toUpperCase()]),J(e,n)}),N(l);var u=V(l,2),d=e=>{var t=Za(),n=z(t),r=e=>{J(e,Fa())};X(n,e=>{$.data.quotaError&&e(r)});var i=V(n,2),c=B(i),l=V(i,2),u=e=>{Ca(e,{})},d=e=>{var t=Ra(),n=R(t),r=B(n),i=V(n,4),a=e=>{J(e,Ia())};X(i,e=>{$.data.credits.length||e(a)}),Z(V(i,2),17,()=>$.data.credits,qr,(e,t)=>{var n=La(),r=R(n),i=B(r),a=B(V(r,2),!0);N(n),H(e=>{Y(i,`${(G(t).title||`Quota reset`)??``} // ${G(t).status??``}`),Y(a,e)},[()=>G(t).expiryKnown?G(t).expires?`EXPIRES `+pa(G(t).expires):`Does not expire`:`Expiry information unavailable`]),J(e,n)}),Se(2),N(t),H(()=>Y(r,`RESET INVENTORY // ${$.data.creditCount??``} AVAILABLE`)),J(e,t)},f=e=>{var t=Xa(),n=z(t);let r;Z(n,21,()=>$.data.meters,qr,(e,t)=>{let n=P(()=>o(G(t)));var r=Ja(),i=R(r),c=B(i,!0),l=V(i,2),u=R(l),d=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`FREE ${100-G(t).used}%`),Y(a,`USED ${G(t).used??``}%`)}),J(e,n)},f=e=>{var n=za(),r=z(n),i=B(r),a=B(V(r));H(()=>{Y(i,`USED ${G(t).used??``}%`),Y(a,`FREE ${100-G(t).used}%`)}),J(e,n)};X(u,e=>{G(a)===`fuel`?e(d):e(f,-1)}),N(l);var p=V(l,2);let m;var h=R(p),g=e=>{var n=Ha(),r=R(n),i=V(R(r)),a=e=>{J(e,Ba())},o=e=>{var n=Va();H(e=>Q(n,`d`,e),[()=>s(G(t).used)]),J(e,n)};X(i,e=>{G(t).used>=100?e(a):G(t).used>0&&e(o,1)}),N(r),N(n),H(()=>Q(r,`aria-label`,`${G(t).used}% quota used`)),J(e,n)},_=e=>{var r=Pr(),i=z(r),a=e=>{{let r=P(()=>G(t).trail||[]);Na(e,{get used(){return G(t).used},get elapsed(){return G(n)},get trail(){return G(r)},get duration(){return G(t).duration}})}},o=e=>{J(e,Ua())};X(i,e=>{G(n)===null?e(o,-1):e(a)}),J(e,r)},v=e=>{var r=Ka(),i=z(r),o=R(i);let s;N(i);var c=V(i,2),l=e=>{J(e,Wa())};X(c,e=>{G(a)===`fuel`&&e(l)});var u=V(c,2),d=e=>{var t=Ga(),r=z(t),i=B(r),o=V(r,2),s=R(o);let c;N(o),H(e=>{Y(i,`RESET CYCLE // ${e??``}% ELAPSED`),c=ui(s,``,c,{width:`${G(a)===`fuel`?100-G(n):G(n)}%`})},[()=>Math.floor(G(n))]),J(e,t)};X(u,e=>{G(n)!==null&&e(d)}),H(()=>{Q(i,`aria-label`,G(a)===`fuel`?`Fuel remaining`:`Quota used`),Q(i,`aria-valuenow`,G(a)===`fuel`?100-G(t).used:G(t).used),s=ui(o,``,s,{width:`${G(a)===`fuel`?100-G(t).used:G(t).used}%`})}),J(e,r)};X(h,e=>{G(a)===`pie`?e(g):G(a)===`pace`?e(_,1):e(v,-1)}),N(p);var y=V(p,2),b=B(y),x=V(y,2),S=e=>{var n=qa(),r=B(n,!0);H(()=>Y(r,G(t).details)),J(e,n)};X(x,e=>{G(t).details&&e(S)}),N(r),H(e=>{Y(c,G(t).name),m=ci(p,1,`meter-graphic`,null,m,{"bar-graphic":G(a)===`bars`||G(a)===`fuel`}),Y(b,`RESETS // ${e??``}`)},[()=>pa(G(t).reset)]),J(e,r)}),N(n);var i=V(n,2),c=e=>{J(e,Ya())};X(i,e=>{$.data.meters.length||e(c)}),H(()=>r=ci(n,1,`quota-grid`,null,r,{radial:G(a)===`pie`,zone:G(a)===`pace`})),J(e,t)};X(l,e=>{G(a)===`thresholds`?e(u):G(a)===`resets`?e(d,1):e(f,-1)}),Se(2),H(e=>Y(c,`QUOTA // OBSERVED ${e??``}`),[()=>pa($.data.quotaAt)]),J(e,t)};X(u,e=>{$.data&&e(d)}),J(e,c),Ge()}var eo=q(`
      `),to=q(`

      `,1);function no(e,t){We(t,!0);let n=Wi(t,`values`,19,()=>[]),r=Wi(t,`label`,3,`Token activity`),i=Wi(t,`capacity`,3,0),a=P(()=>Math.max(0,...n())),o=P(()=>i()>n().length?[...Array(i()-n().length).fill(0),...n()]:n());var s=to(),c=z(s),l=B(c),u=V(c,2);Z(u,21,()=>G(o),qr,(e,t)=>{var n=eo();let r;H((e,t)=>{Q(n,`title`,e),r=ui(n,``,r,{height:t})},[()=>G(t).toLocaleString(`en-GB`)+` tokens`,()=>`${100*G(t)/Math.max(1,G(a))}%`]),J(e,n)}),N(u),H((e,t)=>{Y(l,`SCALE // 0 — ${e??``} TOKENS`),Q(u,`aria-label`,t)},[()=>G(a).toLocaleString(`en-GB`),()=>`${r()}. Peak ${G(a).toLocaleString(`en-GB`)} tokens.`]),J(e,s),Ge()}var ro=q(`

      `),io=q(`

      `,1),ao=q(`

      `),oo=q(`

      Loading / sending…

      `),so=q(`
      `),co=q(`

      Confirmation expired. Reopen the option.

      `),lo=q(`

      `,1),uo=q(`

       
      `,1),fo=q(` `),po=q(``),mo=q(`

      No available matching commands.

      `),ho=q(`

      ↑/↓ select · Tab complete · Enter options · Escape dismiss

      `),go=q(`
      `,1),_o=q(` `,1),vo=q(`
      `),yo=q(`
      `);function bo(e,t){We(t,!0);let n=Wi(t,`query`,3,``),r=Wi(t,`onchange`,3,()=>{}),i=Wi(t,`oncomplete`,3,e=>{}),a=I(!1),o=I(!1),s=I(``),c=I(null),l=I(null),u=I(``),d=I(0),f=I(Xt(Date.now())),p=I(``),m=0,h=I(0),g=I(null),_=I(void 0),v=setInterval(()=>{L(f,Date.now(),!0)},1e3);Ki(()=>{clearInterval(v),m++});let y=P(()=>n().trim().startsWith(`/`)&&!n().trim().startsWith(`//`)),b=P(()=>G(c)?.path===``&&G(y)?n().trim().slice(1).toLowerCase():``),x=P(()=>(G(c)?.choices||[]).filter(e=>!G(b)||e.label.toLowerCase().startsWith(`/`+G(b)))),S=P(()=>!$.connected||!!$.data?.sessionsError),C=P(()=>G(a)&&G(y)&&(!G(c)||G(c).path===``)&&!G(l));yn(()=>{n(),L(h,0)}),yn(()=>{let e=G(h);G(x),G(C)&&ur().then(()=>{let t=G(_)?.children[e];if(!t||!G(_))return;let n=G(_).getBoundingClientRect(),r=t.getBoundingClientRect();r.topn.bottom&&(G(_).scrollTop+=r.bottom-n.bottom)})});function w(e){if(!G(y)||!G(a)||G(c)&&G(c).path!==``||G(l)||G(S)||e.isComposing||e.ctrlKey||e.metaKey||e.altKey||![`ArrowUp`,`ArrowDown`,`Tab`,`Enter`,`Escape`].includes(e.key)||e.key===`Tab`&&e.shiftKey)return;if(e.preventDefault(),e.key===`Escape`){L(a,!1),L(g,n()),L(u,``);return}if(e.key===`ArrowUp`||e.key===`ArrowDown`){L(h,Math.min(Math.max(G(h)+(e.key===`ArrowUp`?-1:1),0),Math.max(G(x).length-1,0)),!0);return}let t=G(x)[G(h)];t&&!G(o)&&(e.key===`Tab`?i()(t.label):E(t))}yn(()=>{G(S)&&(m++,L(o,!1),L(u,``),G(a)&&(L(a,!1),L(g,n())),L(c,null),L(l,null))}),yn(()=>{G(y)&&!G(a)&&n()!==G(g)&&!G(S)&&(L(a,!0),T(``))});async function T(e){let n=++m;L(o,!0),L(l,null),L(u,``),L(s,``);try{let r=await _a(`commands`,{session:t.session,command:{mode:`list`,path:e}});n===m&&((e===``||e===`help`)&&r.choices.push({id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}),L(c,r,!0),L(p,r.value||``,!0),(r.path.startsWith(`rename/`)||r.path.startsWith(`cd/`))&&r.choices.length===1&&E(r.choices[0]))}catch{n===m&&(L(s,`Command catalogue unavailable. Use Codex.`),(e===``||e===`help`)&&L(c,{title:`/ COMMANDS`,help:`Local display settings remain available.`,path:``,revision:``,choices:[{id:`local-statusline`,label:`/statusline`,help:`Choose multiple fields for Codexometer’s detail footer.`,next:`statusline`}]},!0))}finally{n===m&&L(o,!1)}}async function E(e){if(e.next===`statusline`){oa.open=!0,L(a,!1),L(g,n());return}if(e.next){await T(e.next);return}if(L(l,e,!0),L(u,``),L(s,``),!e.action||!G(c))return;let r=++m;L(o,!0);try{let n=await _a(`commands`,{session:t.session,command:{mode:`prepare`,path:G(c).path,revision:G(c).revision,choice:e.id}});r===m&&(L(u,n.confirmation,!0),L(d,Date.parse(n.expires),!0))}catch{r===m&&L(s,`Option changed or unavailable. Refresh before retrying.`)}finally{r===m&&L(o,!1)}}async function ee(){if(!G(u)||G(S)||G(o)||G(f)>=G(d)||!G(c))return;let e=G(u);L(u,``),L(o,!0);let n=++m;try{let i=await _a(`commands`,{session:t.session,confirmation:e,command:{mode:`commit`,path:G(c).path}});n===m&&(L(s,i.message,!0),L(a,!1),L(c,null),L(l,null),L(d,0),L(g,null),r()())}catch{n===m&&L(s,`Change unconfirmed. Check Codex before retrying.`)}finally{n===m&&L(o,!1)}}var D={handleKey:w},O=yo(),k=R(O),te=V(k,2),A=e=>{var t=ro(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(te,e=>{G(s)&&!G(a)&&e(A)});var ne=V(te,2),re=e=>{var n=vo();let r;var i=R(n),a=e=>{var t=io(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(c)?.title||`/ COMMANDS`),Y(i,G(c)?.help||`Loading live options…`)}),J(e,t)};X(i,e=>{G(C)||e(a)});var m=V(i,2),g=e=>{var t=ao(),n=B(t,!0);H(()=>Y(n,G(s))),J(e,t)};X(m,e=>{G(s)&&e(g)});var v=V(m,2),b=e=>{J(e,oo())};X(v,e=>{G(o)&&e(b)});var w=V(v,2),D=e=>{var t=so(),n=R(t),r=R(n),i=V(r);xi(i),N(n);var a=V(n,2),s=B(a);N(t),H((e,t)=>{Y(r,`${e??``} `),Q(i,`aria-label`,G(c).inputLabel||`Session name`),Q(i,`maxlength`,G(c).inputLimit||512),i.disabled=G(o)||G(S),a.disabled=t,Y(s,`REVIEW ${G(c).path===`cd`?`DIRECTORY`:`RENAME`}`)},[()=>(G(c).inputLabel||`Session name`).toUpperCase(),()=>G(o)||G(S)||!G(p).trim()]),Sr(`submit`,t,e=>{e.preventDefault(),G(c)&&G(p).trim()&&!G(o)&&!G(S)&&T(G(c).path+`/`+encodeURIComponent(G(p).trim()))}),Ei(i,()=>G(p),e=>L(p,e)),J(e,t)},O=e=>{var n=uo(),r=z(n),i=B(r,!0),a=V(r,2),s=B(a,!0),p=V(a,2),m=e=>{var n=lo(),r=z(n),i=R(r),a=V(i),s=e=>{J(e,Nr(`Only this session's saved name + changes.`))},l=P(()=>G(c)?.path.startsWith(`rename/`)),p=e=>{J(e,Nr(`Only this session’s directory + changes; project configuration is not reloaded.`))},m=P(()=>G(c)?.path.startsWith(`cd/`)),h=e=>{J(e,Nr(`Changes affect subsequent turns of this session, not global + defaults. Automatic quota thresholds may later supersede model + settings.`))};X(a,e=>{G(l)?e(s):G(m)?e(p,1):e(h,-1)}),N(r);var g=V(r,2),_=V(g,2),v=e=>{J(e,co())};X(_,e=>{G(u)&&G(f)>=G(d)&&e(v)}),H(()=>{Y(i,`TARGET // ${t.session??``}. `),g.disabled=G(o)||G(S)||!G(u)||G(f)>=G(d)}),K(`click`,g,ee),J(e,n)};X(p,e=>{G(l).action&&e(m)});var h=V(p,2);H(()=>{Y(i,G(l).label),Y(s,G(l).help||`No additional help supplied by Codex.`),h.disabled=G(o)}),K(`click`,h,()=>{L(l,null),L(u,``)}),J(e,n)},k=e=>{var t=go(),n=z(t);let r;Z(n,23,()=>G(x),e=>e.id,(e,t,n)=>{var r=po();let i;var a=R(r),s=B(a,!0),l=V(a),u=B(l,!0),d=V(l),f=e=>{var n=fo(),r=B(n,!0);H(()=>Y(r,G(t).help)),J(e,n)};X(d,e=>{G(y)&&G(c)?.path===``&&e(f)}),N(r),H(()=>{r.disabled=G(o)||G(S),Q(r,`title`,G(t).help),Q(r,`aria-label`,G(t).label+(G(t).next?` →`:G(t).action?``:` // HELP`)),i=ci(r,1,`svelte-7bfwr9`,null,i,{suggested:G(y)&&G(c)?.path===``&&G(h)===G(n)}),Y(s,G(t).label),Y(u,G(t).next?` →`:G(t).action?``:` // HELP`)}),K(`click`,r,()=>E(G(t))),J(e,r)}),N(n),Ii(n,e=>L(_,e),()=>G(_));var i=V(n,2),a=e=>{J(e,mo())};X(i,e=>{!G(o)&&!G(x).length&&e(a)});var s=V(i,2),l=e=>{J(e,ho())};X(s,e=>{G(y)&&G(c)?.path===``&&e(l)}),H(()=>r=ci(n,1,`command-options svelte-7bfwr9`,null,r,{vertical:G(C)})),J(e,t)};X(w,e=>{G(c)?.input?e(D):G(l)?e(O,1):e(k,-1)});var te=V(w,2),A=e=>{var t=_o(),n=z(t),r=V(n,2);H(()=>{n.disabled=G(o),r.disabled=G(o)}),K(`click`,n,()=>T(``)),K(`click`,r,()=>T(G(c)?.path||``)),J(e,t)};X(te,e=>{G(C)||e(A)}),N(n),H(()=>{Q(n,`aria-label`,G(C)?`Slash command suggestions`:void 0),r=ci(n,1,`svelte-7bfwr9`,null,r,{"command-popup":G(C)})}),J(e,n)};return X(ne,e=>{G(a)&&e(re)}),N(O),H(()=>k.disabled=G(S)||G(o)),K(`click`,k,()=>{L(a,!G(a)),L(g,G(a)?null:n(),!0),L(u,``),G(a)&&T(``)}),J(e,O),Ge(D)}Cr([`click`]);var xo=q(` `,1),So=q(`
      `),Co=q(`
      /
      `);function wo(e,t){We(t,!0);let n=P(()=>t.lines.filter(e=>e.kind===`addition`).length),r=P(()=>t.lines.filter(e=>e.kind===`removal`).length);var i=Co(),a=R(i),o=R(a),s=B(o),c=B(V(o,2));N(a),Z(V(a,2),17,()=>t.lines,qr,(e,t)=>{var n=So();let r;var i=R(n),a=e=>{var n=xo(),r=z(n),i=B(r,!0),a=B(V(r),!0);H(()=>{Y(i,G(t).old||``),Y(a,G(t).new||``)}),J(e,n)};X(i,e=>{G(t).kind!==`heading`&&G(t).kind!==`metadata`&&e(a)});var o=B(V(i),!0);N(n),H(()=>{r=ci(n,1,`diff-line svelte-x4gtb6`,null,r,{added:G(t).kind===`addition`,removed:G(t).kind===`removal`,heading:G(t).kind===`heading`}),Y(o,G(t).text)}),J(e,n)}),N(i),H(()=>{Q(a,`aria-label`,`${G(n)} lines added, ${G(r)} lines removed`),Y(s,`+${G(n)??``}`),Y(c,`−${G(r)??``}`)}),J(e,i),Ge()}var To=q(`

      `),Eo=q(`

      Send this saved prompt now? This starts Codex work and consumes quota.

      `,1),Do=q(``),Oo=q(`

       

      In memory only. Follows session model, reasoning and speed. Closing + Codexometer cancels pending work.

      `),ko=q(`

      CURRENT PROFILE

      MODEL / REASONING LEVEL / SPEED

       

      PROPOSED PROFILE

      MODEL / REASONING LEVEL / SPEED

       

      Applied settings remain after Codexometer closes.

      `,1),Ao=q(`

      `),jo=q(`

       
      `,1),Mo=q(`

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

      `),No=q(`

      Session controls temporarily unavailable. Check Codex for current state.

      `),Po=q(`

      Checking session controls…

      `),Fo=q(`

      `),Io=q(`
      About browser controls

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

      `),Lo=q(` `,1),Ro=q(` `),zo=q(`Grants permission beyond this one action. Check the scope + carefully.`),Bo=q(``),Vo=q(``),Ho=q(``),Uo=q(``),Wo=q(`

      Not before this time; when quota and idle allow.

      `),Go=q(`

      `,1),Ko=q(`

      The existing trigger remains active until saved or deleted. If + it changes or sends while you edit, saving is blocked.

      `),qo=q(` `,1),Jo=q(``),Yo=q(``),Xo=q(``),Zo=q(` `,1),Qo=q(`
    • `),$o=q(`
      View fixed choices

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

        `),es=q(` `,1),ts=q(`

        `),ns=q(`

        `,1),rs=q(` `,1),is=q(``),as=q(`

        `,1),os=q(`

        `);function ss(e,t){We(t,!0);let n=[],r=Wi(t,`observedCommand`,3,``),i=Wi(t,`observedFileChanges`,19,()=>[]),a=Wi(t,`review`,3,``),o=Wi(t,`suspended`,3,!1),s=Wi(t,`openScheduler`,3,!1),c=Wi(t,`onProtectedChange`,3,e=>{}),l=I(null),u=I(Xt([])),d=I(null),f=I(``),p=I(0),m=I(Xt(Date.now())),h=I(!1),g=I(``),_=I(!1),v=I(!1),y=I(``),b=I(!1),x=I(``),S=I(!1),C=I(``),w=I(`now`),T=I(60),E=I(``),ee=I(!1),D=I(``),O=I(Xt([])),k=P(()=>G(O).find(e=>e.status!==`sent`)),te=I(void 0),A=I(void 0);function ne(e){if(G(b)){ur().then(()=>G(te)?.focus());return}if(e.status!==`pending`||G(h)||!G(l)?.id||G(l).kind!==`prompt`||G(l).questions?.length)return;L(b,!0),L(x,e.id,!0),ur().then(()=>G(te)?.focus()),L(u,[e.text],!0),L(w,e.trigger===`quota`?`quota`:`at`,!0),L(f,``),L(C,``);let t=new Date(e.at);e.trigger!==`quota`&&L(E,new Date(t.getTime()-t.getTimezoneOffset()*6e4).toISOString().slice(0,16),!0)}yn(()=>{s()&&G(k)&&!G(S)&&G(l)?.id&&G(l).kind===`prompt`&&!G(l).questions?.length&&(L(S,!0),ne(G(k)))});async function re(){if(!a())try{L(O,await _a(`schedules`,{session:t.session},ve.signal),!0),G(b)&&!G(O).some(e=>e.id===G(x)&&e.status===`pending`)&&L(f,``),G(C)&&!G(O).some(e=>e.id===G(C)&&e.status===`pending`)&&(L(f,``),L(C,``))}catch{}}async function ie(e){try{L(O,await _a(`schedules`,{session:t.session,cancelId:e},ve.signal),!0),L(b,!1),L(f,``),L(C,``),L(u,[],!0)}catch(e){L(g,e instanceof Error?e.message:`Unable to cancel trigger.`,!0)}}yn(()=>(c()(G(h)||G(u).some(e=>e.length>0)),()=>c()(!1)));let ae=P(()=>$.data?.sessions.find(e=>e.id===t.session)?.status),oe=P(()=>!$.connected||!!$.data?.sessionsError),se=P(()=>a()!==`profile`&&G(l)?.kind===`prompt`&&!G(l).questions?.length&&!!$.data?.profiles?.some(e=>e.session===t.session&&e.pending)),ce=P(()=>!G(oe)&&!G(v)&&!!G(l)?.id&&G(l).kind===`approval`&&G(y)!==G(l).id),le=P(()=>G(ce)?G(l).command:r()),ue=P(()=>!!G(f)&&G(m)G(l)?.questions?.length?G(l).questions:[{text:`Follow-up message`,secret:!1,freeText:!0,options:[]}]),fe=P(()=>G(l)?.kind===`approval`||G(l)?.kind===`profile`?G(d)!==null:G(u).length===G(de).length&&G(u).every((e,t)=>e.trim().length>0&&(G(de)[t].freeText||G(de)[t].options?.includes(e)))),pe=P(()=>G(l)?.kind===`prompt`&&!G(l).questions?.length&&G(w)!==`now`),me=P(()=>G(w)===`delay`?G(m)+G(T)*6e4:Date.parse(G(E))),he=P(()=>{if(!G(pe))return``;if(G(b)&&!G(O).some(e=>e.id===G(x)&&e.status===`pending`))return`Trigger changed, removed or already sent. Go back and reopen it; your draft has not been saved.`;if(!G(u)[0]?.trim())return`Enter a message to schedule.`;if(G(w)===`quota`)return``;if(!Number.isFinite(G(me))||G(me)<=G(m))return`Choose a future date/time or a delay greater than zero.`;let e=new Date(G(m));return e.setFullYear(e.getFullYear()+1),G(me)>=e.getTime()?`Choose a time within one year.`:``});function ge(e){return new Date(e).toLocaleString([],{timeZoneName:`short`})}function _e(e){if(e.status!==`pending`)return e.status;if(e.trigger===`at`&&Date.parse(e.at)>G(m))return`Due in `+Math.ceil((Date.parse(e.at)-G(m))/6e4)+` min`;let t=G(oe)?`waiting for a fresh connection`:e.waitingReason||(e.canSend?`ready; awaiting dispatch`:`waiting for quota and an eligible idle session`);return(e.trigger===`at`?`Time reached — `:``)+t}yn(()=>{(G(oe)||o()||G(se)||G(m)>=G(p))&&L(f,``)});let ve=new AbortController;Gi(()=>{let e=e=>{e.ctrlKey&&e.key.toLowerCase()===`s`&&!a()&&G(k)&&(e.preventDefault(),ne(G(k)))};window.addEventListener(`keydown`,e);let n,r=setInterval(()=>{L(m,Date.now(),!0)},1e3);async function i(){await re();try{let e=await _a(`offer`,{session:t.session,...a()?{review:a()}:{}},ve.signal);if(ve.signal.aborted)return;L(v,!1),G(l)?.id!==e.id&&(L(f,``),L(d,null),L(u,Array(Math.max(1,e.questions?.length||0)).fill(``),!0)),L(l,e,!0),G(_)&&e.id&&e.id!==G(y)&&(L(g,``),L(_,!1))}catch{ve.signal.aborted||(L(l,null),L(v,!0),L(f,``))}finally{ve.signal.aborted||(n=setTimeout(i,2e3))}}return i(),()=>{window.removeEventListener(`keydown`,e),ve.abort(),clearTimeout(n),clearInterval(r)}});async function j(e){if(!e&&G(l)?.kind===`prompt`&&!G(l).questions?.length&&G(u)[0]?.trim().startsWith(`/`)&&!G(u)[0]?.trim().startsWith(`//`)){L(g,`Choose a slash command from COMMANDS; use // for literal slash text.`);return}if(!G(l)?.id||G(h)||G(oe)||o()||G(se)||(e?!e.canSend:!G(fe)||G(he)))return;let n=G(l).id;L(h,!0),L(g,``),L(_,!1),L(f,``),L(C,e?.id||``,!0);try{let r=!e&&G(l).kind===`prompt`&&!G(l).questions?.length&&G(w)!==`now`?{trigger:G(w)===`quota`?`quota`:`at`,zone:Intl.DateTimeFormat().resolvedOptions().timeZone,...G(w)===`quota`?{}:{at:(G(w)===`delay`?new Date(Date.now()+G(T)*6e4):new Date(G(E))).toISOString()}}:void 0;L(ee,!!r),L(D,r?r.trigger===`quota`?`After fresh quota becomes available, when the session is idle`:ge(r.at)+` — not before this time; when quota and idle allow`:``,!0);let i=await _a(`prepare`,{session:t.session,...a()?{review:a()}:{},offer:n,...e?{sendId:e.id}:{},...r?{schedule:r}:{},...r&&G(b)?{editId:G(x)}:{},...G(l).kind===`approval`||G(l).kind===`profile`?{choice:G(d)}:{answers:e?[e.text]:[...G(u)]}},ve.signal);G(l)?.id===n&&!ve.signal.aborted&&!G(oe)&&!o()&&!G(se)&&(L(f,i.confirmation,!0),L(p,Date.parse(i.expires),!0))}catch(e){ve.signal.aborted||L(g,e instanceof Error?e.message:`Unable to prepare action.`,!0)}finally{L(h,!1)}}async function ye(){if(!G(l)?.id||G(h)||o()||G(se)||!G(ue))return;let e=G(l).id,n=G(l).kind,r=G(f);L(f,``),L(h,!0),L(y,e,!0);try{await _a(`commit`,{session:t.session,...a()?{review:a()}:{},offer:e,confirmation:r},ve.signal),L(_,!0),L(b,!1),G(ee)&&(L(y,``),await re()),L(g,G(ee)?`Trigger set. Closing Codexometer cancels it.`:n===`profile`?`Profile decision completed.`:n===`approval`?`Decision sent.`:`Text sent.`,!0)}catch(e){L(g,e instanceof ha?e.message:`Outcome uncertain. Check Codex before taking another action; nothing was retried.`,!0)}finally{L(h,!1),L(C,``),await re(),L(u,[],!0),L(d,null)}}var M=Lo(),be=z(M),xe=e=>{var t=Pr();Z(z(t),17,()=>G(O).filter(e=>e.status!==`sent`),e=>e.id,(e,t)=>{var n=Oo(),r=R(n),i=B(r,!0),a=V(r,2),s=B(a),c=V(a,2),u=B(c,!0),d=V(c,2),p=B(d,!0),m=V(d,2),_=B(m,!0),v=V(m,2),y=e=>{var t=To(),n=B(t,!0);H(()=>Y(n,G(g))),J(e,t)};X(v,e=>{G(g)&&e(y)});var b=V(v,4),x=V(b,2),S=V(x,2),w=e=>{var n=Eo(),r=V(z(n),2),i=V(r,2);H(()=>r.disabled=G(h)||G(oe)||!G(t).canSend),K(`click`,r,ye),K(`click`,i,()=>{L(f,``),L(C,``)}),J(e,n)},T=e=>{var n=Do();H(()=>n.disabled=G(h)||G(oe)||!G(t).canSend||o()),K(`click`,n,()=>j(G(t))),J(e,n)};X(S,e=>{G(ue)&&G(C)===G(t).id?e(w):e(T,-1)}),N(n),H((e,n)=>{Y(i,G(t).status===`uncertain`?`CHECK TRIGGER — outcome uncertain; not retried`:`SCHEDULED FOLLOW-UP`),Y(s,`TARGET // ${G(t).session??``}`),Y(u,e),Y(p,n),Y(_,G(t).text),b.disabled=G(h)||!G(l)?.id||G(l).kind!==`prompt`||!!G(l).questions?.length||G(t).status!==`pending`,x.disabled=G(h)||G(t).status===`sending`},[()=>G(t).trigger===`quota`?`After confirmed quota recovery, when idle`:`Not before ${ge(G(t).at)}`,()=>_e(G(t))]),K(`click`,b,()=>ne(G(t))),K(`click`,x,()=>ie(G(t).id)),J(e,n)}),J(e,t)},Ce=P(()=>!a()&&G(l)?.kind!==`approval`&&!G(l)?.questions?.length&&![`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ae)||``));X(be,e=>{G(Ce)&&e(xe)});var we=V(be,2),Te=e=>{var r=os(),o=R(r),s=B(o,!0),c=V(o,2),x=e=>{var t=ko(),n=z(t),r=B(n),i=V(n,6),a=B(i,!0),o=B(V(i,6),!0);Se(2),H(()=>{Y(r,`Your ${G(l).profile.threshold??``}% quota threshold has been reached. Review + the profile for subsequent turns.`),Y(a,G(l).profile.current),Y(o,G(l).profile.proposed)}),J(e,t)};X(c,e=>{G(l)?.profile&&!G(oe)&&!G(v)&&e(x)});var S=V(c,2),C=e=>{var t=Ao();let n;var r=B(t,!0);H(()=>{n=ci(t,1,`svelte-1oupzfc`,null,n,{notice:!G(_),sent:G(_)}),Y(r,G(g))}),J(e,t)};X(S,e=>{G(g)&&e(C)});var O=V(S,2),k=e=>{wo(e,{get lines(){return G(l).fileChanges}})},ne=e=>{wo(e,{get lines(){return i()}})},re=e=>{var t=jo(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(ce)?`EXACT COMMAND`:`LAST OBSERVED COMMAND`),Y(i,G(le))}),J(e,t)},ie=e=>{J(e,Mo())};X(O,e=>{G(l)?.fileChanges?.length&&!G(oe)&&!G(v)?e(k):i().length?e(ne,1):G(le)?e(re,2):a()!==`profile`&&G(ae)===`APPROVAL NEEDED`&&!G(_)&&e(ie,3)});var se=V(O,2),pe=e=>{J(e,No())},_e=e=>{J(e,Po())},ve=e=>{var t=Lo(),n=z(t),r=e=>{var t=Fo(),n=B(t,!0);H(e=>Y(n,e),[()=>G(ae)===`WORKING`?`Codex is working — nothing to respond to.`:[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ae)||``)?`Respond in Codex for this request.`:`Nothing needs a response right now.`]),J(e,t)};X(n,e=>{(G(ae)===`WORKING`||!G(_)&&!G(h))&&e(r)});var i=V(n,2),a=e=>{J(e,Io())},o=P(()=>[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ae)||``)&&!G(_));X(i,e=>{G(o)&&e(a)}),J(e,t)},M=e=>{var r=as(),i=z(r),o=B(i),s=V(i,2),c=R(s),g=B(c,!0),_=V(c,2),v=e=>{var r=Pr();Z(z(r),17,()=>G(l).choices||[],qr,(e,r,i)=>{var o=Bo(),s=R(o);xi(s),s.value=s.__value=i;var c=V(s),l=V(c),u=e=>{var t=Ro(),n=B(t,!0);H(()=>Y(n,G(r).detail)),J(e,t)};X(l,e=>{G(r).detail&&e(u)});var f=V(l,2),p=e=>{J(e,zo())};X(f,e=>{G(r).persistent&&e(p)}),N(o),H(()=>{Q(s,`name`,`decision-`+t.session+`-`+a()),Y(c,` ${G(r).label??``} `)}),Oi(n,[],s,()=>G(d),e=>L(d,e)),J(e,o)}),J(e,r)},y=e=>{var n=Lo(),r=z(n),i=e=>{var t=qo(),n=z(t),r=V(R(n)),i=R(r),a=e=>{var t=Vo();t.value=t.__value=`now`,J(e,t)};X(i,e=>{G(b)||e(a)});var o=V(i);o.value=o.__value=`quota`;var s=V(o);s.value=s.__value=`delay`;var c=V(s);c.value=c.__value=`at`,N(r),mi(r),N(n);var l=V(n,2),u=e=>{var t=Ho(),n=V(R(t));xi(n),N(t),Ei(n,()=>G(T),e=>L(T,e)),J(e,t)};X(l,e=>{G(w)===`delay`&&e(u)});var d=V(l,2),f=e=>{var t=Uo(),n=V(R(t));xi(n),N(t),Ei(n,()=>G(E),e=>L(E,e)),J(e,t)};X(d,e=>{G(w)===`at`&&e(f)});var p=V(d,2),m=e=>{var t=Go(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,Wo())};X(i,e=>{G(w)!==`quota`&&e(a)});var o=V(i,2);o.textContent=`Timezone: ${Intl.DateTimeFormat().resolvedOptions().timeZone??``}. + One pending request per session; saving replaces it. Memory + only; Codexometer must stay running. Uses session model, + reasoning and speed.`,H(e=>Y(r,`Will send: ${e??``}`),[()=>G(w)===`quota`?`when quota is available and this session is idle`:Number.isFinite(G(me))?ge(G(me)):`choose a date and time`]),J(e,t)};X(p,e=>{G(w)!==`now`&&e(m)});var h=V(p,2),g=e=>{J(e,Ko())};X(h,e=>{G(b)&&e(g)}),hi(r,()=>G(w),e=>L(w,e)),J(e,t)};X(r,e=>{G(l).questions?.length||e(i)}),Z(V(r,2),17,()=>G(de),qr,(e,n,r)=>{var i=es(),o=z(i),s=e=>{{let n=P(()=>G(u)[0]||``);Ii(bo(e,{get session(){return t.session},get query(){return G(n)},oncomplete:e=>{L(u,[e],!0),ur().then(()=>G(te)?.focus())},onchange:()=>{L(u,[``],!0),ur().then(()=>G(te)?.focus())}}),e=>L(A,e,!0),()=>G(A))}};X(o,e=>{r===0&&a()!==`profile`&&G(l).kind===`prompt`&&!G(l).questions?.length&&e(s)});var c=V(o,2),d=R(c),f=V(d),p=e=>{var t=Jo();xi(t),Ei(t,()=>G(u)[r],e=>G(u)[r]=e),J(e,t)},m=e=>{var t=Xo(),i=R(t);i.value=i.__value=``,Z(V(i),17,()=>G(n).options||[],qr,(e,t)=>{var n=Yo(),r=B(n,!0),i={};H(()=>{Y(r,G(t)),i!==(i=G(t))&&(n.value=(n.__value=i)??``)}),J(e,n)}),N(t),mi(t),hi(t,()=>G(u)[r],e=>G(u)[r]=e),J(e,t)},h=e=>{var t=Zo(),i=z(t);nt(i),Ii(i,e=>L(te,e),()=>G(te));var a=V(i,2),o=e=>{var t=Fo(),r=B(t);H(e=>Y(r,`Suggested answers: ${e??``}`),[()=>G(n).options.join(` · `)]),J(e,t)};X(a,e=>{G(n).options?.length&&e(o)}),K(`keydown`,i,e=>{G(l)?.kind===`prompt`&&!G(l).questions?.length&&G(A)?.handleKey(e)}),Ei(i,()=>G(u)[r],e=>G(u)[r]=e),J(e,t)};X(f,e=>{G(n).secret?e(p):G(n).freeText?e(h,-1):e(m,1)}),N(c);var g=V(c,2),_=e=>{var t=$o(),r=V(R(t),4);Z(r,21,()=>G(n).options||[],qr,(e,t)=>{var n=Qo(),r=B(n,!0);H(()=>Y(r,G(t))),J(e,n)}),N(r),N(t),J(e,t)};X(g,e=>{G(n).secret&&!G(n).freeText&&e(_)}),H(()=>Y(d,`${G(n).text??``} `)),J(e,i)}),J(e,n)};X(_,e=>{G(l).kind===`approval`||G(l).kind===`profile`?e(v):e(y,-1)}),N(s);var x=V(s,2),S=e=>{var t=ns(),n=z(t),r=e=>{var t=ts(),n=B(t);H(()=>Y(n,`TRIGGER // ${G(D)??``}`)),J(e,t)};X(n,e=>{G(ee)&&e(r)});var i=V(n,2),a=B(i),o=V(i,2),s=B(o),c=V(o,2);H(e=>{Y(a,`Check the target and ${G(l).kind===`profile`?`profile above`:G(l).kind===`approval`?G(l).fileChanges?.length?`proposed file changes above`:`exact command and permission scope`:`message above`}. ${G(ee)?`This schedules a follow-up that will send automatically when eligible`:`This will send to Codex`}; it may start work using your quota. + Confirmation expires in ${e??``}s.`),o.disabled=G(h)||G(oe),Y(s,`CONFIRM ${(G(l).kind===`approval`||G(l).kind===`profile`?G(l).choices?.[G(d)]?.label:G(ee)?G(b)?`SAVE CHANGES`:`SCHEDULE`:`SEND`)??``}`)},[()=>Math.max(0,Math.ceil((G(p)-G(m))/1e3))]),K(`click`,o,ye),K(`click`,c,()=>{L(f,``)}),J(e,t)},C=e=>{var t=rs(),n=z(t),r=e=>{var t=To(),n=B(t,!0);H(()=>Y(n,G(he))),J(e,t)};X(n,e=>{G(he)&&e(r)});var i=V(n,2),a=B(i,!0);H(()=>{i.disabled=G(h)||G(oe)||!G(fe)||!!G(he),Y(a,G(h)?`SENDING…`:G(b)?`REVIEW CHANGES`:`REVIEW BEFORE SENDING`)}),K(`click`,i,()=>j()),J(e,t)};X(x,e=>{G(ue)?e(S):e(C,-1)});var O=V(x,2),k=e=>{var t=is();K(`click`,t,()=>{L(b,!1),L(f,``),L(u,[],!0)}),J(e,t)};X(O,e=>{G(b)&&e(k)}),H(()=>{Y(o,`TARGET // ${G(l).thread??``} // ${(G(l).directory||`Directory unavailable`)??``}`),s.disabled=G(h)||G(ue)||G(oe),Y(g,G(l).kind===`approval`||G(l).kind===`profile`?`Choose a decision`:G(b)?`EDIT SCHEDULED FOLLOW-UP`:`Reply to this session`)}),J(e,r)};X(se,e=>{G(oe)||G(v)?e(pe):G(l)?G(l).id?G(y)!==G(l).id&&e(M,3):e(ve,2):e(_e,1)}),N(r),H(()=>Y(s,a()===`profile`?`QUOTA THRESHOLD`:`SESSION CONTROL // EXPERIMENTAL`)),J(e,r)};X(we,e=>{!G(se)&&(!G(k)||G(b)||a()||G(l)?.kind!==`prompt`||G(l).questions?.length)&&e(Te)}),J(e,M),Ge()}Cr([`click`,`keydown`]);var cs=q(` `,1),ls=q(`
        `),us=q(`

        STATUS LINE // CODEXOMETER

        Choose multiple fields and their order. These display preferences do not + change Codex CLI configuration. Missing values are omitted.

        `),ds=q(`

        `,1);function fs(e,t){We(t,!0);let n=Wi(t,`stale`,3,!1),r=I(Xt([])),i=I(!1),a=P(()=>$.data?.statusLineFields||[]),o=e=>[...new Set(e??G(a).filter(e=>e.default).map(e=>e.id))].filter(e=>G(a).some(t=>t.id===e)),s=e=>o(e).map(e=>e===`run-state`&&(n()||!$.connected||$.data?.sessionsError)?`STALE`:t.session.statusLine?.[e]).filter(Boolean).join(` · `),c=P(()=>[...G(r).map(e=>G(a).find(t=>t.id===e)).filter(Boolean),...G(a).filter(e=>!G(r).includes(e.id))]);yn(()=>{oa.open&&!G(i)?(L(r,o(aa.statusLine),!0),L(i,!0)):oa.open||L(i,!1)});function l(e,t){L(r,t?[...G(r),e]:G(r).filter(t=>t!==e),!0)}function u(e,t){let n=G(r).indexOf(e),i=n+t;if(n<0||i<0||i>=G(r).length)return;let a=[...G(r)];[a[n],a[i]]=[a[i],a[n]],L(r,a,!0)}var d=ds(),f=z(d),p=e=>{var t=us(),n=V(R(t),4);Z(n,21,()=>G(c),e=>e.id,(e,t)=>{var n=ls(),i=R(n),a=R(i);xi(a);var o=V(a,1,!0),s=B(V(o),!0);N(i);var c=V(i,2),d=e=>{var n=cs(),i=z(n),a=V(i,2);H((e,n)=>{Q(i,`aria-label`,`Move `+G(t).label+` earlier`),i.disabled=e,Q(a,`aria-label`,`Move `+G(t).label+` later`),a.disabled=n},[()=>G(r).indexOf(G(t).id)===0,()=>G(r).indexOf(G(t).id)===G(r).length-1]),K(`click`,i,()=>u(G(t).id,-1)),K(`click`,a,()=>u(G(t).id,1)),J(e,n)},f=P(()=>G(r).includes(G(t).id));X(c,e=>{G(f)&&e(d)}),N(n),H(e=>{Q(i,`title`,G(t).help),Si(a,e),Y(o,G(t).label),Y(s,G(t).help)},[()=>G(r).includes(G(t).id)]),K(`change`,a,e=>l(G(t).id,e.currentTarget.checked)),J(e,n)}),N(n);var i=V(n,2),a=B(i),o=V(i,2),d=V(o,2);N(t),H(e=>Y(a,`Preview // ${e??``}`),[()=>s(G(r))||`—`]),K(`click`,o,()=>{aa.statusLine=[...G(r)],sa(),oa.open=!1}),K(`click`,d,()=>{oa.open=!1}),J(e,t)};X(f,e=>{oa.open&&e(p)});var m=V(f,2),h=R(m),g=B(h,!0),_=V(h,2);N(m),H((e,t)=>{Q(h,`title`,e),Y(g,t)},[()=>s(aa.statusLine),()=>s(aa.statusLine)]),K(`click`,_,()=>{oa.open=!oa.open}),J(e,d),Ge()}Cr([`change`,`click`]);var ps=q(`
        `);function ms(e,t){We(t,!0);let n=Wi(t,`active`,3,!1),r=P(()=>t.session.text||t.session.contextKind===`LAST ACTIVITY`&&t.session.workingCommand||``),i=P(()=>[`LAST REPLY`,`LAST ACTIVITY`].includes(t.session.contextKind)&&!!G(r).trim()),a=I(!1),o=I(``),s=I(!1);yn(()=>{if(!G(s))return;let e=setTimeout(()=>{L(s,!1)},150);return()=>clearTimeout(e)}),yn(()=>{G(r),t.session.status,L(o,``)});async function c(){if(!G(i)||G(a))return;let e=G(r);L(a,!0),L(s,!0),L(o,``);try{await navigator.clipboard.writeText(e),G(r)===e&&L(o,`Copied.`)}catch{G(r)===e&&L(o,`Clipboard unavailable. Select the visible text and copy it manually.`)}finally{L(a,!1)}}function l(e){!n()||!G(i)||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(),c())}var u=Pr();Sr(`keydown`,$t,l);var d=z(u),f=e=>{var t=ps(),n=R(t),r=B(n,!0),i=V(n,2);let l;N(t),H(()=>{Y(r,G(o)),i.disabled=G(a),l=ci(i,1,`svelte-543j00`,null,l,{flashed:G(s)})}),K(`click`,i,c),J(e,t)};X(d,e=>{G(i)&&e(f)}),J(e,u),Ge()}Cr([`click`]);var hs=q(`

         
        `,1),gs=q(`

        LATEST GUIDANCE

         
        `,1),_s=q(`

        CONTEXT

         

        `,1),vs=q(`

        `),ys=q(`

        `),bs=q(`
         
        `),xs=q(`

         
        `,1),Ss=q(`
         
        `),Cs=q(`

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

        `),ws=q(`

        `,1),Ts=q(`

        `),Es=q(` `,1),Ds=q(`
        `),Os=q(`

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

        `),ks=q(`

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

        `),As=q(` `),js=q(` `),Ms=q(` `),Ns=q(``),Ps=q(`

        Read only — reply or approve in Codex.

        `),Fs=q(`

        `),Is=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),Ls=q(`
        `),Rs=q(`
        `),zs=q(`

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

        `),Bs=q(`

        `),Vs=q(``),Hs=q(`

        `),Us=q(` `),Ws=q(`

        `),Gs=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),Ks=q(` `,1),qs=q(`

        `),Js=q(`

        TOKEN ACTIVITY // 30 SECOND SAMPLES

        `),Ys=q(`

        TOKENS

        FULL DETAIL →
        `),Xs=q(`

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

        `),Zs=q(`

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

        `,1),Qs=q(`

        SESSION TOTALS

        `,1);function $s(e,t){We(t,!0);let n=(e,t=f,n,r)=>{let i=mt(()=>g(n?.(),!0)),a=mt(()=>g(r?.(),!1));var o=Es(),s=z(o),c=e=>{var n=hs(),r=z(n),i=B(r,!0),a=B(V(r,2),!0);H(()=>{Y(i,t().contextKind===`LAST REPLY`&&!t().streaming?`TASK`:`CURRENT TASK`),Y(a,t().currentTask)}),J(e,n)};X(s,e=>{t().currentTask&&e(c)});var l=V(s,2),u=e=>{var n=gs(),r=B(V(z(n),2),!0);H(()=>Y(r,t().latestGuidance)),J(e,n)};X(l,e=>{t().latestGuidance&&e(u)});var d=V(l,2),p=e=>{var n=_s(),r=B(V(z(n),2),!0);Se(2),H(()=>Y(r,t().approvalContext)),J(e,n)};X(d,e=>{G(a)&&t().contextKind===`APPROVAL REQUEST`&&t().approvalContext&&e(p)});var m=V(d,2),_=e=>{var n=vs();let r;var i=B(n,!0);H(e=>{r=ci(n,1,`attention-note`,null,r,{inferred:t().status===`CHECK SESSION`}),Y(i,e)},[()=>C(t())]),J(e,n)},v=P(()=>C(t())&&(!G(a)||G(h)||t().status===`CHECK SESSION`));X(m,e=>{G(v)&&e(_)});var y=V(m,2),b=e=>{var n=ys(),r=B(n,!0);H(e=>Y(r,e),[()=>w(t())]),J(e,n)};X(y,e=>{G(i)&&e(b)});var x=V(y,2),S=e=>{var n=bs(),r=B(n,!0);H(()=>Y(r,t().text||`No session context available.`)),J(e,n)};X(x,e=>{(t().text||!t().workingCommand)&&e(S)});var T=V(x,2),E=e=>{var n=xs(),r=V(z(n),2),i=R(r),a=V(i),o=e=>{var n=Nr();H(()=>Y(n,`// +${(t().runningCommands||0)-+(t().commandStatus===`running`)} RUNNING`)),J(e,n)};X(a,e=>{!G(h)&&(t().runningCommands||0)>+(t().commandStatus===`running`)&&e(o)});var s=V(a,2),c=e=>{J(e,Nr(`+`))};X(s,e=>{t().runningLimited&&e(c)}),N(r);var l=B(V(r,2),!0);H(e=>{Y(i,`COMMAND // ${e??``} `),Y(l,t().workingCommand)},[()=>G(h)?`UNKNOWN`:(t().commandStatus||`unknown`).toUpperCase()]),J(e,n)};X(T,e=>{t().workingCommand&&e(E)});var ee=V(T,2),D=e=>{wo(e,{get lines(){return t().fileChanges}})},O=e=>{var n=ws(),r=V(z(n),2),i=B(r,!0),a=V(r,2),o=e=>{var n=Ss(),r=B(n,!0);H(()=>Y(r,t().command)),J(e,n)},s=e=>{J(e,Cs())};X(a,e=>{t().command?e(o):e(s,-1)}),H(()=>Y(i,G(h)||t().status!==`APPROVAL NEEDED`?`LAST OBSERVED COMMAND`:$.data?.control?`COMMAND REQUEST`:`COMMAND TO APPROVE IN CODEX`)),J(e,n)};X(ee,e=>{(!G(a)||!$.data?.control)&&t().fileChanges?.length?e(D):(!G(a)||!$.data?.control)&&(t().command||t().status===`APPROVAL NEEDED`)&&e(O,1)});var k=V(ee,2),te=e=>{var n=Ts(),r=B(n);H(()=>Y(r,`CONTEXT SOURCE // ${(t().source||`LOCAL`)??``} // OBSERVATION`)),J(e,n)};X(k,e=>{G(a)||e(te)}),J(e,o)},r=Wi(t,`params`,19,()=>({})),i=P(()=>$.data?.sessions||[]),a=P(()=>$.data?.control&&$.data.profiles||[]),o=P(()=>($.data?.triggers||[]).filter(e=>G(i).some(t=>t.id===e.session)));function s(e,t){if(r().id&&r().id!==t&&G(l)){e.preventDefault();return}b(t)}function c(e){return[`TURN COMPLETE`,`IDLE`,`ACTIVE`].includes(e.status)&&G(o).some(t=>t.session===e.id)?`TRIGGER SET`:e.status}let l=I(!1);function u(e,t){if(r().id&&r().id!==t&&G(l)){e.preventDefault();return}b(t)}yn(()=>{let e=r().id;e&&pr(()=>{aa.selected=e,da(e,2)})});let d=P(()=>G(i).find(e=>e.id===r().id)),p=P(()=>new URLSearchParams(Yi.querystring).get(`review`)===`profile`&&G(a).some(e=>e.session===r().id&&e.pending)),m=P(()=>G(i).some(e=>e.id===aa.selected)?aa.selected:G(i)[0]?.id),h=P(()=>!$.connected||!!$.data?.sessionsError),v=P(()=>[[`OBSERVED TOKENS`,fa(G(i).reduce((e,t)=>e+t.tokens,0))],[`LISTED SESSIONS`,fa(G(i).length)],...[[`WORKING`,`WORKING`],[`AWAITING APPROVAL`,`APPROVAL NEEDED`],[`AWAITING INPUT`,`INPUT NEEDED`],[`CHECK · INFERRED`,`CHECK SESSION`]].map(([e,t])=>[e,G(h)?`—`:fa(G(i).filter(e=>e.status===t).length)])]),y=P(()=>G(i).filter(e=>[`INPUT NEEDED`,`APPROVAL NEEDED`,`CHECK SESSION`].includes(e.status)));function b(e){aa.selected=e,ur().then(()=>document.querySelector(`.session-row.selected`)?.scrollIntoView({block:`nearest`}))}function x(e,t){if(b(e),r().id){t<0&&(da(e,2),location.hash=`/sessions`);return}let n=la(e)+t;n>2?location.hash=`/sessions/`+encodeURIComponent(e):da(e,n)}function S(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(),x(r().id,-1);else if([`ArrowLeft`,`ArrowRight`].includes(e.key)&&(r().id||G(m)))e.preventDefault(),x(r().id||G(m),e.key===`ArrowLeft`?-1:1);else if(!r().id&&[`ArrowUp`,`ArrowDown`].includes(e.key)&&G(i).length){e.preventDefault();let t=G(i).findIndex(e=>e.id===G(m));b(G(i)[Math.max(0,Math.min(G(i).length-1,t+(e.key===`ArrowUp`?-1:1)))].id)}}}function C(e){return G(h)?`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.`:``}function w(e){return e.streaming&&e.contextKind===`LAST REPLY`?`REPLY // STREAMING`:e.contextKind||`LAST ACTIVITY`}var T=Qs();Sr(`keydown`,$t,S);var E=z(T),ee=B(V(R(E),2));N(E);var D=V(E,2);let O;Z(D,21,()=>G(v),qr,(e,t)=>{var n=P(()=>_(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Ds(),o=R(a),s=B(o,!0),c=B(V(o,2),!0);N(a),H(()=>{Y(s,r()),Y(c,i())}),J(e,a)}),N(D);var k=V(D,2),te=B(k),A=V(k,2),ne=e=>{J(e,Os())};X(A,e=>{G(h)&&e(ne)});var re=V(A,2),ie=e=>{J(e,ks())};X(re,e=>{$.data?.profileError&&e(ie)});var ae=V(re,2),oe=e=>{var t=Ns(),n=R(t);Z(n,17,()=>G(y),qr,(e,t)=>{var n=As();let r;var i=B(n);H((e,a)=>{r=ci(n,1,`button`,null,r,{approval:G(t).status===`APPROVAL NEEDED`}),Q(n,`href`,e),Y(i,`${G(t).status??``} + ${a??``} // ${(G(t).name||G(t).directory||G(t).id)??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,n,()=>b(G(t).id)),J(e,n)});var c=V(n,2);Z(c,17,()=>G(a).filter(e=>e.pending&&G(i).some(t=>t.id===e.session)),qr,(e,t)=>{var n=js(),a=B(n);H((e,i,o)=>{Q(n,`title`,r().id&&r().id!==G(t).session&&G(l)?`Finish sending or clear your current draft before switching sessions.`:`Review this session’s quota threshold`),Q(n,`href`,e),Y(a,`QUOTA THRESHOLD ${i??``} // ${o??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).session)+`?review=profile`,()=>Array.from(G(t).session).slice(-5).join(``).toUpperCase(),()=>G(i).find(e=>e.id===G(t).session)?.name||G(i).find(e=>e.id===G(t).session)?.directory||G(t).session]),K(`click`,n,e=>u(e,G(t).session)),J(e,n)}),Z(V(c,2),17,()=>G(o),qr,(e,t)=>{var n=Ms(),r=B(n);H((e,t,i)=>{Q(n,`href`,e),Y(r,`TRIGGER SET ${t??``} // ${i??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).session),()=>Array.from(G(t).session).slice(-5).join(``).toUpperCase(),()=>G(i).find(e=>e.id===G(t).session)?.name||G(i).find(e=>e.id===G(t).session)?.directory]),K(`click`,n,e=>s(e,G(t).session)),J(e,n)}),N(t),J(e,t)},se=P(()=>(G(y).length||G(a).some(e=>e.pending)||G(o).length)&&!G(h));X(ae,e=>{G(se)&&e(oe)});var ce=V(ae,2),le=e=>{var t=Pr(),i=z(t),o=e=>{var t=Rs(),i=R(t),o=R(i),s=R(o);let u;var f=V(s);N(o);var m=V(o,2);N(i);var g=V(i,2),_=e=>{var t=Ts(),n=B(t,!0);H(()=>Y(n,G(d).directory)),J(e,t)};X(g,e=>{G(d).name&&G(d).directory&&e(_)});var v=V(g,2),y=B(v),x=V(v,2);let S;var C=R(x),w=R(C);n(w,()=>G(d),()=>!0,()=>!0),N(C);var T=V(C,2),E=e=>{var t=Pr();Kr(z(t),()=>G(d).id,e=>{{let t=P(()=>new URLSearchParams(Yi.querystring).get(`schedule`)===`edit`),n=P(()=>G(d).fileChanges||[]);ss(e,{get session(){return G(d).id},get openScheduler(){return G(t)},get observedCommand(){return G(d).command},get observedFileChanges(){return G(n)},get suspended(){return G(p)},onProtectedChange:e=>{L(l,e,!0)}})}}),J(e,t)},ee=e=>{J(e,Ps())};X(T,e=>{$.data?.control?e(E):e(ee,-1)}),N(x);var D=V(x,2);Z(D,17,()=>G(a).filter(e=>e.session===G(d).id),e=>e.session,(e,t)=>{var n=Ls(),r=R(n),i=e=>{var n=Fs(),r=B(n,!0);H(()=>Y(r,G(t).notice)),J(e,n)};X(r,e=>{G(t).notice&&e(i)});var a=V(r,2),o=e=>{ss(e,{get session(){return G(d).id},review:`profile`})},s=e=>{var t=Is();H(e=>Q(t,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(d).id)+`?review=profile`]),J(e,t)};X(a,e=>{G(t).pending&&G(p)?e(o):G(t).pending&&e(s,1)}),N(n),H(()=>Q(n,`id`,`quota-profile-`+G(d).id)),J(e,n)});var O=V(D,2),k=e=>{var t=Pr();Kr(z(t),()=>G(d).id,e=>{ms(e,{get session(){return G(d)},active:!0})}),J(e,t)};X(O,e=>{G(p)||e(k)}),Kr(V(O,2),()=>G(d).id,e=>{fs(e,{get session(){return G(d)},get stale(){return G(h)}})}),N(t),H((e,t)=>{u=ci(s,1,`lamp lit`,null,u,{working:G(d).status===`WORKING`&&!G(h)}),Y(f,`${e??``} // ${(G(d).name||G(d).directory)??``}`),Y(y,`${t??``} TOKENS // ${G(d).id??``} // CONTEXT SOURCE // ${(G(d).source||`LOCAL`)??``}`),S=ui(x,``,S,{display:G(p)?`none`:void 0})},[()=>G(h)?`STALE`:G(p)?`QUOTA THRESHOLD`:c(G(d)),()=>fa(G(d).tokens)]),K(`click`,m,()=>{b(r().id),da(r().id,2)}),J(e,t)},s=e=>{J(e,zs())};X(i,e=>{G(d)?e(o):e(s,-1)}),J(e,t)},ue=e=>{var t=Zs(),r=z(t),o=V(R(r),2),s=R(o),l=V(s,2);N(o),N(r);var d=V(r,2);Z(d,17,()=>G(i),e=>e.id,(e,t)=>{let r=P(()=>la(G(t).id));var i=Ys();let o;var s=R(i),l=R(s),d=e=>{var n=Bs(),r=R(n),i=B(r);N(n),H(e=>{Q(r,`aria-pressed`,G(m)===G(t).id),Y(i,`${e??``} // ${G(t).name??``}`)},[()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,r,()=>b(G(t).id)),J(e,n)};X(l,e=>{G(t).name&&e(d)});var f=V(l,2),p=R(f),g=R(p);let _;var v=V(g,1,!0);N(p),N(f);var y=V(f,2),S=e=>{var n=Vs(),r=B(n,!0);H(()=>{Q(n,`aria-pressed`,G(m)===G(t).id),Y(r,G(t).directory||G(t).id)}),K(`click`,n,()=>b(G(t).id)),J(e,n)};X(y,e=>{G(t).name||e(S)});var C=V(y,2),T=R(C);Se(),N(C);var E=V(C,2),ee=e=>{var n=Ts(),r=B(n,!0);H(()=>Y(r,G(t).directory)),J(e,n)};X(E,e=>{G(t).name&&G(t).directory&&e(ee)});var D=V(E,2),O=B(D),k=V(D,2),te=B(k),A=V(k,2),ne=R(A),re=V(ne,2),ie=B(re,!0),ae=V(re,2);N(A);var oe=V(A,2),se=V(oe,2),ce=e=>{var n=Hs(),r=B(n,!0);H(()=>Y(r,G(t).status===`CHECK SESSION`?`INFERRED INACTIVITY`:$.data?.control?`OPEN FULL DETAIL OR REPLY IN CODEX`:G(t).status===`APPROVAL NEEDED`?`APPROVE OR DECLINE IN CODEX`:`REPLY IN CODEX`)),J(e,n)},le=P(()=>!G(h)&&[`APPROVAL NEEDED`,`INPUT NEEDED`,`CHECK SESSION`].includes(G(t).status));X(se,e=>{G(le)&&e(ce)}),N(s);var ue=V(s,2),de=e=>{var r=qs(),i=R(r),o=R(i),s=B(o,!0),c=V(o,2),l=e=>{var n=Us(),r=B(n,!0);H(e=>{Q(n,`href`,e),Y(r,$.data?.control?`REVIEW IN FULL DETAIL ↗`:`APPROVAL IN CODEX ↗`)},[()=>`#/sessions/`+encodeURIComponent(G(t).id)]),J(e,n)};X(c,e=>{!G(h)&&G(t).status===`APPROVAL NEEDED`&&e(l)}),N(i);var d=V(i,2);n(d,()=>G(t),()=>!1);var f=V(d,2);Z(f,17,()=>G(a).filter(e=>e.session===G(t).id),qr,(e,n)=>{var r=Ks(),i=z(r),a=e=>{var t=Ws(),r=B(t,!0);H(()=>Y(r,G(n).notice)),J(e,t)};X(i,e=>{G(n).notice&&e(a)});var o=V(i,2),s=e=>{var n=Gs();H(e=>Q(n,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(t).id)+`?review=profile`]),K(`click`,n,e=>u(e,G(t).id)),J(e,n)};X(o,e=>{G(n).pending&&e(s)}),J(e,r)});var p=V(f,2);{let e=P(()=>G(m)===G(t).id);ms(p,{get session(){return G(t)},get active(){return G(e)}})}N(r),H(e=>Y(s,e),[()=>w(G(t))]),J(e,r)};X(ue,e=>{G(r)>0&&e(de)});var fe=V(ue,2),pe=e=>{var n=Js(),r=V(R(n),2);{let e=P(()=>(G(t).samples||[]).map(e=>e.tokens));no(r,{get values(){return G(e)},capacity:120})}var i=B(V(r,2));N(n),H(()=>Y(i,`LAST ${(G(t).samples?.length||0)??``} SAMPLES // AUTO SCALE`)),J(e,n)};X(fe,e=>{G(r)<2&&e(pe)}),N(i),H((e,n,a,s,c)=>{o=ci(i,1,`session-row`,null,o,{selected:G(m)===G(t).id,wide:G(r)===2,split:G(r)===1}),Q(i,`aria-label`,`Session `+(G(t).name||G(t).directory||G(t).id)),Q(p,`href`,e),_=ci(g,1,`lamp lit`,null,_,{working:G(t).status===`WORKING`&&!G(h)}),Y(v,n),Y(T,`${a??``} `),Y(O,`${G(t).agents??``} LINKED AGENTS`),Y(te,`ACTIVE // ${s??``}`),ne.disabled=G(r)===0,Q(re,`aria-expanded`,G(r)>0),Y(ie,G(r)?`HIDE DETAIL`:`SHOW DETAIL`),Q(oe,`href`,c)},[()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>G(h)?`STALE`:c(G(t)),()=>fa(G(t).tokens),()=>pa(G(t).activity),()=>`#/sessions/`+encodeURIComponent(G(t).id)]),K(`click`,p,()=>b(G(t).id)),K(`click`,ne,()=>x(G(t).id,-1)),K(`click`,re,()=>{b(G(t).id),da(G(t).id,+!G(r))}),K(`click`,ae,()=>x(G(t).id,1)),K(`click`,oe,()=>b(G(t).id)),J(e,i)});var f=V(d,2),p=e=>{J(e,Xs())};X(f,e=>{G(i).length||e(p)}),K(`click`,s,()=>ua(1)),K(`click`,l,()=>ua(0)),J(e,t)};X(ce,e=>{r().id?e(le):e(ue,-1)}),H(e=>{Y(ee,`OBSERVED ${e??``}`),O=ci(D,1,`session-totals`,null,O,{stale:G(h)}),Y(te,`${G(h)?`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.`)},[()=>pa($.data?.sessionsAt)]),J(e,T),Ge()}Cr([`click`]);var ec=q(`

        `),tc=q(`

        Relative usage/credits are not tokens or quota percentages. Groupings + describe the same usage, not additional consumption.

        `,1),nc=q(`// APPROXIMATE`),rc=q(`

        Partial accounting: totals may still change.

        `),ic=q(`

        Percentage of this period's historical allowance, not today's limit. May + exceed 100%. This is not a manual/automatic reset log.

        `,1),ac=q(`

        `,1),oc=q(`

        This optional account report is unavailable. Token history remains + available; missing data does not mean zero usage.

        `),sc=q(`
        `),cc=q(`
        `),lc=q(`

        No usage reported for this day.

        `),uc=q(`

        Selected breakdown unavailable; missing does not mean zero.

        `),dc=q(`

        `,1);function fc(e,t){We(t,!0);let n=I(`surface`),r=I(0),i=P(()=>t.reports?.daily),a=P(()=>t.reports?.plan),o=P(()=>t.mode===`breakdown`?G(i)?.days.length||0:G(a)?.periods.length||0),s=P(()=>Math.min(G(r),Math.max(0,G(o)-1))),c=P(()=>G(i)?.days[(G(i)?.days.length||0)-1-G(s)]),l=P(()=>G(a)?.periods[G(s)]),u=P(()=>t.mode===`breakdown`?G(i)?.units||``:`%`),d=P(()=>{let e=Object.create(null);if(t.mode===`breakdown`)e=G(c)?.groups[G(n)]||{};else{let t=G(n)===`feature`?`thread_source`:G(n)===`task start`?`turn_trigger`:G(n);for(let n of G(l)?.breakdowns||[])if(n.dimension===t)for(let t of n.rows)e[t.key]=(e[t.key]||0)+t.basis_points/100}return Object.entries(e).sort((e,t)=>t[1]-e[1]||e[0].localeCompare(t[0]))}),f=P(()=>t.mode===`breakdown`?G(c)?.total:G(l)?.used_basis_points==null?null:G(l).used_basis_points/100),p=P(()=>Math.max(1,G(f)||0,...G(d).map(([,e])=>e))),m=e=>e==null?`UNKNOWN`:e.toLocaleString(`en-GB`,{maximumFractionDigits:2});var h=dc(),g=z(h),v=R(g),y=V(R(v)),b=R(y);b.value=b.__value=`surface`;var x=V(b);x.value=x.__value=`model`;var S=V(x);S.value=S.__value=`feature`;var C=V(S);C.value=C.__value=`task start`,N(y),mi(y),N(v);var w=V(v,2),T=V(w,2),E=B(V(T,2),!0);N(g);var ee=V(g,2),D=R(ee),O=B(D,!0),k=V(D,2),te=B(k),A=V(k,2),ne=e=>{var t=tc(),n=z(t),r=B(n),a=V(n,2),o=e=>{var t=ec(),n=B(t);H(()=>Y(n,`Data as of ${G(i).dataAsOf??``}`)),J(e,t)};X(a,e=>{G(i).dataAsOf&&e(o)});var s=B(V(a,2));Se(2),H((e,t)=>{Y(r,`Latest fetch ${e??``} // queried ${G(i).from??``} → ${G(i).through??``}. + Reports are fetched from OpenAI and are not saved between runs.`),Y(s,`${(G(c)?.date||`No daily buckets reported`)??``} // ${t??``} + ${G(u)??``}`)},[()=>pa(G(i).fetchedAt),()=>m(G(f))]),J(e,t)},re=e=>{var t=ac(),n=z(t),r=R(n);let i;var o=B(r,!0),s=V(r),c=e=>{J(e,nc())};X(s,e=>{G(a).approximate&&e(c)});var u=V(s);N(n);var d=V(n,2),p=R(d),h=V(p),g=e=>{var t=Nr();H(()=>Y(t,`// Boundary tolerance ${G(a).boundary_tolerance_seconds??``}s`)),J(e,t)};X(h,e=>{G(a).boundary_tolerance_seconds!=null&&e(g)}),N(d);var _=V(d,2),v=e=>{var t=ic(),n=z(t),r=R(n),i=V(r);let a;var o=B(i);N(n);var s=V(n,2),c=B(s),u=V(s,2),d=e=>{J(e,rc())};X(u,e=>{G(l).accounting_complete||e(d)}),Se(2),H(e=>{Y(r,`${G(l).window_minutes??``} MIN // ${G(l).plan_type??``} // `),a=ci(i,1,`svelte-1fbui7h`,null,a,{muted:G(f)==null,"quota-near":G(f)!=null&&G(f)>=80&&G(f)<100,"quota-full":G(f)!=null&&G(f)>=100}),Y(o,`USED ${e??``}${G(f)==null?``:`%`}`),Y(c,`${G(l).starts_at??``} → ${G(l).ends_at??``}`)},[()=>m(G(f))]),J(e,t)};X(_,e=>{G(l)&&e(v)}),H(e=>{i=ci(r,1,`svelte-1fbui7h`,null,i,{"quality-warning":!G(a).coverage_complete}),Y(o,G(a).coverage_complete?`Reported range complete`:`Partial coverage`),Y(u,` // Latest fetch ${e??``}`),Y(p,`Coverage starts ${(G(a).coverage_start||`unknown`)??``} // Data as of ${(G(a).data_as_of||`unknown`)??``}`)},[()=>pa(G(a).fetchedAt)]),J(e,t)},ie=e=>{J(e,oc())};X(A,e=>{t.mode===`breakdown`&&G(i)?e(ne):t.mode===`periods`&&G(a)?e(re,1):e(ie,-1)});var ae=V(A,2),oe=e=>{var n=cc(),r=R(n),i=B(V(R(r),2),!0);N(r),Z(V(r,2),17,()=>G(d),qr,(e,n,r)=>{var i=P(()=>_(G(n),2));let a=()=>G(i)[0],o=()=>G(i)[1];var s=sc();let c;var l=R(s),u=B(l,!0),d=V(l,2),f=R(d);let h;N(d);var g=B(V(d,2));N(s),H((e,n,i)=>{c=ci(s,1,`report-row svelte-1fbui7h`,null,c,{unknown:e,alternate:r%2==1}),Q(l,`title`,a()),Y(u,a()),h=ui(f,``,h,{width:n}),Y(g,`${i??``}${t.mode===`periods`?`%`:``}`)},[()=>a().trim().toLowerCase()===`unknown`,()=>`${Math.max(0,100*o()/G(p))}%`,()=>m(o())]),J(e,s)}),N(n),H(()=>Y(i,t.mode===`breakdown`?G(u):`QUOTA USED`)),J(e,n)},se=e=>{J(e,lc())},ce=e=>{J(e,uc())};X(ae,e=>{G(d).length?e(oe):t.mode===`breakdown`&&G(c)?.total===0&&G(c)?.groups[G(n)]!=null?e(se,1):(G(i)&&t.mode===`breakdown`||G(a)&&t.mode===`periods`)&&e(ce,2)}),N(ee),H(()=>{w.disabled=G(s)>=G(o)-1,T.disabled=G(s)===0,Y(E,G(o)?`${G(s)+1} / ${G(o)}`:`NO DATA`),Y(O,t.mode===`breakdown`?`DAILY BREAKDOWN`:`QUOTA WINDOWS`),Y(te,`${(t.mode===`breakdown`?t.reports?.dailyStatus||`UNAVAILABLE`:t.reports?.planStatus||`UNAVAILABLE`)??``} // UTC`)}),hi(y,()=>G(n),e=>L(n,e)),K(`click`,w,()=>L(r,G(s)+1)),K(`click`,T,()=>L(r,G(s)-1)),J(e,h),Ge()}Cr([`click`]);var pc=864e5;function mc(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 hc(e,t,n){let r=new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()));for(let e=0;;e++){let i=mc(r,-t),a=new Date(i.getTime()+pc);if(e===n)return{start:a,end:r};r=i}}var gc=q(``),_c=q(``,1),vc=q(`

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

        `),yc=q(`

        Token history unavailable; other reports may still be available.

        `),bc=q(``),xc=q(`
        `),Sc=q(`

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

        `,1),Cc=q(`
        `,1),wc=q(` `),Tc=q(`

        LIFETIME TOKENS

        PEAK DAY

        CURRENT STREAK

        DAYS

        LONGEST TURN

        SECONDS

        LONGEST STREAK

        DAYS

        OPENAI // UTC

        Accessible data table
        Date (UTC)Tokens

        `,1),Ec=q(`

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

        `),Dc=q(`

        USAGE // ACCOUNT HISTORY

        Account-wide history reported by Codex, not the local Sessions counter. Dates + use UTC. Allowance history is approximate where indicated; reset causes are + not provided.

        `,1);function Oc(e,t){We(t,!0);let n=I(`daily`),r=I(12),i=I(0),a=P(()=>{let e=$.data?.usage?.dailyUsageBuckets;if(!e)return[];let{start:t,end:n}=hc(new Date,G(r),G(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=P(()=>Math.max(1,...G(a).map(e=>e.tokens))),s=P(()=>G(a).length?new Date(G(a)[0].date+`T00:00:00Z`).getUTCDay():0),c=P(()=>{if(G(n)===`monthly`){let e=new Map;for(let t of G(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 G(a).map(t=>({date:t.date,tokens:e+=t.tokens}))});var l=Dc(),u=V(z(l),4);Z(u,20,()=>[[`daily`,`Daily`],[`monthly`,`Monthly`],[`cumulative`,`Cumulative`],[`breakdown`,`Breakdown`],[`periods`,`Windows`]],qr,(e,t)=>{var r=P(()=>_(t,2));let a=()=>G(r)[0],o=()=>G(r)[1];var s=gc();let c;var l=B(s,!0);H(()=>{Q(s,`aria-pressed`,G(n)===a()),c=ci(s,1,``,null,c,{active:G(n)===a()}),Y(l,o())}),K(`click`,s,()=>{L(n,a(),!0),L(i,0)}),J(e,s)}),N(u);var d=V(u,2),f=R(d),p=e=>{var t=_c(),n=z(t),a=V(R(n)),o=R(a);o.value=o.__value=6;var s=V(o);s.value=s.__value=12,N(a),mi(a),N(n);var c=V(n),l=V(c);H(()=>l.disabled=G(i)===0),K(`change`,a,()=>L(i,0)),hi(a,()=>G(r),e=>L(r,e)),K(`click`,c,()=>qt(i)),K(`click`,l,()=>qt(i,-1)),J(e,t)};X(f,e=>{G(n)!==`breakdown`&&G(n)!==`periods`&&e(p)}),N(d);var m=V(d,2),h=e=>{J(e,vc())};X(m,e=>{$.data?.usageError&&e(h)});var g=V(m,2),v=e=>{J(e,yc())};X(g,e=>{$.data?.usage?.tokenStatus===`UNAVAILABLE`&&G(n)!==`breakdown`&&G(n)!==`periods`&&e(v)});var y=V(g,2),b=e=>{var t=Pr();Kr(z(t),()=>G(n),e=>{{let t=P(()=>$.data?.usage?.reports);fc(e,{get reports(){return G(t)},get mode(){return G(n)}})}}),J(e,t)},x=e=>{var t=Tc(),r=z(t),i=R(r),l=B(V(R(i),2),!0);N(i);var u=V(i,2),d=B(V(R(u),2),!0);N(u);var f=V(u,2),p=V(R(f),2),m=R(p);Se(),N(p),N(f);var h=V(f,2),g=V(R(h),2),_=R(g);Se(),N(g),N(h);var v=V(h,2),y=V(R(v),2),b=R(y);Se(),N(y),N(v),N(r);var x=V(r,4),S=R(x),C=B(S),w=V(S,2),T=e=>{var t=Sc(),n=z(t),r=R(n),i=R(r);Z(i,17,()=>Array(G(s)),qr,(e,t)=>{J(e,bc())}),Z(V(i,2),17,()=>G(a),qr,(e,t)=>{var n=xc();let r,i;H(e=>{r=ci(n,1,`heat-cell`,null,r,{zero:G(t).tokens===0}),Q(n,`title`,e),i=ui(n,``,i,{opacity:G(t).tokens?.25+.75*G(t).tokens/G(o):1})},[()=>`${G(t).date}: ${fa(G(t).tokens)} tokens`]),J(e,n)}),N(r),N(n),Se(2),J(e,t)},E=e=>{var t=Cc(),r=z(t);{let e=P(()=>G(c).map(e=>e.tokens)),t=P(()=>G(n)+` usage`);no(r,{get values(){return G(e)},get label(){return G(t)}})}var i=V(r,2),a=R(i),o=B(a,!0),s=B(V(a),!0);N(i),H(e=>{Y(o,G(c)[0]?.date),Y(s,e)},[()=>G(c).at(-1)?.date]),J(e,t)};X(w,e=>{G(n)===`daily`?e(T):e(E,-1)});var ee=V(w,2),D=V(R(ee),2),O=R(D),k=V(R(O));Z(k,21,()=>G(n)===`daily`?G(a):G(c),qr,(e,t)=>{var n=wc(),r=R(n),i=B(r,!0),a=B(V(r),!0);N(n),H(e=>{Y(i,G(t).date),Y(a,e)},[()=>fa(G(t).tokens)]),J(e,n)}),N(k),N(O),N(D),N(ee),N(x);var te=B(V(x,2));H((e,t,n,r,i,o,s)=>{Y(l,e),Y(d,t),Y(m,`${n??``} `),Y(_,`${r??``} `),Y(b,`${i??``} `),Y(C,`${G(a)[0]?.date??``} — ${o??``}`),Y(te,`OBSERVED ${s??``} // CUMULATIVE IS FOR THE SELECTED PERIOD`)},[()=>fa($.data.usage.summary.lifetimeTokens),()=>fa($.data.usage.summary.peakDailyTokens),()=>fa($.data.usage.summary.currentStreakDays),()=>fa($.data.usage.summary.longestRunningTurnSec),()=>fa($.data.usage.summary.longestStreakDays),()=>G(a).at(-1)?.date,()=>pa($.data.usageAt)]),J(e,t)},S=e=>{J(e,Ec())};X(y,e=>{G(n)===`breakdown`||G(n)===`periods`?e(b):$.data?.usage&&$.data.usage.dailyUsageBuckets!==null?e(x,1):e(S,-1)}),J(e,l),Ge()}Cr([`click`,`change`]);var kc=q(`

        Page not found

        Return to Quota

        `,1);function Ac(e){var t=kc();Se(2),J(e,t)}var jc=q(` `),Mc=q(`

        `),Nc=q(`

        Connecting to your local Codexometer…

        `),Pc=q(``),Fc=q(`
        CODEXOMETER

        Your quota. Your sessions. Your command centre.

        `);function Ic(e,t){We(t,!0);let n={"/":$a,"/quota/:view?":$a,"/sessions/:id?":$s,"/usage":Oc,"*":Ac},r={quota:/^(?:\/|\/quota(?:\/[^/]+)?\/?)$/,sessions:/^\/sessions(?:\/[^/]+)?\/?$/,usage:/^\/usage\/?$/},i=I(`hacker`),a=[`hacker`,`rust`,`blue-steel`,`ultraviolet`,`nightshade`];yn(()=>{sa()}),yn(()=>{if($.data)for(let[e,t]of Object.entries(r))t.test(Yi.location)&&(aa.tab=e)}),Gi(()=>{try{let e=localStorage.getItem(`codexometer.web.theme`);e&&a.includes(e)&&L(i,e,!0)}catch{}return va()});function o(){try{localStorage.setItem(`codexometer.web.theme`,G(i))}catch{}}var s=Fc(),c=R(s),l=V(R(c),2),u=R(l);let d;var f=V(u,1,!0),p=B(V(f));N(l),N(c);var m=V(c,2);Z(m,21,()=>Object.entries(r),qr,(e,t)=>{var n=P(()=>_(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1],a=P(()=>i().test(Yi.location));var o=jc();let s;var c=B(o,!0);H(e=>{Q(o,`href`,r()===`quota`?`#/quota/`+aa.view:`#/`+r()),Q(o,`aria-current`,G(a)?`page`:void 0),s=ci(o,1,``,null,s,{active:G(a)}),Y(c,e)},[()=>r().toUpperCase()]),J(e,o)}),N(m);var h=V(m,2),g=R(h),v=e=>{var t=Mc(),n=B(t,!0);H(()=>Y(n,$.error)),J(e,t)};X(g,e=>{$.error&&e(v)});var y=V(g,2),b=e=>{$i(e,{get routes(){return n}})},x=e=>{J(e,Nc())};X(y,e=>{$.data?e(b):$.error||e(x,1)}),N(h);var S=V(h,2),C=R(S),w=B(C),T=V(C,2),E=B(T,!0),ee=V(T,2),D=V(R(ee));Z(D,21,()=>a,qr,(e,t)=>{var n=Pc(),r=B(n,!0),i={};H(e=>{Y(r,e),i!==(i=G(t))&&(n.value=(n.__value=i)??``)},[()=>G(t).replace(`-`,` `).toUpperCase()]),J(e,n)}),N(D),mi(D),N(ee),N(S),N(s),H(()=>{Q(s,`data-theme`,G(i)),d=ci(u,1,`lamp`,null,d,{lit:$.connected}),Y(f,$.connected?`CONNECTED`:`OFFLINE`),Y(p,`EXPERIMENTAL // ${$.data?.control?`SESSION CONTROL`:`READ ONLY`}`),Y(w,`v${($.data?.version||`…`)??``} // LOCAL ONLY`),Y(E,$.data?.control?`Session control enabled. Stop the server to revoke access.`:`No actions can be sent from this preview.`)}),K(`change`,D,o),hi(D,()=>G(i),e=>L(i,e)),J(e,s),Ge()}Cr([`change`]),Br(Ic,{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 c331ec2..db1119a 100644 --- a/internal/web/dist/index.html +++ b/internal/web/dist/index.html @@ -5,8 +5,8 @@ Codexometer // Experimental web - - + +
        diff --git a/web/src/ConsumptionZone.svelte b/web/src/ConsumptionPace.svelte similarity index 81% rename from web/src/ConsumptionZone.svelte rename to web/src/ConsumptionPace.svelte index 6b56891..1bd32c8 100644 --- a/web/src/ConsumptionZone.svelte +++ b/web/src/ConsumptionPace.svelte @@ -6,13 +6,11 @@ elapsed, trail = [], duration, - paceView = false, }: { used: number; elapsed: number; trail?: Meter['trail']; duration: number | null; - paceView?: boolean; } = $props(); type TrailPoint = NonNullable[number]; type TrendMode = 'off' | 'halfHour' | 'hour' | 'day' | 'window'; @@ -22,9 +20,8 @@ let trendMode = $state('window'); const ticks = [0, 25, 50, 75, 100]; const trendMinutes = { off: 0, halfHour: 30, hour: 60, day: 1440, window: 0 }; - let yTicks = $derived(paceView ? [-100, -50, 0, 50, 100] : ticks); - let minimum = $derived(paceView ? -100 : 0); - let range = $derived(paceView ? 200 : 100); + const minimum = 0; + const range = 100; let width = $state(400); let height = $state(240); let right = $derived(width - 24); @@ -37,16 +34,13 @@ function plotY(value: number): number { return bottom - ((value - minimum) / range) * plotHeight; } - function graphValue(consumption: number, time: number): number { - return paceView ? consumption - time : consumption; - } - let y = $derived(plotY(graphValue(used, elapsed))); + let y = $derived(plotY(used)); let difference = $derived(used - elapsed); let path = $derived( trail .map( (p, i) => - `${i === 0 || p.break ? 'M' : 'L'}${48 + (p.elapsed / 100) * plotWidth} ${plotY(graphValue(p.used, p.elapsed))}`, + `${i === 0 || p.break ? 'M' : 'L'}${48 + (p.elapsed / 100) * plotWidth} ${plotY(p.used)}`, ) .join(' '), ); @@ -117,7 +111,7 @@ if (slope === null || !duration) return null; const projected = used + slope * (100 - elapsed); const intercept = trendMode === 'window' ? 0 : used - slope * elapsed; - const graphSlope = slope - (paceView ? 1 : 0); + const graphSlope = slope; let x1 = Math.max(0, elapsed - (trendMinutes[trendMode] / duration) * 100); if (trendMode === 'window') x1 = 0; let x2 = 100; @@ -163,19 +157,12 @@ style:--trend-color={trend?.safe ? '#115b35' : '#7f1825'} viewBox={`0 0 ${width} ${height}`} role="img" - aria-label={`${paceView ? 'Pace zone' : 'Consumption zone'}: ${used}% consumed, ${elapsed.toFixed(1)}% of quota period elapsed. ${paceView ? `${difference.toFixed(1)} percentage points from safety.` : `${difference > 0 ? 'Above' : difference < 0 ? 'Below' : 'On'} the steady-consumption line.`}${showTrace && trail.length ? ` Trace path contains ${trail.length} ${trail.length === 1 ? 'observation' : 'observations'}; gaps are not interpolated.` : ''}`} + aria-label={`Pace: ${used}% consumed, ${elapsed.toFixed(1)}% of quota period elapsed. ${difference > 0 ? 'Above' : difference < 0 ? 'Below' : 'On'} the steady-consumption line.${showTrace && trail.length ? ` Trace path contains ${trail.length} ${trail.length === 1 ? 'observation' : 'observations'}; gaps are not interpolated.` : ''}`} > - + - {#if paceView}{/if} - + {tick}% {/each} - {#each yTicks as tick} + {#each ticks as tick} - {paceView ? `${tick > 0 ? '+' : ''}${tick}` : `${tick}%`} + {tick}% {/each} - - {#if paceView}SAFE{/if} + {#if showTrace && trail.length} First observation: {date(trail[0].at)} {/if} @@ -258,9 +231,7 @@ > {/if} - {paceView ? 'DISTANCE FROM SAFETY (PP)' : 'CONSUMPTION'} + CONSUMPTION - {used}% consumed // {elapsed.toFixed(1)}% of period elapsed{paceView - ? ` // ${difference.toFixed(1)} PP from safety` - : ''} + {used}% consumed // {elapsed.toFixed(1)}% of period elapsed