diff --git a/README.md b/README.md index 9ee106e0..b92b8987 100644 --- a/README.md +++ b/README.md @@ -595,7 +595,8 @@ codexometer --codex /path/to/codex | `s` | Open Benchmark Scope (Benchmark view only) | | `o` | Close All session rows; strict confirmation mode adds a second press, with `Esc` to cancel | | `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 | +| `h` | Toggle the trace in Quota → Pace | +| `y` | Cycle all listed Sessions rows: first match the most detailed row, then graph → split → wide → graph; never opens full detail | | `Left` / `Right` | In Sessions, highlight attention pills or cycle status filters when that header area has focus; otherwise 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` | Run All benchmarks; confirmation follows the selected policy (Benchmark view only) | @@ -1525,6 +1526,10 @@ text areas under 12 columns and incomplete, oversized or unsupported destination plain. The version and pricing links continue to use the terminal's native hyperlink handling. +The selected row receives roughly twice the height of other listed rows when space +permits. Every other row keeps at least three terminal lines, and page size stays +the same; selection changes the allocation, while hover does not. + Select a session with `Up`/`Down`, then use `Left` for less detail or `Right` for more. Click the left/right half of that row's combined detail/graph area for the same action on that session. The presentations are: @@ -1602,12 +1607,15 @@ same action on that session. The presentations are: **Unread completed results (shared app-server):** when Codex supplies durable read state, **TURN COMPLETE** remains highlighted and its completion pill stays -visible until the result is reviewed. Deliberately opening partial or full Detail, -or scrolling within its displayed result pane, acknowledges the latest completed -reply. The completion status remains visible in subdued styling afterward. -Rendering a preview, selecting a row, restoring a layout or receiving a new result -in an already-open pane does not acknowledge it. An older history page cannot -acknowledge a newer result; changed receipts require a fresh review action. +visible until the result is reviewed. In the Sessions list, deliberately select +an unread reply in **wide detail** and keep its result visible for **three seconds** +to mark it read. Selecting another row, leaving wide mode, hiding the reply or +receiving a newer result cancels the timer. Split previews stay unread, even when +scrolled. Opening full-screen Detail explicitly acknowledges the visible latest +completed reply immediately; a result arriving in an already-open Detail page +still needs a fresh review gesture. The completion status remains visible in +subdued styling afterward. Bulk Cycle, restored layouts and hover never start a +reading timer. An older history page cannot acknowledge a newer result. These receipts are saved by Codex and shared with supported native Codex views, so reviewed results remain reviewed across restarts. Codexometer does not save a @@ -1690,10 +1698,16 @@ collection or changes the Zero baseline. Dismissed sessions are skipped, and Dow matching session. These up/down session-selection buttons disappear in full detail, where Up/Down scroll the text. On narrow boxes, arrow buttons are omitted if they cannot fit; keyboard and -background half-click navigation still work. Hide/Show and Close retain priority. -The global `h`/Show Detail/Hide Detail control resets **all** rows to split or -graph-only, closes full detail and clears per-row overrides. Only that global -default is persisted across launches. While typing, arrows move the text cursor, +background half-click navigation still work. Cycle and Close retain priority. +The global **C(Y)CLE** (`y`) button first brings mixed listed rows to the most +detailed current overview layout, then cycles them together through **graph only → +split detail/graph → wide detail → graph only**. It includes matching rows off the +current page, leaves filtered-out or dismissed rows unchanged, and never opens +full-screen detail. Full detail and focused editors retain their own keys. +Cycling clears listed rows’ individual layout overrides and pending interaction +state, preserves selection and ordinary drafts, and does not mark replies read. The chosen +global default also applies to newly observed rows and survives restarts. +While typing, arrows move the text cursor, Enter submits, and `Esc` leaves the editor first. Approval controls remain exclusive to the current target. @@ -2127,6 +2141,24 @@ visually marked with a vertical rail. Formatting uses validated structured fields rather than guessing command boundaries from the justification. Legacy or incomplete requests retain their original bounded text. +**Terminal-input approvals (shared app-server):** before Codex sends input to an existing terminal, review its terminal ID, start directory, optional environment, and the exact input. Input is quoted with visible escapes so newlines, control keys and hidden characters cannot disappear in either interface. **SEND INPUT ONCE** and **CANCEL INPUT** act on the original request and are immediate by default; `--confirmation require` adds confirmation. No session-wide or persistent stdin grant is offered. Requests that also ask for unsupported additional permissions remain in Codex. + +**Managed network approvals (shared app-server):** review the requested host and protocol in the terminal or writable web UI. Codexometer offers only Codex’s advertised choices, including one-time access, a conversation grant and persistent host allow/block rules. Both persistent allow and block rules require confirmation by default. Missing or unsupported destination details still require review in Codex. + +**MCP/app tool approvals (shared app-server):** the terminal and writable web +interface show the MCP server, tool/app metadata, request message and +supplied arguments (or an unavailable marker when Codex omits them). Message-only tool approvals offer **APPROVE ONCE**, +**ALLOW FOR SESSION**, **ALWAYS ALLOW TOOL**, and **CANCEL TOOL CALL**, with reusable +grants included only when Codex advertises those scopes. One-time approval and +tool cancellation are immediate by default; session/persistent grants require +confirmation. The launch confirmation policy applies. Each action answers the +original MCP request once; cancellation uses the MCP cancellation action rather +than a command's reject-and-stop decision. Read-only web shows the same review +without enabling decisions. General forms, URL authentication and device +verification remain visible for handling in Codex. Missing turn/item IDs and +connector payloads without a separate tool name are supported; no identity is +guessed from the request prose. + **Managed human approvals (Codex 0.167+):** a managed command policy can require fresh approval each time, even when ordinary approvals have been saved or reviewed automatically. The terminal and writable web mode offer **APPROVE ONCE**, @@ -2260,21 +2292,21 @@ Full approval reviews use a separate **65,536-character** budget, so longer comm Local rollout logs do **not** persist Codex's approval-request events, so a local preview can show only the message preceding an approval. `INPUT NEEDED` or `CHECK SESSION` alone never enables these controls. Requests with missing, -truncated or sanitised-away details, network approvals, incomplete file changes, permission +truncated or sanitised-away details, unsupported network requests, incomplete file changes, permission grants and other unsupported requests remain **REPLY IN CODEX**. The complete eligible request is available in the scrollable detail, not just the compact two-line preview. Unsupported requests may have only a bounded excerpt. When controls are unavailable, the detail page explains why beside **REPLY IN CODEX**: for example, missing command/directory or request identity, -additional permissions, network approval, unavailable complete file changes, no supported decisions, +additional permissions, unsupported network details, unavailable complete file changes, no supported decisions, truncated or sanitised text, local-only observation, or a resolved/disconnected request. Eligible requests on small terminals instead explain that the terminal must be enlarged. These diagnostics do not relax any approval safeguards. -The readout's `[ H: HIDE DETAIL ]`/`[ H: SHOW DETAIL ]` button or `h` toggles all -previews (shortened to `[H:HIDE]`/`[H:SHOW]` in narrow layouts); the choice -survives restarts. No excerpt is saved to disk by Codexometer. Recent-turn browsing +The readout's **C(Y)CLE** button or `y` synchronizes the listed rows at their +most detailed current layout, then cycles graph-only, split and wide layouts +(shortened to `[Y]` in narrow layouts). The global choice survives restarts. No excerpt is saved to disk by Codexometer. Recent-turn browsing uses a bounded in-memory cache and read-only app-server history where available. Each retained excerpt is capped at 4,096 Unicode characters; startup reads only a bounded 256 KiB rollout tail, so older @@ -2287,8 +2319,8 @@ any command; restart the demo to reset its approval. ### Saved presentation preferences Codexometer's presentation preferences store only the selected theme, main tab, -Quota view, benchmark filter, benchmark ranking weight, and the Sessions context -hide/show preference. No benchmark result, message content, credential, session +Quota view, benchmark filter, benchmark ranking weight, and the global Sessions +detail level. No benchmark result, message content, credential, session ID, email, or account ID is written to that file. The small JSON file uses the platform-standard user configuration directory: @@ -3107,7 +3139,10 @@ available from the existing reader. once. These are not account-wide or permanent cumulative totals: removing a session from the observation can reduce the sum. On stale data, token/session totals are labelled last-known and live state counts become unavailable (—). -- Select a session by clicking its directory/name, or use **↑ / ↓**. +- Select a session by clicking its directory/name, or use **↑ / ↓**. The selected + row allows twice as much reply-text height as its neighbours. Deliberate selection + in wide mode marks the visible latest reply read after three seconds; full-page + Detail opens mark it read immediately. Read-only mode never sends receipts. - **[ (C)OPY ]** copies visible reply/activity text from split, wide or full-page detail, including while Codex is working and in read-only mode. `C` targets the selected visible detail; typing and native Ctrl/Cmd+C retain their normal behaviour. @@ -3121,9 +3156,11 @@ available from the existing reader. - Use **← / →** or the row's arrow buttons to move through **graph only → split detail and graph → wide detail → full-page detail**. Each row has its own layout. - **Escape** or **← ALL SESSIONS** returns from full-page detail to that session's - wide detail row. **SHOW ALL DETAILS / HIDE ALL DETAILS** switches all current - rows between split detail and graph-only, clearing individual overrides and - setting the default for newly observed sessions too. This global default is + wide detail row. **C(Y)CLE** or `y` first matches all listed rows to the most + detailed current row, then cycles **graph → split → wide → graph** in unison, + without opening a full-page session. It clears listed rows’ individual overrides + and sets the default for newly observed sessions too. Bulk cycling does not + acknowledge unread results. Keyboard cycling is unavailable while typing or in full detail. This global default is independent of the 100-entry saved per-session history. Narrow screens stack panels. - Attention links jump to the relevant session. Approval indicators remain outside scrollable reply text; available commands are separated from their @@ -3712,7 +3749,7 @@ Potential Sessions follow-ups (not implemented): would become persisted data and the saved-preferences documentation would need updating accordingly. -Currently, the main tab, Quota view and global Sessions hide/show preference are +Currently, the main tab, Quota view and global Sessions detail level are saved, but session selection, per-session detail levels and dismissals remain temporary. diff --git a/assets/screenshots/manifest.json b/assets/screenshots/manifest.json index 1252bc6d..56b699eb 100644 --- a/assets/screenshots/manifest.json +++ b/assets/screenshots/manifest.json @@ -54,8 +54,8 @@ "caption": "Sessions command centre: three synthetic sessions, live activity and an approval awaiting review.", "columns": 136, "rows": 45, - "frameSHA256": "11659ad50a2aeec7c2c35204f37b78e0a6d20b81e2b58551c67a9ae8d8ca8e73", - "pngSHA256": "c1ade89c04afde557347dab3ed2fcb2ff34fbd7e88b99932f12bf3b3a40e068b" + "frameSHA256": "17da84348984e7dc615a6e5f77c117f885adb236c5a9cc7191f922a383f591e2", + "pngSHA256": "e439280fe40e29baca4eaeb3dcd07a42aad79c84e48b54a0295ea5f527511710" }, { "file": "usage.png", diff --git a/assets/screenshots/sessions.png b/assets/screenshots/sessions.png index a8fd98b6..cc7e47fa 100644 Binary files a/assets/screenshots/sessions.png and b/assets/screenshots/sessions.png differ diff --git a/internal/codex/approval_options.go b/internal/codex/approval_options.go index 200ea91d..db624f19 100644 --- a/internal/codex/approval_options.go +++ b/internal/codex/approval_options.go @@ -7,15 +7,52 @@ import ( ) // Fixed-size, immutable value snapshots keep preview comparisons deterministic. -// Value selects an advertised option; Wire is the validated server payload. +// Value selects an advertised option. Wire is a command decision or a complete +// MCP elicitation response, selected by the request's validated protocol. type ApprovalOption struct{ Kind, Value, Wire, Detail string } +// Shared labels keep terminal and browser actions aligned. Grants can have a +// distinct confirmation label; dismissals retain their original wording. +var approvalGrantLabels = map[string][2]string{ + "accept": {"APPROVE ONCE", "CONFIRM APPROVAL"}, + "acceptStdin": {"SEND INPUT ONCE", "CONFIRM INPUT"}, + "acceptForSession": {"ALLOW FOR SESSION", "CONFIRM SESSION GRANT"}, + "acceptWithExecpolicyAmendment": {"ALWAYS ALLOW PREFIX", "CONFIRM PERSISTENT RULE"}, + "allowNetworkHost": {"ALWAYS ALLOW HOST", "CONFIRM HOST ALLOW"}, + "denyNetworkHost": {"ALWAYS BLOCK HOST", "CONFIRM HOST BLOCK"}, + "acceptMcpAlways": {"ALWAYS ALLOW TOOL", "CONFIRM TOOL RULE"}, +} + +func (o ApprovalOption) Label(confirm bool) string { + switch o.Kind { + case "decline": + return "DECLINE" + case "cancel": + return "REJECT & STOP TURN" + case "cancelMcpTool": + return "CANCEL TOOL CALL" + case "cancelStdin": + return "CANCEL INPUT" + } + index := 0 + if confirm { + index = 1 + } + return approvalGrantLabels[o.Kind][index] +} + func oneTimeApproval(kind string) bool { return kind == "accept" || kind == "decline" || kind == "cancel" } func (o ApprovalOption) GrantsPermission() bool { - return o.Kind == "accept" || o.Kind == "acceptForSession" || o.Kind == "acceptWithExecpolicyAmendment" + return o.Kind == "accept" || o.Kind == "acceptForSession" || o.Kind == "acceptWithExecpolicyAmendment" || o.Kind == "acceptMcpAlways" || o.Kind == "allowNetworkHost" || o.Kind == "acceptStdin" +} + +// ChangesPolicy includes persistent denies, which broaden the effect of a decision +// even though they grant no permission. One-time stdin decisions remain narrow. +func (o ApprovalOption) ChangesPolicy() bool { + return o.Kind == "acceptForSession" || o.Kind == "acceptWithExecpolicyAmendment" || o.Kind == "acceptMcpAlways" || o.Kind == "allowNetworkHost" || o.Kind == "denyNetworkHost" } func commandApprovalOptions(raw []json.RawMessage) ([8]ApprovalOption, string) { diff --git a/internal/codex/approval_review.go b/internal/codex/approval_review.go new file mode 100644 index 00000000..798fb770 --- /dev/null +++ b/internal/codex/approval_review.go @@ -0,0 +1,47 @@ +package codex + +import "strconv" + +// ApprovalActionDetails remains a comparable value snapshot. It is populated +// only for a complete validated action, never inferred from explanatory text. +type ApprovalActionDetails struct { + Kind, Target, Protocol, Justification string + Input, Directory, Environment string +} + +// ApprovalReview is a browser-safe projection shared with terminal rendering. +// It deliberately excludes request IDs, decision payloads and capabilities. +type ApprovalReview struct { + Title string `json:"title"` + Fields []ApprovalReviewField `json:"fields"` +} + +type ApprovalReviewField struct { + Label string `json:"label"` + Value string `json:"value"` +} + +func (c SessionContext) ActionReview() *ApprovalReview { + d := c.ActionDetails + var r *ApprovalReview + switch d.Kind { + case "network": + r = &ApprovalReview{Title: "NETWORK APPROVAL", Fields: []ApprovalReviewField{{"HOST", d.Target}, {"PROTOCOL", d.Protocol}}} + case "stdin": + r = &ApprovalReview{Title: "TERMINAL INPUT APPROVAL", Fields: []ApprovalReviewField{{"TERMINAL", d.Target}, {"INPUT (ESCAPED)", strconv.QuoteToASCII(d.Input)}, {"TERMINAL START DIRECTORY", d.Directory}}} + if d.Environment != "" { + r.Fields = append(r.Fields, ApprovalReviewField{"ENVIRONMENT", d.Environment}) + } + default: + return nil + } + if d.Justification != "" { + r.Fields = append(r.Fields, ApprovalReviewField{"JUSTIFICATION", d.Justification}) + } + for _, option := range c.ApprovalOptions { + if option.Detail != "" { + r.Fields = append(r.Fields, ApprovalReviewField{"PERMISSION SCOPE", option.Detail}) + } + } + return r +} diff --git a/internal/codex/mcp_approval.go b/internal/codex/mcp_approval.go new file mode 100644 index 00000000..b22f06ae --- /dev/null +++ b/internal/codex/mcp_approval.go @@ -0,0 +1,187 @@ +package codex + +import ( + "bytes" + "crypto/rand" + "encoding/json" + "strings" +) + +// MCPToolApprovalDetails is a complete bounded review, not a command or a +// reusable capability. Keep value fields so context comparisons remain stable. +type MCPToolApprovalDetails struct { + Server string `json:"server"` + Name string `json:"name,omitempty"` + Title string `json:"title,omitempty"` + Connector string `json:"connector,omitempty"` + Message string `json:"message"` + Arguments string `json:"arguments"` +} + +func configureMCPApproval(c *SessionContext, raw json.RawMessage) { + c.Kind, c.ApprovalBlocked = SessionContextQuestion, "mcp" + c.Text = "MCP request requires review in Codex." + var p struct { + Mode string `json:"mode"` + Server string `json:"serverName"` + Message string `json:"message"` + Schema json.RawMessage `json:"requestedSchema"` + Meta struct { + Kind string `json:"codex_approval_kind"` + Name string `json:"tool_name"` + Title string `json:"tool_title"` + Connector string `json:"connector_name"` + Arguments json.RawMessage `json:"tool_params"` + Display json.RawMessage `json:"tool_params_display"` + Persist json.RawMessage `json:"persist"` + } `json:"_meta"` + } + if len(raw) > approvalTextLimit || json.Unmarshal(raw, &p) != nil { + return + } + if p.Meta.Kind != "mcp_tool_call" { + // General forms, browser auth and device verification need different + // workflows. Observe them without advertising actionable capability. + c.Text = SanitizeSessionContext(c.Text + "\n" + p.Message) + return + } + c.Kind = SessionContextApproval + c.Text = "MCP TOOL APPROVAL\n" + p.Message + "\nMCP server: " + p.Server + if p.Server == "" || strings.TrimSpace(p.Message) == "" || (p.Mode != "form" && p.Mode != "openai/form" && p.Mode != "openaiForm") || !emptyMCPApprovalSchema(p.Schema) { + return + } + arguments, valid := mcpApprovalArguments(p.Meta.Arguments, p.Meta.Display) + if !valid { + return + } + d := MCPToolApprovalDetails{Server: p.Server, Name: p.Meta.Name, Title: p.Meta.Title, Connector: p.Meta.Connector, Message: p.Message, Arguments: arguments} + for _, field := range []struct{ label, text string }{{"Tool", d.Name}, {"Title", d.Title}, {"App", d.Connector}} { + if field.text != "" { + c.Text += "\n" + field.label + ": " + field.text + } + } + if arguments == "" { + c.Text += "\nArguments: —" + } else { + c.Text += "\nArguments:\n" + arguments + } + if strings.ContainsAny(d.Server+d.Name+d.Title+d.Connector, "\n\r\t") { + c.ApprovalBlocked = "sanitised" + return + } + if !approvalTextFits(c.Text) { + c.ApprovalBlocked = "truncated" + return + } + if !approvalTextDisplayable(c.Text) { + c.ApprovalBlocked = "sanitised" + return + } + c.MCPTool = d + add := func(kind, action, persist, detail string) { + var meta any + if persist != "" { + meta = map[string]string{"persist": persist} + } + wire, _ := json.Marshal(struct { + Action string `json:"action"` + Content any `json:"content"` + Meta any `json:"_meta"` + }{action, nil, meta}) + for i := range c.ApprovalOptions { + if c.ApprovalOptions[i].Kind == "" { + c.ApprovalOptions[i] = ApprovalOption{Kind: kind, Value: kind, Wire: string(wire), Detail: detail} + return + } + } + } + add("accept", "accept", "", "") + for _, scope := range mcpApprovalScopes(p.Meta.Persist) { + switch scope { + case "session": + add("acceptForSession", "accept", scope, "Allow future calls covered by this tool approval for the current Codex session.") + case "always": + add("acceptMcpAlways", "accept", scope, "Allow future calls covered by this tool approval, including future Codex sessions.") + } + } + add("cancelMcpTool", "cancel", "", "") + c.ApprovalDecisions = "accept" + for _, option := range c.ApprovalOptions[1:] { + if option.Kind != "" { + c.ApprovalDecisions += ", " + option.Kind + } + } + c.ApprovalToken, c.ApprovalBlocked = rand.Text(), "" +} + +func emptyMCPApprovalSchema(raw json.RawMessage) bool { + if bytes.Equal(bytes.TrimSpace(raw), []byte("null")) { + return true + } + var schema struct { + Type string `json:"type"` + Properties map[string]json.RawMessage `json:"properties"` + Required []string `json:"required"` + } + return json.Unmarshal(raw, &schema) == nil && schema.Type == "object" && schema.Properties != nil && len(schema.Properties) == 0 && len(schema.Required) == 0 +} + +func mcpApprovalArguments(raw, display json.RawMessage) (string, bool) { + if len(raw) == 0 { + // Upstream omits tool_name for some connector approvals, and may + // provide display parameters instead of the raw argument object. + if len(display) > 0 && !bytes.Equal(bytes.TrimSpace(display), []byte("null")) { + var fields []struct { + Name string `json:"name"` + Value json.RawMessage `json:"value"` + DisplayName string `json:"display_name"` + } + if json.Unmarshal(display, &fields) != nil { + return "", false + } + if len(fields) == 0 { + return "", true + } + params := make(map[string]json.RawMessage) + for _, field := range fields { + if field.Name == "" || len(field.Value) == 0 { + return "", false + } + if _, duplicate := params[field.Name]; duplicate { + return "", false + } + params[field.Name] = field.Value + } + raw, _ = json.Marshal(params) + } else { + return "", true // Omitted metadata is not proof of an empty argument object. + } + } + var object map[string]json.RawMessage + if json.Unmarshal(raw, &object) != nil || object == nil { + return "", false + } + formatted, err := json.MarshalIndent(object, "", " ") + return string(formatted), err == nil && approvalTextFits(string(formatted)) +} + +func mcpApprovalScopes(raw json.RawMessage) []string { + var one string + var values []string + if json.Unmarshal(raw, &one) == nil { + values = []string{one} + } else { + _ = json.Unmarshal(raw, &values) + } + var scopes []string + // Match the native UI order, regardless of metadata ordering/duplicates. + for _, scope := range []string{"session", "always"} { + for _, value := range values { + if value == scope { + scopes = append(scopes, scope) + break + } + } + } + return scopes +} diff --git a/internal/codex/mcp_approval_test.go b/internal/codex/mcp_approval_test.go new file mode 100644 index 00000000..bb1e08b8 --- /dev/null +++ b/internal/codex/mcp_approval_test.go @@ -0,0 +1,132 @@ +package codex + +import ( + "encoding/json" + "strings" + "testing" + "time" +) + +func mcpApprovalFixture(t *testing.T, overrides map[string]any) (map[string]*daemonContextState, SessionContext) { + t.Helper() + p := map[string]any{ + "threadId": "root", "serverName": "codex_apps", "mode": "form", + "message": "Allow Calendar to create an event?", + "requestedSchema": map[string]any{"type": "object", "properties": map[string]any{}}, + "_meta": map[string]any{"codex_approval_kind": "mcp_tool_call", "tool_title": "Create Event", "connector_name": "Calendar", "persist": []string{"session", "always"}, "tool_params": map[string]any{"title": "Roadmap review"}}, + } + for key, value := range overrides { + p[key] = value + } + raw, err := json.Marshal(p) + if err != nil { + t.Fatal(err) + } + states := map[string]*daemonContextState{} + daemonContextEvent(states, "mcpServer/elicitation/request", json.RawMessage(`"mcp-request"`), raw, time.Now()) + if states["root"] == nil { + t.Fatal("MCP request not observed") + } + return states, states["root"].requests[`"mcp-request"`] +} + +func TestMCPToolApprovalMatchesNativeFourChoicesWithoutItemTurnOrToolName(t *testing.T) { + _, c := mcpApprovalFixture(t, nil) + if c.Kind != SessionContextApproval || c.ApprovalToken == "" || c.ApprovalBlocked != "" || c.TurnID != "" || c.ItemID != "" || c.MCPTool.Name != "" { + t.Fatalf("native connector request not actionable: %+v", c) + } + if c.MCPTool.Server != "codex_apps" || c.MCPTool.Connector != "Calendar" || !strings.Contains(c.MCPTool.Arguments, `"title": "Roadmap review"`) { + t.Fatal("complete tool review was lost", c.MCPTool) + } + for i, want := range []string{"accept", "acceptForSession", "acceptMcpAlways", "cancelMcpTool"} { + if c.ApprovalOptions[i].Kind != want { + t.Fatal("wrong offered choices", c.ApprovalOptions) + } + var response struct { + Action string `json:"action"` + Content any `json:"content"` + Meta map[string]string `json:"_meta"` + } + if json.Unmarshal([]byte(c.ApprovalOptions[i].Wire), &response) != nil || response.Content != nil { + t.Fatal("invalid response") + } + wantAction := "accept" + if i == 3 { + wantAction = "cancel" + } + if response.Action != wantAction { + t.Fatal("incorrect MCP action", response) + } + if i == 1 && response.Meta["persist"] != "session" || i == 2 && response.Meta["persist"] != "always" || (i == 0 || i == 3) && response.Meta != nil { + t.Fatal("incorrect grant scope", response) + } + } +} + +func TestMCPApprovalOffersOnlyAdvertisedScopesAndModes(t *testing.T) { + for _, mode := range []string{"form", "openai/form", "openaiForm"} { + for _, tc := range []struct { + persist any + count int + }{{nil, 2}, {"session", 3}, {"always", 3}, {[]string{"always", "session", "session"}, 4}, {"future", 2}} { + _, c := mcpApprovalFixture(t, map[string]any{"mode": mode, "_meta": map[string]any{"codex_approval_kind": "mcp_tool_call", "persist": tc.persist}}) + if c.MCPTool.Arguments != "" { + t.Fatal("omitted argument metadata was invented") + } + count := 0 + for _, option := range c.ApprovalOptions { + if option.Kind != "" { + count++ + } + } + if c.ApprovalToken == "" || count != tc.count { + t.Fatalf("mode %s scope %v: %d choices", mode, tc.persist, count) + } + } + } + _, c := mcpApprovalFixture(t, map[string]any{"mode": "openai/form", "requestedSchema": nil, "_meta": map[string]any{"codex_approval_kind": "mcp_tool_call", "tool_params_display": []any{map[string]any{"name": "title", "value": "Demo", "display_name": "Title"}}}}) + if c.ApprovalToken == "" || !strings.Contains(c.MCPTool.Arguments, `"title": "Demo"`) { + t.Fatal("display-only argument metadata not supported") + } +} + +func TestUnsupportedMCPRequestsRemainVisibleWithoutApprovalCapability(t *testing.T) { + for name, override := range map[string]map[string]any{ + "url": {"mode": "url"}, + "auth": {"_meta": map[string]any{"codex_approval_kind": "browser_auth"}}, + "verification": {"mode": "openai/userVerification"}, + "form-fields": {"requestedSchema": map[string]any{"type": "object", "properties": map[string]any{"answer": map[string]string{"type": "string"}}}}, + "required": {"requestedSchema": map[string]any{"type": "object", "properties": map[string]any{}, "required": []string{"answer"}}}, + "missing-server": {"serverName": ""}, + "missing-message": {"message": ""}, + "bad-arguments": {"_meta": map[string]any{"codex_approval_kind": "mcp_tool_call", "tool_params": []string{"argument"}}}, + "bad-display": {"_meta": map[string]any{"codex_approval_kind": "mcp_tool_call", "tool_params_display": []any{map[string]any{"name": "title"}}}}, + "long": {"message": strings.Repeat("x", approvalTextLimit+1)}, + "hidden-text": {"message": "Allow \x1b[31mthis?"}, + "identity-newline": {"serverName": "server\nOther server"}, + } { + t.Run(name, func(t *testing.T) { + _, c := mcpApprovalFixture(t, override) + if c.Text == "" || !c.pending() || c.ApprovalToken != "" || c.ApprovalBlocked == "" { + t.Fatalf("unsupported request disappeared or became actionable: %+v", c) + } + }) + } +} + +func TestMCPApprovalResolutionAndReplayAreRequestBound(t *testing.T) { + states, c := mcpApprovalFixture(t, nil) + daemonContextEvent(states, "mcpServer/elicitation/request", json.RawMessage(`"mcp-request"`), json.RawMessage(`{"threadId":"root","serverName":"codex_apps","mode":"form","message":"Allow updated tool request?","requestedSchema":{"type":"object","properties":{}},"_meta":{"codex_approval_kind":"mcp_tool_call"}}`), time.Now()) + next := states["root"].requests[`"mcp-request"`] + if next.ApprovalToken == "" || c.ApprovalToken == next.ApprovalToken || !next.At.Equal(c.At) { + t.Fatal("replay failed to replace the capability while preserving queue position") + } + daemonContextEvent(states, "serverRequest/resolved", nil, json.RawMessage(`{"threadId":"root","requestId":"other"}`), time.Now()) + if len(states["root"].requests) != 1 { + t.Fatal("another request resolved this approval") + } + daemonContextEvent(states, "serverRequest/resolved", nil, json.RawMessage(`{"threadId":"root","requestId":"mcp-request"}`), time.Now()) + if len(states["root"].requests) != 0 { + t.Fatal("resolved approval remained actionable") + } +} diff --git a/internal/codex/network_approval.go b/internal/codex/network_approval.go new file mode 100644 index 00000000..5d8f3b48 --- /dev/null +++ b/internal/codex/network_approval.go @@ -0,0 +1,105 @@ +package codex + +import ( + "bytes" + "crypto/rand" + "encoding/json" + "strings" + "unicode" +) + +func decodeApprovalObject(raw json.RawMessage, value any) bool { + decoder := json.NewDecoder(bytes.NewReader(raw)) + decoder.DisallowUnknownFields() + return len(raw) <= approvalTextLimit && json.Valid(raw) && decoder.Decode(value) == nil +} + +func configureNetworkApproval(c *SessionContext, raw json.RawMessage, decisions []json.RawMessage, reason string) { + c.Kind, c.ApprovalBlocked = SessionContextApproval, "network" + c.Text = reason + "\nNetwork request: " + string(raw) + var network struct { + Host string `json:"host"` + Protocol string `json:"protocol"` + } + if !decodeApprovalObject(raw, &network) || network.Host == "" || len(network.Host) > 1024 || !approvalTextDisplayable(network.Host) || strings.IndexFunc(network.Host, unicode.IsSpace) >= 0 || strings.ContainsAny(network.Host, " \t\r\n/@?#\\") { + return + } + switch network.Protocol { + case "http", "https", "socks5Tcp", "socks5Udp": + default: + return + } + if !approvalTextFits(c.Text) { + c.ApprovalBlocked = "truncated" + return + } + if !approvalTextDisplayable(c.Text) { + c.ApprovalBlocked = "sanitised" + return + } + var options [8]ApprovalOption + n := 0 + for _, raw := range decisions { + parsed, _ := commandApprovalOptions([]json.RawMessage{raw}) + option := parsed[0] + if oneTimeApproval(option.Kind) || option.Kind == "acceptForSession" { + if option.Kind == "acceptForSession" { + option.Detail = "Allow this host for the current Codex conversation." + } + } else { + option = ApprovalOption{} + var rule struct { + Amendment *struct { + Policy *struct { + Host string `json:"host"` + Action string `json:"action"` + } `json:"network_policy_amendment"` + } `json:"applyNetworkPolicyAmendment"` + } + if decodeApprovalObject(raw, &rule) && rule.Amendment != nil && rule.Amendment.Policy != nil { + policy := rule.Amendment.Policy + if policy.Host == network.Host && (policy.Action == "allow" || policy.Action == "deny") { + kind := "allowNetworkHost" + if policy.Action == "deny" { + kind = "denyNetworkHost" + } + // Preserve the exact advertised object; never construct a wider rule. + option = ApprovalOption{Kind: kind, Value: string(raw), Wire: string(raw), Detail: "Future network requests: " + policy.Action + " " + policy.Host} + } + } + } + if option.Kind == "" || n == len(options) { + continue + } + duplicate := false + for _, old := range options { + duplicate = duplicate || old.Kind == option.Kind + } + if !duplicate { + options[n] = option + n++ + } + } + if n == 0 { + c.ApprovalBlocked = "decisions" + return + } + for i, option := range options { + if option.Kind == "accept" { + copy(options[1:i+1], options[:i]) + options[0] = option + break + } + } + c.ActionDetails = ApprovalActionDetails{Kind: "network", Target: network.Host, Protocol: network.Protocol, Justification: reason} + c.ApprovalOptions = options + for i, option := range options { + if option.Kind != "" { + if i > 0 { + c.ApprovalDecisions += ", " + } + c.ApprovalDecisions += option.Kind + } + } + c.ApprovalToken, c.ApprovalBlocked = rand.Text(), "" +} diff --git a/internal/codex/network_approval_test.go b/internal/codex/network_approval_test.go new file mode 100644 index 00000000..b26a298c --- /dev/null +++ b/internal/codex/network_approval_test.go @@ -0,0 +1,92 @@ +package codex + +import ( + "encoding/json" + "strings" + "testing" + "time" +) + +func networkDecisions() []any { + rule := func(action string) any { + return map[string]any{"applyNetworkPolicyAmendment": map[string]any{"network_policy_amendment": map[string]string{"host": "example.com", "action": action}}} + } + return []any{"accept", "acceptForSession", rule("allow"), rule("deny"), "decline", "cancel"} +} + +func networkApprovalFixture(t *testing.T, overrides map[string]any) (map[string]*daemonContextState, SessionContext) { + t.Helper() + p := map[string]any{"command": nil, "cwd": "", "networkApprovalContext": map[string]string{"host": "example.com", "protocol": "https"}, "availableDecisions": networkDecisions()} + for k, v := range overrides { + p[k] = v + } + return approvalFixture(t, p) +} + +func TestNetworkApprovalRequiresNoCommandAndRetainsExactRules(t *testing.T) { + _, c := networkApprovalFixture(t, nil) + if c.ApprovalToken == "" || c.ApprovalBlocked != "" || c.CommandDetails.Command != "" || c.ActionReview() == nil { + t.Fatalf("network not actionable: %+v", c) + } + if c.ActionDetails.Target != "example.com" || c.ActionDetails.Protocol != "https" { + t.Fatal(c.ActionDetails) + } + for i, kind := range []string{"accept", "acceptForSession", "allowNetworkHost", "denyNetworkHost", "decline", "cancel"} { + if c.ApprovalOptions[i].Kind != kind { + t.Fatal(c.ApprovalOptions) + } + raw, _ := json.Marshal(networkDecisions()[i]) + if c.ApprovalOptions[i].Wire != string(raw) { + t.Fatal("advertised decision changed", c.ApprovalOptions[i]) + } + } + for _, protocol := range []string{"http", "https", "socks5Tcp", "socks5Udp"} { + _, c := networkApprovalFixture(t, map[string]any{"networkApprovalContext": map[string]string{"host": "[::1]:8080", "protocol": protocol}}) + if c.ApprovalToken == "" { + t.Fatal("supported protocol blocked", protocol) + } + for _, option := range c.ApprovalOptions { + if option.Kind == "allowNetworkHost" || option.Kind == "denyNetworkHost" { + t.Fatal("rule for another host offered") + } + } + } +} + +func TestNetworkApprovalRejectsIncompleteAmbiguousOrBroaderRequests(t *testing.T) { + for name, overrides := range map[string]map[string]any{ + "no protocol": {"networkApprovalContext": map[string]string{"host": "example.com"}}, + "unknown protocol": {"networkApprovalContext": map[string]string{"host": "example.com", "protocol": "future"}}, + "extra context": {"networkApprovalContext": map[string]any{"host": "example.com", "protocol": "https", "extra": true}}, + "host controls": {"networkApprovalContext": map[string]string{"host": "example.com\u202e", "protocol": "https"}}, + "host whitespace": {"networkApprovalContext": map[string]string{"host": "example.com\u00a0other", "protocol": "https"}}, + "URL instead of host": {"networkApprovalContext": map[string]string{"host": "https://example.com", "protocol": "https"}}, + "permissions": {"additionalPermissions": map[string]any{"network": map[string]bool{"enabled": true}}}, + "wrong kind": {"kind": "humanCommand"}, "no identity": {"turnId": ""}, + "no decisions": {"availableDecisions": []any{}}, "omitted decisions": {"availableDecisions": nil}, + "unsafe reason": {"reason": "allow\x1b[2J"}, "long reason": {"reason": strings.Repeat("x", approvalTextLimit+1)}, + "unoffered wider rule": {"availableDecisions": []any{map[string]any{"applyNetworkPolicyAmendment": map[string]any{"network_policy_amendment": map[string]string{"host": "*.example.com", "action": "allow"}}}}}, + "exec policy": {"availableDecisions": []any{map[string]any{"acceptWithExecpolicyAmendment": map[string]any{"execpolicy_amendment": []string{"curl"}}}}}, + } { + t.Run(name, func(t *testing.T) { + _, c := networkApprovalFixture(t, overrides) + if c.ApprovalToken != "" || c.ActionReview() != nil { + t.Fatalf("unsupported network request actionable: %+v", c) + } + }) + } +} + +func TestNetworkApprovalReplayAndExpiry(t *testing.T) { + states, first := networkApprovalFixture(t, nil) + raw, _ := json.Marshal(map[string]any{"threadId": "root", "turnId": "turn", "itemId": "cmd", "networkApprovalContext": map[string]string{"host": "changed.example", "protocol": "https"}, "availableDecisions": []string{"accept", "cancel"}}) + daemonContextEvent(states, "item/commandExecution/requestApproval", json.RawMessage(`"req"`), raw, time.Now()) + next := states["root"].requests[`"req"`] + if next.ApprovalToken == "" || next.ApprovalToken == first.ApprovalToken || next.ActionDetails.Target != "changed.example" { + t.Fatal("replay retained network authority") + } + daemonContextEvent(states, "serverRequest/resolved", nil, json.RawMessage(`{"threadId":"root","requestId":"req"}`), time.Now()) + if len(states["root"].requests) != 0 { + t.Fatal("expired network decision remained") + } +} diff --git a/internal/codex/session_167_test.go b/internal/codex/session_167_test.go index ed7eaf0a..0451e5c6 100644 --- a/internal/codex/session_167_test.go +++ b/internal/codex/session_167_test.go @@ -9,7 +9,7 @@ import ( func TestCodex167NetworkExpiryResolvesOnlyItsRequest(t *testing.T) { states := map[string]*daemonContextState{} for _, id := range []string{"expired", "remaining"} { - daemonContextEvent(states, "item/commandExecution/requestApproval", rawJSON(id), rawJSON(map[string]any{"threadId": "root", "turnId": "turn", "itemId": "command", "command": "curl https://example.com", "cwd": "/work", "networkApprovalContext": map[string]any{"host": "example.com", "protocol": "https"}}), time.Now()) + daemonContextEvent(states, "item/commandExecution/requestApproval", rawJSON(id), rawJSON(map[string]any{"threadId": "root", "turnId": "turn", "itemId": "command", "command": "curl https://example.com", "cwd": "/work", "availableDecisions": []string{"accept", "cancel"}, "networkApprovalContext": map[string]any{"host": "example.com", "protocol": "https"}}), time.Now()) } daemonContextEvent(states, "serverRequest/resolved", nil, rawJSON(map[string]any{"threadId": "other", "requestId": "expired"}), time.Now()) if len(states["root"].requests) != 2 { @@ -20,7 +20,7 @@ func TestCodex167NetworkExpiryResolvesOnlyItsRequest(t *testing.T) { t.Fatal("expired network prompt remained or removed its sibling") } c := daemonContextSnapshot(states, []string{"root"}, map[string]sessionRuntimeStatus{"root": sessionRuntimeApproval})["root"] - if c.PendingApprovals != 1 || c.ApprovalBlocked != "network" { + if c.PendingApprovals != 1 || c.ApprovalBlocked != "" || c.ApprovalToken == "" || c.ActionDetails.Kind != "network" { t.Fatal("network expiry changed remaining request semantics", c) } daemonContextEvent(states, "serverRequest/resolved", nil, json.RawMessage(`{"threadId":"root","requestId":"remaining"}`), time.Now()) diff --git a/internal/codex/session_approval_test.go b/internal/codex/session_approval_test.go index 60a56a3c..811b5eaa 100644 --- a/internal/codex/session_approval_test.go +++ b/internal/codex/session_approval_test.go @@ -44,7 +44,7 @@ func TestApprovalCompleteCommandAndFailClosed(t *testing.T) { "hidden directory suffix": {"cwd": "/work\u202e"}, "bidi": {"command": "echo \u202Ehidden"}, "bare carriage return": {"command": "echo visible\rhidden"}, - "network": {"networkApprovalContext": map[string]string{"host": "example.com", "protocol": "https"}}, + "network": {"networkApprovalContext": map[string]string{"host": "example.com", "protocol": "unknown"}}, "permissions": {"additionalPermissions": map[string]any{"network": true}}, "no decisions": {"availableDecisions": []string{}}, "ambiguous argv": {"command": []string{"echo", "a b"}}, @@ -69,7 +69,7 @@ func TestApprovalKindExplicitAndLegacyCommand(t *testing.T) { } } _, c := approvalFixture(t, map[string]any{"kind": "writeStdin", "command": "git push", "cwd": "/work"}) - if c.ApprovalToken != "" || c.ApprovalBlocked != "approval-kind" { + if c.ApprovalToken != "" || c.ApprovalBlocked != "missing-identity" { t.Fatal("stdin treated as command", c) } } diff --git a/internal/codex/session_approval_unix.go b/internal/codex/session_approval_unix.go index 15094d3b..674a3bb4 100644 --- a/internal/codex/session_approval_unix.go +++ b/internal/codex/session_approval_unix.go @@ -42,9 +42,10 @@ func (p *daemonStatusProvider) RespondSessionApproval(ctx context.Context, token p.mu.Unlock() return errors.New("request expired or connection closed; check Codex") } + request := s.requests[id] var wire string - for _, option := range s.requests[id].ApprovalOptions { - if option.Kind != "" && option.Value == decision && (!s.requests[id].RequiredHumanApproval || oneTimeApproval(option.Kind)) { + for _, option := range request.ApprovalOptions { + if option.Kind != "" && option.Value == decision && (!request.RequiredHumanApproval || oneTimeApproval(option.Kind)) { wire = option.Wire break } @@ -59,5 +60,9 @@ func (p *daemonStatusProvider) RespondSessionApproval(ctx context.Context, token p.mu.Unlock() // Never hold the state lock during IO: rendering can check pending state // without waiting for the network. The server arbitrates concurrent replies. - return p.write(connection, map[string]any{"id": json.RawMessage(id), "result": map[string]any{"decision": json.RawMessage(wire)}}) + var result any = map[string]any{"decision": json.RawMessage(wire)} + if request.MCPTool.Server != "" { + result = json.RawMessage(wire) + } + return p.write(connection, map[string]any{"id": json.RawMessage(id), "result": result}) } diff --git a/internal/codex/session_approval_unix_test.go b/internal/codex/session_approval_unix_test.go index 17177fbc..b7032b12 100644 --- a/internal/codex/session_approval_unix_test.go +++ b/internal/codex/session_approval_unix_test.go @@ -56,6 +56,88 @@ func TestApprovalWireOneUseAndDisconnect(t *testing.T) { t.Fatal("file capability reused") } } + for _, decision := range []string{"accept", "cancel"} { + p.contexts, c = stdinApprovalFixture(t, nil) + if err := p.RespondSessionApproval(context.Background(), c.ApprovalToken, "acceptForSession"); err == nil || !p.SessionApprovalPending(c.ApprovalToken) { + t.Fatal("stdin session grant accepted") + } + if err := p.RespondSessionApproval(context.Background(), c.ApprovalToken, decision); err != nil { + t.Fatal(err) + } + select { + case msg := <-received: + if string(msg["id"]) != `"req"` || string(msg["result"]) != `{"decision":"`+decision+`"}` { + t.Fatal("wrong stdin response", msg) + } + case <-time.After(time.Second): + t.Fatal("missing stdin response") + } + if p.SessionApprovalPending(c.ApprovalToken) || p.RespondSessionApproval(context.Background(), c.ApprovalToken, decision) == nil { + t.Fatal("stdin approval reused") + } + } + for i := range networkDecisions() { + p.contexts, c = networkApprovalFixture(t, nil) + option := c.ApprovalOptions[i] + if err := p.RespondSessionApproval(context.Background(), c.ApprovalToken, "unoffered"); err == nil || !p.SessionApprovalPending(c.ApprovalToken) { + t.Fatal("unadvertised network decision accepted") + } + if err := p.RespondSessionApproval(context.Background(), c.ApprovalToken, option.Value); err != nil { + t.Fatal(err) + } + select { + case msg := <-received: + if string(msg["id"]) != `"req"` || string(msg["result"]) != `{"decision":`+option.Wire+`}` { + t.Fatal("wrong network response", msg) + } + case <-time.After(time.Second): + t.Fatal("missing network response") + } + if p.SessionApprovalPending(c.ApprovalToken) || p.RespondSessionApproval(context.Background(), c.ApprovalToken, option.Value) == nil { + t.Fatal("network request reused") + } + } + p.contexts, c = mcpApprovalFixture(t, map[string]any{"_meta": map[string]any{"codex_approval_kind": "mcp_tool_call"}}) + for _, decision := range []string{"acceptForSession", "acceptMcpAlways"} { + if p.RespondSessionApproval(context.Background(), c.ApprovalToken, decision) == nil || !p.SessionApprovalPending(c.ApprovalToken) { + t.Fatal("unadvertised reusable MCP grant was accepted") + } + } + for index, decision := range []string{"accept", "acceptForSession", "acceptMcpAlways", "cancelMcpTool"} { + p.contexts, c = mcpApprovalFixture(t, nil) + if err := p.RespondSessionApproval(context.Background(), c.ApprovalToken, "unoffered"); err == nil || !p.SessionApprovalPending(c.ApprovalToken) { + t.Fatal("unoffered MCP action consumed capability") + } + if err := p.RespondSessionApproval(context.Background(), c.ApprovalToken, decision); err != nil { + t.Fatal(err) + } + select { + case msg := <-received: + var result map[string]json.RawMessage + if string(msg["id"]) != `"mcp-request"` || json.Unmarshal(msg["result"], &result) != nil || len(result) != 3 || len(result["decision"]) > 0 || string(result["content"]) != "null" { + t.Fatal("wrong MCP response envelope", msg) + } + want := `"accept"` + if index == 3 { + want = `"cancel"` + } + meta := "null" + if index == 1 { + meta = `{"persist":"session"}` + } + if index == 2 { + meta = `{"persist":"always"}` + } + if string(result["action"]) != want || string(result["_meta"]) != meta { + t.Fatal("wrong MCP action or persistence", string(msg["result"])) + } + case <-time.After(time.Second): + t.Fatal("missing MCP response") + } + if p.SessionApprovalPending(c.ApprovalToken) || p.RespondSessionApproval(context.Background(), c.ApprovalToken, decision) == nil { + t.Fatal("MCP capability reused") + } + } p.contexts, c = approvalFixture(t, map[string]any{"kind": "humanCommand", "command": "git push", "cwd": "/work", "availableDecisions": []string{"accept", "acceptForSession"}}) // Defend at the response boundary even if a caller hands us a malformed option snapshot. human := p.contexts["root"].requests[`"req"`] diff --git a/internal/codex/session_context.go b/internal/codex/session_context.go index 3db19e82..73e10bea 100644 --- a/internal/codex/session_context.go +++ b/internal/codex/session_context.go @@ -43,6 +43,8 @@ type SessionContext struct { // The count is a lower bound until the turn ends or the connection resets. PendingApprovalsLimited bool RequestID string + ActionDetails ApprovalActionDetails + MCPTool MCPToolApprovalDetails CommandDetails ApprovalCommandDetails FileChanges string // validated, bounded JSON; immutable comparable snapshot InputToken string diff --git a/internal/codex/session_context_daemon.go b/internal/codex/session_context_daemon.go index a2baf2b7..0bac7c9a 100644 --- a/internal/codex/session_context_daemon.go +++ b/internal/codex/session_context_daemon.go @@ -160,7 +160,11 @@ func daemonContextEvent(states map[string]*daemonContextState, method string, id return case "item/commandExecution/requestApproval": kind := "command" // legacy servers omit the discriminator - kindValid := len(p.Kind) == 0 || json.Unmarshal(p.Kind, &kind) == nil && (kind == "command" || kind == "humanCommand") && string(p.Kind) != "null" + kindValid := len(p.Kind) == 0 || json.Unmarshal(p.Kind, &kind) == nil && (kind == "command" || kind == "humanCommand" || kind == "writeStdin") && string(p.Kind) != "null" + if kindValid && kind == "writeStdin" { + configureStdinApproval(&c, raw) + break + } var command string commandValid := len(p.Command) == 0 || string(p.Command) == "null" || json.Unmarshal(p.Command, &command) == nil previous := state.commands[p.TurnID+"/"+p.ItemID] @@ -174,6 +178,10 @@ func daemonContextEvent(states map[string]*daemonContextState, method string, id c.RequiredHumanApproval = kindValid && kind == "humanCommand" c.Text = strings.TrimSpace(p.Reason + "\nCommand: " + command + "\nDirectory: " + p.CWD) special := func(raw json.RawMessage) bool { return len(raw) > 0 && string(raw) != "null" } + if special(p.Network) && kindValid && kind == "command" && !special(p.Permissions) && p.TurnID != "" && p.ItemID != "" { + configureNetworkApproval(&c, p.Network, p.Decisions, p.Reason) + break + } if special(p.Network) { c.Text += "\nNetwork request: " + string(p.Network) } @@ -239,6 +247,8 @@ func daemonContextEvent(states map[string]*daemonContextState, method string, id case "item/fileChange/patchUpdated": state.capturePatch(p.TurnID, p.ItemID, p.Changes) return + case "mcpServer/elicitation/request": + configureMCPApproval(&c, raw) case "item/permissions/requestApproval": c.ApprovalBlocked = "permissions" c.Kind, c.Text = SessionContextApproval, p.Reason diff --git a/internal/codex/stdin_approval.go b/internal/codex/stdin_approval.go new file mode 100644 index 00000000..b7238631 --- /dev/null +++ b/internal/codex/stdin_approval.go @@ -0,0 +1,154 @@ +package codex + +import ( + "crypto/rand" + "encoding/json" + "strconv" + "strings" +) + +type stdinApprovalParams struct { + Command string `json:"command"` + Directory string `json:"cwd"` + Reason string `json:"reason"` + ApprovalID string `json:"approvalId"` + Environment string `json:"environmentId"` + Decisions []json.RawMessage `json:"availableDecisions"` + Permissions json.RawMessage `json:"additionalPermissions"` + Network json.RawMessage `json:"networkApprovalContext"` +} + +func configureStdinApproval(c *SessionContext, raw json.RawMessage) { + c.Kind, c.ApprovalBlocked = SessionContextApproval, "command-format" + c.Text = "Terminal input requires review in Codex." + var p stdinApprovalParams + if len(raw) > approvalTextLimit { + c.ApprovalBlocked = "truncated" + return + } + if json.Unmarshal(raw, &p) != nil { + return + } + c.Text += "\n" + p.Reason + "\n" + p.Command + if c.TurnID == "" || c.ItemID == "" || p.ApprovalID == "" || !approvalTextDisplayable(p.ApprovalID) { + c.ApprovalBlocked = "missing-identity" + return + } + if len(p.Permissions) > 0 && string(p.Permissions) != "null" { + c.ApprovalBlocked = "permissions" + return + } + if len(p.Network) > 0 && string(p.Network) != "null" { + c.ApprovalBlocked = "network" + return + } + if p.Directory == "" { + c.ApprovalBlocked = "missing-directory" + return + } + terminal, input, valid := terminalApprovalInput(p.Command) + if !valid || strings.ContainsRune(input, 0) { + return + } + c.Text = "Terminal: " + terminal + "\nInput (escaped): " + strconv.QuoteToASCII(input) + "\nStart directory: " + p.Directory + "\nEnvironment: " + p.Environment + "\n" + p.Reason + if !approvalTextFits(c.Text) { + c.ApprovalBlocked = "truncated" + return + } + if !approvalTextDisplayable(c.Text) { + c.ApprovalBlocked = "sanitised" + return + } + // Input approval never grants authority for later inputs or commands. + parsed, _ := commandApprovalOptions(p.Decisions) + var options [8]ApprovalOption + n := 0 + for _, option := range parsed { + if !oneTimeApproval(option.Kind) { + continue + } + switch option.Kind { + case "accept": + option.Kind = "acceptStdin" + case "cancel": + option.Kind = "cancelStdin" + } + options[n] = option + n++ + } + if p.Decisions == nil || n == 0 { + c.ApprovalBlocked = "decisions" + return + } + c.ActionDetails = ApprovalActionDetails{Kind: "stdin", Target: terminal, Input: input, Directory: p.Directory, Environment: p.Environment, Justification: p.Reason} + c.ApprovalOptions = options + c.ApprovalToken, c.ApprovalBlocked = rand.Text(), "" +} + +// Codex 0.167 presents stdin as shlex::try_join of exactly four arguments: +// write_stdin, --session-id, a decimal terminal ID, and the literal input. +// Decode that presentation only. This is not a shell evaluator; expansions, +// substitutions, operators and extra arguments are never interpreted. +func terminalApprovalInput(command string) (string, string, bool) { + rest, ok := strings.CutPrefix(command, "write_stdin --session-id ") + if !ok { + return "", "", false + } + terminal, encoded, ok := strings.Cut(rest, " ") + number, err := strconv.ParseUint(terminal, 10, 64) + if !ok || err != nil || strconv.FormatUint(number, 10) != terminal { + return "", "", false + } + input, valid := quotedApprovalArgument(encoded) + return terminal, input, valid +} + +func quotedApprovalArgument(encoded string) (string, bool) { + var out strings.Builder + var quote byte + if encoded == "" { + return "", false + } + for i := 0; i < len(encoded); i++ { + ch := encoded[i] + if quote == '\'' { + if ch == '\'' { + quote = 0 + } else { + out.WriteByte(ch) + } + continue + } + if ch == '\\' { + if i+1 == len(encoded) { + return "", false + } + next := encoded[i+1] + if next == '\n' || next == '\r' { + return "", false + } + if quote == '"' && !strings.ContainsRune("\\\"$`", rune(next)) { + out.WriteByte(ch) + continue + } + out.WriteByte(next) + i++ + continue + } + if ch == '"' || ch == '\'' && quote == 0 { + if quote == ch { + quote = 0 + } else if quote == 0 { + quote = ch + } else { + out.WriteByte(ch) + } + continue + } + if quote == 0 && strings.ContainsRune(" \t\r\n|&;()<>#*?[]{}~", rune(ch)) || ch == '$' || ch == '`' { + return "", false + } + out.WriteByte(ch) + } + return out.String(), quote == 0 +} diff --git a/internal/codex/stdin_approval_test.go b/internal/codex/stdin_approval_test.go new file mode 100644 index 00000000..88f3ac95 --- /dev/null +++ b/internal/codex/stdin_approval_test.go @@ -0,0 +1,100 @@ +package codex + +import ( + "encoding/json" + "strconv" + "strings" + "testing" + "time" +) + +func stdinApprovalFixture(t *testing.T, overrides map[string]any) (map[string]*daemonContextState, SessionContext) { + t.Helper() + p := map[string]any{"kind": "writeStdin", "approvalId": "input-callback", "command": "write_stdin --session-id 123 'echo done\n'", "cwd": "/terminal/start", "environmentId": "local", "availableDecisions": []string{"accept", "cancel"}} + for k, v := range overrides { + p[k] = v + } + return approvalFixture(t, p) +} + +func TestStdinApprovalDecodesNativeInputAndOnlyOneTimeChoices(t *testing.T) { + _, c := stdinApprovalFixture(t, nil) + if c.ApprovalToken == "" || c.ApprovalBlocked != "" || c.ActionDetails.Kind != "stdin" || c.ActionDetails.Target != "123" || c.ActionDetails.Input != "echo done\n" || c.CommandDetails.Command != "" { + t.Fatalf("bad stdin approval: %+v", c) + } + review := c.ActionReview() + if review == nil || review.Title != "TERMINAL INPUT APPROVAL" || review.Fields[1].Value != strconv.QuoteToASCII("echo done\n") { + t.Fatal("literal input not preserved in review", review) + } + if c.ApprovalOptions[0].Kind != "acceptStdin" || c.ApprovalOptions[0].Value != "accept" || c.ApprovalOptions[1].Kind != "cancelStdin" || c.ApprovalOptions[1].Value != "cancel" { + t.Fatal("stdin decision payload changed", c.ApprovalOptions) + } + for _, input := range []string{"", "yes\n", "\x03", "\t", "secret\u202evalue", "こんにちは", "line\r\n"} { + command := "write_stdin --session-id 123 '" + input + "'" + _, c := stdinApprovalFixture(t, map[string]any{"command": command}) + if c.ApprovalToken == "" || c.ActionDetails.Input != input || !approvalTextDisplayable(c.Text) { + t.Fatalf("escaped input lost: %q %+v", input, c) + } + } + _, c = stdinApprovalFixture(t, map[string]any{"availableDecisions": []string{"acceptForSession", "accept", "cancel"}}) + if c.ApprovalOptions[0].Kind != "acceptStdin" || c.ApprovalOptions[2].Kind != "" { + t.Fatal("reusable stdin grant offered") + } +} + +func TestStdinApprovalNeverInfersInputOrBroadensAuthority(t *testing.T) { + for name, fields := range map[string]map[string]any{ + "missing callback": {"approvalId": ""}, "missing turn": {"turnId": ""}, "missing item": {"itemId": ""}, "missing cwd": {"cwd": ""}, + "missing command": {"command": nil}, "command not input": {"command": "git push"}, + "extra argument": {"command": "write_stdin --session-id 123 'yes' extra"}, + "shell expansion": {"command": "write_stdin --session-id 123 \"$HOME\""}, + "invalid terminal": {"command": "write_stdin --session-id nope yes"}, + "hidden cwd": {"cwd": "/work\u202e"}, "hidden environment": {"environmentId": "env\x1b[31m"}, + "NUL": {"command": "write_stdin --session-id 123 'x\x00y'"}, + "additional permissions": {"additionalPermissions": map[string]any{"network": map[string]bool{"enabled": true}}}, + "network request": {"networkApprovalContext": map[string]string{"host": "example.com", "protocol": "https"}}, + "no decisions": {"availableDecisions": []string{}}, "omitted decisions": {"availableDecisions": nil}, + "only reusable": {"availableDecisions": []string{"acceptForSession"}}, + "large": {"command": "write_stdin --session-id 123 '" + strings.Repeat("x", approvalTextLimit) + "'"}, + } { + t.Run(name, func(t *testing.T) { + _, c := stdinApprovalFixture(t, fields) + if c.ApprovalToken != "" || c.ActionReview() != nil || c.ApprovalBlocked == "" || c.Text == "" { + t.Fatalf("invalid input actionable or invisible: %+v", c) + } + }) + } +} + +func TestStdinApprovalPOSIXPresentation(t *testing.T) { + for encoded, want := range map[string]string{ + "'don'\"'\"'t'": "don't", + "\"a\\\"b\\\\c\\$d\"": "a\"b\\c$d", + "hello\\ world": "hello world", + "'$(touch ignored); `literal`'": "$(touch ignored); `literal`", + } { + terminal, input, ok := terminalApprovalInput("write_stdin --session-id 123 " + encoded) + if !ok || terminal != "123" || input != want { + t.Fatalf("incorrect literal decoding %q: %q %v", encoded, input, ok) + } + } + for _, encoded := range []string{"", "'unclosed", "\"unclosed", "a b", "a;run", "$(run)", "`run`", "x\\", "a\\\ncontinued"} { + if _, ok := quotedApprovalArgument(encoded); ok { + t.Fatal("unsupported presentation accepted", encoded) + } + } +} + +func TestStdinApprovalSiblingRequestsRemainIndependent(t *testing.T) { + states, first := stdinApprovalFixture(t, nil) + raw, _ := json.Marshal(map[string]any{"threadId": "root", "turnId": "turn", "itemId": "cmd", "kind": "writeStdin", "approvalId": "other-callback", "command": "write_stdin --session-id 456 'different'", "cwd": "/terminal/start", "availableDecisions": []string{"accept", "cancel"}}) + daemonContextEvent(states, "item/commandExecution/requestApproval", json.RawMessage(`"other"`), raw, time.Now()) + other := states["root"].requests[`"other"`] + if other.ApprovalToken == "" || other.ApprovalToken == first.ApprovalToken { + t.Fatal("input requests share authority") + } + daemonContextEvent(states, "serverRequest/resolved", nil, json.RawMessage(`{"threadId":"root","requestId":"req"}`), time.Now()) + if len(states["root"].requests) != 1 || states["root"].requests[`"other"`].ActionDetails.Target != "456" { + t.Fatal("resolving one input removed another") + } +} diff --git a/internal/confirmation/policy.go b/internal/confirmation/policy.go index e339a525..2b3248f3 100644 --- a/internal/confirmation/policy.go +++ b/internal/confirmation/policy.go @@ -54,7 +54,7 @@ func Command(reversible bool) Action { func Approval(kind string) Action { switch kind { - case "accept", "decline", "cancel": + case "accept", "decline", "cancel", "cancelMcpTool", "acceptStdin", "cancelStdin": return Narrow default: return Guarded diff --git a/internal/confirmation/policy_test.go b/internal/confirmation/policy_test.go index da0e132e..ac572123 100644 --- a/internal/confirmation/policy_test.go +++ b/internal/confirmation/policy_test.go @@ -14,8 +14,8 @@ func TestPolicy(t *testing.T) { if Command(false) != Guarded || Command(true) != Narrow { t.Fatal("unknown commands must remain guarded") } - for _, kind := range []string{"accept", "decline", "cancel", "acceptForSession", "acceptWithExecpolicyAmendment", "unknown"} { - narrow := kind == "accept" || kind == "decline" || kind == "cancel" + for _, kind := range []string{"accept", "decline", "cancel", "acceptForSession", "acceptWithExecpolicyAmendment", "acceptMcpAlways", "cancelMcpTool", "allowNetworkHost", "denyNetworkHost", "acceptStdin", "cancelStdin", "unknown"} { + narrow := kind == "accept" || kind == "decline" || kind == "cancel" || kind == "cancelMcpTool" || kind == "acceptStdin" || kind == "cancelStdin" if (Approval(kind) == Narrow) != narrow { t.Fatal("incorrect approval scope", kind) } diff --git a/internal/i18n/locales/da.json b/internal/i18n/locales/da.json index e0a89acb..3548caee 100644 --- a/internal/i18n/locales/da.json +++ b/internal/i18n/locales/da.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETALJER", "APPROVAL REQUEST": "GODKENDELSESANMODNING", "WORKING": "ARBEJDER", - "[ H: HIDE DETAIL ]": "[ H: SKJUL DETALJER ]", - "[ H: SHOW DETAIL ]": "[ H: VIS DETALJER ]", + "[ C(Y)CLE ]": "[ SKIFT VISNING (Y) ]", "This approval action must be handled in Codex.": "Denne godkendelse skal håndteres i Codex.", "JUSTIFICATION": "BEGRUNDELSE", "COMMAND": "KOMMANDO", @@ -153,8 +152,6 @@ "LAST REPLY": "SENESTE SVAR", "QUESTION": "SPØRGSMÅL", "LAST ACTIVITY": "SENESTE AKTIVITET", - "[H:SHOW]": "[H:VIS]", - "[H:HIDE]": "[H:SKJUL]", "NO CONTEXT": "INGEN KONTEKST", "REPLY IN CODEX": "SVAR I CODEX", "SESSION CONTEXT": "SESSIONSKONTEKST", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F OPDATER ]", "[ ESC CANCEL ]": "[ ESC ANNULLER ]", "HUMAN APPROVAL REQUIRED": "MENNESKELIG GODKENDELSE PÅKRÆVET", - "Managed policy requires approval each time.": "Den administrerede politik kræver godkendelse hver gang." + "Managed policy requires approval each time.": "Den administrerede politik kræver godkendelse hver gang.", + "MCP TOOL APPROVAL": "GODKENDELSE AF MCP-VÆRKTØJ", + "MCP SERVER": "MCP-SERVER", + "TOOL": "VÆRKTØJ", + "TITLE": "TITEL", + "APP": "APP", + "ARGUMENTS": "ARGUMENTER", + "PERMISSION SCOPE": "TILLADELSENS OMFANG", + "[ CONFIRM TOOL RULE ]": "[ BEKRÆFT VÆRKTØJSREGEL ]", + "[ ALWAYS ALLOW TOOL ]": "[ TILLAD ALTID VÆRKTØJET ]", + "[ CANCEL TOOL CALL ]": "[ ANNULLER VÆRKTØJSKALD ]", + "Unsupported MCP request. Review it in Codex.": "MCP-anmodningen understøttes ikke. Gennemgå den i Codex.", + "NETWORK APPROVAL": "NETVÆRKSGODKENDELSE", + "HOST": "VÆRT", + "PROTOCOL": "PROTOKOL", + "[ CONFIRM HOST ALLOW ]": "[ BEKRÆFT TILLADT VÆRT ]", + "[ ALWAYS ALLOW HOST ]": "[ TILLAD ALTID VÆRT ]", + "[ CONFIRM HOST BLOCK ]": "[ BEKRÆFT BLOKERET VÆRT ]", + "[ ALWAYS BLOCK HOST ]": "[ BLOKER ALTID VÆRT ]", + "TERMINAL INPUT APPROVAL": "GODKEND TERMINALINPUT", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "INPUT (MED ESCAPES)", + "TERMINAL START DIRECTORY": "TERMINALENS STARTMAPPE", + "ENVIRONMENT": "MILJØ", + "[ SEND INPUT ONCE ]": "[ SEND INPUT ÉN GANG ]", + "[ CONFIRM INPUT ]": "[ BEKRÆFT INPUT ]", + "[ CANCEL INPUT ]": "[ ANNULLER INPUT ]" } diff --git a/internal/i18n/locales/de.json b/internal/i18n/locales/de.json index 7e5c37b3..41afcffb 100644 --- a/internal/i18n/locales/de.json +++ b/internal/i18n/locales/de.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETAILS", "APPROVAL REQUEST": "GENEHMIGUNGSANFRAGE", "WORKING": "ARBEITET", - "[ H: HIDE DETAIL ]": "[ H: DETAILS VERBERGEN ]", - "[ H: SHOW DETAIL ]": "[ H: DETAILS ZEIGEN ]", + "[ C(Y)CLE ]": "[ WECHSELN (Y) ]", "This approval action must be handled in Codex.": "Diese Genehmigungsaktion muss in Codex bearbeitet werden.", "JUSTIFICATION": "BEGRÜNDUNG", "COMMAND": "BEFEHL", @@ -153,8 +152,6 @@ "LAST REPLY": "LETZTE ANTWORT", "QUESTION": "FRAGE", "LAST ACTIVITY": "LETZTE AKTIVITÄT", - "[H:SHOW]": "[H:ZEIGEN]", - "[H:HIDE]": "[H:VERBERGEN]", "NO CONTEXT": "KEIN KONTEXT", "REPLY IN CODEX": "IN CODEX ANTWORTEN", "SESSION CONTEXT": "SITZUNGSKONTEXT", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F AKTUALISIEREN ]", "[ ESC CANCEL ]": "[ ESC ABBRECHEN ]", "HUMAN APPROVAL REQUIRED": "MENSCHLICHE GENEHMIGUNG ERFORDERLICH", - "Managed policy requires approval each time.": "Die verwaltete Richtlinie erfordert jedes Mal eine Genehmigung." + "Managed policy requires approval each time.": "Die verwaltete Richtlinie erfordert jedes Mal eine Genehmigung.", + "MCP TOOL APPROVAL": "MCP-WERKZEUGFREIGABE", + "MCP SERVER": "MCP-SERVER", + "TOOL": "WERKZEUG", + "TITLE": "TITEL", + "APP": "APP", + "ARGUMENTS": "ARGUMENTE", + "PERMISSION SCOPE": "BERECHTIGUNGSUMFANG", + "[ CONFIRM TOOL RULE ]": "[ WERKZEUGREGEL BESTÄTIGEN ]", + "[ ALWAYS ALLOW TOOL ]": "[ WERKZEUG IMMER ERLAUBEN ]", + "[ CANCEL TOOL CALL ]": "[ WERKZEUGAUFRUF ABBRECHEN ]", + "Unsupported MCP request. Review it in Codex.": "Nicht unterstützte MCP-Anfrage. In Codex prüfen.", + "NETWORK APPROVAL": "NETZWERKFREIGABE", + "HOST": "HOST", + "PROTOCOL": "PROTOKOLL", + "[ CONFIRM HOST ALLOW ]": "[ HOST-FREIGABE BESTÄTIGEN ]", + "[ ALWAYS ALLOW HOST ]": "[ HOST IMMER ERLAUBEN ]", + "[ CONFIRM HOST BLOCK ]": "[ HOST-SPERRE BESTÄTIGEN ]", + "[ ALWAYS BLOCK HOST ]": "[ HOST IMMER SPERREN ]", + "TERMINAL INPUT APPROVAL": "TERMINALEINGABE FREIGEBEN", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "EINGABE (MASKIERT)", + "TERMINAL START DIRECTORY": "STARTVERZEICHNIS DES TERMINALS", + "ENVIRONMENT": "UMGEBUNG", + "[ SEND INPUT ONCE ]": "[ EINGABE EINMAL SENDEN ]", + "[ CONFIRM INPUT ]": "[ EINGABE BESTÄTIGEN ]", + "[ CANCEL INPUT ]": "[ EINGABE ABBRECHEN ]" } diff --git a/internal/i18n/locales/en-GB.json b/internal/i18n/locales/en-GB.json index f2332db2..8988b321 100644 --- a/internal/i18n/locales/en-GB.json +++ b/internal/i18n/locales/en-GB.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETAIL", "APPROVAL REQUEST": "APPROVAL REQUEST", "WORKING": "WORKING", - "[ H: HIDE DETAIL ]": "[ H: HIDE DETAIL ]", - "[ H: SHOW DETAIL ]": "[ H: SHOW DETAIL ]", + "[ C(Y)CLE ]": "[ C(Y)CLE ]", "This approval action must be handled in Codex.": "This approval action must be handled in Codex.", "JUSTIFICATION": "JUSTIFICATION", "COMMAND": "COMMAND", @@ -153,8 +152,6 @@ "LAST REPLY": "LAST REPLY", "QUESTION": "QUESTION", "LAST ACTIVITY": "LAST ACTIVITY", - "[H:SHOW]": "[H:SHOW]", - "[H:HIDE]": "[H:HIDE]", "NO CONTEXT": "NO CONTEXT", "REPLY IN CODEX": "REPLY IN CODEX", "SESSION CONTEXT": "SESSION CONTEXT", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F REFRESH ]", "[ ESC CANCEL ]": "[ ESC CANCEL ]", "HUMAN APPROVAL REQUIRED": "HUMAN APPROVAL REQUIRED", - "Managed policy requires approval each time.": "Managed policy requires approval each time." + "Managed policy requires approval each time.": "Managed policy requires approval each time.", + "MCP TOOL APPROVAL": "MCP TOOL APPROVAL", + "MCP SERVER": "MCP SERVER", + "TOOL": "TOOL", + "TITLE": "TITLE", + "APP": "APP", + "ARGUMENTS": "ARGUMENTS", + "PERMISSION SCOPE": "PERMISSION SCOPE", + "[ CONFIRM TOOL RULE ]": "[ CONFIRM TOOL RULE ]", + "[ ALWAYS ALLOW TOOL ]": "[ ALWAYS ALLOW TOOL ]", + "[ CANCEL TOOL CALL ]": "[ CANCEL TOOL CALL ]", + "Unsupported MCP request. Review it in Codex.": "Unsupported MCP request. Review it in Codex.", + "NETWORK APPROVAL": "NETWORK APPROVAL", + "HOST": "HOST", + "PROTOCOL": "PROTOCOL", + "[ CONFIRM HOST ALLOW ]": "[ CONFIRM HOST ALLOW ]", + "[ ALWAYS ALLOW HOST ]": "[ ALWAYS ALLOW HOST ]", + "[ CONFIRM HOST BLOCK ]": "[ CONFIRM HOST BLOCK ]", + "[ ALWAYS BLOCK HOST ]": "[ ALWAYS BLOCK HOST ]", + "TERMINAL INPUT APPROVAL": "TERMINAL INPUT APPROVAL", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "INPUT (ESCAPED)", + "TERMINAL START DIRECTORY": "TERMINAL START DIRECTORY", + "ENVIRONMENT": "ENVIRONMENT", + "[ SEND INPUT ONCE ]": "[ SEND INPUT ONCE ]", + "[ CONFIRM INPUT ]": "[ CONFIRM INPUT ]", + "[ CANCEL INPUT ]": "[ CANCEL INPUT ]" } diff --git a/internal/i18n/locales/es.json b/internal/i18n/locales/es.json index 8f12d4b1..5c018f0c 100644 --- a/internal/i18n/locales/es.json +++ b/internal/i18n/locales/es.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETALLES", "APPROVAL REQUEST": "SOLICITUD DE APROBACIÓN", "WORKING": "TRABAJANDO", - "[ H: HIDE DETAIL ]": "[ H: OCULTAR DETALLES ]", - "[ H: SHOW DETAIL ]": "[ H: MOSTRAR DETALLES ]", + "[ C(Y)CLE ]": "[ ALTERNAR (Y) ]", "This approval action must be handled in Codex.": "Esta autorización debe gestionarse en Codex.", "JUSTIFICATION": "JUSTIFICACIÓN", "COMMAND": "COMANDO", @@ -153,8 +152,6 @@ "LAST REPLY": "ÚLTIMA RESPUESTA", "QUESTION": "PREGUNTA", "LAST ACTIVITY": "ÚLTIMA ACTIVIDAD", - "[H:SHOW]": "[H:VER]", - "[H:HIDE]": "[H:OCULTAR]", "NO CONTEXT": "SIN CONTEXTO", "REPLY IN CODEX": "RESPONDE EN CODEX", "SESSION CONTEXT": "CONTEXTO DE SESIÓN", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F ACTUALIZAR ]", "[ ESC CANCEL ]": "[ ESC CANCELAR ]", "HUMAN APPROVAL REQUIRED": "APROBACIÓN HUMANA OBLIGATORIA", - "Managed policy requires approval each time.": "La política administrada exige aprobación cada vez." + "Managed policy requires approval each time.": "La política administrada exige aprobación cada vez.", + "MCP TOOL APPROVAL": "APROBACIÓN DE HERRAMIENTA MCP", + "MCP SERVER": "SERVIDOR MCP", + "TOOL": "HERRAMIENTA", + "TITLE": "TÍTULO", + "APP": "APLICACIÓN", + "ARGUMENTS": "ARGUMENTOS", + "PERMISSION SCOPE": "ALCANCE DEL PERMISO", + "[ CONFIRM TOOL RULE ]": "[ CONFIRMAR REGLA DE HERRAMIENTA ]", + "[ ALWAYS ALLOW TOOL ]": "[ PERMITIR SIEMPRE HERRAMIENTA ]", + "[ CANCEL TOOL CALL ]": "[ CANCELAR LLAMADA A HERRAMIENTA ]", + "Unsupported MCP request. Review it in Codex.": "Solicitud MCP no compatible. Revísala en Codex.", + "NETWORK APPROVAL": "APROBACIÓN DE RED", + "HOST": "HOST", + "PROTOCOL": "PROTOCOLO", + "[ CONFIRM HOST ALLOW ]": "[ CONFIRMAR PERMISO DEL HOST ]", + "[ ALWAYS ALLOW HOST ]": "[ PERMITIR HOST SIEMPRE ]", + "[ CONFIRM HOST BLOCK ]": "[ CONFIRMAR BLOQUEO DEL HOST ]", + "[ ALWAYS BLOCK HOST ]": "[ BLOQUEAR HOST SIEMPRE ]", + "TERMINAL INPUT APPROVAL": "APROBACIÓN DE ENTRADA AL TERMINAL", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "ENTRADA (ESCAPADA)", + "TERMINAL START DIRECTORY": "DIRECTORIO INICIAL DEL TERMINAL", + "ENVIRONMENT": "ENTORNO", + "[ SEND INPUT ONCE ]": "[ ENVIAR ENTRADA UNA VEZ ]", + "[ CONFIRM INPUT ]": "[ CONFIRMAR ENTRADA ]", + "[ CANCEL INPUT ]": "[ CANCELAR ENTRADA ]" } diff --git a/internal/i18n/locales/et.json b/internal/i18n/locales/et.json index a202b812..a1029b75 100644 --- a/internal/i18n/locales/et.json +++ b/internal/i18n/locales/et.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ ÜKSIKASJAD", "APPROVAL REQUEST": "KINNITUSE TAOTLUS", "WORKING": "TÖÖTAB", - "[ H: HIDE DETAIL ]": "[ H: PEIDA ÜKSIKASJAD ]", - "[ H: SHOW DETAIL ]": "[ H: NÄITA ÜKSIKASJU ]", + "[ C(Y)CLE ]": "[ VAHETA VAADET (Y) ]", "This approval action must be handled in Codex.": "See kinnitustoiming tuleb teha Codexis.", "JUSTIFICATION": "PÕHJENDUS", "COMMAND": "KÄSK", @@ -153,8 +152,6 @@ "LAST REPLY": "VIIMANE VASTUS", "QUESTION": "KÜSIMUS", "LAST ACTIVITY": "VIIMANE TEGEVUS", - "[H:SHOW]": "[H:NÄITA]", - "[H:HIDE]": "[H:PEIDA]", "NO CONTEXT": "KONTEKST PUUDUB", "REPLY IN CODEX": "VASTA CODEXIS", "SESSION CONTEXT": "SEANSI KONTEKST", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F VÄRSKENDA ]", "[ ESC CANCEL ]": "[ ESC TÜHISTA ]", "HUMAN APPROVAL REQUIRED": "VAJALIK ON INIMESE HEAKSKIIT", - "Managed policy requires approval each time.": "Hallatud poliitika nõuab iga kord heakskiitu." + "Managed policy requires approval each time.": "Hallatud poliitika nõuab iga kord heakskiitu.", + "MCP TOOL APPROVAL": "MCP-TÖÖRIISTA KINNITUS", + "MCP SERVER": "MCP-SERVER", + "TOOL": "TÖÖRIIST", + "TITLE": "PEALKIRI", + "APP": "RAKENDUS", + "ARGUMENTS": "ARGUMENDID", + "PERMISSION SCOPE": "LOA ULATUS", + "[ CONFIRM TOOL RULE ]": "[ KINNITA TÖÖRIISTA REEGEL ]", + "[ ALWAYS ALLOW TOOL ]": "[ LUBA TÖÖRIIST ALATI ]", + "[ CANCEL TOOL CALL ]": "[ TÜHISTA TÖÖRIISTA KUTSE ]", + "Unsupported MCP request. Review it in Codex.": "MCP-päringut ei toetata. Vaata seda Codexis.", + "NETWORK APPROVAL": "VÕRGU KINNITUS", + "HOST": "HOST", + "PROTOCOL": "PROTOKOLL", + "[ CONFIRM HOST ALLOW ]": "[ KINNITA HOSTI LUBAMINE ]", + "[ ALWAYS ALLOW HOST ]": "[ LUBA HOST ALATI ]", + "[ CONFIRM HOST BLOCK ]": "[ KINNITA HOSTI BLOKEERIMINE ]", + "[ ALWAYS BLOCK HOST ]": "[ BLOKEERI HOST ALATI ]", + "TERMINAL INPUT APPROVAL": "TERMINALI SISENDI KINNITUS", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "SISEND (PAOMÄRKIDEGA)", + "TERMINAL START DIRECTORY": "TERMINALI ALGKAUST", + "ENVIRONMENT": "KESKKOND", + "[ SEND INPUT ONCE ]": "[ SAADA SISEND ÜKS KORD ]", + "[ CONFIRM INPUT ]": "[ KINNITA SISEND ]", + "[ CANCEL INPUT ]": "[ TÜHISTA SISEND ]" } diff --git a/internal/i18n/locales/fi.json b/internal/i18n/locales/fi.json index eb50b375..79d7ea26 100644 --- a/internal/i18n/locales/fi.json +++ b/internal/i18n/locales/fi.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ TIEDOT", "APPROVAL REQUEST": "HYVÄKSYNTÄPYYNTÖ", "WORKING": "TYÖSKENTELEE", - "[ H: HIDE DETAIL ]": "[ H: PIILOTA TIEDOT ]", - "[ H: SHOW DETAIL ]": "[ H: NÄYTÄ TIEDOT ]", + "[ C(Y)CLE ]": "[ VAIHDA NÄKYMÄÄ (Y) ]", "This approval action must be handled in Codex.": "Tämä hyväksyntä on käsiteltävä Codexissa.", "JUSTIFICATION": "PERUSTELU", "COMMAND": "KOMENTO", @@ -153,8 +152,6 @@ "LAST REPLY": "VIIMEISIN VASTAUS", "QUESTION": "KYSYMYS", "LAST ACTIVITY": "VIIMEISIN TOIMINTA", - "[H:SHOW]": "[H:NÄYTÄ]", - "[H:HIDE]": "[H:PIILOTA]", "NO CONTEXT": "EI KONTEKSTIA", "REPLY IN CODEX": "VASTAA CODEXISSA", "SESSION CONTEXT": "ISTUNNON KONTEKSTI", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F PÄIVITÄ ]", "[ ESC CANCEL ]": "[ ESC PERUUTA ]", "HUMAN APPROVAL REQUIRED": "IHMISEN HYVÄKSYNTÄ VAADITAAN", - "Managed policy requires approval each time.": "Hallittu käytäntö edellyttää hyväksyntää joka kerta." + "Managed policy requires approval each time.": "Hallittu käytäntö edellyttää hyväksyntää joka kerta.", + "MCP TOOL APPROVAL": "MCP-TYÖKALUN HYVÄKSYNTÄ", + "MCP SERVER": "MCP-PALVELIN", + "TOOL": "TYÖKALU", + "TITLE": "OTSIKKO", + "APP": "SOVELLUS", + "ARGUMENTS": "ARGUMENTIT", + "PERMISSION SCOPE": "LUVAN LAAJUUS", + "[ CONFIRM TOOL RULE ]": "[ VAHVISTA TYÖKALUSÄÄNTÖ ]", + "[ ALWAYS ALLOW TOOL ]": "[ SALLI TYÖKALU AINA ]", + "[ CANCEL TOOL CALL ]": "[ PERU TYÖKALUKUTSU ]", + "Unsupported MCP request. Review it in Codex.": "MCP-pyyntöä ei tueta. Tarkista se Codexissa.", + "NETWORK APPROVAL": "VERKKOHYVÄKSYNTÄ", + "HOST": "PALVELIN", + "PROTOCOL": "PROTOKOLLA", + "[ CONFIRM HOST ALLOW ]": "[ VAHVISTA PALVELIMEN SALLINTA ]", + "[ ALWAYS ALLOW HOST ]": "[ SALLI PALVELIN AINA ]", + "[ CONFIRM HOST BLOCK ]": "[ VAHVISTA PALVELIMEN ESTO ]", + "[ ALWAYS BLOCK HOST ]": "[ ESTÄ PALVELIN AINA ]", + "TERMINAL INPUT APPROVAL": "PÄÄTESYÖTTEEN HYVÄKSYNTÄ", + "TERMINAL": "PÄÄTE", + "INPUT (ESCAPED)": "SYÖTE (PAKOMERKIT)", + "TERMINAL START DIRECTORY": "PÄÄTTEEN ALOITUSHAKEMISTO", + "ENVIRONMENT": "YMPÄRISTÖ", + "[ SEND INPUT ONCE ]": "[ LÄHETÄ SYÖTE KERRAN ]", + "[ CONFIRM INPUT ]": "[ VAHVISTA SYÖTE ]", + "[ CANCEL INPUT ]": "[ PERU SYÖTE ]" } diff --git a/internal/i18n/locales/fr.json b/internal/i18n/locales/fr.json index 82fab6cf..c0b605f0 100644 --- a/internal/i18n/locales/fr.json +++ b/internal/i18n/locales/fr.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DÉTAILS", "APPROVAL REQUEST": "DEMANDE D’APPROBATION", "WORKING": "EN COURS", - "[ H: HIDE DETAIL ]": "[ H: MASQUER LES DÉTAILS ]", - "[ H: SHOW DETAIL ]": "[ H: AFFICHER LES DÉTAILS ]", + "[ C(Y)CLE ]": "[ DÉFILER (Y) ]", "This approval action must be handled in Codex.": "Cette autorisation doit être traitée dans Codex.", "JUSTIFICATION": "JUSTIFICATION", "COMMAND": "COMMANDE", @@ -153,8 +152,6 @@ "LAST REPLY": "DERNIÈRE RÉPONSE", "QUESTION": "QUESTION", "LAST ACTIVITY": "DERNIÈRE ACTIVITÉ", - "[H:SHOW]": "[H:VOIR]", - "[H:HIDE]": "[H:MASQUER]", "NO CONTEXT": "AUCUN CONTEXTE", "REPLY IN CODEX": "RÉPONDRE DANS CODEX", "SESSION CONTEXT": "CONTEXTE DE SESSION", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F ACTUALISER ]", "[ ESC CANCEL ]": "[ ESC ANNULER ]", "HUMAN APPROVAL REQUIRED": "APPROBATION HUMAINE REQUISE", - "Managed policy requires approval each time.": "La politique gérée exige une approbation à chaque fois." + "Managed policy requires approval each time.": "La politique gérée exige une approbation à chaque fois.", + "MCP TOOL APPROVAL": "APPROBATION D’OUTIL MCP", + "MCP SERVER": "SERVEUR MCP", + "TOOL": "OUTIL", + "TITLE": "TITRE", + "APP": "APPLICATION", + "ARGUMENTS": "ARGUMENTS", + "PERMISSION SCOPE": "PORTÉE DE L’AUTORISATION", + "[ CONFIRM TOOL RULE ]": "[ CONFIRMER LA RÈGLE D’OUTIL ]", + "[ ALWAYS ALLOW TOOL ]": "[ TOUJOURS AUTORISER L’OUTIL ]", + "[ CANCEL TOOL CALL ]": "[ ANNULER L’APPEL D’OUTIL ]", + "Unsupported MCP request. Review it in Codex.": "Requête MCP non prise en charge. Consultez-la dans Codex.", + "NETWORK APPROVAL": "AUTORISATION RÉSEAU", + "HOST": "HÔTE", + "PROTOCOL": "PROTOCOLE", + "[ CONFIRM HOST ALLOW ]": "[ CONFIRMER AUTORISATION HÔTE ]", + "[ ALWAYS ALLOW HOST ]": "[ TOUJOURS AUTORISER HÔTE ]", + "[ CONFIRM HOST BLOCK ]": "[ CONFIRMER BLOCAGE HÔTE ]", + "[ ALWAYS BLOCK HOST ]": "[ TOUJOURS BLOQUER HÔTE ]", + "TERMINAL INPUT APPROVAL": "AUTORISATION DE SAISIE TERMINAL", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "SAISIE (ÉCHAPPÉE)", + "TERMINAL START DIRECTORY": "DOSSIER DE DÉMARRAGE DU TERMINAL", + "ENVIRONMENT": "ENVIRONNEMENT", + "[ SEND INPUT ONCE ]": "[ ENVOYER LA SAISIE UNE FOIS ]", + "[ CONFIRM INPUT ]": "[ CONFIRMER LA SAISIE ]", + "[ CANCEL INPUT ]": "[ ANNULER LA SAISIE ]" } diff --git a/internal/i18n/locales/it.json b/internal/i18n/locales/it.json index a387ca51..2f3119d8 100644 --- a/internal/i18n/locales/it.json +++ b/internal/i18n/locales/it.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETTAGLI", "APPROVAL REQUEST": "RICHIESTA DI APPROVAZIONE", "WORKING": "IN ELABORAZIONE", - "[ H: HIDE DETAIL ]": "[ H: NASCONDI DETTAGLI ]", - "[ H: SHOW DETAIL ]": "[ H: MOSTRA DETTAGLI ]", + "[ C(Y)CLE ]": "[ CICLA (Y) ]", "This approval action must be handled in Codex.": "Questa autorizzazione deve essere gestita in Codex.", "JUSTIFICATION": "MOTIVAZIONE", "COMMAND": "COMANDO", @@ -153,8 +152,6 @@ "LAST REPLY": "ULTIMA RISPOSTA", "QUESTION": "DOMANDA", "LAST ACTIVITY": "ULTIMA ATTIVITÀ", - "[H:SHOW]": "[H:MOSTRA]", - "[H:HIDE]": "[H:NASCONDI]", "NO CONTEXT": "NESSUN CONTESTO", "REPLY IN CODEX": "RISPONDI IN CODEX", "SESSION CONTEXT": "CONTESTO SESSIONE", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F AGGIORNA ]", "[ ESC CANCEL ]": "[ ESC ANNULLA ]", "HUMAN APPROVAL REQUIRED": "APPROVAZIONE UMANA RICHIESTA", - "Managed policy requires approval each time.": "La policy gestita richiede ogni volta una nuova approvazione." + "Managed policy requires approval each time.": "La policy gestita richiede ogni volta una nuova approvazione.", + "MCP TOOL APPROVAL": "APPROVAZIONE STRUMENTO MCP", + "MCP SERVER": "SERVER MCP", + "TOOL": "STRUMENTO", + "TITLE": "TITOLO", + "APP": "APP", + "ARGUMENTS": "ARGOMENTI", + "PERMISSION SCOPE": "AMBITO DEL PERMESSO", + "[ CONFIRM TOOL RULE ]": "[ CONFERMA REGOLA STRUMENTO ]", + "[ ALWAYS ALLOW TOOL ]": "[ CONSENTI SEMPRE STRUMENTO ]", + "[ CANCEL TOOL CALL ]": "[ ANNULLA CHIAMATA STRUMENTO ]", + "Unsupported MCP request. Review it in Codex.": "Richiesta MCP non supportata. Esaminala in Codex.", + "NETWORK APPROVAL": "APPROVAZIONE RETE", + "HOST": "HOST", + "PROTOCOL": "PROTOCOLLO", + "[ CONFIRM HOST ALLOW ]": "[ CONFERMA PERMESSO HOST ]", + "[ ALWAYS ALLOW HOST ]": "[ CONSENTI SEMPRE HOST ]", + "[ CONFIRM HOST BLOCK ]": "[ CONFERMA BLOCCO HOST ]", + "[ ALWAYS BLOCK HOST ]": "[ BLOCCA SEMPRE HOST ]", + "TERMINAL INPUT APPROVAL": "APPROVAZIONE INPUT TERMINALE", + "TERMINAL": "TERMINALE", + "INPUT (ESCAPED)": "INPUT (CON ESCAPE)", + "TERMINAL START DIRECTORY": "CARTELLA INIZIALE DEL TERMINALE", + "ENVIRONMENT": "AMBIENTE", + "[ SEND INPUT ONCE ]": "[ INVIA INPUT UNA VOLTA ]", + "[ CONFIRM INPUT ]": "[ CONFERMA INPUT ]", + "[ CANCEL INPUT ]": "[ ANNULLA INPUT ]" } diff --git a/internal/i18n/locales/ja.json b/internal/i18n/locales/ja.json index a148ab8e..36fa837a 100644 --- a/internal/i18n/locales/ja.json +++ b/internal/i18n/locales/ja.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ 詳細", "APPROVAL REQUEST": "承認リクエスト", "WORKING": "処理中", - "[ H: HIDE DETAIL ]": "[ H: 詳細を非表示 ]", - "[ H: SHOW DETAIL ]": "[ H: 詳細を表示 ]", + "[ C(Y)CLE ]": "[ 表示切替 (Y) ]", "This approval action must be handled in Codex.": "この承認操作は Codex で行ってください。", "JUSTIFICATION": "理由", "COMMAND": "コマンド", @@ -153,8 +152,6 @@ "LAST REPLY": "直近の返信", "QUESTION": "質問", "LAST ACTIVITY": "直近の動作", - "[H:SHOW]": "[H:表示]", - "[H:HIDE]": "[H:非表示]", "NO CONTEXT": "情報なし", "REPLY IN CODEX": "CODEX で回答してください", "SESSION CONTEXT": "セッション情報", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F 更新 ]", "[ ESC CANCEL ]": "[ ESC キャンセル ]", "HUMAN APPROVAL REQUIRED": "人による承認が必要", - "Managed policy requires approval each time.": "管理ポリシーにより、毎回承認が必要です。" + "Managed policy requires approval each time.": "管理ポリシーにより、毎回承認が必要です。", + "MCP TOOL APPROVAL": "MCPツール承認", + "MCP SERVER": "MCPサーバー", + "TOOL": "ツール", + "TITLE": "タイトル", + "APP": "アプリ", + "ARGUMENTS": "引数", + "PERMISSION SCOPE": "許可の範囲", + "[ CONFIRM TOOL RULE ]": "[ ツールルールを確認 ]", + "[ ALWAYS ALLOW TOOL ]": "[ ツールを常に許可 ]", + "[ CANCEL TOOL CALL ]": "[ ツール呼び出しをキャンセル ]", + "Unsupported MCP request. Review it in Codex.": "未対応のMCPリクエストです。Codexで確認してください。", + "NETWORK APPROVAL": "ネットワーク承認", + "HOST": "ホスト", + "PROTOCOL": "プロトコル", + "[ CONFIRM HOST ALLOW ]": "[ ホストの許可を確認 ]", + "[ ALWAYS ALLOW HOST ]": "[ ホストを常に許可 ]", + "[ CONFIRM HOST BLOCK ]": "[ ホストの拒否を確認 ]", + "[ ALWAYS BLOCK HOST ]": "[ ホストを常に拒否 ]", + "TERMINAL INPUT APPROVAL": "ターミナル入力の承認", + "TERMINAL": "ターミナル", + "INPUT (ESCAPED)": "入力(エスケープ表示)", + "TERMINAL START DIRECTORY": "ターミナルの開始ディレクトリ", + "ENVIRONMENT": "環境", + "[ SEND INPUT ONCE ]": "[ 入力を一度送信 ]", + "[ CONFIRM INPUT ]": "[ 入力を確認 ]", + "[ CANCEL INPUT ]": "[ 入力をキャンセル ]" } diff --git a/internal/i18n/locales/nb.json b/internal/i18n/locales/nb.json index 31a36791..071fec63 100644 --- a/internal/i18n/locales/nb.json +++ b/internal/i18n/locales/nb.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETALJER", "APPROVAL REQUEST": "GODKJENNINGSFORESPØRSEL", "WORKING": "ARBEIDER", - "[ H: HIDE DETAIL ]": "[ H: SKJUL DETALJER ]", - "[ H: SHOW DETAIL ]": "[ H: VIS DETALJER ]", + "[ C(Y)CLE ]": "[ BYTT VISNING (Y) ]", "This approval action must be handled in Codex.": "Denne handlingen må godkjennes i Codex.", "JUSTIFICATION": "BEGRUNNELSE", "COMMAND": "KOMMANDO", @@ -153,8 +152,6 @@ "LAST REPLY": "SISTE SVAR", "QUESTION": "SPØRSMÅL", "LAST ACTIVITY": "SISTE AKTIVITET", - "[H:SHOW]": "[H:VIS]", - "[H:HIDE]": "[H:SKJUL]", "NO CONTEXT": "INGEN KONTEKST", "REPLY IN CODEX": "SVAR I CODEX", "SESSION CONTEXT": "ØKTKONTEKST", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F OPPDATER ]", "[ ESC CANCEL ]": "[ ESC AVBRYT ]", "HUMAN APPROVAL REQUIRED": "MENNESKELIG GODKJENNING KREVES", - "Managed policy requires approval each time.": "Den administrerte policyen krever godkjenning hver gang." + "Managed policy requires approval each time.": "Den administrerte policyen krever godkjenning hver gang.", + "MCP TOOL APPROVAL": "GODKJENNING AV MCP-VERKTØY", + "MCP SERVER": "MCP-SERVER", + "TOOL": "VERKTØY", + "TITLE": "TITTEL", + "APP": "APP", + "ARGUMENTS": "ARGUMENTER", + "PERMISSION SCOPE": "TILLATELSENS OMFANG", + "[ CONFIRM TOOL RULE ]": "[ BEKREFT VERKTØYREGEL ]", + "[ ALWAYS ALLOW TOOL ]": "[ TILLAT ALLTID VERKTØYET ]", + "[ CANCEL TOOL CALL ]": "[ AVBRYT VERKTØYKALL ]", + "Unsupported MCP request. Review it in Codex.": "MCP-forespørselen støttes ikke. Se den i Codex.", + "NETWORK APPROVAL": "NETTVERKSGODKJENNING", + "HOST": "VERT", + "PROTOCOL": "PROTOKOLL", + "[ CONFIRM HOST ALLOW ]": "[ BEKREFT TILLATT VERT ]", + "[ ALWAYS ALLOW HOST ]": "[ TILLAT ALLTID VERT ]", + "[ CONFIRM HOST BLOCK ]": "[ BEKREFT BLOKKERT VERT ]", + "[ ALWAYS BLOCK HOST ]": "[ BLOKKER ALLTID VERT ]", + "TERMINAL INPUT APPROVAL": "GODKJENN TERMINALINNDATA", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "INNDATA (MED ESCAPES)", + "TERMINAL START DIRECTORY": "TERMINALENS STARTMAPPE", + "ENVIRONMENT": "MILJØ", + "[ SEND INPUT ONCE ]": "[ SEND INNDATA ÉN GANG ]", + "[ CONFIRM INPUT ]": "[ BEKREFT INNDATA ]", + "[ CANCEL INPUT ]": "[ AVBRYT INNDATA ]" } diff --git a/internal/i18n/locales/nl.json b/internal/i18n/locales/nl.json index d460b590..d7cabb37 100644 --- a/internal/i18n/locales/nl.json +++ b/internal/i18n/locales/nl.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETAIL", "APPROVAL REQUEST": "GOEDKEURINGSVERZOEK", "WORKING": "BEZIG", - "[ H: HIDE DETAIL ]": "[ H: DETAILS VERBERGEN ]", - "[ H: SHOW DETAIL ]": "[ H: DETAILS TONEN ]", + "[ C(Y)CLE ]": "[ WISSEL (Y) ]", "This approval action must be handled in Codex.": "Deze goedkeuringsactie moet in Codex worden afgehandeld.", "JUSTIFICATION": "TOELICHTING", "COMMAND": "OPDRACHT", @@ -153,8 +152,6 @@ "LAST REPLY": "LAATSTE ANTWOORD", "QUESTION": "VRAAG", "LAST ACTIVITY": "LAATSTE ACTIVITEIT", - "[H:SHOW]": "[H:TOON]", - "[H:HIDE]": "[H:VERBERG]", "NO CONTEXT": "GEEN CONTEXT", "REPLY IN CODEX": "ANTWOORD IN CODEX", "SESSION CONTEXT": "SESSIECONTEXT", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F VERNIEUWEN ]", "[ ESC CANCEL ]": "[ ESC ANNULEREN ]", "HUMAN APPROVAL REQUIRED": "MENSELIJKE GOEDKEURING VEREIST", - "Managed policy requires approval each time.": "Beheerd beleid vereist elke keer goedkeuring." + "Managed policy requires approval each time.": "Beheerd beleid vereist elke keer goedkeuring.", + "MCP TOOL APPROVAL": "MCP-TOOLGOEDKEURING", + "MCP SERVER": "MCP-SERVER", + "TOOL": "TOOL", + "TITLE": "TITEL", + "APP": "APP", + "ARGUMENTS": "ARGUMENTEN", + "PERMISSION SCOPE": "TOESTEMMINGSBEREIK", + "[ CONFIRM TOOL RULE ]": "[ TOOLREGEL BEVESTIGEN ]", + "[ ALWAYS ALLOW TOOL ]": "[ TOOL ALTIJD TOESTAAN ]", + "[ CANCEL TOOL CALL ]": "[ TOOLAANROEP ANNULEREN ]", + "Unsupported MCP request. Review it in Codex.": "Niet-ondersteund MCP-verzoek. Bekijk het in Codex.", + "NETWORK APPROVAL": "NETWERKGOEDKEURING", + "HOST": "HOST", + "PROTOCOL": "PROTOCOL", + "[ CONFIRM HOST ALLOW ]": "[ HOST TOESTAAN BEVESTIGEN ]", + "[ ALWAYS ALLOW HOST ]": "[ HOST ALTIJD TOESTAAN ]", + "[ CONFIRM HOST BLOCK ]": "[ HOST BLOKKEREN BEVESTIGEN ]", + "[ ALWAYS BLOCK HOST ]": "[ HOST ALTIJD BLOKKEREN ]", + "TERMINAL INPUT APPROVAL": "TERMINALINVOER GOEDKEUREN", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "INVOER (GEËSCAPED)", + "TERMINAL START DIRECTORY": "STARTMAP VAN TERMINAL", + "ENVIRONMENT": "OMGEVING", + "[ SEND INPUT ONCE ]": "[ INVOER EENMALIG VERSTUREN ]", + "[ CONFIRM INPUT ]": "[ INVOER BEVESTIGEN ]", + "[ CANCEL INPUT ]": "[ INVOER ANNULEREN ]" } diff --git a/internal/i18n/locales/pt-BR.json b/internal/i18n/locales/pt-BR.json index 998d967b..88d87dad 100644 --- a/internal/i18n/locales/pt-BR.json +++ b/internal/i18n/locales/pt-BR.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETALHES", "APPROVAL REQUEST": "SOLICITAÇÃO DE APROVAÇÃO", "WORKING": "TRABALHANDO", - "[ H: HIDE DETAIL ]": "[ H: OCULTAR DETALHES ]", - "[ H: SHOW DETAIL ]": "[ H: MOSTRAR DETALHES ]", + "[ C(Y)CLE ]": "[ ALTERNAR (Y) ]", "This approval action must be handled in Codex.": "Esta aprovação deve ser tratada no Codex.", "JUSTIFICATION": "JUSTIFICATIVA", "COMMAND": "COMANDO", @@ -153,8 +152,6 @@ "LAST REPLY": "ÚLTIMA RESPOSTA", "QUESTION": "PERGUNTA", "LAST ACTIVITY": "ÚLTIMA ATIVIDADE", - "[H:SHOW]": "[H:MOSTRAR]", - "[H:HIDE]": "[H:OCULTAR]", "NO CONTEXT": "SEM CONTEXTO", "REPLY IN CODEX": "RESPONDA NO CODEX", "SESSION CONTEXT": "CONTEXTO DA SESSÃO", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F ATUALIZAR ]", "[ ESC CANCEL ]": "[ ESC CANCELAR ]", "HUMAN APPROVAL REQUIRED": "APROVAÇÃO HUMANA NECESSÁRIA", - "Managed policy requires approval each time.": "A política gerenciada exige aprovação a cada vez." + "Managed policy requires approval each time.": "A política gerenciada exige aprovação a cada vez.", + "MCP TOOL APPROVAL": "APROVAÇÃO DE FERRAMENTA MCP", + "MCP SERVER": "SERVIDOR MCP", + "TOOL": "FERRAMENTA", + "TITLE": "TÍTULO", + "APP": "APLICATIVO", + "ARGUMENTS": "ARGUMENTOS", + "PERMISSION SCOPE": "ESCOPO DA PERMISSÃO", + "[ CONFIRM TOOL RULE ]": "[ CONFIRMAR REGRA DA FERRAMENTA ]", + "[ ALWAYS ALLOW TOOL ]": "[ SEMPRE PERMITIR FERRAMENTA ]", + "[ CANCEL TOOL CALL ]": "[ CANCELAR CHAMADA DA FERRAMENTA ]", + "Unsupported MCP request. Review it in Codex.": "Solicitação MCP não compatível. Confira no Codex.", + "NETWORK APPROVAL": "APROVAÇÃO DE REDE", + "HOST": "HOST", + "PROTOCOL": "PROTOCOLO", + "[ CONFIRM HOST ALLOW ]": "[ CONFIRMAR PERMISSÃO DO HOST ]", + "[ ALWAYS ALLOW HOST ]": "[ SEMPRE PERMITIR HOST ]", + "[ CONFIRM HOST BLOCK ]": "[ CONFIRMAR BLOQUEIO DO HOST ]", + "[ ALWAYS BLOCK HOST ]": "[ SEMPRE BLOQUEAR HOST ]", + "TERMINAL INPUT APPROVAL": "APROVAÇÃO DE ENTRADA NO TERMINAL", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "ENTRADA (COM ESCAPES)", + "TERMINAL START DIRECTORY": "DIRETÓRIO INICIAL DO TERMINAL", + "ENVIRONMENT": "AMBIENTE", + "[ SEND INPUT ONCE ]": "[ ENVIAR ENTRADA UMA VEZ ]", + "[ CONFIRM INPUT ]": "[ CONFIRMAR ENTRADA ]", + "[ CANCEL INPUT ]": "[ CANCELAR ENTRADA ]" } diff --git a/internal/i18n/locales/pt-PT.json b/internal/i18n/locales/pt-PT.json index 7133d97d..532805e9 100644 --- a/internal/i18n/locales/pt-PT.json +++ b/internal/i18n/locales/pt-PT.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETALHES", "APPROVAL REQUEST": "PEDIDO DE APROVAÇÃO", "WORKING": "A TRABALHAR", - "[ H: HIDE DETAIL ]": "[ H: OCULTAR DETALHES ]", - "[ H: SHOW DETAIL ]": "[ H: MOSTRAR DETALHES ]", + "[ C(Y)CLE ]": "[ ALTERNAR (Y) ]", "This approval action must be handled in Codex.": "Esta aprovação deve ser tratada no Codex.", "JUSTIFICATION": "JUSTIFICAÇÃO", "COMMAND": "COMANDO", @@ -153,8 +152,6 @@ "LAST REPLY": "ÚLTIMA RESPOSTA", "QUESTION": "PERGUNTA", "LAST ACTIVITY": "ÚLTIMA ATIVIDADE", - "[H:SHOW]": "[H:MOSTRAR]", - "[H:HIDE]": "[H:OCULTAR]", "NO CONTEXT": "SEM CONTEXTO", "REPLY IN CODEX": "RESPONDA NO CODEX", "SESSION CONTEXT": "CONTEXTO DA SESSÃO", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F ATUALIZAR ]", "[ ESC CANCEL ]": "[ ESC CANCELAR ]", "HUMAN APPROVAL REQUIRED": "APROVAÇÃO HUMANA NECESSÁRIA", - "Managed policy requires approval each time.": "A política gerida exige aprovação de cada vez." + "Managed policy requires approval each time.": "A política gerida exige aprovação de cada vez.", + "MCP TOOL APPROVAL": "APROVAÇÃO DE FERRAMENTA MCP", + "MCP SERVER": "SERVIDOR MCP", + "TOOL": "FERRAMENTA", + "TITLE": "TÍTULO", + "APP": "APLICAÇÃO", + "ARGUMENTS": "ARGUMENTOS", + "PERMISSION SCOPE": "ÂMBITO DA PERMISSÃO", + "[ CONFIRM TOOL RULE ]": "[ CONFIRMAR REGRA DA FERRAMENTA ]", + "[ ALWAYS ALLOW TOOL ]": "[ PERMITIR SEMPRE FERRAMENTA ]", + "[ CANCEL TOOL CALL ]": "[ CANCELAR CHAMADA DA FERRAMENTA ]", + "Unsupported MCP request. Review it in Codex.": "Pedido MCP não suportado. Reveja-o no Codex.", + "NETWORK APPROVAL": "APROVAÇÃO DE REDE", + "HOST": "HOST", + "PROTOCOL": "PROTOCOLO", + "[ CONFIRM HOST ALLOW ]": "[ CONFIRMAR PERMISSÃO DO HOST ]", + "[ ALWAYS ALLOW HOST ]": "[ PERMITIR SEMPRE HOST ]", + "[ CONFIRM HOST BLOCK ]": "[ CONFIRMAR BLOQUEIO DO HOST ]", + "[ ALWAYS BLOCK HOST ]": "[ BLOQUEAR SEMPRE HOST ]", + "TERMINAL INPUT APPROVAL": "APROVAÇÃO DE ENTRADA NO TERMINAL", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "ENTRADA (COM ESCAPES)", + "TERMINAL START DIRECTORY": "DIRETÓRIO INICIAL DO TERMINAL", + "ENVIRONMENT": "AMBIENTE", + "[ SEND INPUT ONCE ]": "[ ENVIAR ENTRADA UMA VEZ ]", + "[ CONFIRM INPUT ]": "[ CONFIRMAR ENTRADA ]", + "[ CANCEL INPUT ]": "[ CANCELAR ENTRADA ]" } diff --git a/internal/i18n/locales/ru.json b/internal/i18n/locales/ru.json index 40010321..9f441077 100644 --- a/internal/i18n/locales/ru.json +++ b/internal/i18n/locales/ru.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ ПОДРОБНОСТИ", "APPROVAL REQUEST": "ЗАПРОС ОДОБРЕНИЯ", "WORKING": "РАБОТАЕТ", - "[ H: HIDE DETAIL ]": "[ H: СКРЫТЬ ПОДРОБНОСТИ ]", - "[ H: SHOW DETAIL ]": "[ H: ПОКАЗАТЬ ПОДРОБНОСТИ ]", + "[ C(Y)CLE ]": "[ СМЕНИТЬ ВИД (Y) ]", "This approval action must be handled in Codex.": "Это разрешение нужно обработать в Codex.", "JUSTIFICATION": "ОБОСНОВАНИЕ", "COMMAND": "КОМАНДА", @@ -153,8 +152,6 @@ "LAST REPLY": "ПОСЛЕДНИЙ ОТВЕТ", "QUESTION": "ВОПРОС", "LAST ACTIVITY": "ПОСЛЕДНЯЯ АКТИВНОСТЬ", - "[H:SHOW]": "[H:ПОКАЗАТЬ]", - "[H:HIDE]": "[H:СКРЫТЬ]", "NO CONTEXT": "НЕТ КОНТЕКСТА", "REPLY IN CODEX": "ОТВЕТЬТЕ В CODEX", "SESSION CONTEXT": "КОНТЕКСТ СЕССИИ", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F ОБНОВИТЬ ]", "[ ESC CANCEL ]": "[ ESC ОТМЕНА ]", "HUMAN APPROVAL REQUIRED": "ТРЕБУЕТСЯ ОДОБРЕНИЕ ЧЕЛОВЕКА", - "Managed policy requires approval each time.": "Управляемая политика требует одобрения каждый раз." + "Managed policy requires approval each time.": "Управляемая политика требует одобрения каждый раз.", + "MCP TOOL APPROVAL": "ОДОБРЕНИЕ ИНСТРУМЕНТА MCP", + "MCP SERVER": "СЕРВЕР MCP", + "TOOL": "ИНСТРУМЕНТ", + "TITLE": "НАЗВАНИЕ", + "APP": "ПРИЛОЖЕНИЕ", + "ARGUMENTS": "АРГУМЕНТЫ", + "PERMISSION SCOPE": "ОБЛАСТЬ РАЗРЕШЕНИЯ", + "[ CONFIRM TOOL RULE ]": "[ ПОДТВЕРДИТЬ ПРАВИЛО ]", + "[ ALWAYS ALLOW TOOL ]": "[ ВСЕГДА РАЗРЕШАТЬ ИНСТРУМЕНТ ]", + "[ CANCEL TOOL CALL ]": "[ ОТМЕНИТЬ ВЫЗОВ ИНСТРУМЕНТА ]", + "Unsupported MCP request. Review it in Codex.": "Неподдерживаемый запрос MCP. Просмотрите его в Codex.", + "NETWORK APPROVAL": "ОДОБРЕНИЕ СЕТИ", + "HOST": "ХОСТ", + "PROTOCOL": "ПРОТОКОЛ", + "[ CONFIRM HOST ALLOW ]": "[ ПОДТВЕРДИТЬ ДОСТУП К ХОСТУ ]", + "[ ALWAYS ALLOW HOST ]": "[ ВСЕГДА РАЗРЕШАТЬ ХОСТ ]", + "[ CONFIRM HOST BLOCK ]": "[ ПОДТВЕРДИТЬ БЛОКИРОВКУ ]", + "[ ALWAYS BLOCK HOST ]": "[ ВСЕГДА БЛОКИРОВАТЬ ХОСТ ]", + "TERMINAL INPUT APPROVAL": "ОДОБРЕНИЕ ВВОДА В ТЕРМИНАЛ", + "TERMINAL": "ТЕРМИНАЛ", + "INPUT (ESCAPED)": "ВВОД (С ЭКРАНИРОВАНИЕМ)", + "TERMINAL START DIRECTORY": "НАЧАЛЬНЫЙ КАТАЛОГ ТЕРМИНАЛА", + "ENVIRONMENT": "ОКРУЖЕНИЕ", + "[ SEND INPUT ONCE ]": "[ ОТПРАВИТЬ ВВОД ОДИН РАЗ ]", + "[ CONFIRM INPUT ]": "[ ПОДТВЕРДИТЬ ВВОД ]", + "[ CANCEL INPUT ]": "[ ОТМЕНИТЬ ВВОД ]" } diff --git a/internal/i18n/locales/sv.json b/internal/i18n/locales/sv.json index 4d431bd7..600092b5 100644 --- a/internal/i18n/locales/sv.json +++ b/internal/i18n/locales/sv.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ DETALJER", "APPROVAL REQUEST": "BEGÄRAN OM GODKÄNNANDE", "WORKING": "ARBETAR", - "[ H: HIDE DETAIL ]": "[ H: DÖLJ DETALJER ]", - "[ H: SHOW DETAIL ]": "[ H: VISA DETALJER ]", + "[ C(Y)CLE ]": "[ VÄXLA (Y) ]", "This approval action must be handled in Codex.": "Den här åtgärden måste godkännas i Codex.", "JUSTIFICATION": "MOTIVERING", "COMMAND": "KOMMANDO", @@ -153,8 +152,6 @@ "LAST REPLY": "SENASTE SVAR", "QUESTION": "FRÅGA", "LAST ACTIVITY": "SENASTE AKTIVITET", - "[H:SHOW]": "[H:VISA]", - "[H:HIDE]": "[H:DÖLJ]", "NO CONTEXT": "INGEN KONTEXT", "REPLY IN CODEX": "SVARA I CODEX", "SESSION CONTEXT": "SESSIONSKONTEXT", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F UPPDATERA ]", "[ ESC CANCEL ]": "[ ESC AVBRYT ]", "HUMAN APPROVAL REQUIRED": "MÄNSKLIGT GODKÄNNANDE KRÄVS", - "Managed policy requires approval each time.": "Den hanterade policyn kräver godkännande varje gång." + "Managed policy requires approval each time.": "Den hanterade policyn kräver godkännande varje gång.", + "MCP TOOL APPROVAL": "GODKÄNN MCP-VERKTYG", + "MCP SERVER": "MCP-SERVER", + "TOOL": "VERKTYG", + "TITLE": "TITEL", + "APP": "APP", + "ARGUMENTS": "ARGUMENT", + "PERMISSION SCOPE": "BEHÖRIGHETENS OMFATTNING", + "[ CONFIRM TOOL RULE ]": "[ BEKRÄFTA VERKTYGSREGEL ]", + "[ ALWAYS ALLOW TOOL ]": "[ TILLÅT ALLTID VERKTYGET ]", + "[ CANCEL TOOL CALL ]": "[ AVBRYT VERKTYGSANROP ]", + "Unsupported MCP request. Review it in Codex.": "MCP-begäran stöds inte. Granska den i Codex.", + "NETWORK APPROVAL": "NÄTVERKSGODKÄNNANDE", + "HOST": "VÄRD", + "PROTOCOL": "PROTOKOLL", + "[ CONFIRM HOST ALLOW ]": "[ BEKRÄFTA TILLÅTEN VÄRD ]", + "[ ALWAYS ALLOW HOST ]": "[ TILLÅT ALLTID VÄRD ]", + "[ CONFIRM HOST BLOCK ]": "[ BEKRÄFTA BLOCKERAD VÄRD ]", + "[ ALWAYS BLOCK HOST ]": "[ BLOCKERA ALLTID VÄRD ]", + "TERMINAL INPUT APPROVAL": "GODKÄNN TERMINALINMATNING", + "TERMINAL": "TERMINAL", + "INPUT (ESCAPED)": "INMATNING (MED ESCAPES)", + "TERMINAL START DIRECTORY": "TERMINALENS STARTMAPP", + "ENVIRONMENT": "MILJÖ", + "[ SEND INPUT ONCE ]": "[ SKICKA INMATNING EN GÅNG ]", + "[ CONFIRM INPUT ]": "[ BEKRÄFTA INMATNING ]", + "[ CANCEL INPUT ]": "[ AVBRYT INMATNING ]" } diff --git a/internal/i18n/locales/tr.json b/internal/i18n/locales/tr.json index 6059c276..853558ea 100644 --- a/internal/i18n/locales/tr.json +++ b/internal/i18n/locales/tr.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ AYRINTILAR", "APPROVAL REQUEST": "ONAY İSTEĞİ", "WORKING": "ÇALIŞIYOR", - "[ H: HIDE DETAIL ]": "[ H: AYRINTILARI GİZLE ]", - "[ H: SHOW DETAIL ]": "[ H: AYRINTILARI GÖSTER ]", + "[ C(Y)CLE ]": "[ GÖRÜNÜM DEĞİŞTİR (Y) ]", "This approval action must be handled in Codex.": "Bu onay işlemi Codex üzerinden yapılmalıdır.", "JUSTIFICATION": "GEREKÇE", "COMMAND": "KOMUT", @@ -153,8 +152,6 @@ "LAST REPLY": "SON YANIT", "QUESTION": "SORU", "LAST ACTIVITY": "SON ETKİNLİK", - "[H:SHOW]": "[H:GÖSTER]", - "[H:HIDE]": "[H:GİZLE]", "NO CONTEXT": "BAĞLAM YOK", "REPLY IN CODEX": "CODEX'TE YANITLAYIN", "SESSION CONTEXT": "OTURUM BAĞLAMI", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F YENİLE ]", "[ ESC CANCEL ]": "[ ESC İPTAL ]", "HUMAN APPROVAL REQUIRED": "İNSAN ONAYI GEREKLİ", - "Managed policy requires approval each time.": "Yönetilen ilke her seferinde onay gerektirir." + "Managed policy requires approval each time.": "Yönetilen ilke her seferinde onay gerektirir.", + "MCP TOOL APPROVAL": "MCP ARAÇ ONAYI", + "MCP SERVER": "MCP SUNUCUSU", + "TOOL": "ARAÇ", + "TITLE": "BAŞLIK", + "APP": "UYGULAMA", + "ARGUMENTS": "BAĞIMSIZ DEĞİŞKENLER", + "PERMISSION SCOPE": "İZNİN KAPSAMI", + "[ CONFIRM TOOL RULE ]": "[ ARAÇ KURALINI ONAYLA ]", + "[ ALWAYS ALLOW TOOL ]": "[ ARACA HER ZAMAN İZİN VER ]", + "[ CANCEL TOOL CALL ]": "[ ARAÇ ÇAĞRISINI İPTAL ET ]", + "Unsupported MCP request. Review it in Codex.": "Desteklenmeyen MCP isteği. Codex içinde inceleyin.", + "NETWORK APPROVAL": "AĞ ONAYI", + "HOST": "SUNUCU", + "PROTOCOL": "PROTOKOL", + "[ CONFIRM HOST ALLOW ]": "[ SUNUCU İZNİNİ ONAYLA ]", + "[ ALWAYS ALLOW HOST ]": "[ SUNUCUYA DAİMA İZİN VER ]", + "[ CONFIRM HOST BLOCK ]": "[ SUNUCU ENGELİNİ ONAYLA ]", + "[ ALWAYS BLOCK HOST ]": "[ SUNUCUYU DAİMA ENGELLE ]", + "TERMINAL INPUT APPROVAL": "TERMİNAL GİRDİSİ ONAYI", + "TERMINAL": "TERMİNAL", + "INPUT (ESCAPED)": "GİRDİ (KAÇIŞLI)", + "TERMINAL START DIRECTORY": "TERMİNAL BAŞLANGIÇ DİZİNİ", + "ENVIRONMENT": "ORTAM", + "[ SEND INPUT ONCE ]": "[ GİRDİYİ BİR KEZ GÖNDER ]", + "[ CONFIRM INPUT ]": "[ GİRDİYİ ONAYLA ]", + "[ CANCEL INPUT ]": "[ GİRDİYİ İPTAL ET ]" } diff --git a/internal/i18n/locales/zh-Hans.json b/internal/i18n/locales/zh-Hans.json index 99889258..c8aadb99 100644 --- a/internal/i18n/locales/zh-Hans.json +++ b/internal/i18n/locales/zh-Hans.json @@ -106,8 +106,7 @@ "←/→ DETAIL": "←/→ 详情", "APPROVAL REQUEST": "审批请求", "WORKING": "处理中", - "[ H: HIDE DETAIL ]": "[ H: 隐藏详情 ]", - "[ H: SHOW DETAIL ]": "[ H: 显示详情 ]", + "[ C(Y)CLE ]": "[ 切换视图 (Y) ]", "This approval action must be handled in Codex.": "此审批操作必须在 Codex 中处理。", "JUSTIFICATION": "理由", "COMMAND": "命令", @@ -153,8 +152,6 @@ "LAST REPLY": "最近回复", "QUESTION": "问题", "LAST ACTIVITY": "最近活动", - "[H:SHOW]": "[H:显示]", - "[H:HIDE]": "[H:隐藏]", "NO CONTEXT": "无上下文", "REPLY IN CODEX": "请在 CODEX 中回复", "SESSION CONTEXT": "会话上下文", @@ -545,5 +542,31 @@ "[ F REFRESH ]": "[ F 刷新 ]", "[ ESC CANCEL ]": "[ ESC 取消 ]", "HUMAN APPROVAL REQUIRED": "需要人工批准", - "Managed policy requires approval each time.": "受管策略要求每次都进行批准。" + "Managed policy requires approval each time.": "受管策略要求每次都进行批准。", + "MCP TOOL APPROVAL": "MCP工具审批", + "MCP SERVER": "MCP服务器", + "TOOL": "工具", + "TITLE": "标题", + "APP": "应用", + "ARGUMENTS": "参数", + "PERMISSION SCOPE": "权限范围", + "[ CONFIRM TOOL RULE ]": "[ 确认工具规则 ]", + "[ ALWAYS ALLOW TOOL ]": "[ 始终允许工具 ]", + "[ CANCEL TOOL CALL ]": "[ 取消工具调用 ]", + "Unsupported MCP request. Review it in Codex.": "不支持此MCP请求。请在Codex中查看。", + "NETWORK APPROVAL": "网络审批", + "HOST": "主机", + "PROTOCOL": "协议", + "[ CONFIRM HOST ALLOW ]": "[ 确认允许主机 ]", + "[ ALWAYS ALLOW HOST ]": "[ 始终允许主机 ]", + "[ CONFIRM HOST BLOCK ]": "[ 确认阻止主机 ]", + "[ ALWAYS BLOCK HOST ]": "[ 始终阻止主机 ]", + "TERMINAL INPUT APPROVAL": "终端输入审批", + "TERMINAL": "终端", + "INPUT (ESCAPED)": "输入(转义显示)", + "TERMINAL START DIRECTORY": "终端起始目录", + "ENVIRONMENT": "环境", + "[ SEND INPUT ONCE ]": "[ 发送输入一次 ]", + "[ CONFIRM INPUT ]": "[ 确认输入 ]", + "[ CANCEL INPUT ]": "[ 取消输入 ]" } diff --git a/internal/ui/localisation_test.go b/internal/ui/localisation_test.go index efe57a73..2f2babe4 100644 --- a/internal/ui/localisation_test.go +++ b/internal/ui/localisation_test.go @@ -64,6 +64,10 @@ func TestLocalisedScreensHelper(t *testing.T) { } t.Run("benchmark_click_surfaces", TestBenchmarkRenderedClickSurfacesMatchHitTestingAcrossSizes) t.Run("monitor_click_surfaces", TestMonitorButtonBoxesMatchEnabledHitSurfacesAcrossSizes) + t.Run("approval_button_spacing", TestApprovalButtonsKeepEvenVisibleGapsAndStableConfirmationPositions) + t.Run("mcp_approval_controls", TestMCPApprovalFourButtonsAndConfirmationPolicy) + t.Run("network_approval_controls", TestNetworkApprovalButtonsAndPolicy) + t.Run("stdin_approval_controls", TestStdinApprovalControlsAndEscapedReview) t.Run("monitor_control_shortcuts", TestMonitorCompactControlsKeepShortcutHints) t.Run("schedule_click_surfaces", TestScheduleRenderedControlSurfaces) t.Run("schedule_status_labels", TestScheduleLocalisedStatusAndHint) diff --git a/internal/ui/model.go b/internal/ui/model.go index c1f0b8f1..1de780db 100644 --- a/internal/ui/model.go +++ b/internal/ui/model.go @@ -55,12 +55,13 @@ type Model struct { monitorSuggestions monitorSuggestionState monitorStatusLine []string monitorDrafts map[string]string - monitorContextHidden bool + monitorContextView string monitorContextDetail string monitorContextExpanded string monitorContextRows map[string]rowContextState monitorContextScroll int monitorReadIntent string + monitorReadDwell monitorReadDwell monitorReadBusy bool monitorHistory map[string]monitorTurnHistory monitorHistorySequence uint64 @@ -638,7 +639,7 @@ func (m Model) update(message tea.Msg) (tea.Model, tea.Cmd) { return m.pressFooterButton(footerButtonQuotaTrace) } } - if message.IsRepeat && m.meterView == viewMonitor && (strings.EqualFold(message.String(), "c") || len(message.String()) == 1 && message.String()[0] >= '1' && message.String()[0] <= '8') { + if message.IsRepeat && m.meterView == viewMonitor && (strings.EqualFold(message.String(), "c") || strings.EqualFold(message.String(), "y") || len(message.String()) == 1 && message.String()[0] >= '1' && message.String()[0] <= '8') { return m, nil } if m.meterView == viewMonitor { @@ -2889,6 +2890,7 @@ func (m *Model) selectMonitorSession(direction int) { selected = min(max(selected+direction, 0), len(visible)-1) } m.monitorSelectedID = visible[selected] + m.monitorReadIntent = m.monitorSelectedID if m.monitorContextExpanded != "" && m.monitorContextExpanded != m.monitorSelectedID { m.monitorContextExpanded = "" m.monitorApprovalConfirm = "" diff --git a/internal/ui/monitor.go b/internal/ui/monitor.go index b568b12a..528e8190 100644 --- a/internal/ui/monitor.go +++ b/internal/ui/monitor.go @@ -286,6 +286,26 @@ func (m Model) monitorSessionPage(height int) ([]monitorSession, []int, string) // Joining framed rows with a newline adds no blank row. Allocate the full // height so no row falls below the three lines its frame actually renders. rowHeights := distributeSpace(max(height, rowCount), rowCount) + if rowCount > 1 && height >= 3*rowCount { + for selected, row := range visible { + if row.id != m.monitorSelectedID { + continue + } + // Give selection twice the normal share without dropping another + // row below its title, body and bottom border, or changing paging. + selectedHeight := min(2*height/(rowCount+1), height-3*(rowCount-1)) + others := distributeSpace(height-selectedHeight, rowCount-1) + for i, j := 0, 0; i < rowCount; i++ { + if i == selected { + rowHeights[i] = selectedHeight + } else { + rowHeights[i] = others[j] + j++ + } + } + break + } + } return visible, rowHeights, pageLabel } diff --git a/internal/ui/monitor_approval.go b/internal/ui/monitor_approval.go index 6bb8008b..62c2e1d8 100644 --- a/internal/ui/monitor_approval.go +++ b/internal/ui/monitor_approval.go @@ -30,6 +30,21 @@ func (m Model) monitorApprovalHasOutcome() bool { return ok && !m.hasSessionProfile(s) && s.preview.Kind == codex.SessionContextApproval && s.preview.ApprovalToken != "" && s.preview.ApprovalToken == m.monitorApprovalNoticeToken && (m.monitorApprovalBusy || m.monitorApprovalNotice != "") } +var approvalBlockMessages = map[string]string{ + "mcp": "Unsupported MCP request. Review it in Codex.", + "approval-kind": "This approval action must be handled in Codex.", + "network": "Network approval is not supported here.", + "permissions": "Additional permissions require approval in Codex.", + "file-change": "Complete file changes unavailable. Review in Codex.", + "command-format": "Unsupported command format.", + "missing-command": "Command details are missing.", + "missing-directory": "Working directory is missing.", + "missing-identity": "Turn or item identity is missing.", + "decisions": "No supported approval choices were offered.", + "truncated": "Request details exceed the display limit.", + "sanitised": "Request text was altered for safe display.", +} + func (m Model) monitorApprovalBlockReason(c codex.SessionContext) string { if m.monitorApprovalBusy { return i18n.Text("Sending decision…") @@ -40,30 +55,10 @@ func (m Model) monitorApprovalBlockReason(c codex.SessionContext) string { if c.Source == "LOCAL" { return i18n.Text("Local observation cannot answer live approvals.") } - switch c.ApprovalBlocked { - case "approval-kind": - return i18n.Text("This approval action must be handled in Codex.") - case "network": - return i18n.Text("Network approval is not supported here.") - case "permissions": - return i18n.Text("Additional permissions require approval in Codex.") - case "file-change": - return i18n.Text("Complete file changes unavailable. Review in Codex.") - case "command-format": - return i18n.Text("Unsupported command format.") - case "missing-command": - return i18n.Text("Command details are missing.") - case "missing-directory": - return i18n.Text("Working directory is missing.") - case "missing-identity": - return i18n.Text("Turn or item identity is missing.") - case "decisions": - return i18n.Text("No supported approval choices were offered.") - case "truncated": - return i18n.Text("Request details exceed the display limit.") - case "sanitised": - return i18n.Text("Request text was altered for safe display.") + if message := approvalBlockMessages[c.ApprovalBlocked]; message != "" { + return i18n.Text(message) } + if c.ApprovalToken == "" { return i18n.Text("No actionable live approval was received.") } @@ -86,28 +81,11 @@ func (m Model) monitorApprovalToken() string { } func approvalOptionLabel(kind string, confirm bool) string { - switch kind { - case "accept": - if confirm { - return i18n.Text("[ CONFIRM APPROVAL ]") - } - return i18n.Text("[ APPROVE ONCE ]") - case "acceptForSession": - if confirm { - return i18n.Text("[ CONFIRM SESSION GRANT ]") - } - return i18n.Text("[ ALLOW FOR SESSION ]") - case "acceptWithExecpolicyAmendment": - if confirm { - return i18n.Text("[ CONFIRM PERSISTENT RULE ]") - } - return i18n.Text("[ ALWAYS ALLOW PREFIX ]") - case "decline": - return i18n.Text("[ DECLINE ]") - case "cancel": - return i18n.Text("[ REJECT & STOP TURN ]") + label := (codex.ApprovalOption{Kind: kind}).Label(confirm) + if label == "" { + return "" } - return "" + return i18n.Text("[ " + label + " ]") } type monitorApprovalButton struct { @@ -120,7 +98,7 @@ func approvalShortcutLabel(kind string, confirm bool, index int) string { if label == "" { return "" } - if confirm && (kind == "decline" || kind == "cancel") { + if confirm && (kind == "decline" || kind == "cancel" || kind == "cancelMcpTool" || kind == "cancelStdin") { return i18n.Text("[ C CONFIRM ]") + " " + label } shortcut := strconv.Itoa(index + 1) @@ -135,6 +113,14 @@ func (m Model) approvalButtonLabel(kind string, confirm bool, index int) string if confirm && kind == "accept" && m.keyboardEventTypes { label = strings.Replace(label, "(C)", "("+strconv.Itoa(index+1)+")", 1) } + if m.confirmations.Required(confirmation.Approval(kind)) { + width := max(lipgloss.Width(approvalShortcutLabel(kind, false, index)), lipgloss.Width(approvalShortcutLabel(kind, true, index))) + if padding := width - lipgloss.Width(label); padding > 0 { + // Keep reserved confirmation space inside the painted brackets, + // so visible gaps and neighbouring button positions stay constant. + label = strings.TrimSuffix(label, " ]") + strings.Repeat(" ", padding) + " ]" + } + } return label } @@ -157,9 +143,6 @@ func (m Model) monitorApprovalButtons(width, height int) []monitorApprovalButton } label := m.approvalButtonLabel(option.Kind, false, i) slot := lipgloss.Width(label) - if m.confirmations.Required(confirmation.Approval(option.Kind)) { - slot = max(slot, lipgloss.Width(m.approvalButtonLabel(option.Kind, true, i))) - } if slot > width-4 || label == "" { return nil } diff --git a/internal/ui/monitor_approval_test.go b/internal/ui/monitor_approval_test.go index 1db919ab..cc9a70ba 100644 --- a/internal/ui/monitor_approval_test.go +++ b/internal/ui/monitor_approval_test.go @@ -125,7 +125,7 @@ func TestMonitorApprovalRenderedTargets(t *testing.T) { continue } action := "decision:" + strconv.Itoa(i) - label := approvalShortcutLabel(option.Kind, confirmed && i == 0, i) + label := m.approvalButtonLabel(option.Kind, confirmed && i == 0, i) found := false for y, line := range lines { pos := strings.Index(line, label) @@ -178,11 +178,13 @@ func TestMonitorApprovalStaleAndKeyboardSafety(t *testing.T) { t.Fatal("keyboard approved") } } - m.toggleMonitorContext() + m.setRowContext("root-one", contextWide) + m.cycleMonitorContext() + m.cycleMonitorContext() if m.monitorApprovalToken() != "" { t.Fatal("hidden preview actionable") } - m.toggleMonitorContext() + m.cycleMonitorContext() m.monitorSessionData[0].preview.ApprovalToken = "" if m.monitorApprovalToken() != "" { t.Fatal("local request actionable") @@ -202,7 +204,7 @@ func TestMonitorApprovalNumberSelectsCConfirms(t *testing.T) { t.Fatal("number did not exclusively arm requested choice") } } - if !strings.Contains(ansi.Strip(m.render()), approvalShortcutLabel(m.monitorSessionData[0].preview.ApprovalOptions[index].Kind, true, index)) { + if !strings.Contains(ansi.Strip(m.render()), m.approvalButtonLabel(m.monitorSessionData[0].preview.ApprovalOptions[index].Kind, true, index)) { t.Fatal("C confirmation shortcut missing") } m, cmd, _ = m.updateMonitorContextKey("c") @@ -369,3 +371,162 @@ func TestMonitorApprovalFooterPinnedBelowScrollingText(t *testing.T) { t.Fatal("short terminal did not drop padding first") } } + +func TestApprovalButtonsKeepEvenVisibleGapsAndStableConfirmationPositions(t *testing.T) { + for _, mode := range []confirmation.Mode{confirmation.Balanced, confirmation.None, confirmation.Require} { + for _, middle := range []string{"decline", "acceptForSession"} { + m := approvalTestModel() + m.SetConfirmationMode(mode) + m.monitorSessionData[0].preview.ApprovalOptions = [8]codex.ApprovalOption{{Kind: "accept", Value: "accept"}, {Kind: middle, Value: middle}, {Kind: "cancel", Value: "cancel"}} + before := m.monitorApprovalButtons(140, 20) + if len(before) != 3 { + t.Fatal("three choices were not visible") + } + for armed := -1; armed < len(before); armed++ { + if armed >= 0 && !m.confirmations.Required(confirmation.Approval(m.monitorSessionData[0].preview.ApprovalOptions[armed].Kind)) { + continue + } + m.monitorApprovalConfirm = "" + if armed >= 0 { + m.monitorApprovalConfirm = "live/decision:" + strconv.Itoa(armed) + m.monitorApprovalConfirmUntil = time.Now().Add(monitorApprovalConfirmDuration) + } + buttons := m.monitorApprovalButtons(140, 20) + rendered := ansi.Strip(m.renderMonitorApprovalControls(140, 20, paletteFor(m.theme))) + for i, button := range buttons { + if button.x != before[i].x || button.y != before[i].y { + t.Fatal("arming moved a neighbouring decision") + } + if lipgloss.Width(button.label) != button.slot { + t.Fatal("reserved space was left between buttons") + } + if i > 0 && buttons[i-1].y == button.y { + previous := buttons[i-1] + end := strings.Index(rendered, previous.label) + len(previous.label) + start := strings.Index(rendered, button.label) + if rendered[end:start] != " " { + t.Fatalf("mode %s choice %d has uneven gap: %q", mode, i+1, rendered[end:start]) + } + } + _, _, controlY := monitorContextBodyLayout(20, buttons[len(buttons)-1].y+1) + if monitorButtonAt(buttons, 20, 2+button.x+button.slot-2, controlY+button.y) != button.action { + t.Fatal("painted button padding does not belong to its button") + } + } + } + } + } +} + +func TestMCPApprovalFourButtonsAndConfirmationPolicy(t *testing.T) { + for _, mode := range []confirmation.Mode{confirmation.Balanced, confirmation.None, confirmation.Require} { + for index, kind := range []string{"accept", "acceptForSession", "acceptMcpAlways", "cancelMcpTool"} { + m := approvalTestModel() + m.SetConfirmationMode(mode) + m.monitorSessionData[0].preview = codex.SessionContext{Kind: codex.SessionContextApproval, Source: "LIVE", ThreadID: "root-one", Text: "Allow Calendar to create an event?", ApprovalToken: "live", MCPTool: codex.MCPToolApprovalDetails{Server: "codex_apps", Title: "Create Event", Message: "Allow Calendar to create an event?", Arguments: `{"title":"Demo"}`}, ApprovalOptions: [8]codex.ApprovalOption{{Kind: "accept", Value: "accept"}, {Kind: "acceptForSession", Value: "acceptForSession"}, {Kind: "acceptMcpAlways", Value: "acceptMcpAlways"}, {Kind: "cancelMcpTool", Value: "cancelMcpTool"}}} + buttons := m.visibleMonitorApprovalButtons() + if len(buttons) != 4 { + t.Fatalf("mode %s: four MCP choices not visible", mode) + } + doc := ansi.Strip(m.render()) + for _, text := range []string{i18n.Text("MCP TOOL APPROVAL"), "codex_apps", "Create Event", "Demo", strings.Trim(i18n.Text("[ CANCEL TOOL CALL ]"), "[] ")} { + if !strings.Contains(doc, strings.TrimSuffix(text, " ]")) { + t.Fatalf("missing MCP review text %q", text) + } + } + if strings.Contains(doc, strings.Trim(i18n.Text("[ REJECT & STOP TURN ]"), "[] ")) { + t.Fatal("tool cancellation labelled as turn rejection") + } + next, cmd, _ := m.updateMonitorApprovalKey(strconv.Itoa(index + 1)) + m = next + guarded := mode == confirmation.Require || mode == confirmation.Balanced && (index == 1 || index == 2) + if guarded { + if cmd != nil || m.monitorApprovalConfirm == "" { + t.Fatal("reusable MCP grant bypassed review") + } + m, cmd, _ = m.updateMonitorApprovalKey("c") + } + if cmd == nil { + t.Fatal("explicit MCP decision not sent") + } + cmd() + if m.fetcher.(*approvalTestClient).decision != kind { + t.Fatal("wrong MCP choice") + } + } + } +} + +func TestNetworkApprovalButtonsAndPolicy(t *testing.T) { + for _, mode := range []confirmation.Mode{confirmation.Balanced, confirmation.None, confirmation.Require} { + for index, kind := range []string{"accept", "acceptForSession", "allowNetworkHost", "denyNetworkHost", "decline", "cancel"} { + m := approvalTestModel() + m.SetConfirmationMode(mode) + ctx := codex.SessionContext{Kind: codex.SessionContextApproval, Source: "LIVE", ThreadID: "root-one", ApprovalToken: "live", Text: "Allow network access?", ActionDetails: codex.ApprovalActionDetails{Kind: "network", Target: "example.com", Protocol: "https"}} + for i, k := range []string{"accept", "acceptForSession", "allowNetworkHost", "denyNetworkHost", "decline", "cancel"} { + ctx.ApprovalOptions[i] = codex.ApprovalOption{Kind: k, Value: k} + } + m.monitorSessionData[0].preview = ctx + if len(m.visibleMonitorApprovalButtons()) != 6 { + t.Fatal("network choices missing", mode) + } + doc := ansi.Strip(m.render()) + for _, text := range []string{i18n.Text("NETWORK APPROVAL"), "example.com", "https"} { + if !strings.Contains(doc, text) { + t.Fatal("network review missing", text) + } + } + next, cmd, _ := m.updateMonitorApprovalKey(strconv.Itoa(index + 1)) + m = next + guarded := mode == confirmation.Require || mode == confirmation.Balanced && index >= 1 && index <= 3 + if guarded { + if cmd != nil || m.monitorApprovalConfirm == "" { + t.Fatal("persistent host rule bypassed review") + } + m, cmd, _ = m.updateMonitorApprovalKey("c") + } + if cmd == nil { + t.Fatal("network decision not sent") + } + cmd() + if m.fetcher.(*approvalTestClient).decision != kind { + t.Fatal("wrong network decision") + } + } + } +} + +func TestStdinApprovalControlsAndEscapedReview(t *testing.T) { + for _, mode := range []confirmation.Mode{confirmation.Balanced, confirmation.None, confirmation.Require} { + for index, decision := range []string{"accept", "cancel"} { + m := approvalTestModel() + m.SetConfirmationMode(mode) + input := "yes\n\x03\u202e" + m.monitorSessionData[0].preview = codex.SessionContext{Kind: codex.SessionContextApproval, Source: "LIVE", ThreadID: "root-one", Text: "Review terminal input", ApprovalToken: "live", ActionDetails: codex.ApprovalActionDetails{Kind: "stdin", Target: "123", Input: input, Directory: "/terminal/start"}, ApprovalOptions: [8]codex.ApprovalOption{{Kind: "acceptStdin", Value: "accept"}, {Kind: "cancelStdin", Value: "cancel"}}} + if len(m.visibleMonitorApprovalButtons()) != 2 { + t.Fatal("stdin choices missing") + } + doc := ansi.Strip(m.render()) + for _, text := range []string{i18n.Text("TERMINAL INPUT APPROVAL"), "123", strconv.QuoteToASCII(input), "/terminal/start"} { + if !strings.Contains(doc, text) { + t.Fatal("stdin review missing", text) + } + } + next, cmd, _ := m.updateMonitorApprovalKey(strconv.Itoa(index + 1)) + m = next + if mode == confirmation.Require { + if cmd != nil || m.monitorApprovalConfirm == "" { + t.Fatal("strict input skipped review") + } + m, cmd, _ = m.updateMonitorApprovalKey("c") + } + if cmd == nil { + t.Fatal("stdin decision not sent") + } + cmd() + if m.fetcher.(*approvalTestClient).decision != decision { + t.Fatal("input decision changed") + } + } + } +} diff --git a/internal/ui/monitor_approval_warning_test.go b/internal/ui/monitor_approval_warning_test.go index 0cbfcbbd..0c075951 100644 --- a/internal/ui/monitor_approval_warning_test.go +++ b/internal/ui/monitor_approval_warning_test.go @@ -205,3 +205,56 @@ func TestMonitorApprovalButtonsReappearAfterDismissal(t *testing.T) { t.Fatal("shrink did not restore safety warning") } } + +func TestInlineApprovalRequiresTheCompleteLongReview(t *testing.T) { + for _, family := range []string{"command", "file", "mcp", "network", "stdin"} { + t.Run(family, func(t *testing.T) { + m := approvalTestModel() + m.setRowContext("root-one", contextWide) + c := &m.monitorSessionData[0].preview + text := strings.Repeat("review-data ", 650) + "END OF REVIEW" + c.ThreadID = "root-one" + c.Text = text + c.ApprovalOptions = [8]codex.ApprovalOption{{Kind: "accept", Value: "accept"}, {Kind: "cancel", Value: "cancel"}} + switch family { + case "command": + c.CommandDetails = codex.ApprovalCommandDetails{Command: text, Directory: "/end"} + case "file": + c.FileChanges = `[{"path":"a","kind":{"type":"add"},"diff":"+ok"}]` + case "mcp": + c.MCPTool = codex.MCPToolApprovalDetails{Server: "tools", Message: "Allow tool?", Arguments: text} + case "network": + c.ActionDetails = codex.ApprovalActionDetails{Kind: "network", Target: "example.com", Protocol: "https", Justification: text} + case "stdin": + c.ActionDetails = codex.ApprovalActionDetails{Kind: "stdin", Target: "123", Input: text, Directory: "/end"} + } + row := m.monitorSessionData[0] + const width = 120 + clipped := row + clipped.preview.Text = codex.SanitizeSessionContext(text) + // Leave exactly enough room for the old 4 KiB excerpt, but not its hidden tail. + previewRows := len(expandedContextLines(width, clipped)) + controls := m.monitorApprovalButtons(width, 200) + controlRows := controls[len(controls)-1].y + 1 + height := previewRows + controlRows + 3 + complete := expandedContextLines(width, row) + if !strings.Contains(strings.Join(complete, ""), "END OF REVIEW") || len(complete) <= previewRows { + t.Fatal("complete approval text was truncated") + } + if len(m.expandedApprovalButtons(width, height, row)) != 0 { + t.Fatal("inline buttons allow approval of an unseen tail") + } + navigation := m.expandedContextNavigation(width, height, row) + if len(navigation) == 0 || navigation[0].action != "detail:root-one" { + t.Fatal("missing route to full approval review") + } + if len(m.expandedApprovalButtons(width, len(complete)+controlRows+3, row)) != 2 { + t.Fatal("complete fitting request lost its inline controls") + } + m.openMonitorContext("root-one") + if !strings.Contains(strings.Join(m.contextDetailLines(width-4), ""), "END OF REVIEW") { + t.Fatal("full Detail omitted the review tail") + } + }) + } +} diff --git a/internal/ui/monitor_context.go b/internal/ui/monitor_context.go index a85e4fdf..63e9c26b 100644 --- a/internal/ui/monitor_context.go +++ b/internal/ui/monitor_context.go @@ -37,6 +37,12 @@ func contextTitle(c codex.SessionContext) string { case codex.SessionContextQuestion: return i18n.Text("QUESTION") case codex.SessionContextApproval: + if review := c.ActionReview(); review != nil { + return i18n.Text(review.Title) + } + if c.MCPTool.Server != "" { + return i18n.Text("MCP TOOL APPROVAL") + } if c.RequiredHumanApproval { return i18n.Text("HUMAN APPROVAL REQUIRED") } @@ -53,23 +59,17 @@ func contextTaskTitle(c codex.SessionContext) string { return i18n.Text("CURRENT TASK") } -func (m Model) monitorPrivacyLabel(widths ...int) string { +func (m Model) monitorCycleLabel(widths ...int) string { g := m.monitorDashboardLayout() width := m.monitorArea(g.contentWidth, g.meterHeight).readoutWidth if len(widths) > 0 { width = widths[0] } - hide, show := i18n.Text("[ H: HIDE DETAIL ]"), i18n.Text("[ H: SHOW DETAIL ]") - if width >= max(lipgloss.Width(hide), lipgloss.Width(show))+8 { - if m.monitorContextHidden { - return show - } - return hide - } - if m.monitorContextHidden { - return i18n.Text("[H:SHOW]") + label := i18n.Text("[ C(Y)CLE ]") + if width >= lipgloss.Width(label)+8 { + return label } - return i18n.Text("[H:HIDE]") + return "[Y]" } func (m Model) renderContextAction(id, label string, colors palette) string { @@ -212,8 +212,7 @@ func (m Model) renderMonitorContextDetail(width, height int, colors palette) str layout := m.layoutDetailControls(width, height) controls := layout.render(m, width, height, colors) textRows, gap, _ := m.detailBodyLayout(width, height, layout.rows) - start := min(max(m.monitorContextScroll, 0), max(len(lines)-textRows, 0)) - end := min(start+textRows, len(lines)) + start, end := m.detailVisibleRange(len(lines), textRows) bodyLines := append([]string(nil), lines[start:end]...) if m.historyNavigationRows(width, height) > 0 { bodyLines = append([]string{m.renderMonitorNavigationButtons(m.historyNavigationButtons(width, height), colors)}, bodyLines...) @@ -273,22 +272,6 @@ func monitorContextBodyLayout(height, controls int) (textRows, gap, controlY int return } -func (m *Model) toggleMonitorContext() { - m.clearMonitorHeaderFocus() - m.clearQuotaConfirmation() - m.stashMonitorDraft() - m.monitorPrompt = monitorPromptState{} - m.monitorApprovalConfirm = "" - m.monitorApprovalNotice = "" - m.monitorContextHidden = !m.monitorContextHidden - m.monitorContextRows = nil - m.monitorContextDetail = "" - m.monitorContextExpanded = "" - m.monitorContextHover = "" - m.monitorContextScroll = 0 - m.persistPreferences() -} - func (m *Model) openMonitorContext(id string) { for _, s := range m.monitorSessionData { if s.id == id && (s.preview.Text != "" || s.preview.CurrentTask != "" || s.preview.LatestGuidance != "" || s.preview.Kind == codex.SessionContextApproval || m.hasSessionProfile(s) || id == m.monitorContextExpanded) && m.monitorSessionVisible(s) { @@ -333,8 +316,8 @@ func (m Model) updateMonitorContextKey(key string) (Model, tea.Cmd, bool) { if next, cmd, handled := m.updateMonitorApprovalKey(key); handled { return next, cmd, true } - if key == "h" { - m.toggleMonitorContext() + if key == "y" { + m.cycleMonitorContext() return m, nil, true } if key == "left" || key == "right" { @@ -558,8 +541,8 @@ func (m Model) updateMonitorContextMouse(msg tea.MouseMsg) (Model, tea.Cmd, bool m.showLiveMonitorHistory() cmd := m.focusMonitorPrompt() return m, cmd, true - case "privacy": - m.toggleMonitorContext() + case "cycle": + m.cycleMonitorContext() case "close": m.stepBackMonitorContext() case "history:previous": diff --git a/internal/ui/monitor_context_modes.go b/internal/ui/monitor_context_modes.go index c969369a..34d7fd3c 100644 --- a/internal/ui/monitor_context_modes.go +++ b/internal/ui/monitor_context_modes.go @@ -96,13 +96,82 @@ func (m Model) rowContextMode(id string) int { if state, ok := m.monitorContextRows[id]; ok { return state.mode } - if m.monitorContextHidden { - return contextGraph - } if id != "" && m.monitorContextExpanded == id { return contextWide } - return contextSplit + return m.defaultMonitorContextMode() +} + +var sessionContextViewNames = map[int]string{ + contextGraph: "graph", contextSplit: "split", contextWide: "wide", +} + +func (m Model) defaultMonitorContextMode() int { + switch m.monitorContextView { + case "graph": + return contextGraph + case "wide": + return contextWide + default: + return contextSplit + } +} + +// Mixed rows first converge on the most detailed listed row. Once uniform, +// cycle only the three overview layouts; full-screen detail is independent. +func (m *Model) cycleMonitorContext() { + if m.monitorContextDetail != "" { + return + } + least, most, count := contextWide, contextGraph, 0 + for _, s := range m.monitorSessionData { + if m.monitorSessionInList(s) { + mode := m.rowContextMode(s.id) + least, most, count = min(least, mode), max(most, mode), count+1 + } + } + if count == 0 { + return + } + next := most + if least == most { + next = (most + 1) % contextFull + } + rows := maps.Clone(m.monitorContextRows) + if rows == nil { + rows = make(map[string]rowContextState) + } + for _, s := range m.monitorSessionData { + if m.monitorSessionInList(s) { + delete(rows, s.id) + } else { + // Changing the default must not change filtered or dismissed rows. + state := rows[s.id] + state.mode = m.rowContextMode(s.id) + rows[s.id] = state + } + } + m.clearMonitorHeaderFocus() + m.clearQuotaConfirmation() + m.clearMonitorCloseAllConfirmation() + m.stashMonitorDraft() + m.monitorPrompt = monitorPromptState{} + m.monitorApprovalConfirm, m.monitorApprovalNotice = "", "" + m.monitorContextView = sessionContextViewNames[next] + m.monitorContextRows = rows + m.monitorContextExpanded, m.monitorContextHover = "", "" + m.monitorContextScroll = 0 + m.monitorReadIntent = "" // A bulk layout change is not a review of each reply. + m.monitorReadDwell = monitorReadDwell{} + if next == contextWide { + for _, s := range m.monitorSessionData { + if s.id == m.monitorSelectedID && m.monitorSessionInList(s) { + m.monitorContextExpanded = s.id + break + } + } + } + m.persistPreferences() } func (m Model) contextTargetHidden() bool { @@ -145,12 +214,12 @@ func (m *Model) setRowContext(id string, mode int) { } func expandedContextLines(width int, s monitorSession) []string { - wrap := sessionWebTextLines + wrap, sanitize := sessionWebTextLines, codex.SanitizeSessionContext if s.preview.Kind == codex.SessionContextApproval { - wrap = sessionWebLiteralTextLines + wrap, sanitize = sessionWebLiteralTextLines, codex.SanitizeApprovalText } if s.preview.FileChanges != "" { - lines := wrap(codex.SanitizeSessionContext(s.preview.Text), max(width-4, 1)) + lines := wrap(sanitize(s.preview.Text), max(width-4, 1)) for _, line := range fileApprovalDocument(s.preview.FileChanges, max(width-4, 1)) { lines = append(lines, line.text) } @@ -160,7 +229,7 @@ func expandedContextLines(width int, s monitorSession) []string { return []string{i18n.Text("NO CONTEXT")} } header := terminalLabel(s.preview.ThreadID) + " // " + terminalLabel(s.preview.Source) - text := header + "\n" + codex.SanitizeSessionContext(s.preview.Text) + text := header + "\n" + sanitize(s.preview.Text) if s.preview.CurrentTask != "" || s.preview.LatestGuidance != "" { text = header if s.preview.CurrentTask != "" { @@ -169,7 +238,7 @@ func expandedContextLines(width int, s monitorSession) []string { if s.preview.LatestGuidance != "" { text += "\n" + ansi.Truncate(i18n.Text("LATEST GUIDANCE")+" // "+strings.Join(strings.Fields(codex.SanitizeSessionContext(s.preview.LatestGuidance)), " "), max(width-4, 1), "…") } - text += "\n\n" + codex.SanitizeSessionContext(s.preview.Text) + text += "\n\n" + sanitize(s.preview.Text) } return wrap(text, max(width-4, 1)) } diff --git a/internal/ui/monitor_context_modes_test.go b/internal/ui/monitor_context_modes_test.go index 09141c0b..44b11560 100644 --- a/internal/ui/monitor_context_modes_test.go +++ b/internal/ui/monitor_context_modes_test.go @@ -151,7 +151,7 @@ func TestMonitorContextBackAndForthCycle(t *testing.T) { for _, back := range []tea.KeyPressMsg{{Code: tea.KeyLeft}, {Code: tea.KeyEscape}} { m := contextTestModel() m.monitorSelectedID = "root-two" - m.monitorContextHidden = true + m.monitorContextView = "graph" for _, delta := range []int{-1, 1, 1, 1, 1, -1, -1, -1, -1} { k := tea.KeyPressMsg{Code: tea.KeyRight} if delta < 0 { @@ -163,16 +163,16 @@ func TestMonitorContextBackAndForthCycle(t *testing.T) { if got, want := m.rowContextMode("root-two"), min(max(before+delta, contextGraph), contextFull); got != want { t.Fatalf("got %d want %d", got, want) } - if m.rowContextMode("root-one") != contextGraph || !m.monitorContextHidden { + if m.rowContextMode("root-one") != contextGraph || m.defaultMonitorContextMode() != contextGraph { t.Fatal("changed another row") } } } } -func TestMonitorRowModesIndependentAndGlobalToggle(t *testing.T) { +func TestMonitorRowModesIndependentAndGlobalCycle(t *testing.T) { m := contextTestModel() - m.monitorContextHidden = true + m.monitorContextView = "graph" m.changeMonitorContext("root-one", 1) if m.rowContextMode("root-one") != contextSplit || m.rowContextMode("root-two") != contextGraph { t.Fatal("first row affected second row") @@ -182,24 +182,50 @@ func TestMonitorRowModesIndependentAndGlobalToggle(t *testing.T) { if m.rowContextMode("root-one") != contextWide || m.rowContextMode("root-two") != contextSplit { t.Fatal("switching rows discarded presentation") } - m.changeMonitorContext("root-two", 1) - if m.rowContextMode("root-one") != contextWide || m.rowContextMode("root-two") != contextWide { - t.Fatal("cannot independently expand two rows") - } - m.toggleMonitorContext() // global Show overrides individual choices - for _, s := range m.monitorSessionData { - if m.rowContextMode(s.id) != contextSplit { - t.Fatal("Show did not reset every row to split") + for _, want := range []int{contextWide, contextGraph, contextSplit, contextWide, contextGraph} { + next, _ := m.Update(key('y')) + m = next.(Model) + for _, s := range m.monitorSessionData { + if m.rowContextMode(s.id) != want { + t.Fatalf("row %s mode %d, want %d", s.id, m.rowContextMode(s.id), want) + } } - } - m.toggleMonitorContext() - for _, s := range m.monitorSessionData { - if m.rowContextMode(s.id) != contextGraph { - t.Fatal("Hide did not reset every row to graph") + if m.monitorContextDetail != "" || len(m.monitorContextRows) != 0 { + t.Fatal("global cycle retained overrides or opened full detail") } } - if len(m.monitorContextRows) != 0 || m.monitorContextTarget() != "" { - t.Fatal("global reset retained row overrides") +} + +func TestMonitorCycleOnlyListedRowsAndNoHeldKeys(t *testing.T) { + m := contextTestModel() + m.height = 16 // Keep a matching row off-page while cycling the whole list. + m.monitorSessionData[0].working = false + m.monitorFilter = monitorFilterWorking + m.monitorSelectedID = "root-two" + m.setRowContext("root-three", contextWide) + m.monitorSelectedID = "root-two" + m.monitorContextScroll = 10 + m.monitorApprovalConfirm = "old" + m.monitorReadIntent = "root-two" + next, _ := m.Update(tea.KeyPressMsg{Code: 'y', Text: "y", IsRepeat: true}) + if next.(Model).rowContextMode("root-two") != contextSplit { + t.Fatal("held Cycle changed layout") + } + m.cycleMonitorContext() + if m.rowContextMode("root-one") != contextSplit || m.rowContextMode("root-two") != contextWide || m.rowContextMode("root-three") != contextWide { + t.Fatal("cycle changed filtered rows or missed listed rows") + } + if m.monitorSelectedID != "root-two" || m.monitorContextExpanded != "root-two" || m.monitorContextScroll != 0 || m.monitorApprovalConfirm != "" || m.monitorReadIntent != "" { + t.Fatal("cycle lost selection or retained stale interaction state") + } + m.cycleMonitorContext() + if m.rowContextMode("root-one") != contextSplit || m.rowContextMode("root-two") != contextGraph || m.rowContextMode("root-three") != contextGraph { + t.Fatal("filtered row changed on wrap") + } + m.monitorFilter = monitorFilterInput + m.cycleMonitorContext() + if m.defaultMonitorContextMode() != contextGraph { + t.Fatal("empty list changed default") } } @@ -233,7 +259,7 @@ func TestMonitorRowSurfaceCyclesOnlyClickedSession(t *testing.T) { for _, width := range []int{40, 80, 120, 200} { m := contextTestModel() m.width = width - m.monitorContextHidden = true + m.monitorContextView = "graph" m.monitorSelectedID = "root-one" for _, delta := range []int{-1, 1, 1, 1, 1, -1, -1, -1, -1} { before := m.rowContextMode("root-two") @@ -318,7 +344,7 @@ func TestExpandedContextResponsiveHitTargets(t *testing.T) { m.monitorSessionData = append(m.monitorSessionData, s) } m.monitorSessionData = m.monitorSessionData[:size.n] - if strings.Contains(ansi.Strip(m.render()), approvalShortcutLabel("accept", false, 0)) { + if strings.Contains(ansi.Strip(m.render()), m.approvalButtonLabel("accept", false, 0)) { t.Fatal("compact exposed approval") } m.changeMonitorContext(m.monitorSessionData[0].id, 1) @@ -403,3 +429,46 @@ func TestMonitorObsoleteNavigationKeysDoNotChangeDetail(t *testing.T) { } } } + +func TestMonitorCycleKeepsTypedYAndDrafts(t *testing.T) { + m, _ := promptTestModel() + m.setRowContext("root-one", contextWide) + m.focusMonitorPrompt() + next, _ := m.Update(key('y')) + m = next.(Model) + if m.monitorPrompt.input.Value() != "y" || m.defaultMonitorContextMode() != contextSplit { + t.Fatal("Cycle stole the editor's Y") + } + m.cycleMonitorContext() // Click while a draft is present: converge on wide. + if m.monitorDrafts["root-one"] != "y" || m.monitorPrompt.input.Focused() { + t.Fatal("bulk layout change lost the draft or retained editor focus") + } + m.focusMonitorPrompt() + if m.monitorPrompt.input.Value() != "y" { + t.Fatal("draft did not return to the selected wide row") + } +} + +func TestSelectedSessionGetsSpaceWithoutChangingPageOrMinimum(t *testing.T) { + for _, height := range []int{9, 10, 12, 30, 31} { + m := contextTestModel() + m.monitorSelectedID = "root-two" + rows, heights, label := m.monitorSessionPage(height) + if len(rows) != 3 || label != "" { + t.Fatal("selection changed pagination") + } + total := 0 + for _, h := range heights { + if h < 3 { + t.Fatal("selection clipped another row") + } + total += h + } + if total != height || heights[1] < heights[0] || heights[1] < heights[2] { + t.Fatalf("invalid weighted heights: %v", heights) + } + if height == 30 && heights[1] != 15 { + t.Fatalf("selected row did not receive a double share: %v", heights) + } + } +} diff --git a/internal/ui/monitor_context_test.go b/internal/ui/monitor_context_test.go index 69626f64..c9e9b883 100644 --- a/internal/ui/monitor_context_test.go +++ b/internal/ui/monitor_context_test.go @@ -98,7 +98,10 @@ func TestMonitorCompletionIsIndependentOfPreview(t *testing.T) { m.monitorSessionData[0].attention = codex.SessionAttentionComplete m.monitorSessionData[0].preview = codex.SessionContext{} for _, hidden := range []bool{false, true} { - m.monitorContextHidden = hidden + m.monitorContextView = "split" + if hidden { + m.monitorContextView = "graph" + } if out := ansi.Strip(m.render()); !strings.Contains(out, i18n.Text("TURN COMPLETE")) { t.Fatal("completion badge missing without visible reply") } @@ -162,14 +165,23 @@ func TestMonitorContextPrivacyAndModalIsolation(t *testing.T) { m := contextTestModel() m.openMonitorContext("root-one") m.monitorSessionData[0].preview.Text = strings.Repeat("private context\n", 100) - updated, _ := m.Update(key('h')) + updated, _ := m.Update(key('y')) + m = updated.(Model) + if m.monitorContextDetail != "root-one" { + t.Fatal("Cycle left full detail") + } + updated, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyEscape}) + m = updated.(Model) + updated, _ = m.Update(key('y')) m = updated.(Model) - if !m.monitorContextHidden || m.monitorContextDetail != "" || strings.Contains(m.render(), "private context") { + updated, _ = m.Update(key('y')) + m = updated.(Model) + if m.defaultMonitorContextMode() != contextGraph || m.monitorContextDetail != "" || strings.Contains(m.render(), "private context") { t.Fatal("privacy leak") } updated, _ = m.Update(tea.KeyPressMsg{Code: tea.KeyRight}) m = updated.(Model) - if !m.monitorContextHidden || m.monitorContextDetail != "" || m.rowContextMode("root-one") != contextSplit { + if m.defaultMonitorContextMode() != contextGraph || m.monitorContextDetail != "" || m.rowContextMode("root-one") != contextSplit { t.Fatal("i did not restore inline context") } m.openMonitorContext("root-one") @@ -207,21 +219,23 @@ func TestMonitorContextPrivacyAndModalIsolation(t *testing.T) { } } -func TestMonitorContextPrivacyPersistsWithoutText(t *testing.T) { +func TestMonitorContextCyclePersistsWithoutText(t *testing.T) { m := contextTestModel() store := &memoryPreferenceStore{} m.preferenceStore = store - m.toggleMonitorContext() - if !store.preferences.HideSessionContext { - t.Fatal("privacy not saved") - } - saved, err := json.Marshal(store.preferences) - if err != nil || strings.Contains(string(saved), "Finished") || strings.Contains(string(saved), "root-one") { - t.Fatalf("unexpected stored content: %s", saved) - } - next := NewWithPreferences(nil, time.Minute, store) - if !next.monitorContextHidden { - t.Fatal("privacy not restored") + for _, want := range []int{contextWide, contextGraph, contextSplit} { + m.cycleMonitorContext() + if store.preferences.SessionContextView != sessionContextViewNames[want] { + t.Fatal("global layout not saved") + } + saved, err := json.Marshal(store.preferences) + if err != nil || strings.Contains(string(saved), "Finished") || strings.Contains(string(saved), "root-one") || strings.Contains(string(saved), "hideSessionContext") { + t.Fatalf("unexpected stored content: %s", saved) + } + next := NewWithPreferences(nil, time.Minute, store) + if next.defaultMonitorContextMode() != want || next.rowContextMode("new-session") != want { + t.Fatal("global layout not restored") + } } } @@ -230,17 +244,20 @@ func TestMonitorContextPrivacyAndDismissRenderedTargets(t *testing.T) { m := contextTestModel() m.width = width for _, hidden := range []bool{false, true} { - m.monitorContextHidden = hidden + m.monitorContextView = "split" + if hidden { + m.monitorContextView = "graph" + } for y, line := range strings.Split(ansi.Strip(m.render()), "\n") { - if idx := strings.Index(line, m.monitorPrivacyLabel()); idx >= 0 { + if idx := strings.Index(line, m.monitorCycleLabel()); idx >= 0 { x := lipgloss.Width(line[:idx]) - for n := 0; n < lipgloss.Width(m.monitorPrivacyLabel()); n++ { - if m.monitorContextAt(x+n, y) != "privacy" { + for n := 0; n < lipgloss.Width(m.monitorCycleLabel()); n++ { + if m.monitorContextAt(x+n, y) != "cycle" { t.Fatal("privacy button miss") } } updated, _ := m.Update(tea.MouseClickMsg(tea.Mouse{X: x, Y: y, Button: tea.MouseLeft})) - if updated.(Model).monitorContextHidden == hidden { + if updated.(Model).defaultMonitorContextMode() == m.defaultMonitorContextMode() { t.Fatal("privacy click failed") } } @@ -255,16 +272,12 @@ func TestMonitorContextPrivacyAndDismissRenderedTargets(t *testing.T) { } } -func TestMonitorDetailToggleLabelsAdaptToWidth(t *testing.T) { +func TestMonitorCycleLabelAdaptsToWidth(t *testing.T) { m := contextTestModel() - for _, hidden := range []bool{false, true} { - m.monitorContextHidden = hidden - full, compact := i18n.Text("[ H: HIDE DETAIL ]"), i18n.Text("[H:HIDE]") - if hidden { - full, compact = i18n.Text("[ H: SHOW DETAIL ]"), i18n.Text("[H:SHOW]") - } - if m.monitorPrivacyLabel(100) != full || m.monitorPrivacyLabel(16) != compact { - t.Fatal("unexpected detail toggle label") + for _, view := range []string{"graph", "split", "wide"} { + m.monitorContextView = view + if m.monitorCycleLabel(100) != i18n.Text("[ C(Y)CLE ]") || m.monitorCycleLabel(10) != "[Y]" { + t.Fatal("unexpected Cycle label") } } } diff --git a/internal/ui/monitor_copy_test.go b/internal/ui/monitor_copy_test.go index bb5aa2ee..430962d5 100644 --- a/internal/ui/monitor_copy_test.go +++ b/internal/ui/monitor_copy_test.go @@ -59,7 +59,10 @@ func TestMonitorCopyRequiresVisibleDetail(t *testing.T) { for _, hidden := range []bool{false, true} { m := completedCopyModel() m.setRowContext("root-one", contextGraph) - m.monitorContextHidden = hidden + m.monitorContextView = "split" + if hidden { + m.monitorContextView = "graph" + } _, cmd := m.Update(tea.KeyPressMsg{Code: 'c', Text: "c"}) if cmd != nil { t.Fatal("graph-only/hidden detail unexpectedly copied a reply") diff --git a/internal/ui/monitor_detail.go b/internal/ui/monitor_detail.go index d3010f3b..019640e1 100644 --- a/internal/ui/monitor_detail.go +++ b/internal/ui/monitor_detail.go @@ -74,7 +74,7 @@ func (m Model) contextDetailDocument(width int) (document []detailLine) { var lines []detailLine appendText := func(text, kind, prefix string) { wrap := sessionWebTextLines - if c.Kind == codex.SessionContextApproval || kind != "body" { + if c.Kind == codex.SessionContextApproval || kind != "body" && kind != "reply" { wrap = sessionWebLiteralTextLines } for _, line := range wrap(text, max(width-lipgloss.Width(prefix), 1)) { @@ -128,6 +128,35 @@ func (m Model) contextDetailDocument(width int) (document []detailLine) { appendText(sanitize(c.Text), "body", "") lines = append(lines, detailLine{}) lines = append(lines, fileApprovalDocument(c.FileChanges, width)...) + } else if review := c.ActionReview(); c.Kind == codex.SessionContextApproval && review != nil { + section(i18n.Text(review.Title)) + for _, field := range review.Fields { + section(i18n.Text(field.Label)) + appendText(sanitize(field.Value), "body", "") + } + } else if c.Kind == codex.SessionContextApproval && c.MCPTool.Server != "" { + section(contextTitle(c)) + d := c.MCPTool + if d.Arguments == "" { + d.Arguments = "—" + } + appendText(sanitize(d.Message), "body", "") + for _, field := range []struct{ title, text string }{ + {i18n.Text("MCP SERVER"), d.Server}, {i18n.Text("TOOL"), d.Name}, + {i18n.Text("TITLE"), d.Title}, {i18n.Text("APP"), d.Connector}, + {i18n.Text("ARGUMENTS"), d.Arguments}, + } { + if field.text != "" { + section(field.title) + appendText(sanitize(field.text), "body", "") + } + } + for _, option := range c.ApprovalOptions { + if option.Detail != "" { + section(i18n.Text("PERMISSION SCOPE")) + appendText(sanitize(option.Detail), "warning", "") + } + } } else if c.Kind == codex.SessionContextApproval && c.CommandDetails.Command != "" { section(contextTitle(c)) d := c.CommandDetails @@ -167,7 +196,11 @@ func (m Model) contextDetailDocument(width int) (document []detailLine) { } text = strings.Join(parts, "\n") } - appendText(text, "body", "") + kind := "body" + if c.Kind == codex.SessionContextReply { + kind = "reply" + } + appendText(text, kind, "") } if c.ApprovalDecisions != "" { section(i18n.Text("OFFERED DECISIONS")) @@ -201,3 +234,9 @@ func (m Model) contextDetailLines(width int) []string { } return lines } + +// Rendering and read receipts must use the same clamped document slice. +func (m Model) detailVisibleRange(lineCount, rows int) (int, int) { + start := min(max(m.monitorContextScroll, 0), max(lineCount-rows, 0)) + return start, min(start+rows, lineCount) +} diff --git a/internal/ui/monitor_detail_activity_test.go b/internal/ui/monitor_detail_activity_test.go index 72664340..551def51 100644 --- a/internal/ui/monitor_detail_activity_test.go +++ b/internal/ui/monitor_detail_activity_test.go @@ -110,7 +110,8 @@ func TestMainSessionContextDots(t *testing.T) { t.Fatal("idle monitor animated") } m.monitorState = monitorRunning - m.monitorContextHidden = true + m.cycleMonitorContext() + m.cycleMonitorContext() if m.sessionActivityDots(s) != "" { t.Fatal("hidden context animated") } diff --git a/internal/ui/monitor_history.go b/internal/ui/monitor_history.go index 496248d2..866bef05 100644 --- a/internal/ui/monitor_history.go +++ b/internal/ui/monitor_history.go @@ -330,18 +330,22 @@ func (m Model) historyDocument(width int, s monitorSession, c codex.SessionConte } } lines := []detailLine{{ansi.Truncate(heading, width, "…"), "heading"}} - appendSection := func(title, text string) { + appendSection := func(title, text, kind string) { if text == "" { return } lines = append(lines, detailLine{}, detailLine{ansi.Truncate(title, width, "…"), "heading"}) for _, line := range sessionWebTextLines(codex.SanitizeSessionContext(text), width) { - lines = append(lines, detailLine{ansi.Truncate(line, width, ""), "body"}) + lines = append(lines, detailLine{ansi.Truncate(line, width, ""), kind}) } } - appendSection(i18n.Text("TASK"), c.CurrentTask) - appendSection(i18n.Text("LATEST GUIDANCE"), c.LatestGuidance) - appendSection(i18n.Text("LAST REPLY"), c.Text) + appendSection(i18n.Text("TASK"), c.CurrentTask, "body") + appendSection(i18n.Text("LATEST GUIDANCE"), c.LatestGuidance, "body") + replyKind := "body" + if c.Kind == codex.SessionContextReply && sameHistoryTurn(c, s.preview) && c.Text == s.preview.Text { + replyKind = "reply" + } + appendSection(i18n.Text("LAST REPLY"), c.Text, replyKind) // Current requests are still live; never render controls beside a saved // approval or present historical text as the justification for a new one. if s.preview.Kind == codex.SessionContextApproval || s.preview.Kind == codex.SessionContextQuestion || m.hasSessionProfile(s) { diff --git a/internal/ui/monitor_navigation.go b/internal/ui/monitor_navigation.go index 2627a579..5e5a7bdd 100644 --- a/internal/ui/monitor_navigation.go +++ b/internal/ui/monitor_navigation.go @@ -32,7 +32,7 @@ func (m Model) monitorNavigationButtons(width int, id string, full bool) []monit buttons = []monitorNavigationButton{ {label: "[↑]", action: "session-up", enabled: count > 0 && !m.monitorSummaryFocused}, {label: "[↓]", action: "session-down", enabled: count > 0 && (m.monitorAttentionFocused || m.monitorSummaryFocused || selected < 0 || selected < count-1)}, - {label: m.monitorPrivacyLabel(width - 8), action: "privacy", enabled: true}, + {label: m.monitorCycleLabel(width - 8), action: "cycle", enabled: count > 0}, } } else { mode := m.rowContextMode(id) @@ -52,11 +52,11 @@ func (m Model) monitorNavigationButtons(width int, id string, full bool) []monit return n } if width < groupWidth()+8 { - // Preserve the existing Hide/Show or Close control on small boxes. + // Preserve the Cycle or Close control on small boxes. if len(buttons) == 3 { buttons = buttons[2:] if id == "" { - buttons[0].label = m.monitorPrivacyLabel(width) + buttons[0].label = m.monitorCycleLabel(width) } } else { return nil diff --git a/internal/ui/monitor_prompt_test.go b/internal/ui/monitor_prompt_test.go index a0f72b0d..90f8ca88 100644 --- a/internal/ui/monitor_prompt_test.go +++ b/internal/ui/monitor_prompt_test.go @@ -92,7 +92,7 @@ func TestMonitorPromptEnterAndHotkeyIsolation(t *testing.T) { for _, text := range []string{"Q", "s", "t", "r", "h", "i", "X", "1", "C", "Hello 世界"} { m, _ = promptKey(m, []rune(text)[0], text) } - if m.monitorContextHidden || m.monitorContextDetail != "root-one" { + if m.defaultMonitorContextMode() == contextGraph || m.monitorContextDetail != "root-one" { t.Fatal("typing triggered dashboard action") } want := "QstrhiX1CHello 世界" diff --git a/internal/ui/monitor_read.go b/internal/ui/monitor_read.go index 15a95a48..4ecc7906 100644 --- a/internal/ui/monitor_read.go +++ b/internal/ui/monitor_read.go @@ -3,9 +3,11 @@ package ui import ( "context" "slices" + "strings" "time" tea "charm.land/bubbletea/v2" + "github.com/charmbracelet/x/ansi" "github.com/merefield/codexometer/internal/codex" ) @@ -15,9 +17,22 @@ type monitorReadResult struct { err error } -// Only deliberate input may acknowledge a result. Rendering, refreshes, -// restored layouts, hover and automatic history hydration never do so. +const monitorReadDelay = 3 * time.Second + +type monitorReadDwell struct { + id, turn, revision string + until time.Time +} + +type monitorReadDwellElapsed monitorReadDwell + +// Only deliberate selection/expansion starts the wide-row dwell. Full detail +// reviews immediately; rendering, restored layouts and result arrival do not. func (m Model) Update(message tea.Msg) (tea.Model, tea.Cmd) { + if elapsed, ok := message.(monitorReadDwellElapsed); ok { + command := m.finishMonitorReadDwell(monitorReadDwell(elapsed), time.Now()) + return m, command + } if result, ok := message.(monitorReadResult); ok { m.monitorReadBusy = false if result.err == nil { @@ -31,13 +46,16 @@ func (m Model) Update(message tea.Msg) (tea.Model, tea.Cmd) { } return m, nil } + if d := m.monitorReadDwell; d.id != "" && !m.validMonitorReadDwell(d) { + m.monitorReadDwell = monitorReadDwell{} + } m.monitorReadIntent = "" next, command := m.update(message) updated := next.(Model) deliberate := false switch msg := message.(type) { case tea.KeyPressMsg: - deliberate = true + deliberate = !msg.IsRepeat case tea.MouseClickMsg: deliberate = msg.Button == tea.MouseLeft case tea.MouseWheelMsg: @@ -50,43 +68,113 @@ func (m Model) Update(message tea.Msg) (tea.Model, tea.Cmd) { break } } - } if !deliberate { updated.monitorReadIntent = "" } - receipt := updated.acknowledgeMonitorResult() + if d := updated.monitorReadDwell; d.id != "" && !updated.validMonitorReadDwell(d) { + updated.monitorReadDwell = monitorReadDwell{} + } + id := updated.monitorReadIntent + updated.monitorReadIntent = "" + var receipt tea.Cmd + if id != "" && updated.monitorContextDetail == id { + updated.monitorReadDwell = monitorReadDwell{} + updated.monitorReadIntent = id + receipt = updated.acknowledgeMonitorResult() + } else if id != "" && updated.monitorReadDwell.id == "" { + row, eligible := updated.monitorWideReadResult(id) + if eligible { + d := monitorReadDwell{id: id, turn: row.preview.TurnID, revision: row.readState.Revision, until: time.Now().Add(monitorReadDelay)} + updated.monitorReadDwell = d + receipt = tea.Tick(monitorReadDelay, func(time.Time) tea.Msg { return monitorReadDwellElapsed(d) }) + } + } return updated, tea.Batch(command, receipt) } -func (m *Model) acknowledgeMonitorResult() tea.Cmd { - id := m.monitorReadIntent - m.monitorReadIntent = "" - client, ok := m.fetcher.(codex.SessionReadStateClient) - if !ok || id == "" || m.actionReview != nil || m.monitorReadBusy || m.meterView != viewMonitor || m.monitorState != monitorRunning || m.monitorError != "" || m.monitorCommands.open || m.monitorQueue.open || m.scheduleUI.open || m.rowContextMode(id) == contextGraph { - return nil +func (m Model) monitorUnreadResult(id string) (monitorSession, bool) { + if _, ok := m.fetcher.(codex.SessionReadStateClient); !ok || id == "" || m.width <= 0 || m.height <= 0 || m.actionReview != nil || m.monitorReadBusy || m.meterView != viewMonitor || m.monitorState != monitorRunning || m.monitorError != "" || m.monitorCommands.open || m.monitorQueue.open || m.scheduleUI.open { + return monitorSession{}, false } for _, row := range m.monitorSessionData { c := row.preview if row.id != id || m.hasSessionProfile(row) || !m.monitorSessionVisible(row) || !row.readState.Unread || !row.readState.Known() || c.Kind != codex.SessionContextReply || c.Streaming || c.Text == "" || c.ThreadID != id || c.TurnID == "" { continue } - if _, visible := m.monitorResultRect(id); !visible { - return nil + rect, visible := m.monitorResultRect(id) + if !visible { + return monitorSession{}, false } - if h := m.monitorHistory[id]; h.selected != nil && !sameHistoryTurn(*h.selected, c) { - return nil + if m.monitorContextDetail == id { + document := m.contextDetailDocument(rect.width) + start, end := m.detailVisibleRange(len(document), rect.height) + if !slices.ContainsFunc(document[start:end], func(line detailLine) bool { + return line.kind == "reply" && strings.TrimSpace(ansi.Strip(line.text)) != "" + }) { + return monitorSession{}, false + } } - revision, turn := row.readState.Revision, c.TurnID - m.monitorReadBusy = true - return func() tea.Msg { - ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second) - defer cancel() - state, err := client.AcknowledgeSessionResult(ctx, id, turn, revision) - return monitorReadResult{id: id, revision: revision, state: state, err: err} + if h := m.monitorHistory[id]; h.selected != nil && !sameHistoryTurn(*h.selected, c) { + return monitorSession{}, false } + return row, true + } + return monitorSession{}, false +} + +func (m Model) monitorWideReadResult(id string) (monitorSession, bool) { + if m.monitorContextDetail != "" || m.monitorSelectedID != id || m.rowContextMode(id) != contextWide || m.monitorSummaryFocused || m.monitorAttentionFocused || m.monitorPrompt.input.Focused() { + return monitorSession{}, false + } + row, ok := m.monitorUnreadResult(id) + if !ok { + return monitorSession{}, false + } + rect, _ := m.monitorResultRect(id) + header := terminalLabel(row.preview.ThreadID) + " // " + terminalLabel(row.preview.Source) + if rect.height <= len(sessionWebTextLines(header, max(rect.width, 1))) { + return monitorSession{}, false // Source metadata alone is not a visible reply. + } + return row, true +} + +func (m Model) validMonitorReadDwell(d monitorReadDwell) bool { + row, ok := m.monitorWideReadResult(d.id) + return ok && row.preview.TurnID == d.turn && row.readState.Revision == d.revision +} + +func (m *Model) finishMonitorReadDwell(d monitorReadDwell, now time.Time) tea.Cmd { + if d.id == "" || m.monitorReadDwell != d || now.Before(d.until) { + return nil + } + m.monitorReadDwell = monitorReadDwell{} + if !m.validMonitorReadDwell(d) { + return nil + } + m.monitorReadIntent = d.id + return m.acknowledgeMonitorResult() +} + +func (m *Model) acknowledgeMonitorResult() tea.Cmd { + id := m.monitorReadIntent + m.monitorReadIntent = "" + if m.monitorContextDetail != id && (m.monitorSelectedID != id || m.rowContextMode(id) != contextWide) { + return nil + } + row, ok := m.monitorUnreadResult(id) + if !ok { + return nil + } + client := m.fetcher.(codex.SessionReadStateClient) + revision, turn := row.readState.Revision, row.preview.TurnID + m.monitorReadBusy = true + return func() tea.Msg { + ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second) + defer cancel() + state, err := client.AcknowledgeSessionResult(ctx, id, turn, revision) + return monitorReadResult{id: id, revision: revision, state: state, err: err} } - return nil } // Match the actual displayed context pane, including narrow split layouts diff --git a/internal/ui/monitor_read_test.go b/internal/ui/monitor_read_test.go index 68971363..9a904bbc 100644 --- a/internal/ui/monitor_read_test.go +++ b/internal/ui/monitor_read_test.go @@ -33,7 +33,7 @@ func unreadTestModel() (Model, *readTestClient) { return m, client } -func TestUnreadPartialDetailAcknowledgesOnlyExplicitReview(t *testing.T) { +func TestUnreadSplitStaysUnreadAndWideRequiresDwell(t *testing.T) { m, c := unreadTestModel() m.render() if len(c.reads) != 0 { @@ -49,11 +49,21 @@ func TestUnreadPartialDetailAcknowledgesOnlyExplicitReview(t *testing.T) { m.setRowContext("root-one", contextGraph) next, cmd := m.Update(tea.KeyPressMsg{Code: tea.KeyRight}) m = next.(Model) - if cmd == nil || m.rowContextMode("root-one") != contextSplit { - t.Fatal("opening partial detail did not stage receipt") + if cmd != nil || m.rowContextMode("root-one") != contextSplit || m.monitorReadDwell.id != "" { + t.Fatal("split preview staged a receipt") } - if len(c.reads) != 0 { - t.Fatal("receipt sent before command dispatch") + next, cmd = m.Update(tea.KeyPressMsg{Code: tea.KeyRight}) + m = next.(Model) + dwell := m.monitorReadDwell + if cmd == nil || dwell.id != "root-one" || m.monitorReadBusy || len(c.reads) != 0 { + t.Fatal("wide selection did not start a delayed review") + } + if m.finishMonitorReadDwell(dwell, dwell.until.Add(-time.Millisecond)) != nil { + t.Fatal("wide review completed before three seconds") + } + cmd = m.finishMonitorReadDwell(dwell, dwell.until) + if cmd == nil { + t.Fatal("wide review did not complete after three seconds") } result := cmd().(monitorReadResult) if len(c.reads) != 1 || c.reads[0] != "root-one/t1/v1" { @@ -81,7 +91,7 @@ func TestUnreadPartialDetailAcknowledgesOnlyExplicitReview(t *testing.T) { } func TestUnreadHistoryAndUnavailableContextCannotAcknowledgeLatest(t *testing.T) { - for _, mode := range []string{"older-history", "streaming", "child", "no-text", "stale", "unsupported"} { + for _, mode := range []string{"older-history", "older-text", "streaming", "child", "no-text", "stale", "unsupported"} { t.Run(mode, func(t *testing.T) { m, c := unreadTestModel() m.setRowContext("root-one", contextFull) @@ -90,6 +100,10 @@ func TestUnreadHistoryAndUnavailableContextCannotAcknowledgeLatest(t *testing.T) old := m.monitorSessionData[0].preview old.TurnID = "older" m.saveMonitorHistory("root-one", monitorTurnHistory{selected: &old}) + case "older-text": + old := m.monitorSessionData[0].preview + old.Text = "A previous reply revision" + m.saveMonitorHistory("root-one", monitorTurnHistory{selected: &old}) case "streaming": m.monitorSessionData[0].preview.Streaming = true case "child": @@ -166,26 +180,21 @@ func TestUnreadLiveReviewGestures(t *testing.T) { } } -func TestUnreadIndependentPartialPaneWithHiddenGlobalLayout(t *testing.T) { +func TestUnreadIndependentSplitPaneCannotAcknowledgeByScrolling(t *testing.T) { m, client := unreadTestModel() - m.monitorContextHidden = true + m.monitorContextView = "graph" next, cmd := m.Update(tea.KeyPressMsg{Code: tea.KeyRight}) m = next.(Model) - if !m.contextTargetHidden() || m.rowContextMode("root-one") != contextSplit || cmd == nil || !m.monitorReadBusy { - t.Fatal("opening independent partial pane did not acknowledge visible result") - } - cmd() - if len(client.reads) != 1 { - t.Fatal("visible partial pane was not acknowledged") + if !m.contextTargetHidden() || m.rowContextMode("root-one") != contextSplit || cmd != nil || m.monitorReadBusy { + t.Fatal("split expansion acknowledged a result") } - m.monitorReadBusy = false rect, ok := m.monitorResultRect("root-one") if !ok { t.Fatal("partial result has no visible body") } next, cmd = m.Update(tea.MouseWheelMsg{X: rect.x, Y: rect.y, Button: tea.MouseWheelDown}) - if !next.(Model).monitorReadBusy || cmd == nil { - t.Fatal("wheel over independent result did not acknowledge it") + if next.(Model).monitorReadBusy || cmd != nil || len(client.reads) != 0 { + t.Fatal("wheel over split preview acknowledged a result") } } @@ -206,8 +215,9 @@ func TestUnreadCompactPartialResultBounds(t *testing.T) { t.Fatalf("mode %v height %d: visible compact reply has incorrect bounds: %+v", mode, height, rect) } next, cmd := m.Update(tea.MouseWheelMsg{X: rect.x, Y: rect.y, Button: tea.MouseWheelUp}) - if cmd == nil || !next.(Model).monitorReadBusy { - t.Fatalf("visible compact reply could not be reviewed: mode=%d paneHeight=%d terminalHeight=%d rect=%+v model=%+v", mode, height, terminalHeight, rect, next.(Model).monitorError) + wantDwell := mode == contextWide && height > 3 + if next.(Model).monitorReadBusy || (next.(Model).monitorReadDwell.id != "") != wantDwell || (!wantDwell && cmd != nil) { + t.Fatalf("compact reply bypassed the wide-only delay: mode=%d paneHeight=%d terminalHeight=%d", mode, height, terminalHeight) } found = true break @@ -247,3 +257,155 @@ func TestUnreadFullResultBoundsExcludeControls(t *testing.T) { } } } + +func TestBulkCycleDoesNotAcknowledgeUnreadResults(t *testing.T) { + m, client := unreadTestModel() + m.monitorContextDetail, m.monitorContextExpanded = "", "" + for range 4 { + next, cmd := m.Update(key('y')) + m = next.(Model) + if cmd != nil || m.monitorReadBusy || len(client.reads) != 0 || m.monitorReadIntent != "" { + t.Fatal("bulk layout change acknowledged an unread reply") + } + } +} + +func TestWideReadDwellCancelsWhenReadingContextChanges(t *testing.T) { + for _, change := range []string{"selection", "split", "tab", "revision", "turn", "stale", "history", "commands", "hidden"} { + t.Run(change, func(t *testing.T) { + m, c := unreadTestModel() + m.setRowContext("root-one", contextSplit) + next, _ := m.Update(tea.KeyPressMsg{Code: tea.KeyRight}) + m = next.(Model) + dwell := m.monitorReadDwell + if dwell.id == "" { + t.Fatal("missing dwell") + } + switch change { + case "selection": + m.monitorSelectedID = "root-two" + case "split": + m.setRowContext("root-one", contextSplit) + case "tab": + m.meterView = viewBars + case "revision": + m.monitorSessionData[0].readState.Revision = "new" + case "turn": + m.monitorSessionData[0].preview.TurnID = "new" + case "stale": + m.monitorError = "offline" + case "history": + old := m.monitorSessionData[0].preview + old.TurnID = "old" + m.saveMonitorHistory("root-one", monitorTurnHistory{selected: &old}) + case "commands": + m.monitorCommands.open = true + case "hidden": + m.height = 0 + } + next, _ = m.Update(tea.MouseMotionMsg{}) + m = next.(Model) + if m.finishMonitorReadDwell(dwell, dwell.until) != nil || len(c.reads) != 0 { + t.Fatal("stale dwell acknowledged a result") + } + }) + } +} + +func TestSelectingWideRowStartsDwellButNewArrivalDoesNot(t *testing.T) { + m, _ := unreadTestModel() + m.setRowContext("root-one", contextWide) + m.setRowContext("root-two", contextWide) + next, _ := m.Update(tea.KeyPressMsg{Code: tea.KeyUp}) + m = next.(Model) + if m.monitorReadDwell.id != "root-one" { + t.Fatal("deliberate wide selection did not start dwell") + } + old := m.monitorReadDwell + m.monitorSessionData[0].readState.Revision = "v2" + next, _ = m.Update(tea.MouseMotionMsg{}) + m = next.(Model) + if m.monitorReadDwell.id != "" || m.finishMonitorReadDwell(old, old.until) != nil { + t.Fatal("new result inherited an old dwell") + } +} + +func TestOpeningFullDetailAcknowledgesWithoutWideDelay(t *testing.T) { + m, client := unreadTestModel() + m.setRowContext("root-one", contextWide) + next, cmd := m.Update(tea.KeyPressMsg{Code: tea.KeyRight}) + m = next.(Model) + if cmd == nil || !m.monitorReadBusy || m.monitorReadDwell.id != "" { + t.Fatal("full detail did not acknowledge immediately") + } + cmd() + if len(client.reads) != 1 { + t.Fatal("full detail did not send its receipt") + } +} + +func TestUnreadFullDetailRequiresVisibleReplyLines(t *testing.T) { + for _, prefix := range []string{"task", "guidance", "metadata", "current-history"} { + t.Run(prefix, func(t *testing.T) { + m, client := unreadTestModel() + m.setRowContext("root-one", contextFull) + row := &m.monitorSessionData[0] + row.preview.Text = "VISIBLE REPLY" + long := strings.Repeat("Context before the result.\n", 80) + switch prefix { + case "task", "current-history": + row.preview.CurrentTask = long + case "guidance": + row.preview.LatestGuidance = long + case "metadata": + row.preview.Source = strings.Repeat("SOURCE ", 500) + } + if prefix == "current-history" { + current := row.preview + m.saveMonitorHistory("root-one", monitorTurnHistory{selected: ¤t}) + } + m.monitorReadIntent = "root-one" + if cmd := m.acknowledgeMonitorResult(); cmd != nil || m.monitorReadBusy || len(client.reads) != 0 { + t.Fatal("metadata or hidden reply acknowledged the result") + } + rect, visible := m.monitorResultRect("root-one") + if !visible { + t.Fatal("fixture has no visible document body") + } + document := m.contextDetailDocument(rect.width) + replyAt := -1 + for i, line := range document { + if line.kind == "reply" && strings.Contains(line.text, "VISIBLE REPLY") { + replyAt = i + break + } + } + if replyAt < 0 { + t.Fatal("reply has no document identity") + } + // One actual reply line intersecting the viewport is sufficient. The same + // scroll slice is used by rendering, including its lower/upper clamps. + m.monitorContextScroll = max(replyAt-rect.height+1, 0) + m.monitorReadIntent = "root-one" + cmd := m.acknowledgeMonitorResult() + if cmd == nil { + t.Fatal("visible reply could not be acknowledged") + } + cmd() + if len(client.reads) != 1 || client.reads[0] != "root-one/t1/v1" { + t.Fatal("wrong visible result acknowledged", client.reads) + } + }) + } +} + +func TestUnreadFullDetailDoesNotCountTrailingNotices(t *testing.T) { + m, client := unreadTestModel() + m.setRowContext("root-one", contextFull) + m.quota.notices = map[string]string{"root-one": strings.Repeat("Notice after the reply.\n", 80)} + m.monitorContextScroll = m.monitorContextScrollLimit() + m.monitorReadIntent = "root-one" + if cmd := m.acknowledgeMonitorResult(); cmd != nil || len(client.reads) != 0 { + t.Fatal("notice-only viewport marked reply read") + } +} diff --git a/internal/ui/preferences.go b/internal/ui/preferences.go index 51557038..422e4bd4 100644 --- a/internal/ui/preferences.go +++ b/internal/ui/preferences.go @@ -13,7 +13,8 @@ import ( // Operational, account, quota-estimation, session, and token-event data are // never stored. type Preferences struct { - HideSessionContext bool `json:"hideSessionContext,omitempty"` + HideSessionContext bool `json:"hideSessionContext,omitempty"` // Read legacy preferences only. + SessionContextView string `json:"sessionContextView,omitempty"` Theme string `json:"theme,omitempty"` MainTab string `json:"mainTab,omitempty"` QuotaView string `json:"quotaView,omitempty"` @@ -82,7 +83,14 @@ func (m *Model) applyPreferences(preferences Preferences) { if preferences.StatusLine != nil { m.monitorStatusLine = statusline.Normalize(preferences.StatusLine) } - m.monitorContextHidden = preferences.HideSessionContext + switch preferences.SessionContextView { + case "graph", "split", "wide": + m.monitorContextView = preferences.SessionContextView + default: + if preferences.HideSessionContext { + m.monitorContextView = "graph" + } + } if theme, ok := themePreferenceIDs[preferences.Theme]; ok { m.theme = theme } @@ -115,7 +123,7 @@ func (m Model) persistPreferences() { return } _ = m.preferenceStore.Save(Preferences{ - HideSessionContext: m.monitorContextHidden, + SessionContextView: sessionContextViewNames[m.defaultMonitorContextMode()], Theme: themePreferenceNames[m.theme], MainTab: mainTabPreferenceNames[m.currentMainTab()], QuotaView: quotaViewPreferenceNames[m.selectedQuotaView()], @@ -134,10 +142,10 @@ var themePreferenceNames = map[themeID]string{ themeUltraviolet: "ultraviolet", themeNightshade: "nightshade", } -var themePreferenceIDs = reverseThemePreferences(themePreferenceNames) +var themePreferenceIDs = reversePreferenceNames(themePreferenceNames) -func reverseThemePreferences(values map[themeID]string) map[string]themeID { - reversed := make(map[string]themeID, len(values)) +func reversePreferenceNames[T comparable](values map[T]string) map[string]T { + reversed := make(map[string]T, len(values)) for id, value := range values { reversed[value] = id } @@ -151,10 +159,7 @@ var quotaViewPreferenceNames = map[meterViewID]string{ var quotaViewPreferenceIDs = reverseViewPreferences(quotaViewPreferenceNames) func reverseViewPreferences(values map[meterViewID]string) map[string]meterViewID { - reversed := make(map[string]meterViewID, len(values)) - for id, value := range values { - reversed[value] = id - } + reversed := reversePreferenceNames(values) // Restore previous graph selections to the former Zone, now named Pace. if _, ok := values[viewPace]; ok { reversed["consumption-pace"] = viewPace @@ -167,26 +172,10 @@ var benchmarkFilterPreferenceNames = map[benchmarkResultFilter]string{ benchmarkFilterAll: "all", benchmarkFilterPass: "pass", benchmarkFilterFail: "fail", } -var benchmarkFilterPreferenceIDs = reverseFilterPreferences(benchmarkFilterPreferenceNames) - -func reverseFilterPreferences(values map[benchmarkResultFilter]string) map[string]benchmarkResultFilter { - reversed := make(map[string]benchmarkResultFilter, len(values)) - for id, value := range values { - reversed[value] = id - } - return reversed -} +var benchmarkFilterPreferenceIDs = reversePreferenceNames(benchmarkFilterPreferenceNames) var benchmarkRankPreferenceNames = map[benchmarkRankMode]string{ benchmarkRankBalanced: "balanced", benchmarkRankCost: "cost", benchmarkRankSpeed: "speed", } -var benchmarkRankPreferenceIDs = reverseRankPreferences(benchmarkRankPreferenceNames) - -func reverseRankPreferences(values map[benchmarkRankMode]string) map[string]benchmarkRankMode { - reversed := make(map[string]benchmarkRankMode, len(values)) - for id, value := range values { - reversed[value] = id - } - return reversed -} +var benchmarkRankPreferenceIDs = reversePreferenceNames(benchmarkRankPreferenceNames) diff --git a/internal/ui/preferences_test.go b/internal/ui/preferences_test.go index 22879011..9e7f3b3c 100644 --- a/internal/ui/preferences_test.go +++ b/internal/ui/preferences_test.go @@ -150,3 +150,20 @@ func TestRestoredTabsLoadDataWithoutStartingBenchmark(t *testing.T) { t.Fatal("wrong usage startup command") } } + +func TestSessionContextPreferenceAcceptsThreeViewsAndLegacyHide(t *testing.T) { + for _, tc := range []struct { + view string + hidden bool + want int + }{ + {"", false, contextSplit}, {"", true, contextGraph}, + {"graph", false, contextGraph}, {"split", true, contextSplit}, + {"wide", false, contextWide}, {"full", false, contextSplit}, + } { + m := NewWithPreferences(nil, time.Minute, &memoryPreferenceStore{preferences: Preferences{SessionContextView: tc.view, HideSessionContext: tc.hidden}}) + if m.defaultMonitorContextMode() != tc.want { + t.Fatalf("%+v: got %d", tc, m.defaultMonitorContextMode()) + } + } +} diff --git a/internal/web/control.go b/internal/web/control.go index c0425f8e..db226354 100644 --- a/internal/web/control.go +++ b/internal/web/control.go @@ -50,17 +50,19 @@ type actionQuestion struct { } type actionOffer struct { - RequiredHumanApproval bool `json:"requiredHumanApproval,omitempty"` - FileChanges []codex.FileDiffLine `json:"fileChanges,omitempty"` - Profile *profileReview `json:"profile,omitempty"` - ID string `json:"id"` - Session string `json:"session"` - Thread string `json:"thread"` - Directory string `json:"directory"` - Kind string `json:"kind"` - Command string `json:"command"` - Choices []actionChoice `json:"choices"` - Questions []actionQuestion `json:"questions"` + ApprovalReview *codex.ApprovalReview `json:"approvalReview,omitempty"` + MCPTool *codex.MCPToolApprovalDetails `json:"mcpTool,omitempty"` + RequiredHumanApproval bool `json:"requiredHumanApproval,omitempty"` + FileChanges []codex.FileDiffLine `json:"fileChanges,omitempty"` + Profile *profileReview `json:"profile,omitempty"` + ID string `json:"id"` + Session string `json:"session"` + Thread string `json:"thread"` + Directory string `json:"directory"` + Kind string `json:"kind"` + Command string `json:"command"` + Choices []actionChoice `json:"choices"` + Questions []actionQuestion `json:"questions"` } type offeredAction struct { @@ -119,19 +121,24 @@ func (c *control) offer(id string) (offeredAction, error) { } o := offeredAction{actionOffer: actionOffer{Session: id, Thread: id, Directory: directory}} if ctx.Kind == codex.SessionContextApproval { - if c.approvals == nil || ctx.ApprovalToken == "" || ctx.ApprovalBlocked != "" || (ctx.FileChanges == "" && (ctx.CommandDetails.Command == "" || ctx.CommandDetails.Directory == "")) || ctx.ThreadID == "" || !c.approvals.SessionApprovalPending(ctx.ApprovalToken) { + if c.approvals == nil || ctx.ApprovalToken == "" || ctx.ApprovalBlocked != "" || (ctx.FileChanges == "" && ctx.MCPTool.Server == "" && ctx.ActionReview() == nil && (ctx.CommandDetails.Command == "" || ctx.CommandDetails.Directory == "")) || ctx.ThreadID == "" || !c.approvals.SessionApprovalPending(ctx.ApprovalToken) { return o, nil } o.Kind, o.token = "approval", ctx.ApprovalToken o.RequiredHumanApproval = ctx.RequiredHumanApproval + o.ApprovalReview = ctx.ActionReview() + if ctx.MCPTool.Server != "" { + details := ctx.MCPTool + o.MCPTool = &details + } o.Command, o.Directory, o.Thread = ctx.CommandDetails.Command, ctx.CommandDetails.Directory, ctx.ThreadID o.FileChanges = codex.FileDiffLines(ctx.FileChanges) for _, option := range ctx.ApprovalOptions { - label := map[string]string{"accept": "APPROVE ONCE", "acceptForSession": "ALLOW FOR SESSION", "acceptWithExecpolicyAmendment": "ALWAYS ALLOW PREFIX", "decline": "DECLINE", "cancel": "REJECT & STOP TURN"}[option.Kind] + label := option.Label(false) if label == "" { continue } - o.Choices = append(o.Choices, actionChoice{label, option.Detail, option.Kind == "acceptForSession" || option.Kind == "acceptWithExecpolicyAmendment"}) + o.Choices = append(o.Choices, actionChoice{label, option.Detail, option.ChangesPolicy()}) o.decisions = append(o.decisions, option.Value) } if len(o.Choices) == 0 { diff --git a/internal/web/control_test.go b/internal/web/control_test.go index b4eddb48..9322ca60 100644 --- a/internal/web/control_test.go +++ b/internal/web/control_test.go @@ -405,3 +405,92 @@ func TestLiveTaskAndStreamProjection(t *testing.T) { t.Fatal(got) } } + +func TestMCPApprovalOfferUsesToolDetailsAndAllAdvertisedChoices(t *testing.T) { + s, f, token := controlServer(t) + ctx := codex.SessionContext{Kind: codex.SessionContextApproval, ThreadID: "child", ApprovalToken: "private-approval", Text: "Allow tool?", MCPTool: codex.MCPToolApprovalDetails{Server: "tools", Name: "create_event", Message: "Allow tool?", Arguments: `{"title":"Demo"}`}, ApprovalOptions: [8]codex.ApprovalOption{{Kind: "accept", Value: "accept"}, {Kind: "acceptForSession", Value: "acceptForSession", Detail: "Current session"}, {Kind: "acceptMcpAlways", Value: "acceptMcpAlways", Detail: "Future sessions"}, {Kind: "cancelMcpTool", Value: "cancelMcpTool"}}} + s.store.live(codex.LiveUsageSnapshot{Sessions: []codex.LiveUsageSession{{ID: "parent", Context: ctx}}}, nil, time.Now()) + o := getOffer(t, s, token) + if o.MCPTool == nil || o.MCPTool.Name != "create_event" || o.Command != "" || o.Directory != "" || o.Thread != "child" || len(o.Choices) != 4 { + t.Fatalf("bad MCP offer: %+v", o) + } + for i, label := range []string{"APPROVE ONCE", "ALLOW FOR SESSION", "ALWAYS ALLOW TOOL", "CANCEL TOOL CALL"} { + if o.Choices[i].Label != label || o.Choices[i].Persistent != (i == 1 || i == 2) { + t.Fatal("wrong MCP choice scope", o.Choices) + } + } + index := 2 + r := prepareAction(t, s, token, actionRequest{Session: "parent", Offer: o.ID, Choice: &index}) + changed := ctx + changed.MCPTool.Arguments = `{"title":"Changed"}` + s.store.contexts["parent"] = changed + if w := actionCall(s, token, "commit", r); w.Code != 409 || f.calls != 0 { + t.Fatal("changed MCP arguments reused a review") + } + s.store.contexts["parent"] = ctx + o = getOffer(t, s, token) + r = prepareAction(t, s, token, actionRequest{Session: "parent", Offer: o.ID, Choice: &index}) + w := actionCall(s, token, "commit", r) + if w.Code != 200 || f.decision != "acceptMcpAlways" || f.calls != 1 { + t.Fatalf("MCP grant not committed: %d %s", w.Code, w.Body.String()) + } +} + +func TestNetworkApprovalReviewIsBoundToDestinationAndRule(t *testing.T) { + s, f, token := controlServer(t) + ctx := codex.SessionContext{Kind: codex.SessionContextApproval, ThreadID: "child", ApprovalToken: "private-approval", ActionDetails: codex.ApprovalActionDetails{Kind: "network", Target: "example.com", Protocol: "https"}, ApprovalOptions: [8]codex.ApprovalOption{{Kind: "accept", Value: "accept"}, {Kind: "allowNetworkHost", Value: "allow-rule", Detail: "Future requests"}, {Kind: "denyNetworkHost", Value: "deny-rule", Detail: "Future requests"}}} + s.store.live(codex.LiveUsageSnapshot{Sessions: []codex.LiveUsageSession{{ID: "parent", Context: ctx}}}, nil, time.Now()) + offer := getOffer(t, s, token) + if offer.ApprovalReview == nil || offer.ApprovalReview.Title != "NETWORK APPROVAL" || offer.Command != "" || offer.Thread != "child" || len(offer.Choices) != 3 || !offer.Choices[1].Persistent || !offer.Choices[2].Persistent || offer.Choices[0].Persistent { + t.Fatalf("bad network review: %+v", offer) + } + index := 2 + prepared := prepareAction(t, s, token, actionRequest{Session: "parent", Offer: offer.ID, Choice: &index}) + changed := ctx + changed.ActionDetails.Target = "other.example" + s.store.contexts["parent"] = changed + if w := actionCall(s, token, "commit", prepared); w.Code != 409 || f.calls != 0 { + t.Fatal("changed destination reused review") + } + s.store.contexts["parent"] = ctx + offer = getOffer(t, s, token) + prepared = prepareAction(t, s, token, actionRequest{Session: "parent", Offer: offer.ID, Choice: &index}) + if w := actionCall(s, token, "commit", prepared); w.Code != 200 || f.decision != "deny-rule" { + t.Fatalf("network denial not committed: %d", w.Code) + } +} + +func TestStdinApprovalPreparationBindsExactInputAndTerminal(t *testing.T) { + for _, field := range []string{"input", "target", "directory"} { + t.Run(field, func(t *testing.T) { + s, f, token := controlServer(t) + ctx := codex.SessionContext{Kind: codex.SessionContextApproval, ThreadID: "child", ApprovalToken: "private-approval", ActionDetails: codex.ApprovalActionDetails{Kind: "stdin", Target: "123", Input: "yes\n\x03", Directory: "/start"}, ApprovalOptions: [8]codex.ApprovalOption{{Kind: "acceptStdin", Value: "accept"}, {Kind: "cancelStdin", Value: "cancel"}}} + s.store.live(codex.LiveUsageSnapshot{Sessions: []codex.LiveUsageSession{{ID: "parent", Context: ctx}}}, nil, time.Now()) + offer := getOffer(t, s, token) + if offer.ApprovalReview == nil || offer.Command != "" || len(offer.Choices) != 2 || offer.Choices[0].Persistent || offer.Choices[1].Persistent || offer.Choices[0].Label != "SEND INPUT ONCE" { + t.Fatalf("bad input offer %+v", offer) + } + index := 0 + prepared := prepareAction(t, s, token, actionRequest{Session: "parent", Offer: offer.ID, Choice: &index}) + changed := ctx + switch field { + case "input": + changed.ActionDetails.Input = "no\n" + case "target": + changed.ActionDetails.Target = "456" + case "directory": + changed.ActionDetails.Directory = "/other" + } + s.store.contexts["parent"] = changed + if w := actionCall(s, token, "commit", prepared); w.Code != 409 || f.calls != 0 { + t.Fatal("changed terminal input reused review") + } + s.store.contexts["parent"] = ctx + offer = getOffer(t, s, token) + prepared = prepareAction(t, s, token, actionRequest{Session: "parent", Offer: offer.ID, Choice: &index}) + if w := actionCall(s, token, "commit", prepared); w.Code != 200 || f.decision != "accept" { + t.Fatal("input decision failed") + } + }) + } +} diff --git a/internal/web/dist/assets/index-DYxZORQa.css b/internal/web/dist/assets/index-Ck-q96h6.css similarity index 82% rename from internal/web/dist/assets/index-DYxZORQa.css rename to internal/web/dist/assets/index-Ck-q96h6.css index 7a2f5005..4da888cc 100644 --- a/internal/web/dist/assets/index-DYxZORQa.css +++ b/internal/web/dist/assets/index-Ck-q96h6.css @@ -1 +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}}.usage-diagnostic.svelte-16u6dmb{white-space:pre-wrap;overflow-wrap:anywhere}.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}.goal-summary.svelte-7bfwr9 p:where(.svelte-7bfwr9){white-space:nowrap;text-overflow:ellipsis;margin:0;overflow:hidden}.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}.command-options.svelte-7bfwr9 button.suggested:where(.svelte-7bfwr9) .command-name:where(.svelte-7bfwr9){color:var(--ink);font-weight:700}.command-options.svelte-7bfwr9 button:where(.svelte-7bfwr9):not(.suggested):hover .command-name:where(.svelte-7bfwr9){text-decoration:underline}.command-options.svelte-7bfwr9 button:where(.svelte-7bfwr9){color:var(--muted)}.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:none}.command-help.svelte-7bfwr9{text-overflow:ellipsis;white-space:nowrap;opacity:.75;max-width:32ch;font-size:.8em;display:block;overflow:hidden}.command-actions.svelte-7bfwr9{flex-wrap:wrap;gap:.35rem;margin-top:.4rem;display:flex}.availability.svelte-7bfwr9{font-weight:600}.navigation.svelte-7bfwr9{font-size:.8em}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)}.goal-status.svelte-1yfu3xi{color:var(--accent);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:.8rem;font-weight:700;overflow:hidden}.pursuing.svelte-1yfu3xi{color:#67d391}.blocked.svelte-1yfu3xi{color:var(--approval)}.stale.svelte-1yfu3xi{color:var(--muted)}.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}.compact.svelte-543j00{flex-shrink:0;margin-top:0;padding-top:0}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)}.reviewed.svelte-mm4wfe{color:var(--muted);font-weight:400}.reviewed.svelte-mm4wfe .lamp:where(.svelte-mm4wfe){opacity:.35}.failed.svelte-mm4wfe{color:var(--approval)}.lamp.failed.svelte-mm4wfe{background:var(--approval);box-shadow:0 0 8px color-mix(in srgb, var(--approval) 40%, transparent)}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%}svg.svelte-1jpy949{fill:currentColor;width:100%;height:auto;display:block}.startup.svelte-19xbbtg{z-index:100;background:var(--bg);color:var(--accent);position:fixed;inset:0;overflow:hidden}.wordmark.svelte-19xbbtg{position:absolute}button.svelte-19xbbtg{color:var(--muted);font:inherit;white-space:nowrap;background:0 0;border:0;font-size:12px;position:absolute;bottom:24px;left:50%;transform:translate(-50%)}: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}.shell[data-starting=true]>header,.shell[data-starting=true]>nav,.shell[data-starting=true]>main,.shell[data-starting=true]>footer{visibility:hidden}.brand{width:clamp(240px,32vw,405px);max-width:calc(100vw - 40px);color:var(--accent);text-decoration:none;display:block}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}} +.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}}.usage-diagnostic.svelte-16u6dmb{white-space:pre-wrap;overflow-wrap:anywhere}.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}.goal-summary.svelte-7bfwr9 p:where(.svelte-7bfwr9){white-space:nowrap;text-overflow:ellipsis;margin:0;overflow:hidden}.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}.command-options.svelte-7bfwr9 button.suggested:where(.svelte-7bfwr9) .command-name:where(.svelte-7bfwr9){color:var(--ink);font-weight:700}.command-options.svelte-7bfwr9 button:where(.svelte-7bfwr9):not(.suggested):hover .command-name:where(.svelte-7bfwr9){text-decoration:underline}.command-options.svelte-7bfwr9 button:where(.svelte-7bfwr9){color:var(--muted)}.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:none}.command-help.svelte-7bfwr9{text-overflow:ellipsis;white-space:nowrap;opacity:.75;max-width:32ch;font-size:.8em;display:block;overflow:hidden}.command-actions.svelte-7bfwr9{flex-wrap:wrap;gap:.35rem;margin-top:.4rem;display:flex}.availability.svelte-7bfwr9{font-weight:600}.navigation.svelte-7bfwr9{font-size:.8em}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)}.goal-status.svelte-1yfu3xi{color:var(--accent);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:.8rem;font-weight:700;overflow:hidden}.pursuing.svelte-1yfu3xi{color:#67d391}.blocked.svelte-1yfu3xi{color:var(--approval)}.stale.svelte-1yfu3xi{color:var(--muted)}.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}.compact.svelte-543j00{flex-shrink:0;margin-top:0;padding-top:0}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)}.reviewed.svelte-mm4wfe{color:var(--muted);font-weight:400}.reviewed.svelte-mm4wfe .lamp:where(.svelte-mm4wfe){opacity:.35}.failed.svelte-mm4wfe{color:var(--approval)}.lamp.failed.svelte-mm4wfe{background:var(--approval);box-shadow:0 0 8px color-mix(in srgb, var(--approval) 40%, transparent)}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%}svg.svelte-1jpy949{fill:currentColor;width:100%;height:auto;display:block}.startup.svelte-19xbbtg{z-index:100;background:var(--bg);color:var(--accent);position:fixed;inset:0;overflow:hidden}.wordmark.svelte-19xbbtg{position:absolute}button.svelte-19xbbtg{color:var(--muted);font:inherit;white-space:nowrap;background:0 0;border:0;font-size:12px;position:absolute;bottom:24px;left:50%;transform:translate(-50%)}: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}.shell[data-starting=true]>header,.shell[data-starting=true]>nav,.shell[data-starting=true]>main,.shell[data-starting=true]>footer{visibility:hidden}.brand{width:clamp(240px,32vw,405px);max-width:calc(100vw - 40px);color:var(--accent);text-decoration:none;display:block}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.selected .context pre{max-height:460px}.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-DDOErweg.js b/internal/web/dist/assets/index-DDOErweg.js deleted file mode 100644 index 5a8b4aba..00000000 --- a/internal/web/dist/assets/index-DDOErweg.js +++ /dev/null @@ -1,50 +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,D=1<<20,ee=1<<25,te=1<<21,O=1<<22,ne=1<<23,re=Symbol(`$state`),ie=Symbol(`component`),ae=Symbol(`legacy props`),oe=Symbol(``),se=Symbol(`attributes`),ce=Symbol(`class`),le=Symbol(`style`),ue=Symbol(`text`),de=Symbol(`form reset`),fe=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},pe=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),me={},k=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 M(e){if(e===null)throw _e(),me;return j=e}function xe(){return M(sn(j))}function N(e){if(A){if(sn(j)!==null)throw _e(),me;j=e}}function Se(e=1){if(A){for(var t=e,n=j;t--;)n=sn(n);j=n}}function Ce(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 we(e){if(!e||e.nodeType!==8)throw _e(),me;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,ie,{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){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[de]?.()})},{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[de];e[de]=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:k,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(k),o=!U,s=new Set;return wn(()=>{var t=W,n=h();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==fe&&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|=ne,Gt(a,t)):(a.f&8388608&&(a.f^=ne),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(fe),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);else{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){Ct=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)?e.b.defer_effect(e):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(k,u));r.set(t,e),Jt(o)}}else L(n,k),Jt(o);return!0},get(e,n,i){if(n===re)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]:k),u)),r.set(n,o)),o!==void 0){var c=G(o);return c===k?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===k)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===re)return!0;var n=r.get(t),i=n!==void 0&&n.v!==k||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]):k,u)),r.set(t,n)),G(n)===k)?!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(k,u)),r.set(d+``,p)):L(p,k)}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!==k;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!==k});for(var[n,i]of r)i.v!==k&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Le()}})}function Zt(e){try{if(typeof e==`object`&&e&&re in e)return e[re]}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[ce]=void 0,e[se]=null,e[le]=void 0,e.__e=void 0),u(n)&&(n[ue]=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),M(r),r}return t&&dn(n),M(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),M(r),r}dn(j)}return j}function B(e,t=!1){if(!A)return on(e);var n=R(e,t);return N(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),M(a),a}dn(r)}return M(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|=ne,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|D,e)}function xn(e){return mn(`$effect.pre`),gn(8|D,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(O|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(fe)});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(fe)}),e.ac=null);try{e.f|=te;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(fe),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()),M(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),xe()}else e!==null&&e.before(t)}function Fr(){if(A&&j&&j.nodeType===8&&j.textContent?.startsWith(`$`)){let e=j.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=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;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),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=()=>{t?ye():(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;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)):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){this.has_pending_snippet()?(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))):this.parent&&this.parent.#C(e,t)}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&&(M(this.#t),Se(),M(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[ue]??=e.nodeValue)&&(e[ue]=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),A&&Ar(t,null),l=e(t,i)||Ke(),A&&(W.nodes.end=j,j===null||j.nodeType!==8||j.data!==`]`))throw _e(),me;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,xe());var i=new Wr(e),a=n?T:0;function o(e,t){if(A){var n=we(r);if(e!==parseInt(n.substring(1))){var a=Ce();M(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&&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^=ee,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&&we(c)===`[!`!=(e===0)&&(c=Ce(),M(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|=ee)),e>r.size&&Ae(``,``,``),A&&e>0&&M(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&&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=new Wr(e);En(()=>{let e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},T)}function ri(e,t,n){var r;A&&(r=j,xe());var i=new Wr(e);En(()=>{var e=t()??null;if(A&&we(r)===`[`!=(e!==null)){var a=Ce();M(a),i.anchor=a,be(!1),i.ensure(e,e&&(t=>n(t,e))),be(!0)}else i.ensure(e,e&&(t=>n(t,e)))},T)}var ii=[...` -\r\f\xA0\v`];function ai(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||ii.includes(r[o-1]))&&(s===r.length||ii.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function oi(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 si(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function ci(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(si)),i&&c.push(...Object.keys(i).map(si));var l=0,u=-1;let t=e.length;for(var d=0;d{t.every(vi)||(`__defaultValue`in e&&pi(e,!1),`__value`in e&&mi(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),vn(()=>{t.disconnect()})}function gi(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),_i);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&_i(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(mi(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=_i(s),n(a))}e.__value=a,i=!1})}function _i(e){return`__value`in e?e.__value:e.value}function vi(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 yi=Symbol(`is custom element`),bi=Symbol(`is html`),xi=pe?`link`:`LINK`;function Si(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[de]=n,Xe(n),it()}}function Ci(e,t){var n=wi(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=wi(e);A&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===xi)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[oe]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Ei(e).has(t)?e[t]=n:e.setAttribute(t,n))}function wi(e){return e[se]??={[yi]:e.nodeName.includes(`-`),[bi]:e.namespaceURI===he}}var Ti=new Map;function Ei(e){var t=e.getAttribute(`is`)||e.nodeName,n=Ti.get(t);if(n)return n;Ti.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 Di(e,t,n=t){var r=new WeakSet;ot(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=Mi(e)?Ni(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(Mi(e)?Ni(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}Mi(e)&&n===Ni(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}var Oi=new Set;function ki(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=ji(o,e,n.checked)),i(e)},()=>i(a?[]:null)),Tn(()=>{var e=r();A&&n.defaultChecked!==n.checked?s=!0: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)}),Oi.has(o)||(Oi.add(o),Xe(()=>{o.sort((e,t)=>e.compareDocumentPosition(t)===4?-1:1),Oi.delete(o)})),Xe(()=>{if(s){var e=a?ji(o,e,n.checked):o.find(e=>e.checked)?.__value;i(e)}})}function Ai(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 ji(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 Fi(e,t,n){var r=Pi.observe(e,()=>n(e[t]));Cn(()=>(pr(()=>n(e[t])),r))}function Ii(e,t){return e===t||e?.[re]===t}function Li(e=Ke(),t,n,r){var i=He.r,a=W;return Cn(()=>{var o,s;return Tn(()=>{o=s,s=r?.()||[],pr(()=>{Ii(n(...s),e)||(t(e,...s),o&&Ii(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&&Ii(n(...s),e)&&t(null,...s)},c=r.teardown;r.teardown=()=>{o(),c?.()}}}),e}function Ri(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 zi(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(()=>{Bi(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(()=>{Bi(t,r),m(n.a)})}function Bi(e,t){if(e.l.s)for(let t of e.l.s)G(t);t()}var Vi=!1;function Hi(e){var t=Vi;try{return Vi=!1,[e(),Vi]}finally{Vi=t}}var Ui={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===re||t===ae)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 Wi(...e){return new Proxy({props:e},Ui)}function Gi(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=re in e||ae in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=Hi(()=>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 Ki(e){He===null&&Oe(`onMount`),Be&&He.l!==null?Ji(He).m.push(e):yn(()=>{let t=pr(e);if(typeof t==`function`)return t})}function qi(e){He===null&&Oe(`onDestroy`),Ki(()=>()=>pr(e))}function Ji(e){var t=e.l;return t.u??={a:[],b:[],m:[]}}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);function Yi(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 Xi=new class{#e=I(Zi());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=Zi()}):console.warn(`[svelte-spa-router] window 'window' is not defined, skipping initiation`)}};function Zi(){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 Qi(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 $i(e){e?window.scrollTo(e.__svelte_spa_router_scrollX||0,e.__svelte_spa_router_scrollY||0):window.scrollTo(0,0)}function ea(e,t){We(t,!0);let n=Gi(t,`routes`,19,()=>({})),r=Gi(t,`prefix`,3,``),i=Gi(t,`restoreScrollState`,3,!1),a=Gi(t,`onConditionsFailed`,3,()=>{}),o=Gi(t,`onRouteLoaded`,3,()=>{}),s=Gi(t,`onRouteLoading`,3,()=>{}),c=Gi(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=Yi(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=Xi.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();ri(z(n),()=>G(t),(e,t)=>{t(e,Wi({get params(){return G(f)},get onRouteEvent(){return c()}},()=>G(p)))}),J(e,n)},a=e=>{var n=Pr();ri(z(n),()=>G(t),(e,t)=>{t(e,Wi({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 ta=[`bars`,`pace`,`pie`,`fuel`,`resets`,`thresholds`];function na(e){return e===`zone`||e===`consumption-pace`?`pace`:typeof e==`string`&&ta.includes(e)?e:`bars`}var ra=`codexometer.web.preferences.v1`,ia={statusLine:null,tab:`quota`,view:`bars`,selected:``,defaultDetail:0,layouts:[]};function aa(){try{let e=JSON.parse(localStorage.getItem(ra)||`null`);return!e||typeof e!=`object`?ia:{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:na(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 ia}}var oa=Xt(aa()),sa=Xt({open:!1}),ca=Xt({requests:0});function la(){let e=JSON.stringify(oa);try{localStorage.setItem(ra,e)}catch{}}function ua(){return oa.tab===`quota`?`/quota/`+oa.view:`/`+oa.tab}function da(e){return oa.layouts.find(t=>t.id===e)?.level??oa.defaultDetail}function fa(e){oa.defaultDetail=e,oa.layouts=[]}function pa(e,t){oa.layouts=[...oa.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:``}),ma=e=>e==null?`Unavailable`:e.toLocaleString(`en-GB`),ha=e=>!e||String(e).startsWith(`0001-`)?`Not yet available`:new Date(typeof e==`number`?e*1e3:e).toLocaleString(`en-GB`),ga=`codexometer.web.session`,_a=class extends Error{},va;async function ya(e,t,n){if(!va||!$.connected||!$.data?.control||$.data.sessionsError)throw Error(`Session controls unavailable. Check the live connection.`);return await va(e,t,n)}function ba(){let e=new AbortController,t,n=``;va=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 _a(`Action rejected, expired or changed. Refresh and check Codex; nothing was retried.`);return a.json()};try{n=sessionStorage.getItem(ga)||``}catch{}let r=location.hash,i=r.startsWith(`#pair=`)?r.slice(6):``;(i||!r||r===`#`)&&(history.replaceState(null,``,`/#`+ua()),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(ga,n)}catch{}}catch(t){e.signal.aborted||($.error=t instanceof Error?t.message:`Pairing failed`);return}n?await o():$.error=`Open the private pairing link printed by codexometer --web in your terminal.`}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(ga)}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(),()=>{va=void 0,e.abort(),clearTimeout(t),$.connected=!1}}Ve();var xa=q(`

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

`),Sa=q(`

`),Ca=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),wa=q(`

No threshold-based model steps were configured at launch.

`);function Ta(e,t){We(t,!1),zi();var n=Pr(),r=z(n),i=e=>{var t=Ca(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,xa())};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=Sa();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=li(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`)},[()=>ha($.data.quotaAt)]),J(e,t)},a=e=>{J(e,wa())};X(r,e=>{$.data?.thresholds?.length?e(i):e(a,-1)}),J(e,n),Ge()}var Ea=Mr(` `,1),Da=Mr(` `,1),Oa=Mr(` `,1),ka=Mr(` `,1),Aa=q(`
`,1),ja=q(` `),Ma=q(`
Quota observations
Observed atPeriod elapsedConsumedTrail segment
`),Na=q(`
OBSERVATION DATA
`),Pa=q(`
CONSUMPTIONQUOTA PERIOD ELAPSED
`,1);function Fa(e,t){let n=Fr();We(t,!0);let r=Gi(t,`trail`,19,()=>[]),i=I(!1),a=I(!0),o=I(`window`),s=[0,25,50,75,100],c=P(()=>t.plot?.known?t.plot.elapsed:t.elapsed),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,G(c)))/100*G(p));function g(e){return G(f)-(e-0)/100*G(m)}let _=P(()=>g(t.used)),v=P(()=>t.used-G(c)),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))),S=P(()=>Object.fromEntries((t.plot?.modes||[]).map(e=>[e.id,e.available])));yn(()=>{G(o)!==`window`&&!G(S)[G(o)]&&L(o,`window`)});let C=P(()=>{let e=t.plot?.modes.find(e=>e.id===G(o));if(!e?.segment)return null;let{x1:n,y1:r,x2:i,y2:a}=e.segment,s=Math.hypot((i-n)/100*G(p),(a-r)/100*G(m)),c=Math.max(3,Math.min(9,Math.floor(s/65)+2));return{path:`M${Array.from({length:c},(e,t)=>{let o=n+(i-n)*t/(c-1),s=r+(a-r)*t/(c-1);return`${48+o/100*G(p)} ${g(s)}`}).join(` L`)}`,projected:e.projected,safe:e.safe}}),w=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 T=Pa(),E=z(T),D=R(E);let ee;var te=R(D),O=R(te),ne=V(O);N(te);var re=V(te),ie=V(re);Z(ie,17,()=>s,qr,(e,t)=>{var n=Ea(),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 ae=V(ie);Z(ae,17,()=>s,qr,(e,t)=>{var n=Da(),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 oe=V(ae),se=V(oe),ce=V(se),le=e=>{var t=Oa(),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),()=>ha(r()[0].at)]),J(e,t)};X(ce,e=>{G(a)&&r().length&&e(le)});var ue=V(ce),de=e=>{var t=ka(),r=z(t),i=V(r),a=B(R(i));N(i),H(e=>{Q(r,`d`,G(C).path),Q(i,`d`,G(C).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(C).projected.toFixed(1)]),J(e,t)};X(ue,e=>{G(C)&&e(de)});var fe=V(ue,2),pe=V(fe),me=V(pe),k=B(R(me));N(me),N(D),N(E);var he=V(E,2),ge=R(he),_e=R(ge),ve=V(_e,3),ye=B(ve,!0),A=V(ve,2),be=e=>{var t=Aa(),n=B(V(z(t)));H(e=>Y(n,`TREND // ${e??``}`),[()=>G(C).projected>=100?`QUOTA EXHAUSTION PROJECTED`:`${G(C).projected.toFixed(1)}% PROJECTED AT RESET`]),J(e,t)};X(A,e=>{G(C)&&e(be)}),N(ge);var j=V(ge,2),M=R(j),xe=R(M);Si(xe),Se(),N(M);var Ce=V(M,2),we=V(R(Ce),2),Te=R(we);Te.value=Te.__value=`off`;var Ee=V(Te),De=B(Ee);Ee.value=Ee.__value=`halfHour`;var Oe=V(Ee),ke=B(Oe);Oe.value=Oe.__value=`hour`;var Ae=V(Oe),je=B(Ae);Ae.value=Ae.__value=`day`;var Me=V(Ae),Ne=B(Me);Me.value=Me.__value=`window`,N(we),hi(we),N(Ce);var Pe=B(V(Ce,2));N(j),N(he);var Fe=V(he,2),Ie=e=>{var t=Na(),n=V(R(t),2),a=e=>{var t=Ma(),n=R(t),i=V(R(n),2);Z(i,21,r,qr,(e,t,n)=>{var r=ja(),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`)},[()=>ha(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),Ri(`open`,`toggle`,t,e=>L(i,e),()=>G(i)),J(e,t)};X(Fe,e=>{r().length&&e(Ie)}),H((e,r,i,a,o,s)=>{Q(D,`viewBox`,`0 0 ${G(l)} ${G(u)}`),Q(D,`aria-label`,e),ee=di(D,``,ee,{"--trend-color":G(C)?.safe?`#115b35`:`#7f1825`}),Q(O,`id`,n),Q(ne,`id`,n+`-trend-arrow`),Q(re,`width`,G(p)),Q(re,`height`,G(m)),Q(re,`fill`,`url(#${n})`),Q(oe,`d`,`M48 20 V${G(f)} H${G(d)}`),Q(se,`y1`,r),Q(se,`x2`,G(d)),Q(se,`y2`,i),Q(fe,`x`,48+G(p)/2),Q(fe,`y`,G(u)-5),Q(pe,`cx`,G(h)),Q(pe,`cy`,G(_)),Q(me,`cx`,G(h)),Q(me,`cy`,G(_)),Y(k,`${t.used??``}% consumed // ${a??``}% of period elapsed`),Y(_e,`${t.used??``}% USED // ${o??``}% TIME ELAPSED`),Y(ye,s),Ee.disabled=!G(S).halfHour,Y(De,`LAST 30 MINUTES${G(S).halfHour?``:` — UNAVAILABLE`}`),Oe.disabled=!G(S).hour,Y(ke,`LAST HOUR${G(S).hour?``:` — UNAVAILABLE`}`),Ae.disabled=!G(S).day,Y(je,`LAST 24 HOURS${G(S).day?``:` — UNAVAILABLE`}`),Me.disabled=!G(S).window,Y(Ne,`FROM WINDOW START${G(S).window?``:` — NO TIME ELAPSED`}`),Y(Pe,`HISTORY // ${G(w)??``}`)},[()=>`Pace: ${t.used}% consumed, ${G(c).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),()=>G(c).toFixed(1),()=>G(c).toFixed(1),()=>Math.abs(G(v))<.05?`ON PACE`:G(v)>0?`ABOVE THE LINE — CONSUMING FASTER THAN TIME`:`BELOW THE LINE — WITHIN PACE`]),Fi(E,`clientWidth`,e=>L(l,e)),Fi(E,`clientHeight`,e=>L(u,e)),Ai(xe,()=>G(a),e=>L(a,e)),gi(we,()=>G(o),e=>L(o,e)),J(e,T),Ge()}var Ia=q(` `),La=q(`

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

`),Ra=q(`

`),za=q(`

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

`),Ba=q(`

`),Va=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.

`),Ha=q(` `,1),Ua=Mr(``),Wa=Mr(``),Ga=q(`
`),Ka=q(`

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

`),qa=q(`
EMPTYFULL
`),Ja=q(`

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

`),Za=q(`

`),Qa=q(`

No quota windows reported yet.

`),$a=q(`
`,1),eo=q(`

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

`,1),to=q(` `,1);function no(e,t){We(t,!0);let n=Gi(t,`params`,19,()=>({})),r=P(()=>ta.filter(e=>e!==`thresholds`||!!$.data?.thresholds?.length)),i=I(Xt(Date.now())),a=P(()=>G(r).includes(na(n().view))?na(n().view):`bars`);Ki(()=>{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(()=>{oa.view=G(a),(n().view===`zone`||n().view===`consumption-pace`)&&Qi(`/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=to(),l=z(c);Z(l,21,()=>G(r),qr,(e,t)=>{var n=Ia();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=li(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=eo(),n=z(t),r=e=>{J(e,La())};X(n,e=>{$.data.quotaError&&e(r)});var i=V(n,2),c=e=>{var t=Ra(),n=B(t);H(()=>Y(n,`Last usage accounting issue: - ${$.data.usageDiagnostic??``}`)),J(e,t)};X(i,e=>{$.data.usageDiagnostic&&e(c)});var l=V(i,2),u=B(l),d=V(l,2),f=e=>{Ta(e,{})},p=e=>{var t=Va(),n=R(t),r=B(n),i=V(n,4),a=e=>{J(e,za())};X(i,e=>{$.data.credits.length||e(a)}),Z(V(i,2),17,()=>$.data.credits,qr,(e,t)=>{var n=Ba(),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 `+ha(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)},m=e=>{var t=$a(),n=z(t);let r;Z(n,21,()=>$.data.meters,qr,(e,t)=>{let n=P(()=>o(G(t)));var r=Za(),i=R(r),c=B(i,!0),l=V(i,2),u=R(l),d=e=>{var n=Ha(),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=Ha(),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=Ga(),r=R(n),i=V(R(r)),a=e=>{J(e,Ua())},o=e=>{var n=Wa();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||[]);Fa(e,{get used(){return G(t).used},get elapsed(){return G(n)},get trail(){return G(r)},get plot(){return G(t).plot}})}},o=e=>{J(e,Ka())};X(i,e=>{G(n)===null?e(o,-1):e(a)}),J(e,r)},v=e=>{var r=Ya(),i=z(r),o=R(i);let s;N(i);var c=V(i,2),l=e=>{J(e,qa())};X(c,e=>{G(a)===`fuel`&&e(l)});var u=V(c,2),d=e=>{var t=Ja(),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=di(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=di(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=Xa(),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=li(p,1,`meter-graphic`,null,m,{"bar-graphic":G(a)===`bars`||G(a)===`fuel`}),Y(b,`RESETS // ${e??``}`)},[()=>ha(G(t).reset)]),J(e,r)}),N(n);var i=V(n,2),c=e=>{J(e,Qa())};X(i,e=>{$.data.meters.length||e(c)}),H(()=>r=li(n,1,`quota-grid`,null,r,{radial:G(a)===`pie`,zone:G(a)===`pace`})),J(e,t)};X(d,e=>{G(a)===`thresholds`?e(f):G(a)===`resets`?e(p,1):e(m,-1)}),Se(2),H(e=>Y(u,`QUOTA // OBSERVED ${e??``}`),[()=>ha($.data.quotaAt)]),J(e,t)};X(u,e=>{$.data&&e(d)}),J(e,c),Ge()}var ro=q(`
`),io=q(`

`,1);function ao(e,t){We(t,!0);let n=Gi(t,`values`,19,()=>[]),r=Gi(t,`label`,3,`Token activity`),i=Gi(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=io(),c=z(s),l=B(c),u=V(c,2);Z(u,21,()=>G(o),qr,(e,t)=>{var n=ro();let r;H((e,t)=>{Q(n,`title`,e),r=di(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()}function oo(e,t=!1){return e===`require`||e!==`none`&&!t}function so(e){if(!e||![`LAST REPLY`,`LAST ACTIVITY`].includes(e.contextKind))return``;let t=e.text||e.contextKind===`LAST ACTIVITY`&&e.workingCommand||``;return t.trim()?t:``}var co=[{id:`local-statusline`,label:`/statusline`,help:`Choose fields for Codexometer’s detail footer. Saved display preferences only.`,next:`statusline`},{id:`local-usage`,label:`/usage`,help:`Open Codexometer’s usage history. Existing quota and reset views remain available.`,next:`usage`},{id:`local-copy`,label:`/copy`,help:`Copy the selected session’s observed reply or activity using Codexometer’s copy control.`,next:`copy`},{id:`local-theme`,label:`/theme`,help:`Choose a Codexometer display theme. Saved local display preferences only.`,next:`theme`},{id:`local-exit`,label:`/exit`,help:`Leave this Codexometer interface. Codex sessions continue running.`,next:`exit`},{id:`local-quit`,label:`/quit`,help:`Alias for /exit. Codex sessions continue running.`,next:`quit`}],lo=[`surface`,`model`,`feature`,`task start`],uo=q(` `),fo=q(``),po=q(`

`),mo=q(`

`),ho=q(`
`),go=q(`

`),_o=q(`

`,1),vo=q(`

`),yo=q(`

Loading / sending…

`),bo=q(`
`),xo=q(`

`),So=q(`

 
`),Co=q(`
`),wo=q(`
`),To=q(`

Review expired. Press Enter to review again.

`),Eo=q(`

`,1),Do=q(`

`,1),Oo=q(`

No available matching commands.

`),ko=q(` `,1),Ao=q(`

`),jo=q(`

Review expired. Review the option again.

`),Mo=q(``),No=q(``),Po=q(``),Fo=q(``),Io=q(``),Lo=q(``),Ro=q(`
`),zo=q(`
`);function Bo(e,t){let n=Fr();We(t,!0);let r=e=>{var t=Pr();Z(z(t),19,()=>G(me),e=>e.id,(e,t,r)=>{var i=fo();let o;var s=R(i),c=B(s,!0),l=V(s),u=B(l),d=V(l),f=e=>{var n=uo(),r=B(n,!0);H(()=>Y(r,G(t).help)),J(e,n)};X(d,e=>{(G(v)?.path===``||G(le))&&e(f)}),N(i),H((e,s)=>{Q(i,`id`,`${n}-${G(r)}`),Q(i,`role`,G(le)?`option`:void 0),Q(i,`aria-selected`,G(le)?G(T)===G(r):void 0),Q(i,`tabindex`,G(le)?-1:void 0),i.disabled=G(g)||G(_e)&&!a(),Q(i,`title`,G(t).help),Q(i,`aria-label`,e),o=li(i,1,`svelte-7bfwr9`,null,o,{suggested:G(T)===G(r)}),Y(c,G(t).label),Y(u,`${G(le)&&G(t).selected?` // CURRENT`:``}${s??``}`)},[()=>G(t).label+(G(le)&&G(t).selected?` // CURRENT`:``)+ae(G(t)),()=>ae(G(t))]),Sr(`focus`,i,()=>{G(le)||ye(G(r))}),K(`click`,i,()=>{ye(G(r)),M(G(t))}),J(e,i)}),J(e,t)},i=Gi(t,`query`,3,``),a=Gi(t,`localOnly`,3,!1),o=Gi(t,`oncopy`,3,()=>{}),s=Gi(t,`onchange`,3,()=>{}),c=Gi(t,`oncomplete`,3,e=>{}),l=co.map(e=>e.next);function u(){return co.map(e=>[`exit`,`quit`].includes(e.next||``)?{...e,help:`Return to Sessions. The local server and Codex sessions remain running.`}:{...e})}function d(){return{title:`/ COMMANDS`,help:`Local Codexometer commands remain available without session control.`,path:``,revision:``,choices:u()}}function f(){L(b,``),L(O,``),L(x,0),L(ne,[],!0)}function p(){w++,L(g,!1),L(h,!1),L(E,i()),f(),L(_,``),G(fe)?s()():c()(i())}async function m(e){if(!l.includes(e))return!1;if(e===`copy`&&!so($.data?.sessions.find(e=>e.id===t.session)))return L(_,`No reply or activity text is available to copy for this session.`),!0;if(e===`copy`){let e=o()();p(),await e}else p(),e===`usage`?location.hash=`/usage`:e===`theme`?ca.requests++:e===`statusline`?sa.open=!0:location.hash=`/sessions`;return!0}let h=I(!1),g=I(!1),_=I(``),v=I(null),y=I(null),b=I(``),x=I(0),S=I(Xt(Date.now())),C=I(``),w=0,T=I(0),E=I(null),D=I(void 0),ee=I(void 0),te=I(void 0),O=I(``),ne=I(Xt([])),re=P(()=>!!G(v)?.inputReview),ie=P(()=>!!G(y)&&!G(re)||!!G(O)||G(ne).length>0);function ae(e){return e.unavailable?e.unavailable.startsWith(`Waiting for idle.`)?` // WAITING FOR IDLE`:` // UNAVAILABLE`:e.next?` →`:e.action?``:` // HELP`}async function oe(e){G(v)&&!(G(ve)&&G(pe))&&L(ne,[...G(ne),{path:G(v).path,index:G(T),input:G(C)}],!0),await j(e)}async function se(){if(!G(ie))return;if(w++,L(g,!1),L(b,``),L(x,0),L(_,``),G(O)){L(O,``),G(D)?.focus();return}if(G(y)&&!G(re)){L(y,null),await ur(),G(D)?.focus();return}let e=G(ne).at(-1);e&&(L(ne,G(ne).slice(0,-1),!0),await j(e.path,e))}function ce(){G(v)&&G(C).trim()&&!G(g)&&!G(_e)&&oe(G(v).path+`/`+encodeURIComponent(G(C).trim()))}let le=P(()=>G(h)&&!!G(v)?.picker&&!G(y)),ue=P(()=>G(h)&&!G(v)?.input&&!G(y)),de=setInterval(()=>{L(S,Date.now(),!0)},1e3);qi(()=>{clearInterval(de),w++});let fe=P(()=>i().trim().startsWith(`/`)&&!i().trim().startsWith(`//`)),pe=P(()=>G(v)?.path===``&&G(fe)?i().trim().slice(1).toLowerCase():``),me=P(()=>(G(v)?.choices||[]).filter(e=>!G(pe)||e.label.toLowerCase().startsWith(`/`+G(pe)))),k=P(()=>G(y)||G(me)[G(T)]),he=P(()=>!!G(b)&&G(S)G(me).find(e=>e.id===G(O))),_e=P(()=>!$.connected||!!$.data?.sessionsError),ve=P(()=>G(h)&&G(fe)&&(!G(v)||G(v).path===``)&&!G(y));yn(()=>{i(),L(T,0)}),yn(()=>{let e=G(T);G(me),G(ue)&&ur().then(()=>{let t=G(D)?.children[e];if(!t||!G(D))return;let n=G(D).getBoundingClientRect(),r=t.getBoundingClientRect();r.topn.bottom&&(G(D).scrollTop+=r.bottom-n.bottom)})});function ye(e){G(T)!==e&&G(v)?.picker&&(L(O,``),L(b,``),L(x,0),L(_,``),w++),L(T,e,!0)}function A(){w++,L(g,!1),L(h,!1),L(E,i()),f(),c()(i())}function be(e){let t=!!G(ee)?.contains(e.target);if(!G(h)||!G(ue)&&!G(y)&&!G(v)?.input||!G(fe)&&!t||G(_e)&&!a()||e.isComposing||e.ctrlKey||e.metaKey||e.altKey)return;if(G(v)?.input){e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),A());return}let n=e.key===`ArrowLeft`,r=e.key.toLowerCase()===`f`,o=e.key.toLowerCase()===`c`;if((o||r||n)&&!t||![`ArrowUp`,`ArrowDown`,`Tab`,`Enter`,`Escape`].includes(e.key)&&!o&&!r&&!n||e.key===`Tab`&&(G(y)||G(v)?.path!==``||e.shiftKey)||e.key===`Enter`&&e.target instanceof Element&&e.target.closest(`button`)&&!G(D)?.contains(e.target)&&!e.target.closest(`[data-command-confirm]`)||G(y)&&!t||G(y)&&[`ArrowUp`,`ArrowDown`].includes(e.key))return;if(e.preventDefault(),e.stopPropagation(),e.key===`Escape`){A();return}if(G(g)||e.repeat&&(o||e.key===`Enter`))return;if(n){G(ie)&&se();return}if(r){j(G(v)?.path||``,void 0,!0);return}if(o){(G(y)?.action||G(le)&&G(O))&&Se();return}if(G(y)){e.key===`Enter`&&G(y).action&&!G(he)&&!G(_)&&xe(G(y));return}if(e.key===`ArrowUp`||e.key===`ArrowDown`){ye(Math.min(Math.max(G(T)+(e.key===`ArrowUp`?-1:1),0),Math.max(G(me).length-1,0))),!G(le)&&G(D)?.contains(e.target)&&ur().then(()=>(G(D)?.children[G(T)])?.focus());return}if(e.key===`Enter`&&(G(v)?.path===``||G(v)?.path===`goal`)&&/^\/goal\s+\S/.test(i().trim())){let e=G(v)?.path===`goal`?G(me).find(e=>i().trim().slice(6).trim().toLowerCase()===e.label.toLowerCase()):void 0;if(e){M(e);return}oe(i().trim().slice(1));return}let s=G(me)[G(T)];s&&(e.key===`Tab`?c()(s.label):G(le)?xe(s):M(s))}yn(()=>{G(_e)&&!a()&&(w++,L(g,!1),f(),G(h)&&(L(h,!1),L(E,i())),L(v,null),L(y,null))}),yn(()=>{G(fe)&&!G(h)&&i()!==G(E)&&(!G(_e)||a())&&(f(),L(h,!0),j(``))});async function j(e,n,r=!1){let i=++w;if(G(v)&&L(v,{...G(v),path:e},!0),n&&L(C,n.input,!0),L(g,!0),L(y,null),L(O,``),L(b,``),L(x,0),L(_,``),a())L(v,d(),!0),L(T,n?.index??0,!0),L(g,!1);else try{let a=await ya(`commands`,{session:t.session,command:{mode:`list`,path:e,...r?{refresh:!0}:{}}});i===w&&(a.choices||=[],(e===``||e===`help`)&&(a.choices=[...a.choices.filter(e=>!l.includes(e.label.replace(/^\//,``))),...u()]),L(v,a,!0),L(T,n?Math.min(n.index,Math.max(a.choices.length-1,0)):a.picker?Math.max(a.choices.findIndex(e=>e.selected),0):0,!0),a.picker&&ur().then(()=>G(D)?.focus()),L(C,n?.input??a.value??``,!0),n&&ur().then(()=>{a.input?G(ee)?.querySelector(`input`)?.focus():G(D)?.focus()}),a.inputReview&&a.choices.length===1&&(L(g,!1),M(a.choices[0])))}catch{i===w&&(L(_,`Command catalogue unavailable. Use Codex.`),e===``||e===`help`?(L(v,d(),!0),L(_,``)):L(v,{title:`/`+e,help:``,path:e,revision:``,choices:[]},!0))}finally{i===w&&L(g,!1)}}async function M(e){e.unavailable||G(g)||e.next&&await m(e.next)||G(_)||(G(v)?.picker?(ye(G(me).findIndex(t=>t.id===e.id)),e.action&&!oo($.data?.confirmationMode,!!e.reversible)?await xe(e):G(D)?.focus()):e.next?await oe(e.next):await xe(e))}async function xe(e){if(G(g)||G(_e)||!G(v)||e.unavailable||G(_))return;let n=e.action&&!oo($.data?.confirmationMode,!!e.reversible);if(G(v).picker){if(G(he)&&G(O)===e.id)return;L(O,e.id,!0)}else n||(L(y,e,!0),ur().then(()=>G(te)?.focus()));if(L(b,``),L(x,0),L(_,``),!e.action)return;let r=++w;L(g,!0);try{let n=await ya(`commands`,{session:t.session,command:{mode:`prepare`,path:G(v).path,revision:G(v).revision,choice:e.id}});if(r===w){let e=Date.parse(n.expires);if(!n.confirmation||!Number.isFinite(e)||Date.now()>=e)throw Error(`Review confirmation unavailable`);L(b,n.confirmation,!0),L(x,e,!0)}}catch{r===w&&L(_,`Option changed or unavailable. Refresh before retrying.`)}finally{r===w&&L(g,!1)}n&&r===w&&G(b)&&await Se()}async function Se(){if(!G(b)||G(_e)||G(g)||Date.now()>=G(x)||!G(v)||G(v).picker&&G(O)!==G(me)[G(T)]?.id)return;let e=G(b);L(b,``),L(g,!0);let n=++w;try{let r=await ya(`commands`,{session:t.session,confirmation:e,command:{mode:`commit`,path:G(v).path}});n===w&&(L(_,r.message,!0),L(h,!1),L(v,null),L(y,null),f(),L(E,null),s()())}catch{n===w&&L(_,`Change unconfirmed. Check Codex before retrying.`)}finally{n===w&&L(g,!1)}}var Ce={handleKey:be},we=zo(),Te=R(we),Ee=V(Te,2),De=e=>{var t=po(),n=B(t,!0);H(()=>Y(n,G(_))),J(e,t)};X(Ee,e=>{G(_)&&!G(h)&&e(De)});var Oe=V(Ee,2),ke=e=>{var i=Ro();let o;var s=R(i),c=e=>{var t=_o(),n=z(t),r=B(n,!0),i=V(n,2),a=e=>{var t=ho();Z(t,21,()=>G(v).help.split(` -`),qr,(e,t)=>{var n=mo(),r=B(n,!0);H(()=>{Q(n,`title`,G(t)),Y(r,G(t))}),J(e,n)}),N(t),J(e,t)},o=e=>{var t=go(),n=B(t,!0);H(()=>Y(n,G(v)?.help||`Loading live options…`)),J(e,t)};X(i,e=>{G(v)?.path===`goal`?e(a):e(o,-1)}),H(()=>Y(r,G(v)?.title||`/ COMMANDS`)),J(e,t)};X(s,e=>{G(ve)||e(c)});var l=V(s,2),u=e=>{var t=vo(),n=B(t,!0);H(()=>Y(n,G(_))),J(e,t)};X(l,e=>{G(_)&&e(u)});var d=V(l,2),f=e=>{J(e,yo())};X(d,e=>{G(g)&&e(f)});var p=V(d,2),m=e=>{var t=bo(),r=R(t),i=R(r),o=V(i);Si(o),N(r),N(t),H(e=>{Q(t,`id`,`${n}-input`),Y(i,`${e??``} `),Q(o,`aria-label`,G(v).inputLabel||`Session name`),Q(o,`maxlength`,G(v).inputLimit||512),o.disabled=G(g)||G(_e)&&!a()},[()=>(G(v).inputLabel||`Session name`).toUpperCase()]),Sr(`submit`,t,e=>{e.preventDefault(),ce()}),Di(o,()=>G(C),e=>L(C,e)),J(e,t)},h=e=>{var n=So(),r=R(n),i=B(r,!0),a=V(r,2),o=B(a,!0),s=V(a,2),c=e=>{var n=xo(),r=R(n),i=V(r),a=e=>{J(e,Nr(`Only this session's saved - name changes.`))},o=P(()=>G(v)?.path.startsWith(`rename/`)),s=e=>{J(e,Nr(`Only this session’s - directory changes; project configuration is not reloaded.`))},c=P(()=>G(v)?.path.startsWith(`cd/`)),l=e=>{J(e,Nr(`Only this session's goal - changes.`))},u=P(()=>G(v)?.path.startsWith(`goal/`)),d=e=>{J(e,Nr(`No change sent yet. Model, reasoning and speed settings can - change token usage and cost. Changes affect subsequent turns of - this session, not global defaults. Automatic quota thresholds - may later supersede model settings.`))};X(i,e=>{G(o)?e(a):G(c)?e(s,1):G(u)?e(l,2):e(d,-1)}),N(n),H(()=>Y(r,`TARGET // ${t.session??``}. `)),J(e,n)};X(s,e=>{G(y).action&&e(c)}),N(n),Li(n,e=>L(te,e),()=>G(te)),H(()=>{Y(i,G(y).label),Y(o,G(y).help||`No additional help supplied by Codex.`)}),J(e,n)},w=e=>{var t=ko(),i=z(t),a=e=>{var t=Co(),i=R(t);r(i),N(t),Li(t,e=>L(D,e),()=>G(D)),H(()=>Q(t,`aria-activedescendant`,`${n}-${G(T)}`)),J(e,t)},o=e=>{var t=wo();let n;var i=R(t);r(i),N(t),Li(t,e=>L(D,e),()=>G(D)),H(()=>n=li(t,1,`command-options svelte-7bfwr9`,null,n,{vertical:G(ve)})),J(e,t)};X(i,e=>{G(le)?e(a):e(o,-1)});var s=V(i,2),c=e=>{var t=Do(),n=z(t),r=B(n,!0),i=V(n,2),a=e=>{var t=Eo(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,To())};X(i,e=>{G(b)&&G(S)>=G(x)&&e(a)}),H(()=>Y(r,`REVIEW // ${G(ge).label??``}. No change sent yet.`)),J(e,t)};X(i,e=>{G(ge)&&e(a)}),H(()=>Y(r,G(me)[G(T)]?.help)),J(e,t)};X(s,e=>{G(le)&&e(c)});var l=V(s,2),u=e=>{J(e,Oo())};X(l,e=>{!G(g)&&!G(me).length&&e(u)}),J(e,t)};X(p,e=>{G(v)?.input?e(m):G(y)?e(h,1):e(w,-1)});var E=V(p,2),O=e=>{var t=Ao(),n=B(t,!0);H(()=>Y(n,G(k).unavailable)),J(e,t)};X(E,e=>{G(k)?.unavailable&&e(O)});var ne=V(E,2),re=e=>{J(e,jo())};X(ne,e=>{G(b)&&G(S)>=G(x)&&!G(le)&&e(re)});var ae=V(ne,2),oe=R(ae),ue=e=>{var t=Pr(),r=z(t),i=e=>{var t=Mo(),r=B(t,!0);H((e,i)=>{Q(t,`form`,`${n}-input`),t.disabled=e,Y(r,i)},[()=>G(g)||G(_e)||!G(C).trim(),()=>oo($.data?.confirmationMode,!!G(v).reversibleInput)?`ENTER REVIEW`:`ENTER APPLY`]),J(e,t)},o=e=>{var t=Pr(),n=z(t),r=e=>{var t=No();H(()=>t.disabled=G(g)||G(_e)&&!a()),K(`click`,t,Se),J(e,t)},i=P(()=>G(he)&&oo($.data?.confirmationMode,!!G(k).reversible)),o=e=>{var t=Po(),n=B(t,!0);H(e=>{t.disabled=G(g)||G(_e)&&!a(),Y(n,e)},[()=>oo($.data?.confirmationMode,!!G(k).reversible)?`ENTER REVIEW`:`ENTER APPLY`]),K(`click`,t,()=>{G(k)&&xe(G(k))}),J(e,t)};X(n,e=>{G(i)?e(r):e(o,-1)}),J(e,t)},s=e=>{var t=Po(),n=B(t);H(()=>{t.disabled=G(g)||G(_e)&&!a(),Y(n,`ENTER ${G(k).next?`OPEN`:`HELP`}`)}),K(`click`,t,()=>{G(k)&&M(G(k))}),J(e,t)};X(r,e=>{G(v)?.input?e(i):G(k)?.action&&!G(k).unavailable?e(o,1):!G(y)&&G(k)&&!G(k).unavailable&&e(s,2)}),J(e,t)};X(oe,e=>{G(_)||e(ue)});var de=V(oe,2),fe=e=>{var t=Fo();H(()=>t.disabled=G(g)),K(`click`,t,se),J(e,t)};X(de,e=>{G(ie)&&e(fe)});var pe=V(de,2),ye=e=>{var t=Io();H(()=>t.disabled=G(g)),K(`click`,t,()=>j(G(v)?.path||``,void 0,!0)),J(e,t)};X(pe,e=>{G(ve)||e(ye)});var Ce=V(pe,2);N(ae);var we=V(ae,2),Te=e=>{var t=Lo(),n=B(t);H(()=>Y(n,`↑/↓ select${G(ve)?` · Tab complete`:``}`)),J(e,t)};X(we,e=>{!G(v)?.input&&!G(y)&&e(Te)}),N(i),Li(i,e=>L(ee,e),()=>G(ee)),H(()=>{Q(i,`aria-label`,G(ve)?`Slash command suggestions`:`Session command options`),o=li(i,1,`svelte-7bfwr9`,null,o,{"command-popup":G(ve)})}),K(`keydown`,i,be),K(`click`,Ce,A),J(e,i)};return X(Oe,e=>{G(h)&&e(ke)}),N(we),H(()=>Te.disabled=G(_e)&&!a()||G(g)),K(`click`,Te,()=>{L(h,!G(h)),L(E,G(h)?null:i(),!0),L(b,``),G(h)?(L(ne,[],!0),j(``)):A()}),J(e,we),Ge(Ce)}Cr([`click`,`keydown`]);var Vo=q(` `,1),Ho=q(`
`),Uo=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=Uo(),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=Ho();let r;var i=R(n),a=e=>{var n=Vo(),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=li(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 Go=q(`

`),Ko=q(``),qo=q(`

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

`,1),Jo=q(``),Yo=q(`

 

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

`),Xo=q(`

HUMAN APPROVAL REQUIRED

Managed policy requires approval each time.

`,1),Zo=q(`

CURRENT PROFILE

MODEL / REASONING LEVEL / SPEED

 

PROPOSED PROFILE

MODEL / REASONING LEVEL / SPEED

 

Applied settings remain after Codexometer closes.

`,1),Qo=q(`

`),$o=q(`

 
`,1),es=q(`

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

`),ts=q(`

Session controls temporarily unavailable. Check Codex for current state.

`),ns=q(`

Checking session controls…

`),rs=q(`

`),is=q(`
About browser controls

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

`),as=q(` `,1),os=q(` `),ss=q(`Grants permission beyond this one action. Check the scope - carefully.`),cs=q(``),ls=q(``),us=q(``),ds=q(``),fs=q(`

Not before this time; when quota and idle allow.

`),ps=q(`

`,1),ms=q(`

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

`),hs=q(` `,1),gs=q(``),_s=q(``),vs=q(``),ys=q(` `,1),bs=q(`
  • `),xs=q(`
    View fixed choices

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

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

      `),ws=q(`

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

      `,1),Os=q(`

      `);function ks(e,t){We(t,!0);let n=[],r=Gi(t,`observedCommand`,3,``),i=Gi(t,`observedFileChanges`,19,()=>[]),a=Gi(t,`review`,3,``),o=Gi(t,`suspended`,3,!1),s=Gi(t,`openScheduler`,3,!1),c=Gi(t,`onProtectedChange`,3,e=>{}),l=Gi(t,`oncopy`,3,()=>{}),u=I(null),d=I(Xt([])),f=I(null),p=I(``),m=I(0),h=I(Xt(Date.now())),g=I(!1),_=I(``),v=I(!1),y=I(!1),b=I(``),x=I(!1),S=I(``),C=I(!1),w=I(``),T=I(``),E=I(0),D=I(`now`),ee=I(60),te=I(``),O=I(!1),ne=I(``),re=I(Xt([])),ie=P(()=>G(re).find(e=>e.status!==`sent`)),ae=I(void 0),oe=I(void 0);function se(e){if(G(x)){ur().then(()=>G(ae)?.focus());return}if(e.status!==`pending`||G(g)||!G(u)?.id||G(u).kind!==`prompt`||G(u).questions?.length)return;L(x,!0),L(S,e.id,!0),ur().then(()=>G(ae)?.focus()),L(d,[e.text],!0),L(D,e.trigger===`quota`?`quota`:`at`,!0),L(p,``),L(w,``);let t=new Date(e.at||0);e.trigger!==`quota`&&L(te,new Date(t.getTime()-t.getTimezoneOffset()*6e4).toISOString().slice(0,16),!0)}yn(()=>{s()&&G(ie)&&!G(C)&&G(u)?.id&&G(u).kind===`prompt`&&!G(u).questions?.length&&(L(C,!0),se(G(ie)))});async function ce(){if(!a())try{L(re,await ya(`schedules`,{session:t.session},M.signal),!0),G(x)&&!G(re).some(e=>e.id===G(S)&&e.status===`pending`)&&L(p,``),G(w)&&!G(re).some(e=>e.id===G(w)&&e.status===`pending`)&&(L(p,``),L(w,``))}catch{}}async function le(e){if(oo($.data?.confirmationMode,!0)&&(G(T)!==e||G(h)>=G(E)))L(T,e,!0),L(E,G(h)+3e4);else{L(T,``);try{L(re,await ya(`schedules`,{session:t.session,cancelId:e},M.signal),!0),L(x,!1),L(p,``),L(w,``),L(d,[],!0)}catch(e){L(_,e instanceof Error?e.message:`Unable to cancel trigger.`,!0)}}}yn(()=>(c()(G(g)||G(d).some(e=>e.length>0)),()=>c()(!1)));let ue=P(()=>$.data?.sessions.find(e=>e.id===t.session)?.status),de=P(()=>!$.connected||!!$.data?.sessionsError),fe=P(()=>a()!==`profile`&&G(u)?.kind===`prompt`&&!G(u).questions?.length&&!!$.data?.profiles?.some(e=>e.session===t.session&&e.pending)),pe=P(()=>!G(de)&&!G(y)&&!!G(u)?.id&&G(u).kind===`approval`&&G(b)!==G(u).id),me=P(()=>G(pe)?G(u).command:r()),k=P(()=>!!G(p)&&G(h)oo($.data?.confirmationMode,G(u)?.kind===`approval`?G(f)!==null&&!G(u).choices?.[G(f)]?.persistent:G(u)?.kind===`profile`?G(f)===1:!(G(u)?.kind!==`prompt`||G(w)||G(x)||!G(u).questions?.length&&G(D)!==`now`))),ge=P(()=>G(u)?.questions?.length?G(u).questions:[{text:`Follow-up message`,secret:!1,freeText:!0,options:[]}]),_e=P(()=>G(u)?.kind===`approval`||G(u)?.kind===`profile`?G(f)!==null:G(d).length===G(ge).length&&G(d).every((e,t)=>e.trim().length>0&&(G(ge)[t].freeText||G(ge)[t].options?.includes(e)))),ve=P(()=>G(u)?.kind===`prompt`&&!G(u).questions?.length&&G(D)!==`now`),ye=P(()=>G(D)===`delay`?G(h)+G(ee)*6e4:Date.parse(G(te))),A=P(()=>{if(!G(ve))return``;if(G(x)&&!G(re).some(e=>e.id===G(S)&&e.status===`pending`))return`Trigger changed, removed or already sent. Go back and reopen it; your draft has not been saved.`;if(!G(d)[0]?.trim())return`Enter a message to schedule.`;if(G(D)===`quota`)return``;if(!Number.isFinite(G(ye))||G(ye)<=G(h))return`Choose a future date/time or a delay greater than zero.`;let e=new Date(G(h));return e.setFullYear(e.getFullYear()+1),G(ye)>=e.getTime()?`Choose a time within one year.`:``});function be(e){return e===void 0?`Not yet available`:new Date(e).toLocaleString([],{timeZoneName:`short`})}function j(e){if(e.status!==`pending`)return e.status;if(e.trigger===`at`&&e.at&&Date.parse(e.at)>G(h))return`Due in `+Math.ceil((Date.parse(e.at)-G(h))/6e4)+` min`;let t=G(de)?`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(de)||o()||G(fe)||G(h)>=G(m))&&L(p,``)});let M=new AbortController;Ki(()=>{let e=e=>{e.ctrlKey&&e.key.toLowerCase()===`s`&&!a()&&G(ie)&&(e.preventDefault(),se(G(ie)))};window.addEventListener(`keydown`,e);let n,r=setInterval(()=>{L(h,Date.now(),!0)},1e3);async function i(){await ce();try{let e=await ya(`offer`,{session:t.session,...a()?{review:a()}:{}},M.signal);if(M.signal.aborted)return;L(y,!1),G(u)?.id!==e.id&&(L(p,``),L(f,null),L(d,Array(Math.max(1,e.questions?.length||0)).fill(``),!0)),L(u,e,!0),G(v)&&e.id&&e.id!==G(b)&&(L(_,``),L(v,!1))}catch{M.signal.aborted||(L(u,null),L(y,!0),L(p,``))}finally{M.signal.aborted||(n=setTimeout(i,2e3))}}return i(),()=>{window.removeEventListener(`keydown`,e),M.abort(),clearTimeout(n),clearInterval(r)}});async function xe(e){if(!e&&G(u)?.kind===`prompt`&&!G(u).questions?.length&&G(d)[0]?.trim().startsWith(`/`)&&!G(d)[0]?.trim().startsWith(`//`)){L(_,`Choose a slash command from COMMANDS; use // for literal slash text.`);return}if(!G(u)?.id||G(g)||G(de)||o()||G(fe)||(e?!e.canSend:!G(_e)||G(A)))return;let n=G(u).id;L(g,!0),L(_,``),L(v,!1),L(p,``),L(w,e?.id||``,!0);try{let r=!e&&G(u).kind===`prompt`&&!G(u).questions?.length&&G(D)!==`now`?{trigger:G(D)===`quota`?`quota`:`at`,zone:Intl.DateTimeFormat().resolvedOptions().timeZone,...G(D)===`quota`?{}:{at:(G(D)===`delay`?new Date(Date.now()+G(ee)*6e4):new Date(G(te))).toISOString()}}:void 0;L(O,!!r),L(ne,r?r.trigger===`quota`?`After fresh quota becomes available, when the session is idle`:be(r.at)+` — not before this time; when quota and idle allow`:``,!0);let i=await ya(`prepare`,{session:t.session,...a()?{review:a()}:{},offer:n,...e?{sendId:e.id}:{},...r?{schedule:r}:{},...r&&G(x)?{editId:G(S)}:{},...G(u).kind===`approval`||G(u).kind===`profile`?{choice:G(f)}:{answers:e?[e.text]:[...G(d)]}},M.signal);G(u)?.id!==n||M.signal.aborted||G(de)||o()||G(fe)||(L(p,i.confirmation,!0),L(m,Date.parse(i.expires),!0))}catch(e){M.signal.aborted||L(_,e instanceof Error?e.message:`Unable to prepare action.`,!0)}finally{L(g,!1)}!G(he)&&G(p)&&!M.signal.aborted&&await Ce()}async function Ce(){if(!G(u)?.id||G(g)||o()||G(fe)||!G(k))return;let e=G(u).id,n=G(u).kind,r=G(p);L(p,``),L(g,!0),L(b,e,!0);try{await ya(`commit`,{session:t.session,...a()?{review:a()}:{},offer:e,confirmation:r},M.signal),L(v,!0),L(x,!1),G(O)&&(L(b,``),await ce()),L(_,G(O)?`Trigger set. Closing Codexometer cancels it.`:n===`profile`?`Profile decision completed.`:n===`approval`?`Decision sent.`:`Text sent.`,!0)}catch(e){L(_,e instanceof _a?e.message:`Outcome uncertain. Check Codex before taking another action; nothing was retried.`,!0)}finally{L(g,!1),L(w,``),await ce(),L(d,[],!0),L(f,null)}}var we=as(),Te=z(we),Ee=e=>{var t=Pr();Z(z(t),17,()=>G(re).filter(e=>e.status!==`sent`),e=>e.id,(e,t)=>{var n=Yo(),r=R(n),i=B(r,!0),a=V(r,2),s=B(a),c=V(a,2),l=B(c,!0),d=V(c,2),f=B(d,!0),m=V(d,2),v=B(m,!0),y=V(m,2),b=e=>{var t=Go(),n=B(t,!0);H(()=>Y(n,G(_))),J(e,t)};X(y,e=>{G(_)&&e(b)});var x=V(y,4),S=V(x,2),C=B(S,!0),D=V(S,2),ee=e=>{var t=Ko();K(`click`,t,()=>{L(T,``)}),J(e,t)};X(D,e=>{G(T)===G(t).id&&G(h){var n=qo(),r=V(z(n),2),i=V(r,2);H(()=>r.disabled=G(g)||G(de)||!G(t).canSend),K(`click`,r,Ce),K(`click`,i,()=>{L(p,``),L(w,``)}),J(e,n)},ne=e=>{var n=Jo();H(()=>n.disabled=G(g)||G(de)||!G(t).canSend||o()),K(`click`,n,()=>xe(G(t))),J(e,n)};X(te,e=>{G(k)&&G(w)===G(t).id?e(O):e(ne,-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(l,e),Y(f,n),Y(v,G(t).text),x.disabled=G(g)||!G(u)?.id||G(u).kind!==`prompt`||!!G(u).questions?.length||G(t).status!==`pending`,S.disabled=G(g)||G(t).status===`sending`,Y(C,G(T)===G(t).id&&G(h)G(t).trigger===`quota`?`After confirmed quota recovery, when idle`:`Not before ${be(G(t).at)}`,()=>j(G(t))]),K(`click`,x,()=>se(G(t))),K(`click`,S,()=>le(G(t).id)),J(e,n)}),J(e,t)},De=P(()=>!a()&&G(u)?.kind!==`approval`&&!G(u)?.questions?.length&&![`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ue)||``));X(Te,e=>{G(De)&&e(Ee)});var Oe=V(Te,2),ke=e=>{var r=Os(),o=R(r),s=B(o,!0),c=V(o,2),S=e=>{var t=Xo();Se(2),J(e,t)};X(c,e=>{G(u)?.requiredHumanApproval&&!G(de)&&!G(y)&&e(S)});var C=V(c,2),w=e=>{var t=Zo(),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(u).profile.threshold??``}% quota threshold has been reached. Review - the profile for subsequent turns.`),Y(a,G(u).profile.current),Y(o,G(u).profile.proposed)}),J(e,t)};X(C,e=>{G(u)?.profile&&!G(de)&&!G(y)&&e(w)});var T=V(C,2),E=e=>{var t=Qo();let n;var r=B(t,!0);H(()=>{n=li(t,1,`svelte-1oupzfc`,null,n,{notice:!G(v),sent:G(v)}),Y(r,G(_))}),J(e,t)};X(T,e=>{G(_)&&e(E)});var re=V(T,2),ie=e=>{Wo(e,{get lines(){return G(u).fileChanges}})},se=e=>{Wo(e,{get lines(){return i()}})},ce=e=>{var t=$o(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(pe)?`EXACT COMMAND`:`LAST OBSERVED COMMAND`),Y(i,G(me))}),J(e,t)},le=e=>{J(e,es())};X(re,e=>{G(u)?.fileChanges?.length&&!G(de)&&!G(y)?e(ie):i().length?e(se,1):G(me)?e(ce,2):a()!==`profile`&&G(ue)===`APPROVAL NEEDED`&&!G(v)&&e(le,3)});var fe=V(re,2),ve=e=>{J(e,ts())},j=e=>{J(e,ns())},M=e=>{var t=as(),n=z(t),r=e=>{var t=rs(),n=B(t,!0);H(e=>Y(n,e),[()=>G(ue)===`WORKING`?`Codex is working — nothing to respond to.`:[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ue)||``)?`Respond in Codex for this request.`:`Nothing needs a response right now.`]),J(e,t)};X(n,e=>{(G(ue)===`WORKING`||!G(v)&&!G(g))&&e(r)});var i=V(n,2),a=e=>{J(e,is())},o=P(()=>[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ue)||``)&&!G(v));X(i,e=>{G(o)&&e(a)}),J(e,t)},we=e=>{var r=Ds(),i=z(r),o=B(i),s=V(i,2),c=R(s),_=B(c,!0),v=V(c,2),y=e=>{var r=Pr();Z(z(r),17,()=>G(u).choices||[],qr,(e,r,i)=>{var o=cs(),s=R(o);Si(s),s.value=s.__value=i;var c=V(s),l=V(c),u=e=>{var t=os(),n=B(t,!0);H(()=>Y(n,G(r).detail)),J(e,t)};X(l,e=>{G(r).detail&&e(u)});var d=V(l,2),p=e=>{J(e,ss())};X(d,e=>{G(r).persistent&&e(p)}),N(o),H(()=>{Q(s,`name`,`decision-`+t.session+`-`+a()),Y(c,` ${G(r).label??``} `)}),ki(n,[],s,()=>G(f),e=>L(f,e)),J(e,o)}),J(e,r)},b=e=>{var n=as(),r=z(n),i=e=>{var t=hs(),n=z(t),r=V(R(n)),i=R(r),a=e=>{var t=ls();t.value=t.__value=`now`,J(e,t)};X(i,e=>{G(x)||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),hi(r),N(n);var l=V(n,2),u=e=>{var t=us(),n=V(R(t));Si(n),N(t),Di(n,()=>G(ee),e=>L(ee,e)),J(e,t)};X(l,e=>{G(D)===`delay`&&e(u)});var d=V(l,2),f=e=>{var t=ds(),n=V(R(t));Si(n),N(t),Di(n,()=>G(te),e=>L(te,e)),J(e,t)};X(d,e=>{G(D)===`at`&&e(f)});var p=V(d,2),m=e=>{var t=ps(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,fs())};X(i,e=>{G(D)!==`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(D)===`quota`?`when quota is available and this session is idle`:Number.isFinite(G(ye))?be(G(ye)):`choose a date and time`]),J(e,t)};X(p,e=>{G(D)!==`now`&&e(m)});var h=V(p,2),g=e=>{J(e,ms())};X(h,e=>{G(x)&&e(g)}),gi(r,()=>G(D),e=>L(D,e)),J(e,t)};X(r,e=>{G(u).questions?.length||e(i)}),Z(V(r,2),17,()=>G(ge),qr,(e,n,r)=>{var i=Ss(),o=z(i),s=e=>{{let n=P(()=>G(d)[0]||``);Li(Bo(e,{get session(){return t.session},get oncopy(){return l()},get query(){return G(n)},oncomplete:e=>{L(d,[e],!0),ur().then(()=>G(ae)?.focus())},onchange:()=>{L(d,[``],!0),ur().then(()=>G(ae)?.focus())}}),e=>L(oe,e,!0),()=>G(oe))}};X(o,e=>{r===0&&a()!==`profile`&&G(u).kind===`prompt`&&!G(u).questions?.length&&e(s)});var c=V(o,2),f=R(c),p=V(f),m=e=>{var t=gs();Si(t),Di(t,()=>G(d)[r],e=>G(d)[r]=e),J(e,t)},h=e=>{var t=vs(),i=R(t);i.value=i.__value=``,Z(V(i),17,()=>G(n).options||[],qr,(e,t)=>{var n=_s(),r=B(n,!0),i={};H(()=>{Y(r,G(t)),i!==(i=G(t))&&(n.value=(n.__value=i)??``)}),J(e,n)}),N(t),hi(t),gi(t,()=>G(d)[r],e=>G(d)[r]=e),J(e,t)},g=e=>{var t=ys(),i=z(t);nt(i),Li(i,e=>L(ae,e),()=>G(ae));var a=V(i,2),o=e=>{var t=rs(),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(u)?.kind===`prompt`&&!G(u).questions?.length&&G(oe)?.handleKey(e)}),Di(i,()=>G(d)[r],e=>G(d)[r]=e),J(e,t)};X(p,e=>{G(n).secret?e(m):G(n).freeText?e(g,-1):e(h,1)}),N(c);var _=V(c,2),v=e=>{var t=xs(),r=V(R(t),4);Z(r,21,()=>G(n).options||[],qr,(e,t)=>{var n=bs(),r=B(n,!0);H(()=>Y(r,G(t))),J(e,n)}),N(r),N(t),J(e,t)};X(_,e=>{G(n).secret&&!G(n).freeText&&e(v)}),H(()=>Y(f,`${G(n).text??``} `)),J(e,i)}),J(e,n)};X(v,e=>{G(u).kind===`approval`||G(u).kind===`profile`?e(y):e(b,-1)}),N(s);var S=V(s,2),C=e=>{var t=ws(),n=z(t),r=e=>{var t=Cs(),n=B(t);H(()=>Y(n,`TRIGGER // ${G(ne)??``}`)),J(e,t)};X(n,e=>{G(O)&&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(u).kind===`profile`?`profile above`:G(u).kind===`approval`?G(u).fileChanges?.length?`proposed file changes above`:`exact command and permission scope`:`message above`}. ${G(O)?`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(g)||G(de),Y(s,`CONFIRM ${(G(u).kind===`approval`||G(u).kind===`profile`?G(u).choices?.[G(f)]?.label:G(O)?G(x)?`SAVE CHANGES`:`SCHEDULE`:`SEND`)??``}`)},[()=>Math.max(0,Math.ceil((G(m)-G(h))/1e3))]),K(`click`,o,Ce),K(`click`,c,()=>{L(p,``)}),J(e,t)},w=e=>{var t=Ts(),n=z(t),r=e=>{var t=Go(),n=B(t,!0);H(()=>Y(n,G(A))),J(e,t)};X(n,e=>{G(A)&&e(r)});var i=V(n,2),a=B(i,!0);H(()=>{i.disabled=G(g)||G(de)||!G(_e)||!!G(A),Y(a,G(g)?`SENDING…`:G(he)?G(x)?`REVIEW CHANGES`:`REVIEW BEFORE SENDING`:G(x)?`SAVE CHANGES`:G(u).kind===`approval`||G(u).kind===`profile`?`SEND DECISION`:G(u).kind===`prompt`&&!G(u).questions?.length&&G(D)!==`now`?`SET TRIGGER`:`SEND`)}),K(`click`,i,()=>xe()),J(e,t)};X(S,e=>{G(k)&&G(he)?e(C):e(w,-1)});var T=V(S,2),E=e=>{var t=Es();K(`click`,t,()=>{L(x,!1),L(p,``),L(d,[],!0)}),J(e,t)};X(T,e=>{G(x)&&e(E)}),H(()=>{Y(o,`TARGET // ${G(u).thread??``} // ${(G(u).directory||`Directory unavailable`)??``}`),s.disabled=G(g)||G(k)||G(de),Y(_,G(u).kind===`approval`||G(u).kind===`profile`?`Choose a decision`:G(x)?`EDIT SCHEDULED FOLLOW-UP`:`Reply to this session`)}),J(e,r)};X(fe,e=>{G(de)||G(y)?e(ve):G(u)?G(u).id?G(b)!==G(u).id&&e(we,3):e(M,2):e(j,1)}),N(r),H(()=>Y(s,a()===`profile`?`QUOTA THRESHOLD`:`SESSION CONTROL // EXPERIMENTAL`)),J(e,r)};X(Oe,e=>{!G(fe)&&(!G(ie)||G(x)||a()||G(u)?.kind!==`prompt`||G(u).questions?.length)&&e(ke)}),J(e,we),Ge()}Cr([`click`,`keydown`]);var As=q(` `);function js(e,t){We(t,!0);let n=Gi(t,`stale`,3,!1),r=P(()=>n()||!!t.goal?.stale);var i=Pr(),a=z(i),o=e=>{var n=As();let i;var a=B(n,!0);H((e,o)=>{i=li(n,1,`goal-status svelte-1yfu3xi`,null,i,{stale:G(r),pursuing:!G(r)&&t.goal.status===`active`,blocked:e}),Q(n,`title`,o),Y(a,G(r)?`GOAL STALE`:t.goal.label)},[()=>!G(r)&&[`blocked`,`usageLimited`,`budgetLimited`].includes(t.goal.status),()=>t.goal.objective+` -`+t.goal.tokensUsed.toLocaleString()+(t.goal.tokenBudget===null?` tokens`:` / `+t.goal.tokenBudget.toLocaleString()+` tokens`)]),J(e,n)};X(a,e=>{t.goal&&e(o)}),J(e,i),Ge()}var Ms=q(` `,1),Ns=q(`
      `),Ps=q(`

      STATUS LINE // CODEXOMETER

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

      `),Fs=q(`

      `,1);function Is(e,t){We(t,!0);let n=Gi(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(()=>{sa.open&&!G(i)?(L(r,o(oa.statusLine),!0),L(i,!0)):sa.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=Fs(),p=z(d),m=e=>{var t=Ps(),n=V(R(t),4);Z(n,21,()=>G(c),e=>e.id,(e,t)=>{var n=Ns(),i=R(n),a=R(i);Si(a);var o=V(a,1,!0),s=B(V(o),!0);N(i);var c=V(i,2),d=e=>{var n=Ms(),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),Ci(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,()=>{oa.statusLine=[...G(r)],la(),sa.open=!1}),K(`click`,d,()=>{sa.open=!1}),J(e,t)};X(p,e=>{sa.open&&e(m)});var h=V(p,2),g=R(h),_=B(g,!0),v=V(g,2);{let e=P(()=>n()||!$.connected||!!$.data?.sessionsError);js(v,{get goal(){return t.session.goal},get stale(){return G(e)}})}var y=V(v,2);ni(V(y,2),()=>t.children??f),N(h),H((e,t)=>{Q(g,`title`,e),Y(_,t)},[()=>s(oa.statusLine),()=>s(oa.statusLine)]),K(`click`,y,()=>{sa.open=!sa.open}),J(e,d),Ge()}Cr([`change`,`click`]);var Ls=q(`
      `);function Rs(e,t){We(t,!0);let n=Gi(t,`active`,3,!1),r=Gi(t,`compact`,3,!1),i=P(()=>so(t.session)),a=P(()=>!!G(i)),o=I(!1),s=I(``),c=I(!1);yn(()=>{if(!G(c))return;let e=setTimeout(()=>{L(c,!1)},150);return()=>clearTimeout(e)}),yn(()=>{G(i),t.session.status,L(s,``)});async function l(){if(!G(a)||G(o))return;let e=G(i);L(o,!0),L(c,!0),L(s,``);try{await navigator.clipboard.writeText(e),G(i)===e&&L(s,`Copied.`)}catch{G(i)===e&&L(s,`Clipboard unavailable. Select the visible text and copy it manually.`)}finally{L(o,!1)}}function u(e){!n()||!G(a)||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(),l())}var d={copy:l},f=Pr();Sr(`keydown`,$t,u);var p=z(f),m=e=>{var t=Ls();let n;var i=R(t),a=B(i,!0),u=V(i,2);let d;N(t),H(()=>{n=li(t,1,`session-copy svelte-543j00`,null,n,{compact:r()}),Y(a,G(s)),u.disabled=G(o),d=li(u,1,`svelte-543j00`,null,d,{flashed:G(c)})}),K(`click`,u,l),J(e,t)};return X(p,e=>{G(a)&&e(m)}),J(e,f),Ge(d)}Cr([`click`]);var zs=q(`

       
      `,1),Bs=q(`

      LATEST GUIDANCE

       
      `,1),Vs=q(`

      CONTEXT

       

      `,1),Hs=q(`

      `),Us=q(`

      `),Ws=q(`
       
      `),Gs=q(`

       
      `,1),Ks=q(`
       
      `),qs=q(`

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

      `),Js=q(`

      `,1),Ys=q(`

      `),Xs=q(` `,1),Zs=q(`

      `),Qs=q(`
      `),$s=q(`

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

      `),ec=q(`

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

      `),tc=q(` `),nc=q(` `),rc=q(` `),ic=q(``),ac=q(`

      Read only — reply or approve in Codex.

      `),oc=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),sc=q(`
      `),cc=q(` `,1),lc=q(`
      `),uc=q(`

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

      `),dc=q(`

      `),fc=q(``),pc=q(`

      `),mc=q(` `),hc=q(`

      `),gc=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),_c=q(`

      `),vc=q(`

      TOKEN ACTIVITY // 30 SECOND SAMPLES

      `),yc=q(`

      TOKENS

      FULL DETAIL →
      `),bc=q(`

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

      `),xc=q(`

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

      `,1),Sc=q(`

      SESSION TOTALS

      `,1);function Cc(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=Xs(),s=z(o),c=e=>{var n=zs(),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=Bs(),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=Vs(),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),h=e=>{var n=Hs();let r;var i=B(n,!0);H(e=>{r=li(n,1,`attention-note`,null,r,{inferred:t().status===`CHECK SESSION`}),Y(i,e)},[()=>ie(t())]),J(e,n)},_=P(()=>ie(t())&&(!G(a)||G(v)||t().status===`CHECK SESSION`||y(t())));X(m,e=>{G(_)&&e(h)});var b=V(m,2),x=e=>{var n=Us(),r=B(n,!0);H(e=>Y(r,e),[()=>ae(t())]),J(e,n)};X(b,e=>{G(i)&&e(x)});var S=V(b,2),C=e=>{var n=Ws(),r=B(n,!0);H(()=>Y(r,t().text||`No session context available.`)),J(e,n)};X(S,e=>{(t().text||!t().workingCommand)&&e(C)});var w=V(S,2),T=e=>{var n=Gs(),r=V(z(n),2),i=R(r),a=V(i),o=e=>{var n=Nr();H(()=>Y(n,`// ${t().commandTiming??``}`)),J(e,n)};X(a,e=>{t().commandTiming&&e(o)});var s=V(a,2),c=e=>{var n=Nr();H(()=>Y(n,`// +${(t().runningCommands||0)-+(t().commandStatus===`running`)} RUNNING`)),J(e,n)};X(s,e=>{!G(v)&&(t().runningCommands||0)>+(t().commandStatus===`running`)&&e(c)});var l=V(s,2),u=e=>{J(e,Nr(`+`))};X(l,e=>{t().runningLimited&&e(u)}),N(r);var d=B(V(r,2),!0);H(e=>{Y(i,`COMMAND // ${e??``} `),Y(d,t().workingCommand)},[()=>G(v)?`UNKNOWN`:(t().commandStatus||`unknown`).toUpperCase()]),J(e,n)};X(w,e=>{t().workingCommand&&e(T)});var E=V(w,2),D=e=>{Wo(e,{get lines(){return t().fileChanges}})},ee=e=>{var n=Js(),r=V(z(n),2),i=B(r,!0),a=V(r,2),o=e=>{var n=Ks(),r=B(n,!0);H(()=>Y(r,t().command)),J(e,n)},s=e=>{J(e,qs())};X(a,e=>{t().command?e(o):e(s,-1)}),H(()=>Y(i,G(v)||t().status!==`APPROVAL NEEDED`?`LAST OBSERVED COMMAND`:$.data?.control?`COMMAND REQUEST`:`COMMAND TO APPROVE IN CODEX`)),J(e,n)};X(E,e=>{(!G(a)||!$.data?.control)&&t().fileChanges?.length?e(D):G(a)&&$.data?.control||!t().command&&t().status!==`APPROVAL NEEDED`||e(ee,1)});var te=V(E,2),O=e=>{var n=Ys(),r=B(n);H(()=>Y(r,`CONTEXT SOURCE // ${(t().source||`LOCAL`)??``} // OBSERVATION`)),J(e,n)};X(te,e=>{G(a)||e(O)}),J(e,o)},r=I(void 0),i=Gi(t,`params`,19,()=>({})),a=P(()=>$.data?.sessions||[]),o=P(()=>$.data?.control&&$.data.profiles||[]),s=P(()=>($.data?.triggers||[]).filter(e=>G(a).some(t=>t.id===e.session)));function c(e,t){i().id&&i().id!==t&&G(u)?e.preventDefault():O(t)}function l(e){return[`TURN COMPLETE`,`IDLE`,`ACTIVE`].includes(e.status)&&G(s).some(t=>t.session===e.id)?`TRIGGER SET`:e.status}let u=I(!1);function d(e,t){i().id&&i().id!==t&&G(u)?e.preventDefault():O(t)}yn(()=>{let e=i().id;e&&pr(()=>{oa.selected=e,pa(e,2)})});let p=P(()=>G(a).find(e=>e.id===i().id)),m=P(()=>new URLSearchParams(Xi.querystring).get(`review`)===`profile`&&G(o).some(e=>e.session===i().id&&e.pending)),h=P(()=>G(a).some(e=>e.id===oa.selected)?oa.selected:G(a)[0]?.id),v=P(()=>!$.connected||!!$.data?.sessionsError);function y(e){return e.status!==`STALE`&&e.failed===!0}let b=P(()=>[[`OBSERVED TOKENS`,ma(G(a).reduce((e,t)=>e+t.tokens,0))],[`LISTED SESSIONS`,ma(G(a).length)],...[[`WORKING`,`WORKING`],[`AWAITING APPROVAL`,`APPROVAL NEEDED`],[`AWAITING INPUT`,`INPUT NEEDED`],[`ERRORS`,`ERRORS`],[`CHECK · INFERRED`,`CHECK SESSION`]].map(([e,t])=>[e,G(v)?`—`:ma(G(a).filter(e=>t===`ERRORS`?y(e):e.status===t).length)])]),x=P(()=>G(a).filter(e=>[`INPUT NEEDED`,`APPROVAL NEEDED`].includes(e.status)||y(e)).sort((e,t)=>S(e)-S(t)));function S(e){return e.status===`APPROVAL NEEDED`?0:e.status===`INPUT NEEDED`?1:2}let C=P(()=>G(a).filter(e=>e.status===`TURN COMPLETE`&&(!e.readStateKnown||e.unread)&&!G(s).some(t=>t.session===e.id)&&!G(o).some(t=>t.session===e.id&&t.pending))),w=I(``),T=new Set;async function E(e){if(!$.data?.control||G(v)||!e.unread||!e.readRevision||!e.replyTurn||e.streaming||G(m))return;let t=e.id,n=e.readRevision,r=e.replyTurn,i=JSON.stringify([t,n,r]);if(!T.has(i)){T.add(i);try{await ur();let e=G(a).find(e=>e.id===t),i=document.getElementById(`content`),o=i?.getBoundingClientRect(),s=o?o.left+i.clientLeft:0,c=o?o.top+i.clientTop:0,l=s+(i?.clientWidth||0),u=c+(i?.clientHeight||0);if(!Array.from(document.querySelectorAll(`[data-result-session]`)).some(e=>{let n=e.getBoundingClientRect();return i?.contains(e)&&e.dataset.resultSession===t&&e.dataset.resultTurn===r&&!e.closest(`[inert], [hidden]`)&&document.visibilityState===`visible`&&n.leftMath.max(0,s)&&n.topMath.max(0,c)&&n.width>0&&n.height>0})||e?.readRevision!==n||e?.replyTurn!==r||G(v))return;await ya(`read`,{session:t,read:{turn:r,revision:n}}),L(w,``)}catch{L(w,`Result changed or could not be marked read. Open it again to retry.`)}finally{T.delete(i)}}}function D(e){O(e);let t=G(a).find(t=>t.id===e);t&&E(t)}let ee=I(Xt(pr(()=>i().id||``))),te=I(``);yn(()=>{let e=i().id||``;e!==G(ee)&&(L(ee,e,!0),L(te,e,!0))}),yn(()=>{if(G(te)&&G(p)?.id===G(te)){let e=G(p);L(te,``),pr(()=>{E(e)})}});function O(e){oa.selected=e,ur().then(()=>document.querySelector(`.session-row.selected`)?.scrollIntoView({block:`nearest`}))}function ne(e,t){if(O(e),i().id){t<0&&(pa(e,2),location.hash=`/sessions`);return}let n=da(e)+t;if(n>2)location.hash=`/sessions/`+encodeURIComponent(e);else if(pa(e,n),t>0){let t=G(a).find(t=>t.id===e);t&&E(t)}}function re(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`&&i().id)e.preventDefault(),ne(i().id,-1);else if([`ArrowLeft`,`ArrowRight`].includes(e.key)&&(i().id||G(h)))e.preventDefault(),ne(i().id||G(h),e.key===`ArrowLeft`?-1:1);else if(!i().id&&[`ArrowUp`,`ArrowDown`].includes(e.key)&&G(a).length){e.preventDefault();let t=G(a).findIndex(e=>e.id===G(h));O(G(a)[Math.max(0,Math.min(G(a).length-1,t+(e.key===`ArrowUp`?-1:1)))].id)}}}function ie(e){return G(v)?`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.`:y(e)?e.status===`MODEL BUSY`?`CONFIRMED TURN FAILURE — the selected model was at capacity. Choose another model with /model or retry when ready. This is not a quota-exhaustion signal.`:e.status===`MODEL UNAVAILABLE`?`CONFIRMED TURN FAILURE — the provider could not find the selected model. Choose an available model with /model. No automatic retry or model change.`:e.status===`CAPACITY RESTRICTED`?`CONFIRMED TURN FAILURE — capacity is unavailable on a policy-restricted route. Inspect the error before changing settings or retrying. This is not a quota-exhaustion signal; no automatic retry or policy change.`:`CONFIRMED TURN FAILURE — inspect the error below before sending another prompt. No automatic retry or model change.`:$.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 ae(e){return e.streaming&&e.contextKind===`LAST REPLY`?`REPLY // STREAMING`:e.contextKind||`LAST ACTIVITY`}var oe=Sc();Sr(`keydown`,$t,re);var se=z(oe),ce=e=>{var t=Zs(),n=B(t,!0);H(()=>Y(n,G(w))),J(e,t)};X(se,e=>{G(w)&&e(ce)});var le=V(se,2),ue=B(V(R(le),2));N(le);var de=V(le,2);let fe;Z(de,21,()=>G(b),qr,(e,t)=>{var n=P(()=>_(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=Qs();let o;var s=R(a),c=B(s,!0),l=B(V(s,2),!0);N(a),H(()=>{o=li(a,1,`svelte-mm4wfe`,null,o,{failed:r()===`ERRORS`&&i()!==`0`&&i()!==`—`}),Y(c,r()),Y(l,i())}),J(e,a)}),N(de);var pe=V(de,2),me=B(pe),k=V(pe,2),he=e=>{J(e,$s())};X(k,e=>{G(v)&&e(he)});var ge=V(k,2),_e=e=>{J(e,ec())};X(ge,e=>{$.data?.profileError&&e(_e)});var ve=V(ge,2),ye=e=>{var t=ic(),n=R(t);Z(n,17,()=>G(x),qr,(e,t)=>{var n=tc();let r;var i=B(n);H((e,a,o)=>{r=li(n,1,`button`,null,r,{approval:e}),Q(n,`href`,a),Y(i,`${G(t).status??``} - ${o??``} // ${(G(t).name||G(t).directory||G(t).id)??``}`)},[()=>G(t).status===`APPROVAL NEEDED`||G(t).status===`INPUT NEEDED`||y(G(t)),()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,n,()=>O(G(t).id)),J(e,n)});var r=V(n,2);Z(r,17,()=>G(o).filter(e=>e.pending&&G(a).some(t=>t.id===e.session)),qr,(e,t)=>{var n=nc(),r=B(n);H((e,a,o)=>{Q(n,`title`,i().id&&i().id!==G(t).session&&G(u)?`Finish sending or clear your current draft before switching sessions.`:`Review this session’s quota threshold`),Q(n,`href`,e),Y(r,`QUOTA THRESHOLD ${a??``} // ${o??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).session)+`?review=profile`,()=>Array.from(G(t).session).slice(-5).join(``).toUpperCase(),()=>G(a).find(e=>e.id===G(t).session)?.name||G(a).find(e=>e.id===G(t).session)?.directory||G(t).session]),K(`click`,n,e=>d(e,G(t).session)),J(e,n)});var l=V(r,2);Z(l,17,()=>G(C),qr,(e,t)=>{var n=rc(),r=B(n);H((e,i)=>{Q(n,`href`,e),Y(r,`TURN COMPLETE ${i??``} // - ${(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,()=>O(G(t).id)),J(e,n)}),Z(V(l,2),17,()=>G(s),qr,(e,t)=>{var n=rc(),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(a).find(e=>e.id===G(t).session)?.name||G(a).find(e=>e.id===G(t).session)?.directory]),K(`click`,n,e=>c(e,G(t).session)),J(e,n)}),N(t),J(e,t)},A=P(()=>(G(x).length||G(C).length||G(o).some(e=>e.pending)||G(s).length)&&!G(v));X(ve,e=>{G(A)&&e(ye)});var be=V(ve,2),j=e=>{var t=Pr(),a=z(t),s=e=>{var t=lc(),a=R(t),s=R(a);let c;var d=R(s);let f;var h=V(d);N(s);var g=V(s,2);N(a);var _=V(a,2),b=e=>{var t=Ys(),n=B(t,!0);H(()=>Y(n,G(p).directory)),J(e,t)};X(_,e=>{G(p).name&&G(p).directory&&e(b)});var x=V(_,2),S=B(x),C=V(x,2);let w;var T=R(C),D=R(T);n(D,()=>G(p),()=>!0,()=>!0),N(T);var ee=V(T,2),te=e=>{var t=Pr();Kr(z(t),()=>G(p).id,e=>{{let t=P(()=>new URLSearchParams(Xi.querystring).get(`schedule`)===`edit`),n=P(()=>G(p).fileChanges||[]);ks(e,{get session(){return G(p).id},oncopy:()=>G(r)?.copy(),get openScheduler(){return G(t)},get observedCommand(){return G(p).command},get observedFileChanges(){return G(n)},get suspended(){return G(m)},onProtectedChange:e=>{L(u,e,!0)}})}}),J(e,t)},ne=e=>{var t=ac();Kr(V(R(t),2),()=>G(p).id,e=>{Bo(e,{get session(){return G(p).id},localOnly:!0,oncopy:()=>G(r)?.copy()})}),N(t),J(e,t)};X(ee,e=>{$.data?.control?e(te):e(ne,-1)}),N(C);var re=V(C,2);Z(re,17,()=>G(o).filter(e=>e.session===G(p).id),e=>e.session,(e,t)=>{var n=sc(),r=R(n),i=e=>{var n=Zs(),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=>{ks(e,{get session(){return G(p).id},review:`profile`})},s=e=>{var t=oc();H(e=>Q(t,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(p).id)+`?review=profile`]),J(e,t)};X(a,e=>{G(t).pending&&G(m)?e(o):G(t).pending&&e(s,1)}),N(n),H(()=>Q(n,`id`,`quota-profile-`+G(p).id)),J(e,n)});var ie=V(re,2),ae=e=>{var t=Pr();Kr(z(t),()=>G(p).id,e=>{Is(e,{get session(){return G(p)},get stale(){return G(v)},children:e=>{var t=Pr(),n=z(t),i=e=>{Li(Rs(e,{get session(){return G(p)},active:!0,compact:!0}),e=>L(r,e,!0),()=>G(r))};X(n,e=>{G(m)||e(i)}),J(e,t)},$$slots:{default:!0}})}),J(e,t)},oe=e=>{var t=cc(),n=z(t),i=e=>{var t=Pr();Kr(z(t),()=>G(p).id,e=>{Li(Rs(e,{get session(){return G(p)},active:!0}),e=>L(r,e,!0),()=>G(r))}),J(e,t)};X(n,e=>{G(m)||e(i)}),Kr(V(n,2),()=>G(p).id,e=>{Is(e,{get session(){return G(p)},get stale(){return G(v)}})}),J(e,t)};X(ie,e=>{G(p).goal?e(ae):e(oe,-1)}),N(t),H((e,t,n,r)=>{c=li(s,1,`svelte-mm4wfe`,null,c,{failed:e,reviewed:G(p).status===`TURN COMPLETE`&&G(p).readStateKnown&&!G(p).unread}),f=li(d,1,`lamp lit svelte-mm4wfe`,null,f,{failed:t,working:G(p).status===`WORKING`&&!G(v)}),Y(h,`${n??``} // ${(G(p).name||G(p).directory)??``}`),Y(S,`${r??``} TOKENS // ${G(p).id??``} // CONTEXT SOURCE // ${(G(p).source||`LOCAL`)??``}`),w=di(C,``,w,{display:G(m)?`none`:void 0}),Q(T,`data-result-session`,G(p).id),Q(T,`data-result-turn`,G(p).replyTurn)},[()=>y(G(p))&&!G(v)&&!G(m),()=>y(G(p))&&!G(v),()=>G(v)?`STALE`:G(m)?`QUOTA THRESHOLD`:l(G(p)),()=>ma(G(p).tokens)]),K(`click`,g,()=>{O(i().id),pa(i().id,2)}),Sr(`wheel`,T,()=>{E(G(p))}),J(e,t)},c=e=>{J(e,uc())};X(a,e=>{G(p)?e(s):e(c,-1)}),J(e,t)},M=e=>{var t=xc(),r=z(t),i=V(R(r),2),s=R(i),c=V(s,2);N(i),N(r);var u=V(r,2);Z(u,17,()=>G(a),e=>e.id,(e,t)=>{let r=P(()=>da(G(t).id));var i=yc();let a;var s=R(i),c=R(s),u=e=>{var n=dc(),r=R(n),i=B(r);N(n),H(e=>{Q(r,`aria-pressed`,G(h)===G(t).id),Y(i,`${e??``} // ${G(t).name??``}`)},[()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,r,()=>O(G(t).id)),J(e,n)};X(c,e=>{G(t).name&&e(u)});var f=V(c,2),p=R(f);let m;var g=R(p);let _;var b=V(g,1,!0);N(p),N(f);var x=V(f,2),S=e=>{var n=fc(),r=B(n,!0);H(()=>{Q(n,`aria-pressed`,G(h)===G(t).id),Y(r,G(t).directory||G(t).id)}),K(`click`,n,()=>O(G(t).id)),J(e,n)};X(x,e=>{G(t).name||e(S)});var C=V(x,2),w=R(C);Se(),N(C);var T=V(C,2),ee=e=>{var n=Ys(),r=B(n,!0);H(()=>Y(r,G(t).directory)),J(e,n)};X(T,e=>{G(t).name&&G(t).directory&&e(ee)});var te=V(T,2),re=B(te),ie=V(te,2),oe=B(ie),se=V(ie,2);js(se,{get goal(){return G(t).goal},get stale(){return G(v)}});var ce=V(se,2),le=R(ce),ue=V(le,2),de=B(ue,!0),fe=V(ue,2);N(ce);var pe=V(ce,2),me=V(pe,2),k=e=>{var n=pc(),r=B(n,!0);H(e=>Y(r,e),[()=>G(t).status===`CHECK SESSION`?`INFERRED INACTIVITY`:y(G(t))?`OPEN DETAIL FOR THE TURN ERROR`:$.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)},he=P(()=>!G(v)&&([`APPROVAL NEEDED`,`INPUT NEEDED`,`CHECK SESSION`].includes(G(t).status)||y(G(t))));X(me,e=>{G(he)&&e(k)}),N(s);var ge=V(s,2),_e=e=>{var r=_c(),i=R(r),a=R(i),s=B(a,!0),c=V(a,2),l=e=>{var n=mc(),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(v)&&G(t).status===`APPROVAL NEEDED`&&e(l)}),N(i);var u=V(i,2),f=R(u);n(f,()=>G(t),()=>!1),N(u);var p=V(u,2);Z(p,17,()=>G(o).filter(e=>e.session===G(t).id),qr,(e,n)=>{var r=cc(),i=z(r),a=e=>{var t=hc(),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=gc();H(e=>Q(n,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(t).id)+`?review=profile`]),K(`click`,n,e=>d(e,G(t).id)),J(e,n)};X(o,e=>{G(n).pending&&e(s)}),J(e,r)});var m=V(p,2);{let e=P(()=>G(h)===G(t).id);Rs(m,{get session(){return G(t)},get active(){return G(e)}})}N(r),H(e=>{Y(s,e),Q(u,`data-result-session`,G(t).id),Q(u,`data-result-turn`,G(t).replyTurn)},[()=>ae(G(t))]),Sr(`wheel`,u,()=>{E(G(t))}),J(e,r)};X(ge,e=>{G(r)>0&&e(_e)});var ve=V(ge,2),ye=e=>{var n=vc(),r=V(R(n),2);{let e=P(()=>(G(t).samples||[]).map(e=>e.tokens));ao(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(ve,e=>{G(r)<2&&e(ye)}),N(i),H((e,n,o,s,c,l,u)=>{a=li(i,1,`session-row`,null,a,{selected:G(h)===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)),m=li(p,1,`status-detail svelte-mm4wfe`,null,m,{reviewed:G(t).status===`TURN COMPLETE`&&G(t).readStateKnown&&!G(t).unread,failed:e}),Q(p,`href`,n),_=li(g,1,`lamp lit svelte-mm4wfe`,null,_,{failed:o,working:G(t).status===`WORKING`&&!G(v)}),Y(b,s),Y(w,`${c??``} `),Y(re,`${G(t).agents??``} LINKED AGENTS`),Y(oe,`ACTIVE // ${l??``}`),le.disabled=G(r)===0,Q(ue,`aria-expanded`,G(r)>0),Y(de,G(r)?`HIDE DETAIL`:`SHOW DETAIL`),Q(pe,`href`,u)},[()=>y(G(t))&&!G(v),()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>y(G(t))&&!G(v),()=>G(v)?`STALE`:l(G(t)),()=>ma(G(t).tokens),()=>ha(G(t).activity),()=>`#/sessions/`+encodeURIComponent(G(t).id)]),K(`click`,p,()=>D(G(t).id)),K(`click`,le,()=>ne(G(t).id,-1)),K(`click`,ue,()=>{let e=G(r)===0;O(G(t).id),pa(G(t).id,+!!e),e&&E(G(t))}),K(`click`,fe,()=>ne(G(t).id,1)),K(`click`,pe,()=>D(G(t).id)),J(e,i)});var f=V(u,2),p=e=>{J(e,bc())};X(f,e=>{G(a).length||e(p)}),K(`click`,s,()=>fa(1)),K(`click`,c,()=>fa(0)),J(e,t)};X(be,e=>{i().id?e(j):e(M,-1)}),H(e=>{Y(ue,`OBSERVED ${e??``}`),fe=li(de,1,`session-totals`,null,fe,{stale:G(v)}),Y(me,`${G(v)?`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.`)},[()=>ha($.data?.sessionsAt)]),J(e,oe),Ge()}Cr([`click`]);var wc=q(``),Tc=q(`

      `),Ec=q(`

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

      `,1),Dc=q(`// APPROXIMATE`),Oc=q(`

      Partial accounting: totals may still change.

      `),kc=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),jc=q(`

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

      `),Mc=q(`
      `),Nc=q(`
      `),Pc=q(`

      No usage reported for this day.

      `),Fc=q(`

      Selected breakdown unavailable; missing does not mean zero.

      `),Ic=q(`

      `,1);function Lc(e,t){We(t,!0);let n=I(Xt(lo[0])),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(()=>(t.mode===`breakdown`?G(c):G(l))?.views?.[G(n)]),f=P(()=>G(d)?.rows||[]),p=P(()=>G(d)?.total),m=P(()=>G(d)?.level||`unknown`),h=P(()=>G(d)?.peak||1),g=e=>e==null?`UNKNOWN`:e.toLocaleString(`en-GB`,{maximumFractionDigits:2});var _=Ic(),v=z(_),y=R(v),b=V(R(y));Z(b,21,()=>lo,qr,(e,t)=>{var n=wc(),r=B(n,!0),i={};H(e=>{Y(r,e),i!==(i=G(t))&&(n.value=(n.__value=i)??``)},[()=>G(t).charAt(0).toUpperCase()+G(t).slice(1)]),J(e,n)}),N(b),hi(b),N(y);var x=V(y,2),S=V(x,2),C=B(V(S,2),!0);N(v);var w=V(v,2),T=R(w),E=B(T,!0),D=V(T,2),ee=B(D),te=V(D,2),O=e=>{var t=Ec(),n=z(t),r=B(n),a=V(n,2),o=e=>{var t=Tc(),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)??``}`)},[()=>ha(G(i).fetchedAt),()=>g(G(p))]),J(e,t)},ne=e=>{var t=Ac(),n=z(t),r=R(n);let i;var o=B(r,!0),s=V(r),c=e=>{J(e,Dc())};X(s,e=>{G(a).approximate&&e(c)});var u=V(s);N(n);var d=V(n,2),f=R(d),h=V(f),_=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(_)}),N(d);var v=V(d,2),y=e=>{var t=kc(),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,Oc())};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=li(i,1,`svelte-1fbui7h`,null,a,{muted:G(m)===`unknown`,"quota-near":G(m)===`near`,"quota-full":G(m)===`full`}),Y(o,`USED ${e??``}${G(p)==null?``:`%`}`),Y(c,`${G(l).starts_at??``} → ${G(l).ends_at??``}`)},[()=>g(G(p))]),J(e,t)};X(v,e=>{G(l)&&e(y)}),H(e=>{i=li(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(f,`Coverage starts ${(G(a).coverage_start||`unknown`)??``} // Data as of ${(G(a).data_as_of||`unknown`)??``}`)},[()=>ha(G(a).fetchedAt)]),J(e,t)},re=e=>{J(e,jc())};X(te,e=>{t.mode===`breakdown`&&G(i)?e(O):t.mode===`periods`&&G(a)?e(ne,1):e(re,-1)});var ie=V(te,2),ae=e=>{var n=Nc(),r=R(n),i=B(V(R(r),2),!0);N(r),Z(V(r,2),17,()=>G(f),qr,(e,n,r)=>{let i=()=>G(n).name,a=()=>G(n).value;var o=Mc();let s;var c=R(o),l=B(c,!0),u=V(c,2),d=R(u);let f;N(u);var p=B(V(u,2));N(o),H((e,n,a)=>{s=li(o,1,`report-row svelte-1fbui7h`,null,s,{unknown:e,alternate:r%2==1}),Q(c,`title`,i()),Y(l,i()),f=di(d,``,f,{width:n}),Y(p,`${a??``}${t.mode===`periods`?`%`:``}`)},[()=>i().trim().toLowerCase()===`unknown`,()=>`${Math.max(0,100*a()/G(h))}%`,()=>g(a())]),J(e,o)}),N(n),H(()=>Y(i,t.mode===`breakdown`?G(u):`QUOTA USED`)),J(e,n)},oe=e=>{J(e,Pc())},se=e=>{J(e,Fc())};X(ie,e=>{G(f).length?e(ae):t.mode===`breakdown`&&G(d)?.knownEmpty?e(oe,1):(G(i)&&t.mode===`breakdown`||G(a)&&t.mode===`periods`)&&e(se,2)}),N(w),H(()=>{x.disabled=G(s)>=G(o)-1,S.disabled=G(s)===0,Y(C,G(o)?`${G(s)+1} / ${G(o)}`:`NO DATA`),Y(E,t.mode===`breakdown`?`DAILY BREAKDOWN`:`QUOTA WINDOWS`),Y(ee,`${(t.mode===`breakdown`?t.reports?.dailyStatus||`UNAVAILABLE`:t.reports?.planStatus||`UNAVAILABLE`)??``} // UTC`)}),gi(b,()=>G(n),e=>L(n,e)),K(`click`,x,()=>L(r,G(s)+1)),K(`click`,S,()=>L(r,G(s)-1)),J(e,_),Ge()}Cr([`click`]);var Rc=864e5;function zc(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 Bc(e,t,n){let r=new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()));for(let e=0;;e++){let i=zc(r,-t),a=new Date(i.getTime()+Rc);if(e===n)return{start:a,end:r};r=i}}var Vc=q(``),Hc=q(``,1),Uc=q(`

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

      `),Wc=q(`

      Token history unavailable; other reports may still be available.

      `),Gc=q(``),Kc=q(`
      `),qc=q(`

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

      `,1),Jc=q(`
      `,1),Yc=q(` `),Xc=q(`

      LIFETIME TOKENS

      PEAK DAY

      CURRENT STREAK

      DAYS

      LONGEST TURN

      SECONDS

      LONGEST STREAK

      DAYS

      OPENAI // UTC

      Accessible data table
      Date (UTC)Tokens

      `,1),Zc=q(`

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

      `),Qc=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 $c(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}=Bc(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=Qc(),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=Vc();let c;var l=B(s,!0);H(()=>{Q(s,`aria-pressed`,G(n)===a()),c=li(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=Hc(),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),hi(a),N(n);var c=V(n),l=V(c);H(()=>l.disabled=G(i)===0),K(`change`,a,()=>L(i,0)),gi(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,Uc())};X(m,e=>{$.data?.usageError&&e(h)});var g=V(m,2),v=e=>{J(e,Wc())};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);Lc(e,{get reports(){return G(t)},get mode(){return G(n)}})}}),J(e,t)},x=e=>{var t=Xc(),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=qc(),n=z(t),r=R(n),i=R(r);Z(i,17,()=>Array(G(s)),qr,(e,t)=>{J(e,Gc())}),Z(V(i,2),17,()=>G(a),qr,(e,t)=>{var n=Kc();let r,i;H(e=>{r=li(n,1,`heat-cell`,null,r,{zero:G(t).tokens===0}),Q(n,`title`,e),i=di(n,``,i,{opacity:G(t).tokens?.25+.75*G(t).tokens/G(o):1})},[()=>`${G(t).date}: ${ma(G(t).tokens)} tokens`]),J(e,n)}),N(r),N(n),Se(2),J(e,t)},E=e=>{var t=Jc(),r=z(t);{let e=P(()=>G(c).map(e=>e.tokens)),t=P(()=>G(n)+` usage`);ao(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 D=V(w,2),ee=V(R(D),2),te=R(ee),O=V(R(te));Z(O,21,()=>G(n)===`daily`?G(a):G(c),qr,(e,t)=>{var n=Yc(),r=R(n),i=B(r,!0),a=B(V(r),!0);N(n),H(e=>{Y(i,G(t).date),Y(a,e)},[()=>ma(G(t).tokens)]),J(e,n)}),N(O),N(te),N(ee),N(D),N(x);var ne=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(ne,`OBSERVED ${s??``} // CUMULATIVE IS FOR THE SELECTED PERIOD`)},[()=>ma($.data.usage.summary.lifetimeTokens),()=>ma($.data.usage.summary.peakDailyTokens),()=>ma($.data.usage.summary.currentStreakDays),()=>ma($.data.usage.summary.longestRunningTurnSec),()=>ma($.data.usage.summary.longestStreakDays),()=>G(a).at(-1)?.date,()=>ha($.data.usageAt)]),J(e,t)},S=e=>{J(e,Zc())};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 el=q(`

      Page not found

      Return to Quota

      `,1);function tl(e){var t=el();Se(2),J(e,t)}var nl=`CODEXOMETER`,rl=[`█▀▀ █▀█ █▀▄ █▀▀ ▀▄▀ █▀█ █▀▄▀█ █▀▀ ▀█▀ █▀▀ █▀█`,`█▄▄ █▄█ █▄▀ ██▄ █ █ █▄█ █ ▀ █ ██▄ █ ██▄ █▀▄`].flatMap(e=>[[...e].map(e=>e===`█`||e===`▀`),[...e].map(e=>e===`█`||e===`▄`)]),il=rl[0].length,al=rl.length,ol=0,sl=[...nl].map(e=>{let t=e===`M`?5:3,n={start:ol,width:t};return ol+=t+1,n}),cl=`ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`,ll=`010 101 111 101.110 111 101 110.111 100 100 111.110 101 101 110.111 100 110 111.111 100 110 100.111 100 101 111.101 101 111 101.111 010 010 111.001 001 101 111.101 110 110 101.100 100 100 111.101 111 101 101.101 111 111 101.111 101 101 111.111 101 111 100.111 101 111 001.111 101 110 101.111 100 001 111.111 010 010 010.101 101 101 111.101 101 101 010.101 101 111 101.101 010 010 101.101 101 010 010.111 001 100 111.111 101 101 111.110 010 010 111.111 001 110 111.111 011 001 111.101 101 111 001.111 110 001 111.100 111 101 111.111 001 010 010.111 111 101 111.111 101 111 001`.split(`.`).map(e=>e.split(` `));function ul(e=nl,t=-1,n=!1){let r=``;for(let i=0;i{e|=0,e=e+1831565813|0;let t=Math.imul(e^e>>>15,1|e);return t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296}}function ml(){let e=dl[Math.floor(Math.random()*dl.length)],t=Math.floor(Math.random()*4294967296),n=pl(t),r=[...nl].map((e,t)=>t);for(let e=r.length-1;e>0;e--){let t=Math.floor(n()*(e+1));[r[e],r[t]]=[r[t],r[e]]}return{variant:e,seed:t,order:r}}function hl(e,t){if(e.variant===`typing`){let e=t<1080,n=e?0:Math.min(Math.floor((t-1080)/90)+1,11);return{text:nl.slice(0,n).padEnd(11),cursor:n,dot:e?Math.floor(t/180)%2==0:n<11}}if(e.variant===`shuffle`){let n=pl(e.seed^Math.floor(t/70)),r=[...nl].map(e=>{let t;do t=cl[Math.floor(n()*36)];while(t===e);return t}),i=Math.min(Math.floor(t/110),11);for(let t of e.order.slice(0,i))r[t]=nl[t];return{text:r.join(``),cursor:-1,dot:!1}}return{text:nl,cursor:-1,dot:!1}}var gl=Mr(``);function _l(e,t){We(t,!0);let n=Gi(t,`text`,3,nl),r=Gi(t,`cursor`,19,()=>-1),i=Gi(t,`dot`,3,!1),a=P(()=>ul(n(),r(),i()));var o=gl(),s=B(o);H(()=>{Q(o,`viewBox`,`0 0 ${il} ${al}`),Q(o,`width`,il),Q(o,`height`,al),Q(s,`d`,G(a))}),J(e,o),Ge()}var vl=q(`
      `),yl=q(`
      `);function bl(e,t){We(t,!0);let n=I(void 0),r=I(0),i=I(Xt({width:0,height:0,pixelRatio:1})),a=I(Xt({x:0,y:0,width:0})),o=P(()=>G(n)?hl(G(n),G(r)):void 0),s=P(()=>{if(!G(n))return{x:0,y:0,width:0};let e=fl[G(n).variant],t=Math.min(Math.max((G(r)-e-180)/800,0),1),o=t*t*(3-2*t),s=G(i).width+(G(a).width-G(i).width)*o,c=Math.max((G(i).height-G(i).width*al/il)/2,0),l=(G(n).variant===`slide`&&G(r)Math.round(e*G(i).pixelRatio)/G(i).pixelRatio;return{x:d(l),y:d(u),width:d(s)}});Ki(()=>{let e=matchMedia(`(prefers-reduced-motion: reduce)`);if(e.matches){t.onfinish();return}L(n,ml(),!0);let o=fl[G(n).variant]+180+800,s=0,c=!1,l=performance.now(),u=()=>{let e=t.target?.getBoundingClientRect();L(i,{width:window.innerWidth,height:window.innerHeight,pixelRatio:window.devicePixelRatio||1},!0),e&&L(a,{x:e.x,y:e.y,width:e.width},!0)},d=()=>{c||(c=!0,cancelAnimationFrame(s),t.onfinish())},f=e=>{e instanceof PointerEvent&&e.button!==0||e instanceof KeyboardEvent&&(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)||e instanceof KeyboardEvent&&[`Shift`,`Control`,`Alt`,`Meta`].includes(e.key)||(e.preventDefault(),e.stopImmediatePropagation(),d())},p=()=>{e.matches&&d()},m=e=>{L(r,Math.max(e-l,0),!0),G(r)>=o?d():s=requestAnimationFrame(m)},h=new ResizeObserver(u);if(t.target){h.observe(t.target),t.target.parentElement&&h.observe(t.target.parentElement);let e=t.target.closest(`header`);e&&h.observe(e)}return u(),window.addEventListener(`resize`,u),document.addEventListener(`keydown`,f,!0),document.addEventListener(`pointerdown`,f,!0),e.addEventListener(`change`,p),s=requestAnimationFrame(m),()=>{c=!0,cancelAnimationFrame(s),h.disconnect(),window.removeEventListener(`resize`,u),document.removeEventListener(`keydown`,f,!0),document.removeEventListener(`pointerdown`,f,!0),e.removeEventListener(`change`,p)}});var c=yl(),l=R(c),u=e=>{var t=vl();let n;_l(R(t),{get text(){return G(o).text},get cursor(){return G(o).cursor},get dot(){return G(o).dot}}),N(t),H(()=>{Q(t,`data-text`,G(o).text),Q(t,`data-cursor`,G(o).dot?G(o).cursor:void 0),n=di(t,``,n,{left:`${G(s).x}px`,top:`${G(s).y}px`,width:`${G(s).width}px`})}),J(e,t)};X(l,e=>{G(o)&&e(u)});var d=V(l,2);N(c),H(()=>Q(c,`data-entrance`,G(n)?.variant)),K(`click`,d,function(...e){t.onfinish?.apply(this,e)}),J(e,c),Ge()}Cr([`click`]);var xl=q(` `),Sl=q(`

      `),Cl=q(`

      Connecting to your local Codexometer…

      `),wl=q(``),Tl=q(`

      Your quota. Your sessions. Your command centre.

      `);function El(e,t){We(t,!0);let n={"/":no,"/quota/:view?":no,"/sessions/:id?":Cc,"/usage":$c,"*":tl},r={quota:/^(?:\/|\/quota(?:\/[^/]+)?\/?)$/,sessions:/^\/sessions(?:\/[^/]+)?\/?$/,usage:/^\/usage\/?$/},i=I(`hacker`),a=I(!0),o=I(void 0);yn(()=>{ca.requests&&ur().then(()=>{G(o)?.focus(),G(o)?.scrollIntoView({block:`nearest`})})});let s=I(void 0),c=[`hacker`,`rust`,`blue-steel`,`ultraviolet`,`nightshade`];yn(()=>{la()}),yn(()=>{if($.data)for(let[e,t]of Object.entries(r))t.test(Xi.location)&&(oa.tab=e)}),Ki(()=>{try{let e=localStorage.getItem(`codexometer.web.theme`);e&&c.includes(e)&&L(i,e,!0)}catch{}return ba()});function l(){try{localStorage.setItem(`codexometer.web.theme`,G(i))}catch{}}var u=Tl(),d=R(u),f=R(d),p=R(f);_l(R(p),{}),N(p),Li(p,e=>L(s,e),()=>G(s)),Se(2),N(f);var m=V(f,2),h=R(m);let g;var v=V(h,1,!0),y=B(V(v));N(m),N(d);var b=V(d,2);Z(b,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(Xi.location));var o=xl();let s;var c=B(o,!0);H(e=>{Q(o,`href`,r()===`quota`?`#/quota/`+oa.view:`#/`+r()),Q(o,`aria-current`,G(a)?`page`:void 0),s=li(o,1,``,null,s,{active:G(a)}),Y(c,e)},[()=>r().toUpperCase()]),J(e,o)}),N(b);var x=V(b,2),S=R(x),C=e=>{var t=Sl(),n=B(t,!0);H(()=>Y(n,$.error)),J(e,t)};X(S,e=>{$.error&&e(C)});var w=V(S,2),T=e=>{ea(e,{get routes(){return n}})},E=e=>{J(e,Cl())};X(w,e=>{$.data?e(T):$.error||e(E,1)}),N(x);var D=V(x,2),ee=R(D),te=B(ee),O=V(ee,2),ne=B(O,!0),re=V(O,2),ie=V(R(re));Z(ie,21,()=>c,qr,(e,t)=>{var n=wl(),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(ie),Li(ie,e=>L(o,e),()=>G(o)),hi(ie),N(re),N(D);var ae=V(D,2),oe=e=>{bl(e,{get target(){return G(s)},onfinish:()=>L(a,!1)})};X(ae,e=>{G(a)&&e(oe)}),N(u),H(()=>{Q(u,`data-theme`,G(i)),Q(u,`data-starting`,G(a)),d.inert=G(a),g=li(h,1,`lamp`,null,g,{lit:$.connected}),Y(v,$.connected?`CONNECTED`:`OFFLINE`),Y(y,`EXPERIMENTAL // ${$.data?.control?`SESSION CONTROL`:`READ ONLY`}`),b.inert=G(a),x.inert=G(a),D.inert=G(a),Y(te,`v${($.data?.version||`…`)??``} // LOCAL ONLY`),Y(ne,$.data?.control?`Session control enabled. Stop the server to revoke access.`:`No actions can be sent from this preview.`)}),K(`change`,ie,l),gi(ie,()=>G(i),e=>L(i,e)),J(e,u),Ge()}Cr([`change`]),Br(El,{target:document.getElementById(`app`)}); \ No newline at end of file diff --git a/internal/web/dist/assets/index-DzV0x1A7.js b/internal/web/dist/assets/index-DzV0x1A7.js new file mode 100644 index 00000000..22515eb2 --- /dev/null +++ b/internal/web/dist/assets/index-DzV0x1A7.js @@ -0,0 +1,50 @@ +(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,ee=1<<19,E=1<<20,te=1<<25,ne=1<<21,D=1<<22,re=1<<23,O=Symbol(`$state`),ie=Symbol(`component`),ae=Symbol(`legacy props`),oe=Symbol(``),se=Symbol(`attributes`),ce=Symbol(`class`),le=Symbol(`style`),ue=Symbol(`text`),de=Symbol(`form reset`),fe=new class extends Error{name=`StaleReactionError`;message="The reaction that called `getAbortSignal()` was re-run or destroyed"},pe=!!globalThis.document?.contentType&&globalThis.document.contentType.includes(`xml`),me={},k=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 M(e){if(e===null)throw _e(),me;return j=e}function xe(){return M(sn(j))}function N(e){if(A){if(sn(j)!==null)throw _e(),me;j=e}}function Se(e=1){if(A){for(var t=e,n=j;t--;)n=sn(n);j=n}}function Ce(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 we(e){if(!e||e.nodeType!==8)throw _e(),me;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,ie,{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){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[de]?.()})},{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[de];e[de]=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|=ee),{ctx:He,deps:null,effects:null,equals:Te,f:t,fn:e,reactions:null,rv:0,v:k,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(k),o=!U,s=new Set;return wn(()=>{var t=W,n=h();i=n.promise;try{Promise.resolve(e()).then(n.resolve,e=>{e!==fe&&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|=re,Gt(a,t)):(a.f&8388608&&(a.f^=re),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(fe),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);else{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){Ct=e,e.b?.is_pending&&e.f&16777228&&!(e.f&32768)?e.b.defer_effect(e):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(k,u));r.set(t,e),Jt(o)}}else L(n,k),Jt(o);return!0},get(e,n,i){if(n===O)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]:k),u)),r.set(n,o)),o!==void 0){var c=G(o);return c===k?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===k)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===O)return!0;var n=r.get(t),i=n!==void 0&&n.v!==k||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]):k,u)),r.set(t,n)),G(n)===k)?!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(k,u)),r.set(d+``,p)):L(p,k)}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!==k;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!==k});for(var[n,i]of r)i.v!==k&&!(n in e)&&t.push(n);return t},setPrototypeOf(){Le()}})}function Zt(e){try{if(typeof e==`object`&&e&&O in e)return e[O]}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[ce]=void 0,e[se]=null,e[le]=void 0,e.__e=void 0),u(n)&&(n[ue]=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),M(r),r}return t&&dn(n),M(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),M(r),r}dn(j)}return j}function B(e,t=!1){if(!A)return on(e);var n=R(e,t);return N(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),M(a),a}dn(r)}return M(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|=re,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|E,e)}function xn(e){return mn(`$effect.pre`),gn(8|E,e)}function Sn(e){At.ensure();let t=gn(64|ee,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(D|ee,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|ee,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(fe)});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(fe)}),e.ac=null);try{e.f|=ne;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(fe),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()),M(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),xe()}else e!==null&&e.before(t)}function Fr(){if(A&&j&&j.nodeType===8&&j.textContent?.startsWith(`$`)){let e=j.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|ee;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;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),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=()=>{t?ye():(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;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)):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){this.has_pending_snippet()?(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))):this.parent&&this.parent.#C(e,t)}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&&(M(this.#t),Se(),M(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[ue]??=e.nodeValue)&&(e[ue]=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),A&&Ar(t,null),l=e(t,i)||Ke(),A&&(W.nodes.end=j,j===null||j.nodeType!==8||j.data!==`]`))throw _e(),me;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,xe());var i=new Wr(e),a=n?T:0;function o(e,t){if(A){var n=we(r);if(e!==parseInt(n.substring(1))){var a=Ce();M(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&&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^=te,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&&we(c)===`[!`!=(e===0)&&(c=Ce(),M(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|=te)),e>r.size&&Ae(``,``,``),A&&e>0&&M(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&&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 ee=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=new Wr(e);En(()=>{let e=t()??null;r.ensure(e,e&&(t=>e(t,...n)))},T)}function ri(e,t,n){var r;A&&(r=j,xe());var i=new Wr(e);En(()=>{var e=t()??null;if(A&&we(r)===`[`!=(e!==null)){var a=Ce();M(a),i.anchor=a,be(!1),i.ensure(e,e&&(t=>n(t,e))),be(!0)}else i.ensure(e,e&&(t=>n(t,e)))},T)}var ii=[...` +\r\f\xA0\v`];function ai(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||ii.includes(r[o-1]))&&(s===r.length||ii.includes(r[s]))?r=(o===0?``:r.substring(0,o))+r.substring(s+1):o=s}}return r===``?null:r}function oi(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 si(e){return e[0]!==`-`||e[1]!==`-`?e.toLowerCase():e}function ci(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(si)),i&&c.push(...Object.keys(i).map(si));var l=0,u=-1;let t=e.length;for(var d=0;d{t.every(vi)||(`__defaultValue`in e&&pi(e,!1),`__value`in e&&mi(e,e.__value))});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`value`]}),vn(()=>{t.disconnect()})}function gi(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),_i);else{var o=e.querySelector(i)??e.querySelector(`option:not([disabled])`);a=o&&_i(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(mi(e,a,i),i&&a===void 0){var s=e.querySelector(`:checked`);s!==null&&(a=_i(s),n(a))}e.__value=a,i=!1})}function _i(e){return`__value`in e?e.__value:e.value}function vi(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 yi=Symbol(`is custom element`),bi=Symbol(`is html`),xi=pe?`link`:`LINK`;function Si(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[de]=n,Xe(n),it()}}function Ci(e,t){var n=wi(e);n.checked!==(n.checked=t??void 0)&&(e.checked=t)}function Q(e,t,n,r){var i=wi(e);A&&(i[t]=e.getAttribute(t),t===`src`||t===`srcset`||t===`href`&&e.nodeName===xi)||i[t]!==(i[t]=n)&&(t===`loading`&&(e[oe]=n),n==null?e.removeAttribute(t):typeof n!=`string`&&Ei(e).has(t)?e[t]=n:e.setAttribute(t,n))}function wi(e){return e[se]??={[yi]:e.nodeName.includes(`-`),[bi]:e.namespaceURI===he}}var Ti=new Map;function Ei(e){var t=e.getAttribute(`is`)||e.nodeName,n=Ti.get(t);if(n)return n;Ti.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 Di(e,t,n=t){var r=new WeakSet;ot(e,`input`,async i=>{var a=i?e.defaultValue:e.value;if(a=Mi(e)?Ni(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(Mi(e)?Ni(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}Mi(e)&&n===Ni(e.value)||(e.type!==`date`||n||e.value)&&n!==e.value&&(e.value=n??``)})}var Oi=new Set;function ki(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=ji(o,e,n.checked)),i(e)},()=>i(a?[]:null)),Tn(()=>{var e=r();A&&n.defaultChecked!==n.checked?s=!0: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)}),Oi.has(o)||(Oi.add(o),Xe(()=>{o.sort((e,t)=>e.compareDocumentPosition(t)===4?-1:1),Oi.delete(o)})),Xe(()=>{if(s){var e=a?ji(o,e,n.checked):o.find(e=>e.checked)?.__value;i(e)}})}function Ai(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 ji(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 Fi(e,t,n){var r=Pi.observe(e,()=>n(e[t]));Cn(()=>(pr(()=>n(e[t])),r))}function Ii(e,t){return e===t||e?.[O]===t}function Li(e=Ke(),t,n,r){var i=He.r,a=W;return Cn(()=>{var o,s;return Tn(()=>{o=s,s=r?.()||[],pr(()=>{Ii(n(...s),e)||(t(e,...s),o&&Ii(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&&Ii(n(...s),e)&&t(null,...s)},c=r.teardown;r.teardown=()=>{o(),c?.()}}}),e}function Ri(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 zi(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(()=>{Bi(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(()=>{Bi(t,r),m(n.a)})}function Bi(e,t){if(e.l.s)for(let t of e.l.s)G(t);t()}var Vi=!1;function Hi(e){var t=Vi;try{return Vi=!1,[e(),Vi]}finally{Vi=t}}var Ui={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===O||t===ae)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 Wi(...e){return new Proxy({props:e},Ui)}function Gi(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=O in e||ae in e;f=a(e,t)?.set??(p&&t in e?n=>e[t]=n:void 0)}var m,h=!1;o?[m,h]=Hi(()=>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 Ki(e){He===null&&Oe(`onMount`),Be&&He.l!==null?Ji(He).m.push(e):yn(()=>{let t=pr(e);if(typeof t==`function`)return t})}function qi(e){He===null&&Oe(`onDestroy`),Ki(()=>()=>pr(e))}function Ji(e){var t=e.l;return t.u??={a:[],b:[],m:[]}}typeof window<`u`&&((window.__svelte??={}).v??=new Set).add(`5`);function Yi(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 Xi=new class{#e=I(Zi());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=Zi()}):console.warn(`[svelte-spa-router] window 'window' is not defined, skipping initiation`)}};function Zi(){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 Qi(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 $i(e){e?window.scrollTo(e.__svelte_spa_router_scrollX||0,e.__svelte_spa_router_scrollY||0):window.scrollTo(0,0)}function ea(e,t){We(t,!0);let n=Gi(t,`routes`,19,()=>({})),r=Gi(t,`prefix`,3,``),i=Gi(t,`restoreScrollState`,3,!1),a=Gi(t,`onConditionsFailed`,3,()=>{}),o=Gi(t,`onRouteLoaded`,3,()=>{}),s=Gi(t,`onRouteLoading`,3,()=>{}),c=Gi(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=Yi(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=Xi.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();ri(z(n),()=>G(t),(e,t)=>{t(e,Wi({get params(){return G(f)},get onRouteEvent(){return c()}},()=>G(p)))}),J(e,n)},a=e=>{var n=Pr();ri(z(n),()=>G(t),(e,t)=>{t(e,Wi({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 ta=[`bars`,`pace`,`pie`,`fuel`,`resets`,`thresholds`];function na(e){return e===`zone`||e===`consumption-pace`?`pace`:typeof e==`string`&&ta.includes(e)?e:`bars`}var ra=`codexometer.web.preferences.v1`,ia={statusLine:null,tab:`quota`,view:`bars`,selected:``,defaultDetail:0,layouts:[]};function aa(){try{let e=JSON.parse(localStorage.getItem(ra)||`null`);return!e||typeof e!=`object`?ia:{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:na(e.view),selected:typeof e.selected==`string`?e.selected.slice(0,256):``,defaultDetail:[0,1,2].includes(e.defaultDetail)?e.defaultDetail:0,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 ia}}var oa=Xt(aa()),sa=Xt({open:!1}),ca=Xt({requests:0});function la(){let e=JSON.stringify(oa);try{localStorage.setItem(ra,e)}catch{}}function ua(){return oa.tab===`quota`?`/quota/`+oa.view:`/`+oa.tab}function da(e){return oa.layouts.find(t=>t.id===e)?.level??oa.defaultDetail}function fa(e){if(!e.length)return;let t=e.map(da),n=Math.max(...t);oa.defaultDetail=t.every(e=>e===n)?(n+1)%3:n;let r=new Set(e);oa.layouts=oa.layouts.filter(e=>!r.has(e.id))}function pa(e,t){oa.layouts=[...oa.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:``}),ma=e=>e==null?`Unavailable`:e.toLocaleString(`en-GB`),ha=e=>!e||String(e).startsWith(`0001-`)?`Not yet available`:new Date(typeof e==`number`?e*1e3:e).toLocaleString(`en-GB`),ga=`codexometer.web.session`,_a=class extends Error{},va;async function ya(e,t,n){if(!va||!$.connected||!$.data?.control||$.data.sessionsError)throw Error(`Session controls unavailable. Check the live connection.`);return await va(e,t,n)}function ba(){let e=new AbortController,t,n=``;va=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 _a(`Action rejected, expired or changed. Refresh and check Codex; nothing was retried.`);return a.json()};try{n=sessionStorage.getItem(ga)||``}catch{}let r=location.hash,i=r.startsWith(`#pair=`)?r.slice(6):``;(i||!r||r===`#`)&&(history.replaceState(null,``,`/#`+ua()),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(ga,n)}catch{}}catch(t){e.signal.aborted||($.error=t instanceof Error?t.message:`Pairing failed`);return}n?await o():$.error=`Open the private pairing link printed by codexometer --web in your terminal.`}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(ga)}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(),()=>{va=void 0,e.abort(),clearTimeout(t),$.connected=!1}}Ve();var xa=q(`

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

      `),Sa=q(`

      `),Ca=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),wa=q(`

      No threshold-based model steps were configured at launch.

      `);function Ta(e,t){We(t,!1),zi();var n=Pr(),r=z(n),i=e=>{var t=Ca(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,xa())};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=Sa();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=li(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`)},[()=>ha($.data.quotaAt)]),J(e,t)},a=e=>{J(e,wa())};X(r,e=>{$.data?.thresholds?.length?e(i):e(a,-1)}),J(e,n),Ge()}var Ea=Mr(` `,1),Da=Mr(` `,1),Oa=Mr(` `,1),ka=Mr(` `,1),Aa=q(`
      `,1),ja=q(` `),Ma=q(`
      Quota observations
      Observed atPeriod elapsedConsumedTrail segment
      `),Na=q(`
      OBSERVATION DATA
      `),Pa=q(`
      CONSUMPTIONQUOTA PERIOD ELAPSED
      `,1);function Fa(e,t){let n=Fr();We(t,!0);let r=Gi(t,`trail`,19,()=>[]),i=I(!1),a=I(!0),o=I(`window`),s=[0,25,50,75,100],c=P(()=>t.plot?.known?t.plot.elapsed:t.elapsed),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,G(c)))/100*G(p));function g(e){return G(f)-(e-0)/100*G(m)}let _=P(()=>g(t.used)),v=P(()=>t.used-G(c)),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))),S=P(()=>Object.fromEntries((t.plot?.modes||[]).map(e=>[e.id,e.available])));yn(()=>{G(o)!==`window`&&!G(S)[G(o)]&&L(o,`window`)});let C=P(()=>{let e=t.plot?.modes.find(e=>e.id===G(o));if(!e?.segment)return null;let{x1:n,y1:r,x2:i,y2:a}=e.segment,s=Math.hypot((i-n)/100*G(p),(a-r)/100*G(m)),c=Math.max(3,Math.min(9,Math.floor(s/65)+2));return{path:`M${Array.from({length:c},(e,t)=>{let o=n+(i-n)*t/(c-1),s=r+(a-r)*t/(c-1);return`${48+o/100*G(p)} ${g(s)}`}).join(` L`)}`,projected:e.projected,safe:e.safe}}),w=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 T=Pa(),ee=z(T),E=R(ee);let te;var ne=R(E),D=R(ne),re=V(D);N(ne);var O=V(ne),ie=V(O);Z(ie,17,()=>s,qr,(e,t)=>{var n=Ea(),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 ae=V(ie);Z(ae,17,()=>s,qr,(e,t)=>{var n=Da(),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 oe=V(ae),se=V(oe),ce=V(se),le=e=>{var t=Oa(),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),()=>ha(r()[0].at)]),J(e,t)};X(ce,e=>{G(a)&&r().length&&e(le)});var ue=V(ce),de=e=>{var t=ka(),r=z(t),i=V(r),a=B(R(i));N(i),H(e=>{Q(r,`d`,G(C).path),Q(i,`d`,G(C).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(C).projected.toFixed(1)]),J(e,t)};X(ue,e=>{G(C)&&e(de)});var fe=V(ue,2),pe=V(fe),me=V(pe),k=B(R(me));N(me),N(E),N(ee);var he=V(ee,2),ge=R(he),_e=R(ge),ve=V(_e,3),ye=B(ve,!0),A=V(ve,2),be=e=>{var t=Aa(),n=B(V(z(t)));H(e=>Y(n,`TREND // ${e??``}`),[()=>G(C).projected>=100?`QUOTA EXHAUSTION PROJECTED`:`${G(C).projected.toFixed(1)}% PROJECTED AT RESET`]),J(e,t)};X(A,e=>{G(C)&&e(be)}),N(ge);var j=V(ge,2),M=R(j),xe=R(M);Si(xe),Se(),N(M);var Ce=V(M,2),we=V(R(Ce),2),Te=R(we);Te.value=Te.__value=`off`;var Ee=V(Te),De=B(Ee);Ee.value=Ee.__value=`halfHour`;var Oe=V(Ee),ke=B(Oe);Oe.value=Oe.__value=`hour`;var Ae=V(Oe),je=B(Ae);Ae.value=Ae.__value=`day`;var Me=V(Ae),Ne=B(Me);Me.value=Me.__value=`window`,N(we),hi(we),N(Ce);var Pe=B(V(Ce,2));N(j),N(he);var Fe=V(he,2),Ie=e=>{var t=Na(),n=V(R(t),2),a=e=>{var t=Ma(),n=R(t),i=V(R(n),2);Z(i,21,r,qr,(e,t,n)=>{var r=ja(),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`)},[()=>ha(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),Ri(`open`,`toggle`,t,e=>L(i,e),()=>G(i)),J(e,t)};X(Fe,e=>{r().length&&e(Ie)}),H((e,r,i,a,o,s)=>{Q(E,`viewBox`,`0 0 ${G(l)} ${G(u)}`),Q(E,`aria-label`,e),te=di(E,``,te,{"--trend-color":G(C)?.safe?`#115b35`:`#7f1825`}),Q(D,`id`,n),Q(re,`id`,n+`-trend-arrow`),Q(O,`width`,G(p)),Q(O,`height`,G(m)),Q(O,`fill`,`url(#${n})`),Q(oe,`d`,`M48 20 V${G(f)} H${G(d)}`),Q(se,`y1`,r),Q(se,`x2`,G(d)),Q(se,`y2`,i),Q(fe,`x`,48+G(p)/2),Q(fe,`y`,G(u)-5),Q(pe,`cx`,G(h)),Q(pe,`cy`,G(_)),Q(me,`cx`,G(h)),Q(me,`cy`,G(_)),Y(k,`${t.used??``}% consumed // ${a??``}% of period elapsed`),Y(_e,`${t.used??``}% USED // ${o??``}% TIME ELAPSED`),Y(ye,s),Ee.disabled=!G(S).halfHour,Y(De,`LAST 30 MINUTES${G(S).halfHour?``:` — UNAVAILABLE`}`),Oe.disabled=!G(S).hour,Y(ke,`LAST HOUR${G(S).hour?``:` — UNAVAILABLE`}`),Ae.disabled=!G(S).day,Y(je,`LAST 24 HOURS${G(S).day?``:` — UNAVAILABLE`}`),Me.disabled=!G(S).window,Y(Ne,`FROM WINDOW START${G(S).window?``:` — NO TIME ELAPSED`}`),Y(Pe,`HISTORY // ${G(w)??``}`)},[()=>`Pace: ${t.used}% consumed, ${G(c).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),()=>G(c).toFixed(1),()=>G(c).toFixed(1),()=>Math.abs(G(v))<.05?`ON PACE`:G(v)>0?`ABOVE THE LINE — CONSUMING FASTER THAN TIME`:`BELOW THE LINE — WITHIN PACE`]),Fi(ee,`clientWidth`,e=>L(l,e)),Fi(ee,`clientHeight`,e=>L(u,e)),Ai(xe,()=>G(a),e=>L(a,e)),gi(we,()=>G(o),e=>L(o,e)),J(e,T),Ge()}var Ia=q(` `),La=q(`

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

      `),Ra=q(`

      `),za=q(`

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

      `),Ba=q(`

      `),Va=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.

      `),Ha=q(` `,1),Ua=Mr(``),Wa=Mr(``),Ga=q(`
      `),Ka=q(`

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

      `),qa=q(`
      EMPTYFULL
      `),Ja=q(`

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

      `),Za=q(`

      `),Qa=q(`

      No quota windows reported yet.

      `),$a=q(`
      `,1),eo=q(`

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

      `,1),to=q(` `,1);function no(e,t){We(t,!0);let n=Gi(t,`params`,19,()=>({})),r=P(()=>ta.filter(e=>e!==`thresholds`||!!$.data?.thresholds?.length)),i=I(Xt(Date.now())),a=P(()=>G(r).includes(na(n().view))?na(n().view):`bars`);Ki(()=>{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(()=>{oa.view=G(a),(n().view===`zone`||n().view===`consumption-pace`)&&Qi(`/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=to(),l=z(c);Z(l,21,()=>G(r),qr,(e,t)=>{var n=Ia();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=li(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=eo(),n=z(t),r=e=>{J(e,La())};X(n,e=>{$.data.quotaError&&e(r)});var i=V(n,2),c=e=>{var t=Ra(),n=B(t);H(()=>Y(n,`Last usage accounting issue: + ${$.data.usageDiagnostic??``}`)),J(e,t)};X(i,e=>{$.data.usageDiagnostic&&e(c)});var l=V(i,2),u=B(l),d=V(l,2),f=e=>{Ta(e,{})},p=e=>{var t=Va(),n=R(t),r=B(n),i=V(n,4),a=e=>{J(e,za())};X(i,e=>{$.data.credits.length||e(a)}),Z(V(i,2),17,()=>$.data.credits,qr,(e,t)=>{var n=Ba(),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 `+ha(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)},m=e=>{var t=$a(),n=z(t);let r;Z(n,21,()=>$.data.meters,qr,(e,t)=>{let n=P(()=>o(G(t)));var r=Za(),i=R(r),c=B(i,!0),l=V(i,2),u=R(l),d=e=>{var n=Ha(),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=Ha(),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=Ga(),r=R(n),i=V(R(r)),a=e=>{J(e,Ua())},o=e=>{var n=Wa();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||[]);Fa(e,{get used(){return G(t).used},get elapsed(){return G(n)},get trail(){return G(r)},get plot(){return G(t).plot}})}},o=e=>{J(e,Ka())};X(i,e=>{G(n)===null?e(o,-1):e(a)}),J(e,r)},v=e=>{var r=Ya(),i=z(r),o=R(i);let s;N(i);var c=V(i,2),l=e=>{J(e,qa())};X(c,e=>{G(a)===`fuel`&&e(l)});var u=V(c,2),d=e=>{var t=Ja(),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=di(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=di(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=Xa(),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=li(p,1,`meter-graphic`,null,m,{"bar-graphic":G(a)===`bars`||G(a)===`fuel`}),Y(b,`RESETS // ${e??``}`)},[()=>ha(G(t).reset)]),J(e,r)}),N(n);var i=V(n,2),c=e=>{J(e,Qa())};X(i,e=>{$.data.meters.length||e(c)}),H(()=>r=li(n,1,`quota-grid`,null,r,{radial:G(a)===`pie`,zone:G(a)===`pace`})),J(e,t)};X(d,e=>{G(a)===`thresholds`?e(f):G(a)===`resets`?e(p,1):e(m,-1)}),Se(2),H(e=>Y(u,`QUOTA // OBSERVED ${e??``}`),[()=>ha($.data.quotaAt)]),J(e,t)};X(u,e=>{$.data&&e(d)}),J(e,c),Ge()}var ro=q(`
      `),io=q(`

      `,1);function ao(e,t){We(t,!0);let n=Gi(t,`values`,19,()=>[]),r=Gi(t,`label`,3,`Token activity`),i=Gi(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=io(),c=z(s),l=B(c),u=V(c,2);Z(u,21,()=>G(o),qr,(e,t)=>{var n=ro();let r;H((e,t)=>{Q(n,`title`,e),r=di(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()}function oo(e,t=!1){return e===`require`||e!==`none`&&!t}function so(e){if(!e||![`LAST REPLY`,`LAST ACTIVITY`].includes(e.contextKind))return``;let t=e.text||e.contextKind===`LAST ACTIVITY`&&e.workingCommand||``;return t.trim()?t:``}var co=[{id:`local-statusline`,label:`/statusline`,help:`Choose fields for Codexometer’s detail footer. Saved display preferences only.`,next:`statusline`},{id:`local-usage`,label:`/usage`,help:`Open Codexometer’s usage history. Existing quota and reset views remain available.`,next:`usage`},{id:`local-copy`,label:`/copy`,help:`Copy the selected session’s observed reply or activity using Codexometer’s copy control.`,next:`copy`},{id:`local-theme`,label:`/theme`,help:`Choose a Codexometer display theme. Saved local display preferences only.`,next:`theme`},{id:`local-exit`,label:`/exit`,help:`Leave this Codexometer interface. Codex sessions continue running.`,next:`exit`},{id:`local-quit`,label:`/quit`,help:`Alias for /exit. Codex sessions continue running.`,next:`quit`}],lo=[`surface`,`model`,`feature`,`task start`],uo=q(` `),fo=q(``),po=q(`

      `),mo=q(`

      `),ho=q(`
      `),go=q(`

      `),_o=q(`

      `,1),vo=q(`

      `),yo=q(`

      Loading / sending…

      `),bo=q(`
      `),xo=q(`

      `),So=q(`

       
      `),Co=q(`
      `),wo=q(`
      `),To=q(`

      Review expired. Press Enter to review again.

      `),Eo=q(`

      `,1),Do=q(`

      `,1),Oo=q(`

      No available matching commands.

      `),ko=q(` `,1),Ao=q(`

      `),jo=q(`

      Review expired. Review the option again.

      `),Mo=q(``),No=q(``),Po=q(``),Fo=q(``),Io=q(``),Lo=q(``),Ro=q(`
      `),zo=q(`
      `);function Bo(e,t){let n=Fr();We(t,!0);let r=e=>{var t=Pr();Z(z(t),19,()=>G(me),e=>e.id,(e,t,r)=>{var i=fo();let o;var s=R(i),c=B(s,!0),l=V(s),u=B(l),d=V(l),f=e=>{var n=uo(),r=B(n,!0);H(()=>Y(r,G(t).help)),J(e,n)};X(d,e=>{(G(v)?.path===``||G(le))&&e(f)}),N(i),H((e,s)=>{Q(i,`id`,`${n}-${G(r)}`),Q(i,`role`,G(le)?`option`:void 0),Q(i,`aria-selected`,G(le)?G(T)===G(r):void 0),Q(i,`tabindex`,G(le)?-1:void 0),i.disabled=G(g)||G(_e)&&!a(),Q(i,`title`,G(t).help),Q(i,`aria-label`,e),o=li(i,1,`svelte-7bfwr9`,null,o,{suggested:G(T)===G(r)}),Y(c,G(t).label),Y(u,`${G(le)&&G(t).selected?` // CURRENT`:``}${s??``}`)},[()=>G(t).label+(G(le)&&G(t).selected?` // CURRENT`:``)+ae(G(t)),()=>ae(G(t))]),Sr(`focus`,i,()=>{G(le)||ye(G(r))}),K(`click`,i,()=>{ye(G(r)),M(G(t))}),J(e,i)}),J(e,t)},i=Gi(t,`query`,3,``),a=Gi(t,`localOnly`,3,!1),o=Gi(t,`oncopy`,3,()=>{}),s=Gi(t,`onchange`,3,()=>{}),c=Gi(t,`oncomplete`,3,e=>{}),l=co.map(e=>e.next);function u(){return co.map(e=>[`exit`,`quit`].includes(e.next||``)?{...e,help:`Return to Sessions. The local server and Codex sessions remain running.`}:{...e})}function d(){return{title:`/ COMMANDS`,help:`Local Codexometer commands remain available without session control.`,path:``,revision:``,choices:u()}}function f(){L(b,``),L(D,``),L(x,0),L(re,[],!0)}function p(){w++,L(g,!1),L(h,!1),L(ee,i()),f(),L(_,``),G(fe)?s()():c()(i())}async function m(e){if(!l.includes(e))return!1;if(e===`copy`&&!so($.data?.sessions.find(e=>e.id===t.session)))return L(_,`No reply or activity text is available to copy for this session.`),!0;if(e===`copy`){let e=o()();p(),await e}else p(),e===`usage`?location.hash=`/usage`:e===`theme`?ca.requests++:e===`statusline`?sa.open=!0:location.hash=`/sessions`;return!0}let h=I(!1),g=I(!1),_=I(``),v=I(null),y=I(null),b=I(``),x=I(0),S=I(Xt(Date.now())),C=I(``),w=0,T=I(0),ee=I(null),E=I(void 0),te=I(void 0),ne=I(void 0),D=I(``),re=I(Xt([])),O=P(()=>!!G(v)?.inputReview),ie=P(()=>!!G(y)&&!G(O)||!!G(D)||G(re).length>0);function ae(e){return e.unavailable?e.unavailable.startsWith(`Waiting for idle.`)?` // WAITING FOR IDLE`:` // UNAVAILABLE`:e.next?` →`:e.action?``:` // HELP`}async function oe(e){G(v)&&!(G(ve)&&G(pe))&&L(re,[...G(re),{path:G(v).path,index:G(T),input:G(C)}],!0),await j(e)}async function se(){if(!G(ie))return;if(w++,L(g,!1),L(b,``),L(x,0),L(_,``),G(D)){L(D,``),G(E)?.focus();return}if(G(y)&&!G(O)){L(y,null),await ur(),G(E)?.focus();return}let e=G(re).at(-1);e&&(L(re,G(re).slice(0,-1),!0),await j(e.path,e))}function ce(){G(v)&&G(C).trim()&&!G(g)&&!G(_e)&&oe(G(v).path+`/`+encodeURIComponent(G(C).trim()))}let le=P(()=>G(h)&&!!G(v)?.picker&&!G(y)),ue=P(()=>G(h)&&!G(v)?.input&&!G(y)),de=setInterval(()=>{L(S,Date.now(),!0)},1e3);qi(()=>{clearInterval(de),w++});let fe=P(()=>i().trim().startsWith(`/`)&&!i().trim().startsWith(`//`)),pe=P(()=>G(v)?.path===``&&G(fe)?i().trim().slice(1).toLowerCase():``),me=P(()=>(G(v)?.choices||[]).filter(e=>!G(pe)||e.label.toLowerCase().startsWith(`/`+G(pe)))),k=P(()=>G(y)||G(me)[G(T)]),he=P(()=>!!G(b)&&G(S)G(me).find(e=>e.id===G(D))),_e=P(()=>!$.connected||!!$.data?.sessionsError),ve=P(()=>G(h)&&G(fe)&&(!G(v)||G(v).path===``)&&!G(y));yn(()=>{i(),L(T,0)}),yn(()=>{let e=G(T);G(me),G(ue)&&ur().then(()=>{let t=G(E)?.children[e];if(!t||!G(E))return;let n=G(E).getBoundingClientRect(),r=t.getBoundingClientRect();r.topn.bottom&&(G(E).scrollTop+=r.bottom-n.bottom)})});function ye(e){G(T)!==e&&G(v)?.picker&&(L(D,``),L(b,``),L(x,0),L(_,``),w++),L(T,e,!0)}function A(){w++,L(g,!1),L(h,!1),L(ee,i()),f(),c()(i())}function be(e){let t=!!G(te)?.contains(e.target);if(!G(h)||!G(ue)&&!G(y)&&!G(v)?.input||!G(fe)&&!t||G(_e)&&!a()||e.isComposing||e.ctrlKey||e.metaKey||e.altKey)return;if(G(v)?.input){e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),A());return}let n=e.key===`ArrowLeft`,r=e.key.toLowerCase()===`f`,o=e.key.toLowerCase()===`c`;if((o||r||n)&&!t||![`ArrowUp`,`ArrowDown`,`Tab`,`Enter`,`Escape`].includes(e.key)&&!o&&!r&&!n||e.key===`Tab`&&(G(y)||G(v)?.path!==``||e.shiftKey)||e.key===`Enter`&&e.target instanceof Element&&e.target.closest(`button`)&&!G(E)?.contains(e.target)&&!e.target.closest(`[data-command-confirm]`)||G(y)&&!t||G(y)&&[`ArrowUp`,`ArrowDown`].includes(e.key))return;if(e.preventDefault(),e.stopPropagation(),e.key===`Escape`){A();return}if(G(g)||e.repeat&&(o||e.key===`Enter`))return;if(n){G(ie)&&se();return}if(r){j(G(v)?.path||``,void 0,!0);return}if(o){(G(y)?.action||G(le)&&G(D))&&Se();return}if(G(y)){e.key===`Enter`&&G(y).action&&!G(he)&&!G(_)&&xe(G(y));return}if(e.key===`ArrowUp`||e.key===`ArrowDown`){ye(Math.min(Math.max(G(T)+(e.key===`ArrowUp`?-1:1),0),Math.max(G(me).length-1,0))),!G(le)&&G(E)?.contains(e.target)&&ur().then(()=>(G(E)?.children[G(T)])?.focus());return}if(e.key===`Enter`&&(G(v)?.path===``||G(v)?.path===`goal`)&&/^\/goal\s+\S/.test(i().trim())){let e=G(v)?.path===`goal`?G(me).find(e=>i().trim().slice(6).trim().toLowerCase()===e.label.toLowerCase()):void 0;if(e){M(e);return}oe(i().trim().slice(1));return}let s=G(me)[G(T)];s&&(e.key===`Tab`?c()(s.label):G(le)?xe(s):M(s))}yn(()=>{G(_e)&&!a()&&(w++,L(g,!1),f(),G(h)&&(L(h,!1),L(ee,i())),L(v,null),L(y,null))}),yn(()=>{G(fe)&&!G(h)&&i()!==G(ee)&&(!G(_e)||a())&&(f(),L(h,!0),j(``))});async function j(e,n,r=!1){let i=++w;if(G(v)&&L(v,{...G(v),path:e},!0),n&&L(C,n.input,!0),L(g,!0),L(y,null),L(D,``),L(b,``),L(x,0),L(_,``),a())L(v,d(),!0),L(T,n?.index??0,!0),L(g,!1);else try{let a=await ya(`commands`,{session:t.session,command:{mode:`list`,path:e,...r?{refresh:!0}:{}}});i===w&&(a.choices||=[],(e===``||e===`help`)&&(a.choices=[...a.choices.filter(e=>!l.includes(e.label.replace(/^\//,``))),...u()]),L(v,a,!0),L(T,n?Math.min(n.index,Math.max(a.choices.length-1,0)):a.picker?Math.max(a.choices.findIndex(e=>e.selected),0):0,!0),a.picker&&ur().then(()=>G(E)?.focus()),L(C,n?.input??a.value??``,!0),n&&ur().then(()=>{a.input?G(te)?.querySelector(`input`)?.focus():G(E)?.focus()}),a.inputReview&&a.choices.length===1&&(L(g,!1),M(a.choices[0])))}catch{i===w&&(L(_,`Command catalogue unavailable. Use Codex.`),e===``||e===`help`?(L(v,d(),!0),L(_,``)):L(v,{title:`/`+e,help:``,path:e,revision:``,choices:[]},!0))}finally{i===w&&L(g,!1)}}async function M(e){e.unavailable||G(g)||e.next&&await m(e.next)||G(_)||(G(v)?.picker?(ye(G(me).findIndex(t=>t.id===e.id)),e.action&&!oo($.data?.confirmationMode,!!e.reversible)?await xe(e):G(E)?.focus()):e.next?await oe(e.next):await xe(e))}async function xe(e){if(G(g)||G(_e)||!G(v)||e.unavailable||G(_))return;let n=e.action&&!oo($.data?.confirmationMode,!!e.reversible);if(G(v).picker){if(G(he)&&G(D)===e.id)return;L(D,e.id,!0)}else n||(L(y,e,!0),ur().then(()=>G(ne)?.focus()));if(L(b,``),L(x,0),L(_,``),!e.action)return;let r=++w;L(g,!0);try{let n=await ya(`commands`,{session:t.session,command:{mode:`prepare`,path:G(v).path,revision:G(v).revision,choice:e.id}});if(r===w){let e=Date.parse(n.expires);if(!n.confirmation||!Number.isFinite(e)||Date.now()>=e)throw Error(`Review confirmation unavailable`);L(b,n.confirmation,!0),L(x,e,!0)}}catch{r===w&&L(_,`Option changed or unavailable. Refresh before retrying.`)}finally{r===w&&L(g,!1)}n&&r===w&&G(b)&&await Se()}async function Se(){if(!G(b)||G(_e)||G(g)||Date.now()>=G(x)||!G(v)||G(v).picker&&G(D)!==G(me)[G(T)]?.id)return;let e=G(b);L(b,``),L(g,!0);let n=++w;try{let r=await ya(`commands`,{session:t.session,confirmation:e,command:{mode:`commit`,path:G(v).path}});n===w&&(L(_,r.message,!0),L(h,!1),L(v,null),L(y,null),f(),L(ee,null),s()())}catch{n===w&&L(_,`Change unconfirmed. Check Codex before retrying.`)}finally{n===w&&L(g,!1)}}var Ce={handleKey:be},we=zo(),Te=R(we),Ee=V(Te,2),De=e=>{var t=po(),n=B(t,!0);H(()=>Y(n,G(_))),J(e,t)};X(Ee,e=>{G(_)&&!G(h)&&e(De)});var Oe=V(Ee,2),ke=e=>{var i=Ro();let o;var s=R(i),c=e=>{var t=_o(),n=z(t),r=B(n,!0),i=V(n,2),a=e=>{var t=ho();Z(t,21,()=>G(v).help.split(` +`),qr,(e,t)=>{var n=mo(),r=B(n,!0);H(()=>{Q(n,`title`,G(t)),Y(r,G(t))}),J(e,n)}),N(t),J(e,t)},o=e=>{var t=go(),n=B(t,!0);H(()=>Y(n,G(v)?.help||`Loading live options…`)),J(e,t)};X(i,e=>{G(v)?.path===`goal`?e(a):e(o,-1)}),H(()=>Y(r,G(v)?.title||`/ COMMANDS`)),J(e,t)};X(s,e=>{G(ve)||e(c)});var l=V(s,2),u=e=>{var t=vo(),n=B(t,!0);H(()=>Y(n,G(_))),J(e,t)};X(l,e=>{G(_)&&e(u)});var d=V(l,2),f=e=>{J(e,yo())};X(d,e=>{G(g)&&e(f)});var p=V(d,2),m=e=>{var t=bo(),r=R(t),i=R(r),o=V(i);Si(o),N(r),N(t),H(e=>{Q(t,`id`,`${n}-input`),Y(i,`${e??``} `),Q(o,`aria-label`,G(v).inputLabel||`Session name`),Q(o,`maxlength`,G(v).inputLimit||512),o.disabled=G(g)||G(_e)&&!a()},[()=>(G(v).inputLabel||`Session name`).toUpperCase()]),Sr(`submit`,t,e=>{e.preventDefault(),ce()}),Di(o,()=>G(C),e=>L(C,e)),J(e,t)},h=e=>{var n=So(),r=R(n),i=B(r,!0),a=V(r,2),o=B(a,!0),s=V(a,2),c=e=>{var n=xo(),r=R(n),i=V(r),a=e=>{J(e,Nr(`Only this session's saved + name changes.`))},o=P(()=>G(v)?.path.startsWith(`rename/`)),s=e=>{J(e,Nr(`Only this session’s + directory changes; project configuration is not reloaded.`))},c=P(()=>G(v)?.path.startsWith(`cd/`)),l=e=>{J(e,Nr(`Only this session's goal + changes.`))},u=P(()=>G(v)?.path.startsWith(`goal/`)),d=e=>{J(e,Nr(`No change sent yet. Model, reasoning and speed settings can + change token usage and cost. Changes affect subsequent turns of + this session, not global defaults. Automatic quota thresholds + may later supersede model settings.`))};X(i,e=>{G(o)?e(a):G(c)?e(s,1):G(u)?e(l,2):e(d,-1)}),N(n),H(()=>Y(r,`TARGET // ${t.session??``}. `)),J(e,n)};X(s,e=>{G(y).action&&e(c)}),N(n),Li(n,e=>L(ne,e),()=>G(ne)),H(()=>{Y(i,G(y).label),Y(o,G(y).help||`No additional help supplied by Codex.`)}),J(e,n)},w=e=>{var t=ko(),i=z(t),a=e=>{var t=Co(),i=R(t);r(i),N(t),Li(t,e=>L(E,e),()=>G(E)),H(()=>Q(t,`aria-activedescendant`,`${n}-${G(T)}`)),J(e,t)},o=e=>{var t=wo();let n;var i=R(t);r(i),N(t),Li(t,e=>L(E,e),()=>G(E)),H(()=>n=li(t,1,`command-options svelte-7bfwr9`,null,n,{vertical:G(ve)})),J(e,t)};X(i,e=>{G(le)?e(a):e(o,-1)});var s=V(i,2),c=e=>{var t=Do(),n=z(t),r=B(n,!0),i=V(n,2),a=e=>{var t=Eo(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,To())};X(i,e=>{G(b)&&G(S)>=G(x)&&e(a)}),H(()=>Y(r,`REVIEW // ${G(ge).label??``}. No change sent yet.`)),J(e,t)};X(i,e=>{G(ge)&&e(a)}),H(()=>Y(r,G(me)[G(T)]?.help)),J(e,t)};X(s,e=>{G(le)&&e(c)});var l=V(s,2),u=e=>{J(e,Oo())};X(l,e=>{!G(g)&&!G(me).length&&e(u)}),J(e,t)};X(p,e=>{G(v)?.input?e(m):G(y)?e(h,1):e(w,-1)});var ee=V(p,2),D=e=>{var t=Ao(),n=B(t,!0);H(()=>Y(n,G(k).unavailable)),J(e,t)};X(ee,e=>{G(k)?.unavailable&&e(D)});var re=V(ee,2),O=e=>{J(e,jo())};X(re,e=>{G(b)&&G(S)>=G(x)&&!G(le)&&e(O)});var ae=V(re,2),oe=R(ae),ue=e=>{var t=Pr(),r=z(t),i=e=>{var t=Mo(),r=B(t,!0);H((e,i)=>{Q(t,`form`,`${n}-input`),t.disabled=e,Y(r,i)},[()=>G(g)||G(_e)||!G(C).trim(),()=>oo($.data?.confirmationMode,!!G(v).reversibleInput)?`ENTER REVIEW`:`ENTER APPLY`]),J(e,t)},o=e=>{var t=Pr(),n=z(t),r=e=>{var t=No();H(()=>t.disabled=G(g)||G(_e)&&!a()),K(`click`,t,Se),J(e,t)},i=P(()=>G(he)&&oo($.data?.confirmationMode,!!G(k).reversible)),o=e=>{var t=Po(),n=B(t,!0);H(e=>{t.disabled=G(g)||G(_e)&&!a(),Y(n,e)},[()=>oo($.data?.confirmationMode,!!G(k).reversible)?`ENTER REVIEW`:`ENTER APPLY`]),K(`click`,t,()=>{G(k)&&xe(G(k))}),J(e,t)};X(n,e=>{G(i)?e(r):e(o,-1)}),J(e,t)},s=e=>{var t=Po(),n=B(t);H(()=>{t.disabled=G(g)||G(_e)&&!a(),Y(n,`ENTER ${G(k).next?`OPEN`:`HELP`}`)}),K(`click`,t,()=>{G(k)&&M(G(k))}),J(e,t)};X(r,e=>{G(v)?.input?e(i):G(k)?.action&&!G(k).unavailable?e(o,1):!G(y)&&G(k)&&!G(k).unavailable&&e(s,2)}),J(e,t)};X(oe,e=>{G(_)||e(ue)});var de=V(oe,2),fe=e=>{var t=Fo();H(()=>t.disabled=G(g)),K(`click`,t,se),J(e,t)};X(de,e=>{G(ie)&&e(fe)});var pe=V(de,2),ye=e=>{var t=Io();H(()=>t.disabled=G(g)),K(`click`,t,()=>j(G(v)?.path||``,void 0,!0)),J(e,t)};X(pe,e=>{G(ve)||e(ye)});var Ce=V(pe,2);N(ae);var we=V(ae,2),Te=e=>{var t=Lo(),n=B(t);H(()=>Y(n,`↑/↓ select${G(ve)?` · Tab complete`:``}`)),J(e,t)};X(we,e=>{!G(v)?.input&&!G(y)&&e(Te)}),N(i),Li(i,e=>L(te,e),()=>G(te)),H(()=>{Q(i,`aria-label`,G(ve)?`Slash command suggestions`:`Session command options`),o=li(i,1,`svelte-7bfwr9`,null,o,{"command-popup":G(ve)})}),K(`keydown`,i,be),K(`click`,Ce,A),J(e,i)};return X(Oe,e=>{G(h)&&e(ke)}),N(we),H(()=>Te.disabled=G(_e)&&!a()||G(g)),K(`click`,Te,()=>{L(h,!G(h)),L(ee,G(h)?null:i(),!0),L(b,``),G(h)?(L(re,[],!0),j(``)):A()}),J(e,we),Ge(Ce)}Cr([`click`,`keydown`]);var Vo=q(` `,1),Ho=q(`
      `),Uo=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=Uo(),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=Ho();let r;var i=R(n),a=e=>{var n=Vo(),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=li(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 Go=q(`

      TOOL

       
      `,1),Ko=q(`

      TITLE

      `,1),qo=q(`

      APP

      `,1),Jo=q(`

      MCP TOOL APPROVAL

      MCP SERVER

       

      ARGUMENTS

       
      `);function Yo(e,t){We(t,!0);var n=Jo(),r=V(R(n),2),i=B(r,!0),a=V(r,4),o=B(a,!0),s=V(a,2),c=e=>{var n=Go(),r=B(V(z(n),2),!0);H(()=>Y(r,t.details.name)),J(e,n)};X(s,e=>{t.details.name&&e(c)});var l=V(s,2),u=e=>{var n=Ko(),r=B(V(z(n),2),!0);H(()=>Y(r,t.details.title)),J(e,n)};X(l,e=>{t.details.title&&e(u)});var d=V(l,2),f=e=>{var n=qo(),r=B(V(z(n),2),!0);H(()=>Y(r,t.details.connector)),J(e,n)};X(d,e=>{t.details.connector&&e(f)});var p=B(V(d,4),!0);N(n),H(()=>{Y(i,t.details.message),Y(o,t.details.server),Y(p,t.details.arguments||`—`)}),J(e,n),Ge()}var Xo=q(`

       
      `,1),Zo=q(`

      `);function Qo(e,t){We(t,!0);var n=Zo(),r=R(n),i=B(r,!0);Z(V(r,2),17,()=>t.review.fields||[],qr,(e,t)=>{var n=Xo(),r=z(n),i=B(r,!0),a=B(V(r,2),!0);H(()=>{Y(i,G(t).label),Y(a,G(t).value)}),J(e,n)}),N(n),H(()=>{Q(n,`aria-label`,t.review.title),Y(i,t.review.title)}),J(e,n),Ge()}var $o=q(`

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

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

      `,1),ns=q(``),rs=q(`

       

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

      `),is=q(`

      HUMAN APPROVAL REQUIRED

      Managed policy requires approval each time.

      `,1),as=q(`

      CURRENT PROFILE

      MODEL / REASONING LEVEL / SPEED

       

      PROPOSED PROFILE

      MODEL / REASONING LEVEL / SPEED

       

      Applied settings remain after Codexometer closes.

      `,1),os=q(`

      `),ss=q(`

       
      `,1),cs=q(`

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

      `),ls=q(`

      Session controls temporarily unavailable. Check Codex for current state.

      `),us=q(`

      Checking session controls…

      `),ds=q(`

      `),fs=q(`
      About browser controls

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

      `),ps=q(` `,1),ms=q(` `),hs=q(`Grants permission beyond this one action. Check the scope + carefully.`),gs=q(``),_s=q(``),vs=q(``),ys=q(``),bs=q(`

      Not before this time; when quota and idle allow.

      `),xs=q(`

      `,1),Ss=q(`

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

      `),Cs=q(` `,1),ws=q(``),Ts=q(``),Es=q(``),Ds=q(` `,1),Os=q(`
    • `),ks=q(`
      View fixed choices

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

        `),As=q(` `,1),js=q(`

        `),Ms=q(`

        `,1),Ns=q(` `,1),Ps=q(``),Fs=q(`

        `,1),Is=q(`

        `);function Ls(e,t){We(t,!0);let n=[],r=Gi(t,`observedCommand`,3,``),i=Gi(t,`observedFileChanges`,19,()=>[]),a=Gi(t,`review`,3,``),o=Gi(t,`suspended`,3,!1),s=Gi(t,`openScheduler`,3,!1),c=Gi(t,`onProtectedChange`,3,e=>{}),l=Gi(t,`oncopy`,3,()=>{}),u=I(null),d=I(Xt([])),f=I(null),p=I(``),m=I(0),h=I(Xt(Date.now())),g=I(!1),_=I(``),v=I(!1),y=I(!1),b=I(``),x=I(!1),S=I(``),C=I(!1),w=I(``),T=I(``),ee=I(0),E=I(`now`),te=I(60),ne=I(``),D=I(!1),re=I(``),O=I(Xt([])),ie=P(()=>G(O).find(e=>e.status!==`sent`)),ae=I(void 0),oe=I(void 0);function se(e){if(G(x)){ur().then(()=>G(ae)?.focus());return}if(e.status!==`pending`||G(g)||!G(u)?.id||G(u).kind!==`prompt`||G(u).questions?.length)return;L(x,!0),L(S,e.id,!0),ur().then(()=>G(ae)?.focus()),L(d,[e.text],!0),L(E,e.trigger===`quota`?`quota`:`at`,!0),L(p,``),L(w,``);let t=new Date(e.at||0);e.trigger!==`quota`&&L(ne,new Date(t.getTime()-t.getTimezoneOffset()*6e4).toISOString().slice(0,16),!0)}yn(()=>{s()&&G(ie)&&!G(C)&&G(u)?.id&&G(u).kind===`prompt`&&!G(u).questions?.length&&(L(C,!0),se(G(ie)))});async function ce(){if(!a())try{L(O,await ya(`schedules`,{session:t.session},M.signal),!0),G(x)&&!G(O).some(e=>e.id===G(S)&&e.status===`pending`)&&L(p,``),G(w)&&!G(O).some(e=>e.id===G(w)&&e.status===`pending`)&&(L(p,``),L(w,``))}catch{}}async function le(e){if(oo($.data?.confirmationMode,!0)&&(G(T)!==e||G(h)>=G(ee)))L(T,e,!0),L(ee,G(h)+3e4);else{L(T,``);try{L(O,await ya(`schedules`,{session:t.session,cancelId:e},M.signal),!0),L(x,!1),L(p,``),L(w,``),L(d,[],!0)}catch(e){L(_,e instanceof Error?e.message:`Unable to cancel trigger.`,!0)}}}yn(()=>(c()(G(g)||G(d).some(e=>e.length>0)),()=>c()(!1)));let ue=P(()=>$.data?.sessions.find(e=>e.id===t.session)?.status),de=P(()=>!$.connected||!!$.data?.sessionsError),fe=P(()=>a()!==`profile`&&G(u)?.kind===`prompt`&&!G(u).questions?.length&&!!$.data?.profiles?.some(e=>e.session===t.session&&e.pending)),pe=P(()=>!G(de)&&!G(y)&&!!G(u)?.id&&G(u).kind===`approval`&&G(b)!==G(u).id),me=P(()=>G(pe)?G(u).command:r()),k=P(()=>!!G(p)&&G(h)oo($.data?.confirmationMode,G(u)?.kind===`approval`?G(f)!==null&&!G(u).choices?.[G(f)]?.persistent:G(u)?.kind===`profile`?G(f)===1:!(G(u)?.kind!==`prompt`||G(w)||G(x)||!G(u).questions?.length&&G(E)!==`now`))),ge=P(()=>G(u)?.questions?.length?G(u).questions:[{text:`Follow-up message`,secret:!1,freeText:!0,options:[]}]),_e=P(()=>G(u)?.kind===`approval`||G(u)?.kind===`profile`?G(f)!==null:G(d).length===G(ge).length&&G(d).every((e,t)=>e.trim().length>0&&(G(ge)[t].freeText||G(ge)[t].options?.includes(e)))),ve=P(()=>G(u)?.kind===`prompt`&&!G(u).questions?.length&&G(E)!==`now`),ye=P(()=>G(E)===`delay`?G(h)+G(te)*6e4:Date.parse(G(ne))),A=P(()=>{if(!G(ve))return``;if(G(x)&&!G(O).some(e=>e.id===G(S)&&e.status===`pending`))return`Trigger changed, removed or already sent. Go back and reopen it; your draft has not been saved.`;if(!G(d)[0]?.trim())return`Enter a message to schedule.`;if(G(E)===`quota`)return``;if(!Number.isFinite(G(ye))||G(ye)<=G(h))return`Choose a future date/time or a delay greater than zero.`;let e=new Date(G(h));return e.setFullYear(e.getFullYear()+1),G(ye)>=e.getTime()?`Choose a time within one year.`:``});function be(e){return e===void 0?`Not yet available`:new Date(e).toLocaleString([],{timeZoneName:`short`})}function j(e){if(e.status!==`pending`)return e.status;if(e.trigger===`at`&&e.at&&Date.parse(e.at)>G(h))return`Due in `+Math.ceil((Date.parse(e.at)-G(h))/6e4)+` min`;let t=G(de)?`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(de)||o()||G(fe)||G(h)>=G(m))&&L(p,``)});let M=new AbortController;Ki(()=>{let e=e=>{e.ctrlKey&&e.key.toLowerCase()===`s`&&!a()&&G(ie)&&(e.preventDefault(),se(G(ie)))};window.addEventListener(`keydown`,e);let n,r=setInterval(()=>{L(h,Date.now(),!0)},1e3);async function i(){await ce();try{let e=await ya(`offer`,{session:t.session,...a()?{review:a()}:{}},M.signal);if(M.signal.aborted)return;L(y,!1),G(u)?.id!==e.id&&(L(p,``),L(f,null),L(d,Array(Math.max(1,e.questions?.length||0)).fill(``),!0)),L(u,e,!0),G(v)&&e.id&&e.id!==G(b)&&(L(_,``),L(v,!1))}catch{M.signal.aborted||(L(u,null),L(y,!0),L(p,``))}finally{M.signal.aborted||(n=setTimeout(i,2e3))}}return i(),()=>{window.removeEventListener(`keydown`,e),M.abort(),clearTimeout(n),clearInterval(r)}});async function xe(e){if(!e&&G(u)?.kind===`prompt`&&!G(u).questions?.length&&G(d)[0]?.trim().startsWith(`/`)&&!G(d)[0]?.trim().startsWith(`//`)){L(_,`Choose a slash command from COMMANDS; use // for literal slash text.`);return}if(!G(u)?.id||G(g)||G(de)||o()||G(fe)||(e?!e.canSend:!G(_e)||G(A)))return;let n=G(u).id;L(g,!0),L(_,``),L(v,!1),L(p,``),L(w,e?.id||``,!0);try{let r=!e&&G(u).kind===`prompt`&&!G(u).questions?.length&&G(E)!==`now`?{trigger:G(E)===`quota`?`quota`:`at`,zone:Intl.DateTimeFormat().resolvedOptions().timeZone,...G(E)===`quota`?{}:{at:(G(E)===`delay`?new Date(Date.now()+G(te)*6e4):new Date(G(ne))).toISOString()}}:void 0;L(D,!!r),L(re,r?r.trigger===`quota`?`After fresh quota becomes available, when the session is idle`:be(r.at)+` — not before this time; when quota and idle allow`:``,!0);let i=await ya(`prepare`,{session:t.session,...a()?{review:a()}:{},offer:n,...e?{sendId:e.id}:{},...r?{schedule:r}:{},...r&&G(x)?{editId:G(S)}:{},...G(u).kind===`approval`||G(u).kind===`profile`?{choice:G(f)}:{answers:e?[e.text]:[...G(d)]}},M.signal);G(u)?.id!==n||M.signal.aborted||G(de)||o()||G(fe)||(L(p,i.confirmation,!0),L(m,Date.parse(i.expires),!0))}catch(e){M.signal.aborted||L(_,e instanceof Error?e.message:`Unable to prepare action.`,!0)}finally{L(g,!1)}!G(he)&&G(p)&&!M.signal.aborted&&await Ce()}async function Ce(){if(!G(u)?.id||G(g)||o()||G(fe)||!G(k))return;let e=G(u).id,n=G(u).kind,r=G(p);L(p,``),L(g,!0),L(b,e,!0);try{await ya(`commit`,{session:t.session,...a()?{review:a()}:{},offer:e,confirmation:r},M.signal),L(v,!0),L(x,!1),G(D)&&(L(b,``),await ce()),L(_,G(D)?`Trigger set. Closing Codexometer cancels it.`:n===`profile`?`Profile decision completed.`:n===`approval`?`Decision sent.`:`Text sent.`,!0)}catch(e){L(_,e instanceof _a?e.message:`Outcome uncertain. Check Codex before taking another action; nothing was retried.`,!0)}finally{L(g,!1),L(w,``),await ce(),L(d,[],!0),L(f,null)}}var we=ps(),Te=z(we),Ee=e=>{var t=Pr();Z(z(t),17,()=>G(O).filter(e=>e.status!==`sent`),e=>e.id,(e,t)=>{var n=rs(),r=R(n),i=B(r,!0),a=V(r,2),s=B(a),c=V(a,2),l=B(c,!0),d=V(c,2),f=B(d,!0),m=V(d,2),v=B(m,!0),y=V(m,2),b=e=>{var t=$o(),n=B(t,!0);H(()=>Y(n,G(_))),J(e,t)};X(y,e=>{G(_)&&e(b)});var x=V(y,4),S=V(x,2),C=B(S,!0),E=V(S,2),te=e=>{var t=es();K(`click`,t,()=>{L(T,``)}),J(e,t)};X(E,e=>{G(T)===G(t).id&&G(h){var n=ts(),r=V(z(n),2),i=V(r,2);H(()=>r.disabled=G(g)||G(de)||!G(t).canSend),K(`click`,r,Ce),K(`click`,i,()=>{L(p,``),L(w,``)}),J(e,n)},re=e=>{var n=ns();H(()=>n.disabled=G(g)||G(de)||!G(t).canSend||o()),K(`click`,n,()=>xe(G(t))),J(e,n)};X(ne,e=>{G(k)&&G(w)===G(t).id?e(D):e(re,-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(l,e),Y(f,n),Y(v,G(t).text),x.disabled=G(g)||!G(u)?.id||G(u).kind!==`prompt`||!!G(u).questions?.length||G(t).status!==`pending`,S.disabled=G(g)||G(t).status===`sending`,Y(C,G(T)===G(t).id&&G(h)G(t).trigger===`quota`?`After confirmed quota recovery, when idle`:`Not before ${be(G(t).at)}`,()=>j(G(t))]),K(`click`,x,()=>se(G(t))),K(`click`,S,()=>le(G(t).id)),J(e,n)}),J(e,t)},De=P(()=>!a()&&G(u)?.kind!==`approval`&&!G(u)?.questions?.length&&![`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ue)||``));X(Te,e=>{G(De)&&e(Ee)});var Oe=V(Te,2),ke=e=>{var r=Is(),o=R(r),s=B(o,!0),c=V(o,2),S=e=>{var t=is();Se(2),J(e,t)};X(c,e=>{G(u)?.requiredHumanApproval&&!G(de)&&!G(y)&&e(S)});var C=V(c,2),w=e=>{var t=as(),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(u).profile.threshold??``}% quota threshold has been reached. Review + the profile for subsequent turns.`),Y(a,G(u).profile.current),Y(o,G(u).profile.proposed)}),J(e,t)};X(C,e=>{G(u)?.profile&&!G(de)&&!G(y)&&e(w)});var T=V(C,2),ee=e=>{var t=os();let n;var r=B(t,!0);H(()=>{n=li(t,1,`svelte-1oupzfc`,null,n,{notice:!G(v),sent:G(v)}),Y(r,G(_))}),J(e,t)};X(T,e=>{G(_)&&e(ee)});var O=V(T,2),ie=e=>{Qo(e,{get review(){return G(u).approvalReview}})},se=e=>{Yo(e,{get details(){return G(u).mcpTool}})},ce=e=>{Wo(e,{get lines(){return G(u).fileChanges}})},le=e=>{Wo(e,{get lines(){return i()}})},fe=e=>{var t=ss(),n=z(t),r=B(n,!0),i=B(V(n,2),!0);H(()=>{Y(r,G(pe)?`EXACT COMMAND`:`LAST OBSERVED COMMAND`),Y(i,G(me))}),J(e,t)},ve=e=>{J(e,cs())};X(O,e=>{G(u)?.approvalReview&&!G(de)&&!G(y)?e(ie):G(u)?.mcpTool&&!G(de)&&!G(y)?e(se,1):G(u)?.fileChanges?.length&&!G(de)&&!G(y)?e(ce,2):i().length?e(le,3):G(me)?e(fe,4):a()!==`profile`&&G(ue)===`APPROVAL NEEDED`&&!G(v)&&e(ve,5)});var j=V(O,2),M=e=>{J(e,ls())},we=e=>{J(e,us())},Te=e=>{var t=ps(),n=z(t),r=e=>{var t=ds(),n=B(t,!0);H(e=>Y(n,e),[()=>G(ue)===`WORKING`?`Codex is working — nothing to respond to.`:[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ue)||``)?`Respond in Codex for this request.`:`Nothing needs a response right now.`]),J(e,t)};X(n,e=>{(G(ue)===`WORKING`||!G(v)&&!G(g))&&e(r)});var i=V(n,2),a=e=>{J(e,fs())},o=P(()=>[`APPROVAL NEEDED`,`INPUT NEEDED`].includes(G(ue)||``)&&!G(v));X(i,e=>{G(o)&&e(a)}),J(e,t)},Ee=e=>{var r=Fs(),i=z(r),o=B(i),s=V(i,2),c=R(s),_=B(c,!0),v=V(c,2),y=e=>{var r=Pr();Z(z(r),17,()=>G(u).choices||[],qr,(e,r,i)=>{var o=gs(),s=R(o);Si(s),s.value=s.__value=i;var c=V(s),l=V(c),u=e=>{var t=ms(),n=B(t,!0);H(()=>Y(n,G(r).detail)),J(e,t)};X(l,e=>{G(r).detail&&e(u)});var d=V(l,2),p=e=>{J(e,hs())};X(d,e=>{G(r).persistent&&e(p)}),N(o),H(()=>{Q(s,`name`,`decision-`+t.session+`-`+a()),Y(c,` ${G(r).label??``} `)}),ki(n,[],s,()=>G(f),e=>L(f,e)),J(e,o)}),J(e,r)},b=e=>{var n=ps(),r=z(n),i=e=>{var t=Cs(),n=z(t),r=V(R(n)),i=R(r),a=e=>{var t=_s();t.value=t.__value=`now`,J(e,t)};X(i,e=>{G(x)||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),hi(r),N(n);var l=V(n,2),u=e=>{var t=vs(),n=V(R(t));Si(n),N(t),Di(n,()=>G(te),e=>L(te,e)),J(e,t)};X(l,e=>{G(E)===`delay`&&e(u)});var d=V(l,2),f=e=>{var t=ys(),n=V(R(t));Si(n),N(t),Di(n,()=>G(ne),e=>L(ne,e)),J(e,t)};X(d,e=>{G(E)===`at`&&e(f)});var p=V(d,2),m=e=>{var t=xs(),n=z(t),r=B(n),i=V(n,2),a=e=>{J(e,bs())};X(i,e=>{G(E)!==`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(E)===`quota`?`when quota is available and this session is idle`:Number.isFinite(G(ye))?be(G(ye)):`choose a date and time`]),J(e,t)};X(p,e=>{G(E)!==`now`&&e(m)});var h=V(p,2),g=e=>{J(e,Ss())};X(h,e=>{G(x)&&e(g)}),gi(r,()=>G(E),e=>L(E,e)),J(e,t)};X(r,e=>{G(u).questions?.length||e(i)}),Z(V(r,2),17,()=>G(ge),qr,(e,n,r)=>{var i=As(),o=z(i),s=e=>{{let n=P(()=>G(d)[0]||``);Li(Bo(e,{get session(){return t.session},get oncopy(){return l()},get query(){return G(n)},oncomplete:e=>{L(d,[e],!0),ur().then(()=>G(ae)?.focus())},onchange:()=>{L(d,[``],!0),ur().then(()=>G(ae)?.focus())}}),e=>L(oe,e,!0),()=>G(oe))}};X(o,e=>{r===0&&a()!==`profile`&&G(u).kind===`prompt`&&!G(u).questions?.length&&e(s)});var c=V(o,2),f=R(c),p=V(f),m=e=>{var t=ws();Si(t),Di(t,()=>G(d)[r],e=>G(d)[r]=e),J(e,t)},h=e=>{var t=Es(),i=R(t);i.value=i.__value=``,Z(V(i),17,()=>G(n).options||[],qr,(e,t)=>{var n=Ts(),r=B(n,!0),i={};H(()=>{Y(r,G(t)),i!==(i=G(t))&&(n.value=(n.__value=i)??``)}),J(e,n)}),N(t),hi(t),gi(t,()=>G(d)[r],e=>G(d)[r]=e),J(e,t)},g=e=>{var t=Ds(),i=z(t);nt(i),Li(i,e=>L(ae,e),()=>G(ae));var a=V(i,2),o=e=>{var t=ds(),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(u)?.kind===`prompt`&&!G(u).questions?.length&&G(oe)?.handleKey(e)}),Di(i,()=>G(d)[r],e=>G(d)[r]=e),J(e,t)};X(p,e=>{G(n).secret?e(m):G(n).freeText?e(g,-1):e(h,1)}),N(c);var _=V(c,2),v=e=>{var t=ks(),r=V(R(t),4);Z(r,21,()=>G(n).options||[],qr,(e,t)=>{var n=Os(),r=B(n,!0);H(()=>Y(r,G(t))),J(e,n)}),N(r),N(t),J(e,t)};X(_,e=>{G(n).secret&&!G(n).freeText&&e(v)}),H(()=>Y(f,`${G(n).text??``} `)),J(e,i)}),J(e,n)};X(v,e=>{G(u).kind===`approval`||G(u).kind===`profile`?e(y):e(b,-1)}),N(s);var S=V(s,2),C=e=>{var t=Ms(),n=z(t),r=e=>{var t=js(),n=B(t);H(()=>Y(n,`TRIGGER // ${G(re)??``}`)),J(e,t)};X(n,e=>{G(D)&&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(u).kind===`profile`?`profile above`:G(u).kind===`approval`?G(u).fileChanges?.length?`proposed file changes above`:`exact command and permission scope`:`message above`}. ${G(D)?`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(g)||G(de),Y(s,`CONFIRM ${(G(u).kind===`approval`||G(u).kind===`profile`?G(u).choices?.[G(f)]?.label:G(D)?G(x)?`SAVE CHANGES`:`SCHEDULE`:`SEND`)??``}`)},[()=>Math.max(0,Math.ceil((G(m)-G(h))/1e3))]),K(`click`,o,Ce),K(`click`,c,()=>{L(p,``)}),J(e,t)},w=e=>{var t=Ns(),n=z(t),r=e=>{var t=$o(),n=B(t,!0);H(()=>Y(n,G(A))),J(e,t)};X(n,e=>{G(A)&&e(r)});var i=V(n,2),a=B(i,!0);H(()=>{i.disabled=G(g)||G(de)||!G(_e)||!!G(A),Y(a,G(g)?`SENDING…`:G(he)?G(x)?`REVIEW CHANGES`:`REVIEW BEFORE SENDING`:G(x)?`SAVE CHANGES`:G(u).kind===`approval`||G(u).kind===`profile`?`SEND DECISION`:G(u).kind===`prompt`&&!G(u).questions?.length&&G(E)!==`now`?`SET TRIGGER`:`SEND`)}),K(`click`,i,()=>xe()),J(e,t)};X(S,e=>{G(k)&&G(he)?e(C):e(w,-1)});var T=V(S,2),ee=e=>{var t=Ps();K(`click`,t,()=>{L(x,!1),L(p,``),L(d,[],!0)}),J(e,t)};X(T,e=>{G(x)&&e(ee)}),H(()=>{Y(o,`TARGET // ${G(u).thread??``} // ${(G(u).directory||`Directory unavailable`)??``}`),s.disabled=G(g)||G(k)||G(de),Y(_,G(u).kind===`approval`||G(u).kind===`profile`?`Choose a decision`:G(x)?`EDIT SCHEDULED FOLLOW-UP`:`Reply to this session`)}),J(e,r)};X(j,e=>{G(de)||G(y)?e(M):G(u)?G(u).id?G(b)!==G(u).id&&e(Ee,3):e(Te,2):e(we,1)}),N(r),H(()=>Y(s,a()===`profile`?`QUOTA THRESHOLD`:`SESSION CONTROL // EXPERIMENTAL`)),J(e,r)};X(Oe,e=>{!G(fe)&&(!G(ie)||G(x)||a()||G(u)?.kind!==`prompt`||G(u).questions?.length)&&e(ke)}),J(e,we),Ge()}Cr([`click`,`keydown`]);var Rs=q(` `);function zs(e,t){We(t,!0);let n=Gi(t,`stale`,3,!1),r=P(()=>n()||!!t.goal?.stale);var i=Pr(),a=z(i),o=e=>{var n=Rs();let i;var a=B(n,!0);H((e,o)=>{i=li(n,1,`goal-status svelte-1yfu3xi`,null,i,{stale:G(r),pursuing:!G(r)&&t.goal.status===`active`,blocked:e}),Q(n,`title`,o),Y(a,G(r)?`GOAL STALE`:t.goal.label)},[()=>!G(r)&&[`blocked`,`usageLimited`,`budgetLimited`].includes(t.goal.status),()=>t.goal.objective+` +`+t.goal.tokensUsed.toLocaleString()+(t.goal.tokenBudget===null?` tokens`:` / `+t.goal.tokenBudget.toLocaleString()+` tokens`)]),J(e,n)};X(a,e=>{t.goal&&e(o)}),J(e,i),Ge()}var Bs=q(` `,1),Vs=q(`
        `),Hs=q(`

        STATUS LINE // CODEXOMETER

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

        `),Us=q(`

        `,1);function Ws(e,t){We(t,!0);let n=Gi(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(()=>{sa.open&&!G(i)?(L(r,o(oa.statusLine),!0),L(i,!0)):sa.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=Us(),p=z(d),m=e=>{var t=Hs(),n=V(R(t),4);Z(n,21,()=>G(c),e=>e.id,(e,t)=>{var n=Vs(),i=R(n),a=R(i);Si(a);var o=V(a,1,!0),s=B(V(o),!0);N(i);var c=V(i,2),d=e=>{var n=Bs(),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),Ci(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,()=>{oa.statusLine=[...G(r)],la(),sa.open=!1}),K(`click`,d,()=>{sa.open=!1}),J(e,t)};X(p,e=>{sa.open&&e(m)});var h=V(p,2),g=R(h),_=B(g,!0),v=V(g,2);{let e=P(()=>n()||!$.connected||!!$.data?.sessionsError);zs(v,{get goal(){return t.session.goal},get stale(){return G(e)}})}var y=V(v,2);ni(V(y,2),()=>t.children??f),N(h),H((e,t)=>{Q(g,`title`,e),Y(_,t)},[()=>s(oa.statusLine),()=>s(oa.statusLine)]),K(`click`,y,()=>{sa.open=!sa.open}),J(e,d),Ge()}Cr([`change`,`click`]);var Gs=q(`
        `);function Ks(e,t){We(t,!0);let n=Gi(t,`active`,3,!1),r=Gi(t,`compact`,3,!1),i=P(()=>so(t.session)),a=P(()=>!!G(i)),o=I(!1),s=I(``),c=I(!1);yn(()=>{if(!G(c))return;let e=setTimeout(()=>{L(c,!1)},150);return()=>clearTimeout(e)}),yn(()=>{G(i),t.session.status,L(s,``)});async function l(){if(!G(a)||G(o))return;let e=G(i);L(o,!0),L(c,!0),L(s,``);try{await navigator.clipboard.writeText(e),G(i)===e&&L(s,`Copied.`)}catch{G(i)===e&&L(s,`Clipboard unavailable. Select the visible text and copy it manually.`)}finally{L(o,!1)}}function u(e){!n()||!G(a)||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(),l())}var d={copy:l},f=Pr();Sr(`keydown`,$t,u);var p=z(f),m=e=>{var t=Gs();let n;var i=R(t),a=B(i,!0),u=V(i,2);let d;N(t),H(()=>{n=li(t,1,`session-copy svelte-543j00`,null,n,{compact:r()}),Y(a,G(s)),u.disabled=G(o),d=li(u,1,`svelte-543j00`,null,d,{flashed:G(c)})}),K(`click`,u,l),J(e,t)};return X(p,e=>{G(a)&&e(m)}),J(e,f),Ge(d)}Cr([`click`]);var qs=q(`

         
        `,1),Js=q(`

        LATEST GUIDANCE

         
        `,1),Ys=q(`

        CONTEXT

         

        `,1),Xs=q(`

        `),Zs=q(`

        `),Qs=q(`
         
        `),$s=q(`

         
        `,1),ec=q(`
         
        `),tc=q(`

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

        `),nc=q(`

        `,1),rc=q(`

        `),ic=q(` `,1),ac=q(`

        `),oc=q(`
        `),sc=q(`

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

        `),cc=q(`

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

        `),lc=q(` `),uc=q(` `),dc=q(` `),fc=q(``),pc=q(`

        Read only — reply or approve in Codex.

        `),mc=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),hc=q(`
        `),gc=q(` `,1),_c=q(`
        `),vc=q(`

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

        `),yc=q(`

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

        `),Sc=q(` `),Cc=q(`

        `),wc=q(`QUOTA THRESHOLD // REVIEW PROFILE ↗`),Tc=q(`

        `),Ec=q(`

        TOKEN ACTIVITY // 30 SECOND SAMPLES

        `),Dc=q(`

        TOKENS

        FULL DETAIL →
        `),Oc=q(`

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

        `),kc=q(`

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

        `,1),Ac=q(`

        SESSION TOTALS

        `,1);function jc(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=ic(),s=z(o),c=e=>{var n=qs(),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=Js(),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=Ys(),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),h=e=>{var n=Xs();let r;var i=B(n,!0);H(e=>{r=li(n,1,`attention-note`,null,r,{inferred:t().status===`CHECK SESSION`}),Y(i,e)},[()=>me(t())]),J(e,n)},_=P(()=>me(t())&&(!G(a)||G(v)||t().status===`CHECK SESSION`||y(t())));X(m,e=>{G(_)&&e(h)});var b=V(m,2),x=e=>{var n=Zs(),r=B(n,!0);H(e=>Y(r,e),[()=>k(t())]),J(e,n)};X(b,e=>{G(i)&&e(x)});var S=V(b,2),C=e=>{Qo(e,{get review(){return t().approvalReview}})},w=e=>{Yo(e,{get details(){return t().mcpTool}})},T=e=>{var n=Qs(),r=B(n,!0);H(()=>Y(r,t().text||`No session context available.`)),J(e,n)};X(S,e=>{t().approvalReview&&(!G(a)||!$.data?.control)?e(C):t().mcpTool&&(!G(a)||!$.data?.control)?e(w,1):(t().text||!t().workingCommand)&&e(T,2)});var ee=V(S,2),E=e=>{var n=$s(),r=V(z(n),2),i=R(r),a=V(i),o=e=>{var n=Nr();H(()=>Y(n,`// ${t().commandTiming??``}`)),J(e,n)};X(a,e=>{t().commandTiming&&e(o)});var s=V(a,2),c=e=>{var n=Nr();H(()=>Y(n,`// +${(t().runningCommands||0)-+(t().commandStatus===`running`)} RUNNING`)),J(e,n)};X(s,e=>{!G(v)&&(t().runningCommands||0)>+(t().commandStatus===`running`)&&e(c)});var l=V(s,2),u=e=>{J(e,Nr(`+`))};X(l,e=>{t().runningLimited&&e(u)}),N(r);var d=B(V(r,2),!0);H(e=>{Y(i,`COMMAND // ${e??``} `),Y(d,t().workingCommand)},[()=>G(v)?`UNKNOWN`:(t().commandStatus||`unknown`).toUpperCase()]),J(e,n)};X(ee,e=>{t().workingCommand&&e(E)});var te=V(ee,2),ne=e=>{Wo(e,{get lines(){return t().fileChanges}})},D=e=>{var n=nc(),r=V(z(n),2),i=B(r,!0),a=V(r,2),o=e=>{var n=ec(),r=B(n,!0);H(()=>Y(r,t().command)),J(e,n)},s=e=>{J(e,tc())};X(a,e=>{t().command?e(o):e(s,-1)}),H(()=>Y(i,G(v)||t().status!==`APPROVAL NEEDED`?`LAST OBSERVED COMMAND`:$.data?.control?`COMMAND REQUEST`:`COMMAND TO APPROVE IN CODEX`)),J(e,n)};X(te,e=>{(!G(a)||!$.data?.control)&&t().fileChanges?.length?e(ne):G(a)&&$.data?.control||t().mcpTool||t().approvalReview||!t().command&&t().status!==`APPROVAL NEEDED`||e(D,1)});var re=V(te,2),O=e=>{var n=rc(),r=B(n);H(()=>Y(r,`CONTEXT SOURCE // ${(t().source||`LOCAL`)??``} // OBSERVATION`)),J(e,n)};X(re,e=>{G(a)||e(O)}),J(e,o)},r=I(void 0),i=Gi(t,`params`,19,()=>({})),a=P(()=>$.data?.sessions||[]),o=P(()=>$.data?.control&&$.data.profiles||[]),s=P(()=>($.data?.triggers||[]).filter(e=>G(a).some(t=>t.id===e.session)));function c(e,t){i().id&&i().id!==t&&G(u)?e.preventDefault():ue(t)}function l(e){return[`TURN COMPLETE`,`IDLE`,`ACTIVE`].includes(e.status)&&G(s).some(t=>t.session===e.id)?`TRIGGER SET`:e.status}let u=I(!1);function d(e,t){i().id&&i().id!==t&&G(u)?e.preventDefault():ue(t)}yn(()=>{let e=i().id;e&&pr(()=>{oa.selected=e,pa(e,2)})});let p=P(()=>G(a).find(e=>e.id===i().id)),m=P(()=>new URLSearchParams(Xi.querystring).get(`review`)===`profile`&&G(o).some(e=>e.session===i().id&&e.pending)),h=P(()=>G(a).some(e=>e.id===oa.selected)?oa.selected:G(a)[0]?.id),v=P(()=>!$.connected||!!$.data?.sessionsError);function y(e){return e.status!==`STALE`&&e.failed===!0}let b=P(()=>[[`OBSERVED TOKENS`,ma(G(a).reduce((e,t)=>e+t.tokens,0))],[`LISTED SESSIONS`,ma(G(a).length)],...[[`WORKING`,`WORKING`],[`AWAITING APPROVAL`,`APPROVAL NEEDED`],[`AWAITING INPUT`,`INPUT NEEDED`],[`ERRORS`,`ERRORS`],[`CHECK · INFERRED`,`CHECK SESSION`]].map(([e,t])=>[e,G(v)?`—`:ma(G(a).filter(e=>t===`ERRORS`?y(e):e.status===t).length)])]),x=P(()=>G(a).filter(e=>[`INPUT NEEDED`,`APPROVAL NEEDED`].includes(e.status)||y(e)).sort((e,t)=>S(e)-S(t)));function S(e){return e.status===`APPROVAL NEEDED`?0:e.status===`INPUT NEEDED`?1:2}let C=P(()=>G(a).filter(e=>e.status===`TURN COMPLETE`&&(!e.readStateKnown||e.unread)&&!G(s).some(t=>t.session===e.id)&&!G(o).some(t=>t.session===e.id&&t.pending))),w=I(``),T=new Set,ee=0,E=I(void 0);function te(e){return $.data?.control&&!G(v)&&e.unread&&e.readRevision&&e.replyTurn&&!e.streaming&&e.contextKind===`LAST REPLY`&&!!e.text&&!G(m)&&!G(o).some(t=>t.session===e.id&&t.pending)}function ne(e){let t=document.getElementById(`content`),n=t?.getBoundingClientRect(),r=n?n.left+t.clientLeft:0,i=n?n.top+t.clientTop:0,a=r+(t?.clientWidth||0),o=i+(t?.clientHeight||0);return Array.from(document.querySelectorAll(`[data-result-session]`)).some(n=>{let s=n.querySelector(`[data-reply-text]`);if(!s)return!1;let c=s.getBoundingClientRect();return t?.contains(n)&&n.dataset.resultSession===e.id&&n.dataset.resultTurn===e.replyTurn&&!n.closest(`[inert], [hidden]`)&&document.visibilityState===`visible`&&c.leftMath.max(0,r)&&c.topMath.max(0,i)&&c.width>0&&c.height>0})}function D(){G(E)&&clearTimeout(G(E).timer),L(E,void 0)}function re(e){return!i().id&&G(h)===e.id&&da(e.id)===2&&te(e)}function O(){if(!G(E))return;let e=G(a).find(e=>e.id===G(E).id);e&&re(e)&&e.replyTurn===G(E).turn&&e.readRevision===G(E).revision&&ne(e)||D()}function ie(e){if(O(),!re(e)||!ne(e)||G(E))return;let t=e.id,n=e.replyTurn,r=e.readRevision,i=++ee;L(E,{sequence:i,id:t,turn:n,revision:r,timer:setTimeout(()=>{if(O(),!G(E)||G(E).sequence!==i||G(E).id!==t||G(E).turn!==n||G(E).revision!==r)return;let e=G(a).find(e=>e.id===t);D(),e&&ae(e)},3e3)},!0)}yn(()=>{O()}),Ki(()=>(document.addEventListener(`scroll`,O,!0),document.addEventListener(`visibilitychange`,O),window.addEventListener(`resize`,O),()=>{D(),document.removeEventListener(`scroll`,O,!0),document.removeEventListener(`visibilitychange`,O),window.removeEventListener(`resize`,O)}));async function ae(e){if(!te(e))return;let t=e.id,n=e.readRevision,r=e.replyTurn,i=JSON.stringify([t,n,r]);if(!T.has(i)){T.add(i);try{await ur();let e=G(a).find(e=>e.id===t);if(!e||!te(e)||!ne(e)||e.readRevision!==n||e.replyTurn!==r)return;await ya(`read`,{session:t,read:{turn:r,revision:n}}),L(w,``)}catch{L(w,`Result changed or could not be marked read. Open it again to retry.`)}finally{T.delete(i)}}}function oe(e){i().id===e.id?ae(e):ie(e)}function se(e){if(D(),ue(e,!1),i().id===e){let t=G(a).find(t=>t.id===e);t&&ae(t)}}let ce=I(Xt(pr(()=>i().id||``))),le=I(``);yn(()=>{let e=i().id||``;e!==G(ce)&&(L(ce,e,!0),L(le,e,!0))}),yn(()=>{if(G(le)&&G(p)?.id===G(le)){let e=G(p);L(le,``),pr(()=>{ae(e)})}});function ue(e,t=!0){e!==G(h)&&D(),oa.selected=e,ur().then(()=>{document.querySelector(`.session-row.selected`)?.scrollIntoView({block:`nearest`});let n=G(a).find(t=>t.id===e);t&&n&&ie(n)})}function de(e,t){if(ue(e),i().id){t<0&&(pa(e,2),location.hash=`/sessions`);return}let n=da(e)+t;n>2?location.hash=`/sessions/`+encodeURIComponent(e):pa(e,n)}function fe(){D(),i().id||fa(G(a).map(e=>e.id))}function pe(e){let t=e.target;if(!(e.altKey||e.ctrlKey||e.metaKey||e.shiftKey||t.closest(`input, textarea, select, [contenteditable="true"]`))){if(e.key.toLowerCase()===`y`&&!i().id)e.preventDefault(),e.repeat||fe();else if(e.key===`Escape`&&i().id)e.preventDefault(),de(i().id,-1);else if([`ArrowLeft`,`ArrowRight`].includes(e.key)&&(i().id||G(h)))e.preventDefault(),de(i().id||G(h),e.key===`ArrowLeft`?-1:1);else if(!i().id&&[`ArrowUp`,`ArrowDown`].includes(e.key)&&G(a).length){e.preventDefault();let t=G(a).findIndex(e=>e.id===G(h));ue(G(a)[Math.max(0,Math.min(G(a).length-1,t+(e.key===`ArrowUp`?-1:1)))].id)}}}function me(e){return G(v)?`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.`:y(e)?e.status===`MODEL BUSY`?`CONFIRMED TURN FAILURE — the selected model was at capacity. Choose another model with /model or retry when ready. This is not a quota-exhaustion signal.`:e.status===`MODEL UNAVAILABLE`?`CONFIRMED TURN FAILURE — the provider could not find the selected model. Choose an available model with /model. No automatic retry or model change.`:e.status===`CAPACITY RESTRICTED`?`CONFIRMED TURN FAILURE — capacity is unavailable on a policy-restricted route. Inspect the error before changing settings or retrying. This is not a quota-exhaustion signal; no automatic retry or policy change.`:`CONFIRMED TURN FAILURE — inspect the error below before sending another prompt. No automatic retry or model change.`:$.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 k(e){return e.streaming&&e.contextKind===`LAST REPLY`?`REPLY // STREAMING`:e.contextKind||`LAST ACTIVITY`}var he=Ac();Sr(`keydown`,$t,pe);var ge=z(he),_e=e=>{var t=ac(),n=B(t,!0);H(()=>Y(n,G(w))),J(e,t)};X(ge,e=>{G(w)&&e(_e)});var ve=V(ge,2),ye=B(V(R(ve),2));N(ve);var A=V(ve,2);let be;Z(A,21,()=>G(b),qr,(e,t)=>{var n=P(()=>_(G(t),2));let r=()=>G(n)[0],i=()=>G(n)[1];var a=oc();let o;var s=R(a),c=B(s,!0),l=B(V(s,2),!0);N(a),H(()=>{o=li(a,1,`svelte-mm4wfe`,null,o,{failed:r()===`ERRORS`&&i()!==`0`&&i()!==`—`}),Y(c,r()),Y(l,i())}),J(e,a)}),N(A);var j=V(A,2),M=B(j),xe=V(j,2),Ce=e=>{J(e,sc())};X(xe,e=>{G(v)&&e(Ce)});var we=V(xe,2),Te=e=>{J(e,cc())};X(we,e=>{$.data?.profileError&&e(Te)});var Ee=V(we,2),De=e=>{var t=fc(),n=R(t);Z(n,17,()=>G(x),qr,(e,t)=>{var n=lc();let r;var i=B(n);H((e,a,o)=>{r=li(n,1,`button`,null,r,{approval:e}),Q(n,`href`,a),Y(i,`${G(t).status??``} + ${o??``} // ${(G(t).name||G(t).directory||G(t).id)??``}`)},[()=>G(t).status===`APPROVAL NEEDED`||G(t).status===`INPUT NEEDED`||y(G(t)),()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,n,()=>ue(G(t).id)),J(e,n)});var r=V(n,2);Z(r,17,()=>G(o).filter(e=>e.pending&&G(a).some(t=>t.id===e.session)),qr,(e,t)=>{var n=uc(),r=B(n);H((e,a,o)=>{Q(n,`title`,i().id&&i().id!==G(t).session&&G(u)?`Finish sending or clear your current draft before switching sessions.`:`Review this session’s quota threshold`),Q(n,`href`,e),Y(r,`QUOTA THRESHOLD ${a??``} // ${o??``}`)},[()=>`#/sessions/`+encodeURIComponent(G(t).session)+`?review=profile`,()=>Array.from(G(t).session).slice(-5).join(``).toUpperCase(),()=>G(a).find(e=>e.id===G(t).session)?.name||G(a).find(e=>e.id===G(t).session)?.directory||G(t).session]),K(`click`,n,e=>d(e,G(t).session)),J(e,n)});var l=V(r,2);Z(l,17,()=>G(C),qr,(e,t)=>{var n=dc(),r=B(n);H((e,i)=>{Q(n,`href`,e),Y(r,`TURN COMPLETE ${i??``} // + ${(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,()=>ue(G(t).id)),J(e,n)}),Z(V(l,2),17,()=>G(s),qr,(e,t)=>{var n=dc(),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(a).find(e=>e.id===G(t).session)?.name||G(a).find(e=>e.id===G(t).session)?.directory]),K(`click`,n,e=>c(e,G(t).session)),J(e,n)}),N(t),J(e,t)},Oe=P(()=>(G(x).length||G(C).length||G(o).some(e=>e.pending)||G(s).length)&&!G(v));X(Ee,e=>{G(Oe)&&e(De)});var ke=V(Ee,2),Ae=e=>{var t=Pr(),a=z(t),s=e=>{var t=_c(),a=R(t),s=R(a);let c;var d=R(s);let f;var h=V(d);N(s);var g=V(s,2);N(a);var _=V(a,2),b=e=>{var t=rc(),n=B(t,!0);H(()=>Y(n,G(p).directory)),J(e,t)};X(_,e=>{G(p).name&&G(p).directory&&e(b)});var x=V(_,2),S=B(x),C=V(x,2);let w;var T=R(C),ee=R(T);n(ee,()=>G(p),()=>!0,()=>!0),N(T);var E=V(T,2),te=e=>{var t=Pr();Kr(z(t),()=>G(p).id,e=>{{let t=P(()=>new URLSearchParams(Xi.querystring).get(`schedule`)===`edit`),n=P(()=>G(p).fileChanges||[]);Ls(e,{get session(){return G(p).id},oncopy:()=>G(r)?.copy(),get openScheduler(){return G(t)},get observedCommand(){return G(p).command},get observedFileChanges(){return G(n)},get suspended(){return G(m)},onProtectedChange:e=>{L(u,e,!0)}})}}),J(e,t)},ne=e=>{var t=pc();Kr(V(R(t),2),()=>G(p).id,e=>{Bo(e,{get session(){return G(p).id},localOnly:!0,oncopy:()=>G(r)?.copy()})}),N(t),J(e,t)};X(E,e=>{$.data?.control?e(te):e(ne,-1)}),N(C);var D=V(C,2);Z(D,17,()=>G(o).filter(e=>e.session===G(p).id),e=>e.session,(e,t)=>{var n=hc(),r=R(n),i=e=>{var n=ac(),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=>{Ls(e,{get session(){return G(p).id},review:`profile`})},s=e=>{var t=mc();H(e=>Q(t,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(p).id)+`?review=profile`]),J(e,t)};X(a,e=>{G(t).pending&&G(m)?e(o):G(t).pending&&e(s,1)}),N(n),H(()=>Q(n,`id`,`quota-profile-`+G(p).id)),J(e,n)});var re=V(D,2),O=e=>{var t=Pr();Kr(z(t),()=>G(p).id,e=>{Ws(e,{get session(){return G(p)},get stale(){return G(v)},children:e=>{var t=Pr(),n=z(t),i=e=>{Li(Ks(e,{get session(){return G(p)},active:!0,compact:!0}),e=>L(r,e,!0),()=>G(r))};X(n,e=>{G(m)||e(i)}),J(e,t)},$$slots:{default:!0}})}),J(e,t)},ie=e=>{var t=gc(),n=z(t),i=e=>{var t=Pr();Kr(z(t),()=>G(p).id,e=>{Li(Ks(e,{get session(){return G(p)},active:!0}),e=>L(r,e,!0),()=>G(r))}),J(e,t)};X(n,e=>{G(m)||e(i)}),Kr(V(n,2),()=>G(p).id,e=>{Ws(e,{get session(){return G(p)},get stale(){return G(v)}})}),J(e,t)};X(re,e=>{G(p).goal?e(O):e(ie,-1)}),N(t),H((e,t,n,r)=>{c=li(s,1,`svelte-mm4wfe`,null,c,{failed:e,reviewed:G(p).status===`TURN COMPLETE`&&G(p).readStateKnown&&!G(p).unread}),f=li(d,1,`lamp lit svelte-mm4wfe`,null,f,{failed:t,working:G(p).status===`WORKING`&&!G(v)}),Y(h,`${n??``} // ${(G(p).name||G(p).directory)??``}`),Y(S,`${r??``} TOKENS // ${G(p).id??``} // CONTEXT SOURCE // ${(G(p).source||`LOCAL`)??``}`),w=di(C,``,w,{display:G(m)?`none`:void 0}),Q(T,`data-result-session`,G(p).id),Q(T,`data-result-turn`,G(p).replyTurn)},[()=>y(G(p))&&!G(v)&&!G(m),()=>y(G(p))&&!G(v),()=>G(v)?`STALE`:G(m)?`QUOTA THRESHOLD`:l(G(p)),()=>ma(G(p).tokens)]),K(`click`,g,()=>{ue(i().id),pa(i().id,2)}),Sr(`wheel`,T,()=>{oe(G(p))}),J(e,t)},c=e=>{J(e,vc())};X(a,e=>{G(p)?e(s):e(c,-1)}),J(e,t)},je=e=>{var t=kc(),r=z(t),i=B(V(R(r),2));N(r);var s=V(r,2);Z(s,17,()=>G(a),e=>e.id,(e,t)=>{let r=P(()=>da(G(t).id));var i=Dc();let a;var s=R(i),c=R(s),u=e=>{var n=yc(),r=R(n),i=B(r);N(n),H(e=>{Q(r,`aria-pressed`,G(h)===G(t).id),Y(i,`${e??``} // ${G(t).name??``}`)},[()=>Array.from(G(t).id).slice(-5).join(``).toUpperCase()]),K(`click`,r,()=>ue(G(t).id)),J(e,n)};X(c,e=>{G(t).name&&e(u)});var f=V(c,2),p=R(f);let m;var g=R(p);let _;var b=V(g,1,!0);N(p),N(f);var x=V(f,2),S=e=>{var n=bc(),r=B(n,!0);H(()=>{Q(n,`aria-pressed`,G(h)===G(t).id),Y(r,G(t).directory||G(t).id)}),K(`click`,n,()=>ue(G(t).id)),J(e,n)};X(x,e=>{G(t).name||e(S)});var C=V(x,2),w=R(C);Se(),N(C);var T=V(C,2),ee=e=>{var n=rc(),r=B(n,!0);H(()=>Y(r,G(t).directory)),J(e,n)};X(T,e=>{G(t).name&&G(t).directory&&e(ee)});var E=V(T,2),te=B(E),ne=V(E,2),D=B(ne),re=V(ne,2);zs(re,{get goal(){return G(t).goal},get stale(){return G(v)}});var O=V(re,2),ie=R(O),ae=V(ie,2),ce=B(ae,!0),le=V(ae,2);N(O);var fe=V(O,2),pe=V(fe,2),me=e=>{var n=xc(),r=B(n,!0);H(e=>Y(r,e),[()=>G(t).status===`CHECK SESSION`?`INFERRED INACTIVITY`:y(G(t))?`OPEN DETAIL FOR THE TURN ERROR`:$.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)},he=P(()=>!G(v)&&([`APPROVAL NEEDED`,`INPUT NEEDED`,`CHECK SESSION`].includes(G(t).status)||y(G(t))));X(pe,e=>{G(he)&&e(me)}),N(s);var ge=V(s,2),_e=e=>{var r=Tc(),i=R(r),a=R(i),s=B(a,!0),c=V(a,2),l=e=>{var n=Sc(),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(v)&&G(t).status===`APPROVAL NEEDED`&&e(l)}),N(i);var u=V(i,2),f=R(u);n(f,()=>G(t),()=>!1),N(u);var p=V(u,2);Z(p,17,()=>G(o).filter(e=>e.session===G(t).id),qr,(e,n)=>{var r=gc(),i=z(r),a=e=>{var t=Cc(),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=wc();H(e=>Q(n,`href`,e),[()=>`#/sessions/`+encodeURIComponent(G(t).id)+`?review=profile`]),K(`click`,n,e=>d(e,G(t).id)),J(e,n)};X(o,e=>{G(n).pending&&e(s)}),J(e,r)});var m=V(p,2);{let e=P(()=>G(h)===G(t).id);Ks(m,{get session(){return G(t)},get active(){return G(e)}})}N(r),H(e=>{Y(s,e),Q(u,`data-result-session`,G(t).id),Q(u,`data-result-turn`,G(t).replyTurn)},[()=>k(G(t))]),Sr(`wheel`,u,()=>{oe(G(t))}),J(e,r)};X(ge,e=>{G(r)>0&&e(_e)});var ve=V(ge,2),ye=e=>{var n=Ec(),r=V(R(n),2);{let e=P(()=>(G(t).samples||[]).map(e=>e.tokens));ao(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(ve,e=>{G(r)<2&&e(ye)}),N(i),H((e,n,o,s,c,l,u)=>{a=li(i,1,`session-row`,null,a,{selected:G(h)===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)),m=li(p,1,`status-detail svelte-mm4wfe`,null,m,{reviewed:G(t).status===`TURN COMPLETE`&&G(t).readStateKnown&&!G(t).unread,failed:e}),Q(p,`href`,n),_=li(g,1,`lamp lit svelte-mm4wfe`,null,_,{failed:o,working:G(t).status===`WORKING`&&!G(v)}),Y(b,s),Y(w,`${c??``} `),Y(te,`${G(t).agents??``} LINKED AGENTS`),Y(D,`ACTIVE // ${l??``}`),ie.disabled=G(r)===0,Q(ae,`aria-expanded`,G(r)>0),Y(ce,G(r)?`HIDE DETAIL`:`SHOW DETAIL`),Q(fe,`href`,u)},[()=>y(G(t))&&!G(v),()=>`#/sessions/`+encodeURIComponent(G(t).id),()=>y(G(t))&&!G(v),()=>G(v)?`STALE`:l(G(t)),()=>ma(G(t).tokens),()=>ha(G(t).activity),()=>`#/sessions/`+encodeURIComponent(G(t).id)]),K(`click`,p,()=>se(G(t).id)),K(`click`,ie,()=>de(G(t).id,-1)),K(`click`,ae,()=>{let e=G(r)===0;ue(G(t).id),pa(G(t).id,+!!e)}),K(`click`,le,()=>de(G(t).id,1)),K(`click`,fe,()=>se(G(t).id)),J(e,i)});var c=V(s,2),u=e=>{J(e,Oc())};X(c,e=>{G(a).length||e(u)}),H(()=>i.disabled=!G(a).length),K(`click`,i,fe),J(e,t)};X(ke,e=>{i().id?e(Ae):e(je,-1)}),H(e=>{Y(ye,`OBSERVED ${e??``}`),be=li(A,1,`session-totals`,null,be,{stale:G(v)}),Y(M,`${G(v)?`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.`)},[()=>ha($.data?.sessionsAt)]),J(e,he),Ge()}Cr([`click`]);var Mc=q(``),Nc=q(`

        `),Pc=q(`

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

        `,1),Fc=q(`// APPROXIMATE`),Ic=q(`

        Partial accounting: totals may still change.

        `),Lc=q(`

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

        `,1),Rc=q(`

        `,1),zc=q(`

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

        `),Bc=q(`
        `),Vc=q(`
        `),Hc=q(`

        No usage reported for this day.

        `),Uc=q(`

        Selected breakdown unavailable; missing does not mean zero.

        `),Wc=q(`

        `,1);function Gc(e,t){We(t,!0);let n=I(Xt(lo[0])),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(()=>(t.mode===`breakdown`?G(c):G(l))?.views?.[G(n)]),f=P(()=>G(d)?.rows||[]),p=P(()=>G(d)?.total),m=P(()=>G(d)?.level||`unknown`),h=P(()=>G(d)?.peak||1),g=e=>e==null?`UNKNOWN`:e.toLocaleString(`en-GB`,{maximumFractionDigits:2});var _=Wc(),v=z(_),y=R(v),b=V(R(y));Z(b,21,()=>lo,qr,(e,t)=>{var n=Mc(),r=B(n,!0),i={};H(e=>{Y(r,e),i!==(i=G(t))&&(n.value=(n.__value=i)??``)},[()=>G(t).charAt(0).toUpperCase()+G(t).slice(1)]),J(e,n)}),N(b),hi(b),N(y);var x=V(y,2),S=V(x,2),C=B(V(S,2),!0);N(v);var w=V(v,2),T=R(w),ee=B(T,!0),E=V(T,2),te=B(E),ne=V(E,2),D=e=>{var t=Pc(),n=z(t),r=B(n),a=V(n,2),o=e=>{var t=Nc(),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)??``}`)},[()=>ha(G(i).fetchedAt),()=>g(G(p))]),J(e,t)},re=e=>{var t=Rc(),n=z(t),r=R(n);let i;var o=B(r,!0),s=V(r),c=e=>{J(e,Fc())};X(s,e=>{G(a).approximate&&e(c)});var u=V(s);N(n);var d=V(n,2),f=R(d),h=V(f),_=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(_)}),N(d);var v=V(d,2),y=e=>{var t=Lc(),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,Ic())};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=li(i,1,`svelte-1fbui7h`,null,a,{muted:G(m)===`unknown`,"quota-near":G(m)===`near`,"quota-full":G(m)===`full`}),Y(o,`USED ${e??``}${G(p)==null?``:`%`}`),Y(c,`${G(l).starts_at??``} → ${G(l).ends_at??``}`)},[()=>g(G(p))]),J(e,t)};X(v,e=>{G(l)&&e(y)}),H(e=>{i=li(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(f,`Coverage starts ${(G(a).coverage_start||`unknown`)??``} // Data as of ${(G(a).data_as_of||`unknown`)??``}`)},[()=>ha(G(a).fetchedAt)]),J(e,t)},O=e=>{J(e,zc())};X(ne,e=>{t.mode===`breakdown`&&G(i)?e(D):t.mode===`periods`&&G(a)?e(re,1):e(O,-1)});var ie=V(ne,2),ae=e=>{var n=Vc(),r=R(n),i=B(V(R(r),2),!0);N(r),Z(V(r,2),17,()=>G(f),qr,(e,n,r)=>{let i=()=>G(n).name,a=()=>G(n).value;var o=Bc();let s;var c=R(o),l=B(c,!0),u=V(c,2),d=R(u);let f;N(u);var p=B(V(u,2));N(o),H((e,n,a)=>{s=li(o,1,`report-row svelte-1fbui7h`,null,s,{unknown:e,alternate:r%2==1}),Q(c,`title`,i()),Y(l,i()),f=di(d,``,f,{width:n}),Y(p,`${a??``}${t.mode===`periods`?`%`:``}`)},[()=>i().trim().toLowerCase()===`unknown`,()=>`${Math.max(0,100*a()/G(h))}%`,()=>g(a())]),J(e,o)}),N(n),H(()=>Y(i,t.mode===`breakdown`?G(u):`QUOTA USED`)),J(e,n)},oe=e=>{J(e,Hc())},se=e=>{J(e,Uc())};X(ie,e=>{G(f).length?e(ae):t.mode===`breakdown`&&G(d)?.knownEmpty?e(oe,1):(G(i)&&t.mode===`breakdown`||G(a)&&t.mode===`periods`)&&e(se,2)}),N(w),H(()=>{x.disabled=G(s)>=G(o)-1,S.disabled=G(s)===0,Y(C,G(o)?`${G(s)+1} / ${G(o)}`:`NO DATA`),Y(ee,t.mode===`breakdown`?`DAILY BREAKDOWN`:`QUOTA WINDOWS`),Y(te,`${(t.mode===`breakdown`?t.reports?.dailyStatus||`UNAVAILABLE`:t.reports?.planStatus||`UNAVAILABLE`)??``} // UTC`)}),gi(b,()=>G(n),e=>L(n,e)),K(`click`,x,()=>L(r,G(s)+1)),K(`click`,S,()=>L(r,G(s)-1)),J(e,_),Ge()}Cr([`click`]);var Kc=864e5;function qc(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 Jc(e,t,n){let r=new Date(Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()));for(let e=0;;e++){let i=qc(r,-t),a=new Date(i.getTime()+Kc);if(e===n)return{start:a,end:r};r=i}}var Yc=q(``),Xc=q(``,1),Zc=q(`

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

        `),Qc=q(`

        Token history unavailable; other reports may still be available.

        `),$c=q(``),el=q(`
        `),tl=q(`

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

        `,1),nl=q(`
        `,1),rl=q(` `),il=q(`

        LIFETIME TOKENS

        PEAK DAY

        CURRENT STREAK

        DAYS

        LONGEST TURN

        SECONDS

        LONGEST STREAK

        DAYS

        OPENAI // UTC

        Accessible data table
        Date (UTC)Tokens

        `,1),al=q(`

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

        `),ol=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 sl(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}=Jc(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=ol(),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=Yc();let c;var l=B(s,!0);H(()=>{Q(s,`aria-pressed`,G(n)===a()),c=li(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=Xc(),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),hi(a),N(n);var c=V(n),l=V(c);H(()=>l.disabled=G(i)===0),K(`change`,a,()=>L(i,0)),gi(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,Zc())};X(m,e=>{$.data?.usageError&&e(h)});var g=V(m,2),v=e=>{J(e,Qc())};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);Gc(e,{get reports(){return G(t)},get mode(){return G(n)}})}}),J(e,t)},x=e=>{var t=il(),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=tl(),n=z(t),r=R(n),i=R(r);Z(i,17,()=>Array(G(s)),qr,(e,t)=>{J(e,$c())}),Z(V(i,2),17,()=>G(a),qr,(e,t)=>{var n=el();let r,i;H(e=>{r=li(n,1,`heat-cell`,null,r,{zero:G(t).tokens===0}),Q(n,`title`,e),i=di(n,``,i,{opacity:G(t).tokens?.25+.75*G(t).tokens/G(o):1})},[()=>`${G(t).date}: ${ma(G(t).tokens)} tokens`]),J(e,n)}),N(r),N(n),Se(2),J(e,t)},ee=e=>{var t=nl(),r=z(t);{let e=P(()=>G(c).map(e=>e.tokens)),t=P(()=>G(n)+` usage`);ao(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(ee,-1)});var E=V(w,2),te=V(R(E),2),ne=R(te),D=V(R(ne));Z(D,21,()=>G(n)===`daily`?G(a):G(c),qr,(e,t)=>{var n=rl(),r=R(n),i=B(r,!0),a=B(V(r),!0);N(n),H(e=>{Y(i,G(t).date),Y(a,e)},[()=>ma(G(t).tokens)]),J(e,n)}),N(D),N(ne),N(te),N(E),N(x);var re=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(re,`OBSERVED ${s??``} // CUMULATIVE IS FOR THE SELECTED PERIOD`)},[()=>ma($.data.usage.summary.lifetimeTokens),()=>ma($.data.usage.summary.peakDailyTokens),()=>ma($.data.usage.summary.currentStreakDays),()=>ma($.data.usage.summary.longestRunningTurnSec),()=>ma($.data.usage.summary.longestStreakDays),()=>G(a).at(-1)?.date,()=>ha($.data.usageAt)]),J(e,t)},S=e=>{J(e,al())};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 cl=q(`

        Page not found

        Return to Quota

        `,1);function ll(e){var t=cl();Se(2),J(e,t)}var ul=`CODEXOMETER`,dl=[`█▀▀ █▀█ █▀▄ █▀▀ ▀▄▀ █▀█ █▀▄▀█ █▀▀ ▀█▀ █▀▀ █▀█`,`█▄▄ █▄█ █▄▀ ██▄ █ █ █▄█ █ ▀ █ ██▄ █ ██▄ █▀▄`].flatMap(e=>[[...e].map(e=>e===`█`||e===`▀`),[...e].map(e=>e===`█`||e===`▄`)]),fl=dl[0].length,pl=dl.length,ml=0,hl=[...ul].map(e=>{let t=e===`M`?5:3,n={start:ml,width:t};return ml+=t+1,n}),gl=`ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`,_l=`010 101 111 101.110 111 101 110.111 100 100 111.110 101 101 110.111 100 110 111.111 100 110 100.111 100 101 111.101 101 111 101.111 010 010 111.001 001 101 111.101 110 110 101.100 100 100 111.101 111 101 101.101 111 111 101.111 101 101 111.111 101 111 100.111 101 111 001.111 101 110 101.111 100 001 111.111 010 010 010.101 101 101 111.101 101 101 010.101 101 111 101.101 010 010 101.101 101 010 010.111 001 100 111.111 101 101 111.110 010 010 111.111 001 110 111.111 011 001 111.101 101 111 001.111 110 001 111.100 111 101 111.111 001 010 010.111 111 101 111.111 101 111 001`.split(`.`).map(e=>e.split(` `));function vl(e=ul,t=-1,n=!1){let r=``;for(let i=0;i{e|=0,e=e+1831565813|0;let t=Math.imul(e^e>>>15,1|e);return t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296}}function Sl(){let e=yl[Math.floor(Math.random()*yl.length)],t=Math.floor(Math.random()*4294967296),n=xl(t),r=[...ul].map((e,t)=>t);for(let e=r.length-1;e>0;e--){let t=Math.floor(n()*(e+1));[r[e],r[t]]=[r[t],r[e]]}return{variant:e,seed:t,order:r}}function Cl(e,t){if(e.variant===`typing`){let e=t<1080,n=e?0:Math.min(Math.floor((t-1080)/90)+1,11);return{text:ul.slice(0,n).padEnd(11),cursor:n,dot:e?Math.floor(t/180)%2==0:n<11}}if(e.variant===`shuffle`){let n=xl(e.seed^Math.floor(t/70)),r=[...ul].map(e=>{let t;do t=gl[Math.floor(n()*36)];while(t===e);return t}),i=Math.min(Math.floor(t/110),11);for(let t of e.order.slice(0,i))r[t]=ul[t];return{text:r.join(``),cursor:-1,dot:!1}}return{text:ul,cursor:-1,dot:!1}}var wl=Mr(``);function Tl(e,t){We(t,!0);let n=Gi(t,`text`,3,ul),r=Gi(t,`cursor`,19,()=>-1),i=Gi(t,`dot`,3,!1),a=P(()=>vl(n(),r(),i()));var o=wl(),s=B(o);H(()=>{Q(o,`viewBox`,`0 0 ${fl} ${pl}`),Q(o,`width`,fl),Q(o,`height`,pl),Q(s,`d`,G(a))}),J(e,o),Ge()}var El=q(`
        `),Dl=q(`
        `);function Ol(e,t){We(t,!0);let n=I(void 0),r=I(0),i=I(Xt({width:0,height:0,pixelRatio:1})),a=I(Xt({x:0,y:0,width:0})),o=P(()=>G(n)?Cl(G(n),G(r)):void 0),s=P(()=>{if(!G(n))return{x:0,y:0,width:0};let e=bl[G(n).variant],t=Math.min(Math.max((G(r)-e-180)/800,0),1),o=t*t*(3-2*t),s=G(i).width+(G(a).width-G(i).width)*o,c=Math.max((G(i).height-G(i).width*pl/fl)/2,0),l=(G(n).variant===`slide`&&G(r)Math.round(e*G(i).pixelRatio)/G(i).pixelRatio;return{x:d(l),y:d(u),width:d(s)}});Ki(()=>{let e=matchMedia(`(prefers-reduced-motion: reduce)`);if(e.matches){t.onfinish();return}L(n,Sl(),!0);let o=bl[G(n).variant]+180+800,s=0,c=!1,l=performance.now(),u=()=>{let e=t.target?.getBoundingClientRect();L(i,{width:window.innerWidth,height:window.innerHeight,pixelRatio:window.devicePixelRatio||1},!0),e&&L(a,{x:e.x,y:e.y,width:e.width},!0)},d=()=>{c||(c=!0,cancelAnimationFrame(s),t.onfinish())},f=e=>{e instanceof PointerEvent&&e.button!==0||e instanceof KeyboardEvent&&(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)||e instanceof KeyboardEvent&&[`Shift`,`Control`,`Alt`,`Meta`].includes(e.key)||(e.preventDefault(),e.stopImmediatePropagation(),d())},p=()=>{e.matches&&d()},m=e=>{L(r,Math.max(e-l,0),!0),G(r)>=o?d():s=requestAnimationFrame(m)},h=new ResizeObserver(u);if(t.target){h.observe(t.target),t.target.parentElement&&h.observe(t.target.parentElement);let e=t.target.closest(`header`);e&&h.observe(e)}return u(),window.addEventListener(`resize`,u),document.addEventListener(`keydown`,f,!0),document.addEventListener(`pointerdown`,f,!0),e.addEventListener(`change`,p),s=requestAnimationFrame(m),()=>{c=!0,cancelAnimationFrame(s),h.disconnect(),window.removeEventListener(`resize`,u),document.removeEventListener(`keydown`,f,!0),document.removeEventListener(`pointerdown`,f,!0),e.removeEventListener(`change`,p)}});var c=Dl(),l=R(c),u=e=>{var t=El();let n;Tl(R(t),{get text(){return G(o).text},get cursor(){return G(o).cursor},get dot(){return G(o).dot}}),N(t),H(()=>{Q(t,`data-text`,G(o).text),Q(t,`data-cursor`,G(o).dot?G(o).cursor:void 0),n=di(t,``,n,{left:`${G(s).x}px`,top:`${G(s).y}px`,width:`${G(s).width}px`})}),J(e,t)};X(l,e=>{G(o)&&e(u)});var d=V(l,2);N(c),H(()=>Q(c,`data-entrance`,G(n)?.variant)),K(`click`,d,function(...e){t.onfinish?.apply(this,e)}),J(e,c),Ge()}Cr([`click`]);var kl=q(` `),Al=q(`

        `),jl=q(`

        Connecting to your local Codexometer…

        `),Ml=q(``),Nl=q(`

        Your quota. Your sessions. Your command centre.

        `);function Pl(e,t){We(t,!0);let n={"/":no,"/quota/:view?":no,"/sessions/:id?":jc,"/usage":sl,"*":ll},r={quota:/^(?:\/|\/quota(?:\/[^/]+)?\/?)$/,sessions:/^\/sessions(?:\/[^/]+)?\/?$/,usage:/^\/usage\/?$/},i=I(`hacker`),a=I(!0),o=I(void 0);yn(()=>{ca.requests&&ur().then(()=>{G(o)?.focus(),G(o)?.scrollIntoView({block:`nearest`})})});let s=I(void 0),c=[`hacker`,`rust`,`blue-steel`,`ultraviolet`,`nightshade`];yn(()=>{la()}),yn(()=>{if($.data)for(let[e,t]of Object.entries(r))t.test(Xi.location)&&(oa.tab=e)}),Ki(()=>{try{let e=localStorage.getItem(`codexometer.web.theme`);e&&c.includes(e)&&L(i,e,!0)}catch{}return ba()});function l(){try{localStorage.setItem(`codexometer.web.theme`,G(i))}catch{}}var u=Nl(),d=R(u),f=R(d),p=R(f);Tl(R(p),{}),N(p),Li(p,e=>L(s,e),()=>G(s)),Se(2),N(f);var m=V(f,2),h=R(m);let g;var v=V(h,1,!0),y=B(V(v));N(m),N(d);var b=V(d,2);Z(b,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(Xi.location));var o=kl();let s;var c=B(o,!0);H(e=>{Q(o,`href`,r()===`quota`?`#/quota/`+oa.view:`#/`+r()),Q(o,`aria-current`,G(a)?`page`:void 0),s=li(o,1,``,null,s,{active:G(a)}),Y(c,e)},[()=>r().toUpperCase()]),J(e,o)}),N(b);var x=V(b,2),S=R(x),C=e=>{var t=Al(),n=B(t,!0);H(()=>Y(n,$.error)),J(e,t)};X(S,e=>{$.error&&e(C)});var w=V(S,2),T=e=>{ea(e,{get routes(){return n}})},ee=e=>{J(e,jl())};X(w,e=>{$.data?e(T):$.error||e(ee,1)}),N(x);var E=V(x,2),te=R(E),ne=B(te),D=V(te,2),re=B(D,!0),O=V(D,2),ie=V(R(O));Z(ie,21,()=>c,qr,(e,t)=>{var n=Ml(),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(ie),Li(ie,e=>L(o,e),()=>G(o)),hi(ie),N(O),N(E);var ae=V(E,2),oe=e=>{Ol(e,{get target(){return G(s)},onfinish:()=>L(a,!1)})};X(ae,e=>{G(a)&&e(oe)}),N(u),H(()=>{Q(u,`data-theme`,G(i)),Q(u,`data-starting`,G(a)),d.inert=G(a),g=li(h,1,`lamp`,null,g,{lit:$.connected}),Y(v,$.connected?`CONNECTED`:`OFFLINE`),Y(y,`EXPERIMENTAL // ${$.data?.control?`SESSION CONTROL`:`READ ONLY`}`),b.inert=G(a),x.inert=G(a),E.inert=G(a),Y(ne,`v${($.data?.version||`…`)??``} // LOCAL ONLY`),Y(re,$.data?.control?`Session control enabled. Stop the server to revoke access.`:`No actions can be sent from this preview.`)}),K(`change`,ie,l),gi(ie,()=>G(i),e=>L(i,e)),J(e,u),Ge()}Cr([`change`]),Br(Pl,{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 cd6d11ec..42c7ca81 100644 --- a/internal/web/dist/index.html +++ b/internal/web/dist/index.html @@ -5,8 +5,8 @@ Codexometer // Experimental web - - + +
        diff --git a/internal/web/state.go b/internal/web/state.go index 9f34f3a9..cb149fa1 100644 --- a/internal/web/state.go +++ b/internal/web/state.go @@ -24,36 +24,38 @@ type Source interface { // Deliberately project source types: never serialize approval/input capabilities, // account fingerprints, arbitrary errors, or authentication objects to browsers. type session struct { - ReadStateKnown bool `json:"readStateKnown,omitempty"` - Unread bool `json:"unread,omitempty"` - ReadRevision string `json:"readRevision,omitempty"` - ReplyTurn string `json:"replyTurn,omitempty"` - RequiredHumanApproval bool `json:"requiredHumanApproval,omitempty"` - Goal *goal `json:"goal,omitempty"` - StatusLine map[string]string `json:"statusLine"` - FileChanges []codex.FileDiffLine `json:"fileChanges,omitempty"` - CurrentTask string `json:"currentTask,omitempty"` - LatestGuidance string `json:"latestGuidance,omitempty"` - Streaming bool `json:"streaming,omitempty"` - Name string `json:"name,omitempty"` - ID string `json:"id"` - Directory string `json:"directory"` - Tokens int64 `json:"tokens"` - Agents int `json:"agents"` - Status string `json:"status"` - Failed bool `json:"failed,omitempty"` - ContextKind string `json:"contextKind"` - Text string `json:"text"` - Command string `json:"command"` - WorkingCommand string `json:"workingCommand,omitempty"` - ApprovalContext string `json:"approvalContext,omitempty"` - CommandStatus string `json:"commandStatus,omitempty"` - CommandTiming string `json:"commandTiming,omitempty"` - RunningCommands int `json:"runningCommands,omitempty"` - RunningLimited bool `json:"runningLimited,omitempty"` - Source string `json:"source"` - Activity time.Time `json:"activity"` - Samples []sample `json:"samples"` + ApprovalReview *codex.ApprovalReview `json:"approvalReview,omitempty"` + MCPTool *codex.MCPToolApprovalDetails `json:"mcpTool,omitempty"` + ReadStateKnown bool `json:"readStateKnown,omitempty"` + Unread bool `json:"unread,omitempty"` + ReadRevision string `json:"readRevision,omitempty"` + ReplyTurn string `json:"replyTurn,omitempty"` + RequiredHumanApproval bool `json:"requiredHumanApproval,omitempty"` + Goal *goal `json:"goal,omitempty"` + StatusLine map[string]string `json:"statusLine"` + FileChanges []codex.FileDiffLine `json:"fileChanges,omitempty"` + CurrentTask string `json:"currentTask,omitempty"` + LatestGuidance string `json:"latestGuidance,omitempty"` + Streaming bool `json:"streaming,omitempty"` + Name string `json:"name,omitempty"` + ID string `json:"id"` + Directory string `json:"directory"` + Tokens int64 `json:"tokens"` + Agents int `json:"agents"` + Status string `json:"status"` + Failed bool `json:"failed,omitempty"` + ContextKind string `json:"contextKind"` + Text string `json:"text"` + Command string `json:"command"` + WorkingCommand string `json:"workingCommand,omitempty"` + ApprovalContext string `json:"approvalContext,omitempty"` + CommandStatus string `json:"commandStatus,omitempty"` + CommandTiming string `json:"commandTiming,omitempty"` + RunningCommands int `json:"runningCommands,omitempty"` + RunningLimited bool `json:"runningLimited,omitempty"` + Source string `json:"source"` + Activity time.Time `json:"activity"` + Samples []sample `json:"samples"` } type goal struct { @@ -326,6 +328,12 @@ func (s *store) live(l codex.LiveUsageSnapshot, err error, now time.Time) { if row.Context.Kind == codex.SessionContextApproval { approvalContext = codex.SanitizeSessionContext(row.Context.ApprovalContext) } + var mcpTool *codex.MCPToolApprovalDetails + if row.Context.MCPTool.Server != "" { + details := row.Context.MCPTool + mcpTool = &details + text = details.Message + } var activity codex.SessionActivity if row.Context.Kind == codex.SessionContextActivity { activity = row.Context.Activity @@ -341,8 +349,10 @@ func (s *store) live(l codex.LiveUsageSnapshot, err error, now time.Time) { } s.state.Sessions = append(s.state.Sessions, session{ ReadStateKnown: row.ReadState.Known(), Unread: row.ReadState.Unread, ReadRevision: row.ReadState.Revision, ReplyTurn: sessionReplyTurn(row), - Goal: projectGoal(row.Goal), - ID: row.ID, Name: codex.SanitizeSessionContext(row.Name), Directory: row.WorkingDirectory, Tokens: row.TotalTokens, Agents: row.AgentCount, + ApprovalReview: row.Context.ActionReview(), + MCPTool: mcpTool, + Goal: projectGoal(row.Goal), + ID: row.ID, Name: codex.SanitizeSessionContext(row.Name), Directory: row.WorkingDirectory, Tokens: row.TotalTokens, Agents: row.AgentCount, StatusLine: statusline.Values(statusline.Data{Model: row.ModelSettings.Model, Effort: row.ModelSettings.ReasoningEffort, Speed: row.ModelSettings.ServiceTier, Directory: row.WorkingDirectory, Name: row.Name, ID: row.ID, State: sessionStatus(row), Source: row.Context.Source, Tokens: row.TotalTokens, Agents: row.AgentCount}), Status: sessionStatus(row), ContextKind: contextKind(row.Context.Kind), Text: text, Failed: row.Attention == codex.SessionAttentionError, diff --git a/intro-post.md b/intro-post.md index 0cbd8ec2..7fde2c5a 100644 --- a/intro-post.md +++ b/intro-post.md @@ -19,7 +19,7 @@ It is useful when you want to: - compare available models and reasoning levels on the same checked tasks; or - inspect how a benchmark was solved rather than seeing only a final score. -The interface runs locally in a terminal, with clickable and hover-highlighted controls, keyboard shortcuts, responsive layouts, five colour themes, and 16 languages with 17 locale options, including Brazilian and European Portuguese. Extra rate-limit windows are accommodated as Codex returns them. Your main tab, theme, Quota view, benchmark filter, ranking and global Sessions hide/show preferences survive restarts. +The interface runs locally in a terminal, with clickable and hover-highlighted controls, keyboard shortcuts, responsive layouts, five colour themes, and 16 languages with 17 locale options, including Brazilian and European Portuguese. Extra rate-limit windows are accommodated as Codex returns them. Your main tab, theme, Quota view, benchmark filter, ranking and global Sessions detail preferences survive restarts. ## What does it show? @@ -49,7 +49,7 @@ On tall terminals, full detail retains the summary too. As space runs short, the summary disappears before the attention strip so text and action controls keep priority. These shortcuts navigate only; they never approve or send for you. -**Keep track of unread results:** on supported shared app-servers, **TURN COMPLETE** stays bright and its completion pill remains until you review the reply. Deliberately opening partial or full Detail, or scrolling within the displayed result, marks the latest completed reply as read; its status then stays visible in subdued text. Selecting a row, restoring a layout, or receiving another reply in an already-open pane does not mark it read. Reading an older turn cannot acknowledge a newer one. Codex saves these receipts and shares them with supported native clients, so they survive restarts. Read-only web mode displays this state without changing it. Older setups retain their existing completion behaviour. +**Keep track of unread results:** on supported shared app-servers, **TURN COMPLETE** stays bright and its completion pill remains until you review the reply. Deliberately select a row in **wide detail** and keep its reply visible for **three seconds** to mark it read. Selecting another row, leaving wide mode, hiding the reply or receiving a newer result cancels the timer. Split previews, bulk Cycle, restored layouts and hover leave results unread. Explicitly opening full-screen Detail marks the visible latest completed reply read immediately; a result arriving while Detail is already open still needs a fresh review gesture. Reading an older turn cannot acknowledge a newer one. Codex saves these receipts and shares them with supported native clients, so they survive restarts. Read-only web mode displays this state without changing it. Older setups retain their existing completion behaviour. **Zero or clear the list:** `(Z)ERO` (`z`) starts a fresh measurement baseline and restores dismissed rows. `CL(O)SE ALL` (`o`) dismisses every currently listed row, including off-page rows matching the current filter, without stopping sessions or resetting measurements. Later activity can restore a dismissed row. Close All is immediate by default; strict confirmation mode adds a second action. @@ -75,9 +75,9 @@ Start with the session that needs you. A **WORKING** badge in its telemetry box Below each session's token count, the latest observed model, reasoning level and Fast setting take priority—for example, **gpt-6-astra medium fast**. These are recorded selections, not proof of the delivered backend model or speed; unavailable fields are omitted. **AVG TOK/MIN** shows average observed usage since measurement began rather than instantaneous generation speed. Total and per-session rates refresh together every five seconds, not on mouse movement or keypresses. -Give each session as much space as it needs. Select a session with `Up`/`Down`, then use `Left`/`Right` for less/more detail: **graph only ↔ split detail/graph ↔ full-width detail ↔ full-screen detail**. Clicking the left/right half of that row’s detail/graph area does the same thing, without wrapping at either end. Only that session changes; approval buttons and reply editors keep their own actions. From full-screen detail, Left or Escape returns to the Sessions overview with the same session showing full-width detail. While typing, arrows edit your text. Escape leaves an idle editor; during an active turn, Escape requests interruption and Ctrl+C leaves the editor without interrupting. +Give each session as much space as it needs. The selected terminal row gets roughly twice the height of other rows when space permits, while preserving their minimum height and the page size; the browser allows twice as much reply-text height for its selected row. Select a session with `Up`/`Down`, then use `Left`/`Right` for less/more detail: **graph only ↔ split detail/graph ↔ full-width detail ↔ full-screen detail**. Clicking the left/right half of that row’s detail/graph area does the same thing, without wrapping at either end. Only that session changes; approval buttons and reply editors keep their own actions. From full-screen detail, Left or Escape returns to the Sessions overview with the same session showing full-width detail. While typing, arrows edit your text. Escape leaves an idle editor; during an active turn, Escape requests interruption and Ctrl+C leaves the editor without interrupting. -Global **Show Detail / Hide Detail** (`h`) resets all rows to split detail/graph or graph-only. That global preference survives restarts, as do your last main tab and Quota view; individual row layouts, selection and dismissals are temporary. +Global **C(Y)CLE** (`y`) first matches every listed row to the most detailed current overview layout, then cycles them together through graph only → split detail/graph → wide detail → graph only. It includes off-page rows matching the current filter and never opens a session’s full-screen Detail page. Cycling preserves selection and ordinary drafts without marking results read. The global choice survives restarts; individual terminal row layouts and dismissals are temporary. Prefer visible controls? Click **[←] [→]** at the top-right of each row's rightmost box to adjust detail, or **[↑] [↓]** in the Sessions header to select sessions. Unavailable directions are dimmed. The session-selection buttons stay out of full-screen detail, where Up/Down scroll the text; tiny boxes fall back to keyboard and background clicks. @@ -97,6 +97,12 @@ Missing or unsafe patches and broader directory grants stay in Codex—no blind **Choose the scope of an approval:** **APPROVE ONCE** appears first when Codex offers it and acts immediately by default. Broader **ALLOW FOR SESSION** and **ALWAYS ALLOW PREFIX** decisions show their scope or exact persistent rule and require confirmation by default. Numbered shortcuts follow the displayed order; strict mode also reviews one-time approvals, declines and stop decisions. When confirmation is required, use `C` or click the confirmation button. For Approve Once, terminals with detected Kitty keyboard-protocol key-release support also allow its number, release, then the same number again. Confirming a broader grant requires `C` or a click. Confirmations expire after five seconds; follow the hint on the button. Unsupported or incomplete requests remain in Codex. +Terminal-input approvals show the target terminal, its start directory and the exact proposed input with visible escapes. Send that input once or cancel it; strict confirmation mode adds review. Additional permission requests remain in Codex. + +Managed network approvals show the requested host and protocol, with only the choices Codex offers: one-time access, a conversation grant, or a persistent allow/block rule. Both persistent choices require confirmation by default. + +**Approve MCP/app tools:** terminal and writable web Detail show the server, supplied tool/app identity, request and arguments. Approve once, allow for the session, always allow the tool, or cancel its call. Reusable grants appear only when Codex offers them and require confirmation by default; the launch confirmation policy applies. Read-only web can show the review. Other MCP forms and authentication requests remain in Codex. + **Managed human checkpoints:** Codex 0.167+ can require fresh human approval under a managed command policy. The terminal and writable web interface label these **HUMAN APPROVAL REQUIRED** and offer the supported one-time approve, decline and stop decisions. Session-wide and persistent grants cannot satisfy them. Every request needs an explicit human action, including with `--confirmation none`; strict mode adds a separate review step. Passive monitoring and read-only web mode leave these checkpoints to a capable native Codex client. Subtle animated dots in inline and full-screen detail indicate observed work, disappearing when the session is no longer observed working or needs attention. When FOLLOW-UPS is visible, the dots sit above the queue to associate them with the active task rather than the waiting messages. “Text sent ...” and “Decision sent ...” confirmations linger briefly so fast updates do not swallow the acknowledgement. Local activity signals remain best-effort, not proof that a model is still executing. @@ -238,7 +244,7 @@ Prefer a non-interactive run? `codexometer --digbench-game P-1` runs a named gam ## Privacy, authentication, and cost -Quota monitoring uses the prevailing Codex login. Sessions can show a bounded last-reply, activity, question, or approval preview beside each session. Excerpts remain in memory and do not trigger another model call; global Hide Detail hides them until you choose to show them again, including by expanding an individual row. With a shared app-server, full detail lets you answer supported blocking questions or send a follow-up to an idle session; a selected wide inline row also offers follow-ups when space permits. Unsupported questions and approvals remain in Codex. Supported command decisions use clickable buttons or numbered shortcuts. One-time decisions are immediate by default; broader grants use a separately labelled confirmation with `C` or a click, and persistent-prefix rules are shown for review. The launch confirmation policy controls additional review steps. Approval controls belong to only the current target session. +Quota monitoring uses the prevailing Codex login. Sessions can show a bounded last-reply, activity, question, or approval preview beside each session. Excerpts remain in memory and do not trigger another model call; Cycle can hide them by choosing graph-only, and individual row controls can show them again. With a shared app-server, full detail lets you answer supported blocking questions or send a follow-up to an idle session; a selected wide inline row also offers follow-ups when space permits. Unsupported questions and approvals remain in Codex. Supported command decisions use clickable buttons or numbered shortcuts. One-time decisions are immediate by default; broader grants use a separately labelled confirmation with `C` or a click, and persistent-prefix rules are shown for review. The launch confirmation policy controls additional review steps. Approval controls belong to only the current target session. Drafts stay in memory; submitted text becomes part of Codex's normal session history, and follow-up turns consume model usage. Sessions uses bounded task, reply, request and recent-history excerpts rather than collecting reasoning or unrestricted tool-output transcripts. Detailed tool-interaction capture is restricted to isolated benchmark turns created by Codexometer. Shared read receipts are saved by Codex; Codexometer does not write conversation previews to disk. diff --git a/web/src/ActionApproval.svelte b/web/src/ActionApproval.svelte new file mode 100644 index 00000000..c689b1fc --- /dev/null +++ b/web/src/ActionApproval.svelte @@ -0,0 +1,12 @@ + + +
        +

        {review.title}

        + {#each review.fields || [] as field} +

        {field.label}

        +
        {field.value}
        + {/each} +
        diff --git a/web/src/MCPApproval.svelte b/web/src/MCPApproval.svelte new file mode 100644 index 00000000..fe21b8e3 --- /dev/null +++ b/web/src/MCPApproval.svelte @@ -0,0 +1,19 @@ + + +
        +

        MCP TOOL APPROVAL

        +

        {details.message}

        +

        MCP SERVER

        +
        {details.server}
        + {#if details.name}

        TOOL

        +
        {details.name}
        {/if} + {#if details.title}

        TITLE

        +

        {details.title}

        {/if} + {#if details.connector}

        APP

        +

        {details.connector}

        {/if} +

        ARGUMENTS

        +
        {details.arguments || '—'}
        +
        diff --git a/web/src/SessionActions.svelte b/web/src/SessionActions.svelte index 69f09bbc..8c40b3bb 100644 --- a/web/src/SessionActions.svelte +++ b/web/src/SessionActions.svelte @@ -3,6 +3,8 @@ import { onMount, tick } from 'svelte'; import SessionCommands from './SessionCommands.svelte'; import FileDiff from './FileDiff.svelte'; + import MCPApproval from './MCPApproval.svelte'; + import ActionApproval from './ActionApproval.svelte'; import type { FileDiffLine } from './state.svelte'; import { live, controlRequest, ControlRejected } from './state.svelte'; let { @@ -530,7 +532,11 @@ {#if notice}

        {notice}

        {/if} - {#if offer?.fileChanges?.length && !stale && !offerError} + {#if offer?.approvalReview && !stale && !offerError} + + {:else if offer?.mcpTool && !stale && !offerError} + + {:else if offer?.fileChanges?.length && !stale && !offerError} {:else if observedFileChanges.length} @@ -539,8 +545,8 @@
        {command}
        {:else if review !== 'profile' && status === 'APPROVAL NEEDED' && !success}

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

        {/if} {#if stale || offerError} diff --git a/web/src/Sessions.svelte b/web/src/Sessions.svelte index 237d91f9..04e5f8d9 100644 --- a/web/src/Sessions.svelte +++ b/web/src/Sessions.svelte @@ -1,5 +1,5 @@