dsh-codex-subscription 3.0.0-beta.4 → 3.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -1075,6 +1075,8 @@ window.__ModuleLoader__.load({
1075
1075
  "account/select",
1076
1076
  "account/remove",
1077
1077
  "usage",
1078
+ "usage/history",
1079
+ "usage/profile",
1078
1080
  "diagnostics",
1079
1081
  "preferences/status",
1080
1082
  "preferences/models",
@@ -5678,6 +5680,24 @@ window.__ModuleLoader__.load({
5678
5680
  inputImageDetail_low: "低",
5679
5681
  inputImageDetail_high: "高",
5680
5682
  inputImageDetail_original: "原图",
5683
+ connectors: "ChatGPT 连接器",
5684
+ connectorsHint: "让 DSH 里的任何模型使用你在 ChatGPT 网页里已连接的应用(GitHub、Gmail、Google 云端硬盘、日历等)。只读:模型只能读取;允许写入:发邮件、改文件等写操作每次都要你批准。应用返回的内容来自第三方,模型不会照其中的指令行事。需先在 ChatGPT 里连接应用。",
5685
+ connectors_off: "关闭",
5686
+ connectors_read: "只读",
5687
+ connectors_ask: "允许写入(每次审批)",
5688
+ reasoningSummary: "推理摘要",
5689
+ reasoningSummaryHint: "让模型在会话的“思考”部分给出推理摘要。自动由模型决定;简洁更短;详细更完整;关闭则不要摘要。",
5690
+ retryPolicy: "请求重试",
5691
+ retryPolicyHint: "请求因网络或服务端错误失败时的自动重试次数。默认沿用 DSH 的标准重试;无限会一直重试直到成功或手动停止。",
5692
+ retryPolicy_default: "默认",
5693
+ retryPolicy_off: "不重试",
5694
+ retryPolicy_10: "10 次",
5695
+ retryPolicy_20: "20 次",
5696
+ retryPolicy_unlimited: "无限",
5697
+ reasoningSummary_auto: "自动",
5698
+ reasoningSummary_concise: "简洁",
5699
+ reasoningSummary_detailed: "详细",
5700
+ reasoningSummary_none: "关闭",
5681
5701
  subagentBackendTitle: "独立子任务",
5682
5702
  subagentBackend_dsh: "DSH",
5683
5703
  subagentBackend_codex: "Codex",
@@ -5972,6 +5992,10 @@ window.__ModuleLoader__.load({
5972
5992
  deviceHint: "在登录页输入此设备代码:",
5973
5993
  waiting: "正在等待登录完成…",
5974
5994
  failed: "登录失败,请重试。",
5995
+ failed_account_claim: "登录已授权,但这个账号的令牌里没有 ChatGPT 账号 ID(常见于只用手机号注册的账号)。请改用邮箱账号登录,或先在 ChatGPT 里为账号绑定邮箱后重试。",
5996
+ failed_network: "登录时网络连接失败。请检查网络或代理后重试。",
5997
+ failed_token_exchange: "授权已完成,但换取令牌失败。请重试;反复出现时请检查网络或代理。",
5998
+ failed_callback: "没有收到浏览器的授权回调。请重试,或改用设备码登录。",
5975
5999
  accountRetry: "重试",
5976
6000
  accountRetrying: "正在重试账户状态…",
5977
6001
  accountCredentialUnavailable: "登录凭据暂时不可用。请重试;不会删除已保存的登录信息。",
@@ -6004,6 +6028,45 @@ window.__ModuleLoader__.load({
6004
6028
  refresh: "刷新",
6005
6029
  refreshing: "刷新中…",
6006
6030
  noUsage: "登录后可读取 ChatGPT 返回的额度窗口。",
6031
+ overviewTitle: "使用概览",
6032
+ overviewLoading: "正在读取使用统计…",
6033
+ overviewUnavailable: "当前账户没有提供使用统计。",
6034
+ overviewHeatmap: "最近半年每天的 token 用量",
6035
+ overviewNoUse: "没有使用",
6036
+ overviewTokens: "{value} token",
6037
+ overviewDays: "{value} 天",
6038
+ overviewLifetime: "累计 token",
6039
+ overviewPeak: "单日最高",
6040
+ overviewStreak: "连续使用",
6041
+ overviewLongestStreak: "最长连续",
6042
+ overviewThreads: "会话总数",
6043
+ overviewEffort: "最常用推理档",
6044
+ overviewFast: "快速模式占比",
6045
+ overviewLongestTurn: "最长单轮",
6046
+ settingsRestartRequired: "设置已保存,但运行中的 DSH 没有应用它(宿主无法热更新这项设置)。请重启 DSH 后生效。",
6047
+ historyTitle: "额度去向(每周)",
6048
+ historyLoading: "正在读取用量历史…",
6049
+ historyUnavailable: "当前账户没有提供用量历史。",
6050
+ historyEmpty: "还没有已统计完成的额度周期。官方统计有延迟,过一两天再看。",
6051
+ historyPeriods: "额度周期",
6052
+ historyUsed: "这个周期已用 {value}% 的周额度",
6053
+ historyPartial: "(统计尚未完成)",
6054
+ historyApproximate: "数据来自官方用量报告,是近似值,可能有一两天延迟。",
6055
+ historyBy_model: "按模型",
6056
+ historyBy_surface: "按入口",
6057
+ historyBy_thread_source: "按来源",
6058
+ historyBy_turn_trigger: "按触发方式",
6059
+ historyDesktopApp: "桌面应用",
6060
+ historyCli: "命令行",
6061
+ historyIde: "IDE 扩展",
6062
+ historyWeb: "网页",
6063
+ historyMobile: "手机",
6064
+ historyUser: "你的对话",
6065
+ historySubagent: "子任务",
6066
+ historyMemory: "记忆整理",
6067
+ historyReview: "审查",
6068
+ historyComposer: "输入框发送",
6069
+ historyAutomation: "自动任务",
6007
6070
  usageLoading: "正在读取额度…",
6008
6071
  usageEmpty: "当前账户没有返回可显示的额度窗口。请稍后刷新;这不代表额度为零。",
6009
6072
  usageUpdated: "更新于 {value}",
@@ -6133,6 +6196,8 @@ window.__ModuleLoader__.load({
6133
6196
  effortLabel: "推理等级",
6134
6197
  providerDefault: "默认",
6135
6198
  selectModel: "选择模型",
6199
+ modelSearch: "搜索模型",
6200
+ modelNoMatch: "没有匹配的模型。",
6136
6201
  modelsLoading: "正在读取模型…",
6137
6202
  modelsEmpty: "没有可用模型;请先登录,并确认网络可用。",
6138
6203
  modelsHidden: "所有模型都已从列表中隐藏;可在设置中重新显示。",
@@ -6288,6 +6353,24 @@ window.__ModuleLoader__.load({
6288
6353
  inputImageDetail_low: "Low",
6289
6354
  inputImageDetail_high: "High",
6290
6355
  inputImageDetail_original: "Original",
6356
+ connectors: "ChatGPT connectors",
6357
+ connectorsHint: "Lets any model in DSH use the apps you have connected in ChatGPT (GitHub, Gmail, Google Drive, Calendar and more). Read-only: models can only read. Allow writes: anything that changes data, such as sending mail or editing files, asks for your approval every time. What apps return is third-party content and models do not follow instructions inside it. Connect the apps in ChatGPT first.",
6358
+ connectors_off: "Off",
6359
+ connectors_read: "Read-only",
6360
+ connectors_ask: "Allow writes (ask each time)",
6361
+ reasoningSummary: "Reasoning summary",
6362
+ reasoningSummaryHint: "Shows a summary of the reasoning in the Thinking section of the conversation. Auto lets the model decide; concise is shorter; detailed is fuller; off asks for none.",
6363
+ retryPolicy: "Request retries",
6364
+ retryPolicyHint: "How many times a request is retried after a network or server error. Default keeps the standard DSH retries; Unlimited keeps retrying until it succeeds or you stop it.",
6365
+ retryPolicy_default: "Default",
6366
+ retryPolicy_off: "No retries",
6367
+ retryPolicy_10: "10",
6368
+ retryPolicy_20: "20",
6369
+ retryPolicy_unlimited: "Unlimited",
6370
+ reasoningSummary_auto: "Auto",
6371
+ reasoningSummary_concise: "Concise",
6372
+ reasoningSummary_detailed: "Detailed",
6373
+ reasoningSummary_none: "Off",
6291
6374
  subagentBackendTitle: "Independent subtasks",
6292
6375
  subagentBackend_dsh: "DSH",
6293
6376
  subagentBackend_codex: "Codex",
@@ -6582,6 +6665,10 @@ window.__ModuleLoader__.load({
6582
6665
  deviceHint: "Enter this device code on the sign-in page:",
6583
6666
  waiting: "Waiting for sign-in to finish…",
6584
6667
  failed: "Sign-in failed. Try again.",
6668
+ failed_account_claim: "Sign-in was authorized, but the token of this account has no ChatGPT account ID (common for accounts created with only a phone number). Sign in with an email account, or add an email to the account in ChatGPT first, then try again.",
6669
+ failed_network: "The network connection failed during sign-in. Check the network or proxy and try again.",
6670
+ failed_token_exchange: "Authorization finished, but exchanging it for a token failed. Try again; if it keeps happening, check the network or proxy.",
6671
+ failed_callback: "The browser did not send the authorization back. Try again, or use device code sign-in.",
6585
6672
  accountRetry: "Retry",
6586
6673
  accountRetrying: "Retrying account status…",
6587
6674
  accountCredentialUnavailable: "The saved sign-in credentials are temporarily unavailable. Retry; saved sign-in information will not be deleted.",
@@ -6614,6 +6701,45 @@ window.__ModuleLoader__.load({
6614
6701
  refresh: "Refresh",
6615
6702
  refreshing: "Refreshing…",
6616
6703
  noUsage: "Sign in to read quota windows reported by ChatGPT.",
6704
+ overviewTitle: "Usage overview",
6705
+ overviewLoading: "Reading usage statistics…",
6706
+ overviewUnavailable: "This account does not provide usage statistics.",
6707
+ overviewHeatmap: "Daily token use over the last half year",
6708
+ overviewNoUse: "no use",
6709
+ overviewTokens: "{value} tokens",
6710
+ overviewDays: "{value} days",
6711
+ overviewLifetime: "Lifetime tokens",
6712
+ overviewPeak: "Busiest day",
6713
+ overviewStreak: "Current streak",
6714
+ overviewLongestStreak: "Longest streak",
6715
+ overviewThreads: "Conversations",
6716
+ overviewEffort: "Most used reasoning",
6717
+ overviewFast: "Fast mode share",
6718
+ overviewLongestTurn: "Longest turn",
6719
+ settingsRestartRequired: "The setting was saved, but the running DSH did not apply it (the host cannot update it live). Restart DSH to apply it.",
6720
+ historyTitle: "Where the allowance went (weekly)",
6721
+ historyLoading: "Reading usage history…",
6722
+ historyUnavailable: "This account does not provide a usage history.",
6723
+ historyEmpty: "No allowance period has been counted yet. The official report lags; check again in a day or two.",
6724
+ historyPeriods: "Allowance periods",
6725
+ historyUsed: "{value}% of this period's weekly allowance used",
6726
+ historyPartial: "(still being counted)",
6727
+ historyApproximate: "From the official usage report; values are approximate and may lag by a day or two.",
6728
+ historyBy_model: "By model",
6729
+ historyBy_surface: "By surface",
6730
+ historyBy_thread_source: "By source",
6731
+ historyBy_turn_trigger: "By trigger",
6732
+ historyDesktopApp: "Desktop app",
6733
+ historyCli: "CLI",
6734
+ historyIde: "IDE extension",
6735
+ historyWeb: "Web",
6736
+ historyMobile: "Mobile",
6737
+ historyUser: "Your chats",
6738
+ historySubagent: "Subtasks",
6739
+ historyMemory: "Memory upkeep",
6740
+ historyReview: "Review",
6741
+ historyComposer: "Composer",
6742
+ historyAutomation: "Automations",
6617
6743
  usageLoading: "Reading quota…",
6618
6744
  usageEmpty: "This account returned no displayable quota windows. Refresh later; this does not mean zero quota.",
6619
6745
  usageUpdated: "Updated {value}",
@@ -6743,6 +6869,8 @@ window.__ModuleLoader__.load({
6743
6869
  effortLabel: "Effort",
6744
6870
  providerDefault: "Default",
6745
6871
  selectModel: "Select model",
6872
+ modelSearch: "Search models",
6873
+ modelNoMatch: "No matching models.",
6746
6874
  modelsLoading: "Loading models…",
6747
6875
  modelsEmpty: "No models available. Sign in and make sure the network is reachable.",
6748
6876
  modelsHidden: "All models are hidden from this list. Show one in settings.",
@@ -6890,6 +7018,28 @@ window.__ModuleLoader__.load({
6890
7018
  .codexSubscriptionRefresh{flex:0 0 auto;min-width:72px;width:max-content;white-space:nowrap!important;word-break:keep-all!important;overflow-wrap:normal!important;writing-mode:horizontal-tb!important}
6891
7019
  .codexSubscriptionRefresh *{white-space:nowrap!important;word-break:keep-all!important;writing-mode:horizontal-tb!important}
6892
7020
  .codexSubscriptionEmpty{padding:18px;border:1px dashed var(--dsw-alias-border-l3);border-radius:10px;text-align:center;font-size:13px;line-height:20px;color:var(--dsw-alias-label-tertiary)}
7021
+ .codexSubscriptionHistory{margin-top:10px;border-top:1px solid var(--dsw-alias-border-l3);padding-top:8px}
7022
+ .codexSubscriptionHistory>summary{cursor:pointer;font-size:13px;font-weight:500;color:var(--dsw-alias-label-secondary)}
7023
+ .codexSubscriptionHistoryPeriods{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0}
7024
+ .codexSubscriptionHistoryPeriods button{height:26px;padding:0 10px;border:1px solid var(--dsw-alias-border-l3);border-radius:13px;background:transparent;color:inherit;font-size:12px;cursor:pointer}
7025
+ .codexSubscriptionHistoryPeriods button[aria-pressed=true]{background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-inverted)}
7026
+ .codexSubscriptionHistorySummary{margin:4px 0 8px;font-size:13px}
7027
+ .codexSubscriptionHistoryGroup{margin:8px 0}
7028
+ .codexSubscriptionHistoryGroup h4{margin:0 0 4px;font-size:12px;font-weight:500;color:var(--dsw-alias-label-tertiary)}
7029
+ .codexSubscriptionOverviewStats{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:8px;margin:10px 0}
7030
+ .codexSubscriptionOverviewStats div{padding:8px 10px;border-radius:10px;background:var(--dsw-alias-bg-layer-3,rgba(127,127,127,.08))}
7031
+ .codexSubscriptionOverviewStats dt{margin:0;font-size:11px;color:var(--dsw-alias-label-tertiary)}
7032
+ .codexSubscriptionOverviewStats dd{margin:2px 0 0;font-size:15px;font-weight:600}
7033
+ .codexSubscriptionHeatmap{display:block;width:100%;max-width:520px;margin:6px 0 4px}
7034
+ .codexSubscriptionHeatmap rect{fill:var(--dsw-alias-border-l3,rgba(127,127,127,.25))}
7035
+ .codexSubscriptionHeatmap rect[data-level="1"]{fill:#0a84ff;fill-opacity:.3}
7036
+ .codexSubscriptionHeatmap rect[data-level="2"]{fill:#0a84ff;fill-opacity:.5}
7037
+ .codexSubscriptionHeatmap rect[data-level="3"]{fill:#0a84ff;fill-opacity:.75}
7038
+ .codexSubscriptionHeatmap rect[data-level="4"]{fill:#0a84ff}
7039
+ .codexSubscriptionHistoryRow{display:grid;grid-template-columns:minmax(80px,32%) 1fr 52px;align-items:center;gap:8px;font-size:12px;line-height:20px}
7040
+ .codexSubscriptionHistoryKey{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
7041
+ .codexSubscriptionHistoryRow progress{width:100%;height:6px}
7042
+ .codexSubscriptionHistoryRow strong{text-align:right;font-weight:500}
6893
7043
  .codexSubscriptionLimits{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:6px}
6894
7044
  .codexSubscriptionLimit{min-width:0;border-radius:10px;padding:9px 12px;background:var(--dsw-alias-bg-module-platform);display:flex;flex-direction:column;gap:6px}
6895
7045
  .codexSubscriptionLimitTop{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
@@ -6991,13 +7141,17 @@ window.__ModuleLoader__.load({
6991
7141
  .codexModelSelectMenu,.codexModelSelectSubmenu{position:absolute;z-index:30;box-sizing:border-box;width:max-content;min-width:min(240px,calc(100vw - 32px));max-width:min(420px,calc(100vw - 32px));max-height:min(360px,calc(100vh - 96px));padding:4px;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;background:var(--dsw-alias-bg-layer-2,#2c2c2e);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary);overflow:hidden}
6992
7142
  .codexModelSelectMenu{right:0;bottom:calc(100% + 8px)}
6993
7143
  .codexModelSelectSubmenu{right:calc(100% + 8px);bottom:0;min-width:min(230px,calc(100vw - 32px))}
7144
+ /* Keep search outside the scroll viewport; let the model list fit the bounded menu. */
7145
+ .codexModelSelectModelMenu{display:flex;flex-direction:column}
6994
7146
  .codexModelSelectCell{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;height:40px;box-sizing:border-box;padding:0 10px;border:0;border-radius:10px;background:transparent;color:inherit;font-size:14px;line-height:22px;text-align:left;cursor:pointer}
6995
7147
  .codexModelSelectCell:hover,.codexModelSelectCell:focus-visible,.codexModelSelectCell[data-open=true]{background:var(--dsw-alias-interactive-bg-hover);outline:0}
6996
7148
  .codexModelSelectCell:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}
6997
7149
  .codexModelSelectCellLabel{flex:none;white-space:nowrap}
6998
7150
  .codexModelSelectCellValue{flex:auto;min-width:0;overflow:hidden;color:var(--dsw-alias-label-tertiary);text-align:right;text-overflow:ellipsis;white-space:nowrap}
6999
7151
  .codexModelSelectCellChevron{flex:none;color:var(--dsw-alias-label-tertiary)}
7000
- .codexModelSelectGroups{min-height:0;max-height:352px;overflow-y:auto}
7152
+ .codexModelSelectSearch{display:block;flex-shrink:0;width:100%;box-sizing:border-box;height:32px;margin:0 0 4px;padding:0 10px;border:1px solid var(--dsw-alias-border-l3);border-radius:8px;outline:0;background:transparent;color:inherit;font:inherit;font-size:13px}
7153
+ .codexModelSelectSearch:focus-visible{box-shadow:0 0 0 2px var(--dsw-alias-border-l3)}
7154
+ .codexModelSelectGroups{flex:1 1 auto;min-height:0;overflow-y:auto}
7001
7155
  .codexModelSelectGroup+.codexModelSelectGroup{margin-top:4px}
7002
7156
  .codexModelSelectGroupTitle{position:sticky;top:0;z-index:1;padding:5px 8px 3px;background:var(--dsw-alias-bg-layer-2,#2c2c2e);color:var(--dsw-alias-label-tertiary);font-size:12px;font-weight:500;line-height:18px}
7003
7157
  .codexModelSelectOption{display:flex;align-items:center;gap:8px;width:100%;min-width:100%;min-height:38px;box-sizing:border-box;padding:6px 8px;border:0;border-radius:10px;outline:0;background:transparent;color:inherit;text-align:left;cursor:pointer}
@@ -8419,6 +8573,29 @@ window.__ModuleLoader__.load({
8419
8573
  const OUTPUT_VERBOSITY_MEDIUM = "medium";
8420
8574
  const OUTPUT_VERBOSITY_HIGH = "high";
8421
8575
  const DEFAULT_OUTPUT_VERBOSITY = OUTPUT_VERBOSITY_DEFAULT;
8576
+ const REASONING_SUMMARY_FIELD = "reasoningSummary";
8577
+ const REASONING_SUMMARIES = Object.freeze([
8578
+ "auto",
8579
+ "concise",
8580
+ "detailed",
8581
+ "none"
8582
+ ]);
8583
+ const DEFAULT_REASONING_SUMMARY = "auto";
8584
+ const RETRY_POLICY_FIELD = "retryPolicy";
8585
+ const RETRY_POLICIES = Object.freeze([
8586
+ "default",
8587
+ "off",
8588
+ "10",
8589
+ "20",
8590
+ "unlimited"
8591
+ ]);
8592
+ const DEFAULT_RETRY_POLICY = "default";
8593
+ const CONNECTORS_FIELD = "connectors";
8594
+ const CONNECTOR_MODES = Object.freeze([
8595
+ "off",
8596
+ "read",
8597
+ "ask"
8598
+ ]);
8422
8599
  const INPUT_IMAGE_DETAIL_FIELD = "inputImageDetail";
8423
8600
  const INPUT_IMAGE_DETAILS = Object.freeze([
8424
8601
  "low",
@@ -8478,6 +8655,9 @@ window.__ModuleLoader__.load({
8478
8655
  "medium",
8479
8656
  "high"
8480
8657
  ].includes(value) ? value : DEFAULT_OUTPUT_VERBOSITY;
8658
+ const normalizeReasoningSummary = (value) => REASONING_SUMMARIES.includes(value) ? value : DEFAULT_REASONING_SUMMARY;
8659
+ const normalizeRetryPolicy = (value) => RETRY_POLICIES.includes(value) ? value : DEFAULT_RETRY_POLICY;
8660
+ const normalizeConnectorMode = (value) => CONNECTOR_MODES.includes(value) ? value : "off";
8481
8661
  const normalizeInputImageDetail = (value) => INPUT_IMAGE_DETAILS.includes(value) ? value : DEFAULT_INPUT_IMAGE_DETAIL;
8482
8662
  const normalizeStreamIdleTimeoutMinutes = (value) => STREAM_IDLE_TIMEOUT_MINUTES.includes(value) ? value : 10;
8483
8663
  const normalizeSpeedMode = (value) => [
@@ -8532,6 +8712,7 @@ window.__ModuleLoader__.load({
8532
8712
  let disposed = false;
8533
8713
  let subagentBackendAvailable = false;
8534
8714
  let subagentRuntimeInstalled = false;
8715
+ let restartRequired = false;
8535
8716
  const sameModels = (left, right) => left.length === right.length && left.every((model, index) => JSON.stringify(model) === JSON.stringify(right[index]));
8536
8717
  const read = () => {
8537
8718
  const current = fallback ?? { status: "unavailable" };
@@ -8556,6 +8737,9 @@ window.__ModuleLoader__.load({
8556
8737
  speedMode: normalizeSpeedMode(value?.[SPEED_MODE_FIELD]),
8557
8738
  outputVerbosity: normalizeOutputVerbosity(value?.[OUTPUT_VERBOSITY_FIELD]),
8558
8739
  inputImageDetail: normalizeInputImageDetail(value?.[INPUT_IMAGE_DETAIL_FIELD]),
8740
+ reasoningSummary: normalizeReasoningSummary(value?.[REASONING_SUMMARY_FIELD]),
8741
+ retryPolicy: normalizeRetryPolicy(value?.[RETRY_POLICY_FIELD]),
8742
+ connectors: normalizeConnectorMode(value?.[CONNECTORS_FIELD]),
8559
8743
  streamIdleTimeoutMinutes: normalizeStreamIdleTimeoutMinutes(value?.[STREAM_IDLE_TIMEOUT_MINUTES_FIELD]),
8560
8744
  contextMode: normalizeContextMode(value?.[CONTEXT_MODE_FIELD]),
8561
8745
  customContextWindow: normalizeCustomContextWindow(value?.[CUSTOM_CONTEXT_WINDOW_FIELD]),
@@ -8574,6 +8758,7 @@ window.__ModuleLoader__.load({
8574
8758
  modelError,
8575
8759
  writable: !updating && current.status === "ready" && current.writable === true,
8576
8760
  saving: updating,
8761
+ restartRequired,
8577
8762
  error
8578
8763
  });
8579
8764
  };
@@ -8584,6 +8769,7 @@ window.__ModuleLoader__.load({
8584
8769
  for (const listener of listeners) listener();
8585
8770
  };
8586
8771
  const acceptFallback = (value) => {
8772
+ if (value?.liveSynced === false) restartRequired = true;
8587
8773
  subagentBackendAvailable = value?.subagentBackendAvailable === true;
8588
8774
  subagentRuntimeInstalled = value?.subagentRuntimeInstalled === true;
8589
8775
  if (!modelRefreshStarted) {
@@ -8610,6 +8796,9 @@ window.__ModuleLoader__.load({
8610
8796
  [SPEED_MODE_FIELD]: normalizeSpeedMode(value?.[SPEED_MODE_FIELD]),
8611
8797
  [OUTPUT_VERBOSITY_FIELD]: normalizeOutputVerbosity(value?.[OUTPUT_VERBOSITY_FIELD]),
8612
8798
  [INPUT_IMAGE_DETAIL_FIELD]: normalizeInputImageDetail(value?.[INPUT_IMAGE_DETAIL_FIELD]),
8799
+ [REASONING_SUMMARY_FIELD]: normalizeReasoningSummary(value?.[REASONING_SUMMARY_FIELD]),
8800
+ [RETRY_POLICY_FIELD]: normalizeRetryPolicy(value?.[RETRY_POLICY_FIELD]),
8801
+ [CONNECTORS_FIELD]: normalizeConnectorMode(value?.[CONNECTORS_FIELD]),
8613
8802
  [STREAM_IDLE_TIMEOUT_MINUTES_FIELD]: normalizeStreamIdleTimeoutMinutes(value?.[STREAM_IDLE_TIMEOUT_MINUTES_FIELD]),
8614
8803
  [CONTEXT_MODE_FIELD]: normalizeContextMode(value?.[CONTEXT_MODE_FIELD]),
8615
8804
  [CUSTOM_CONTEXT_WINDOW_FIELD]: normalizeCustomContextWindow(value?.[CUSTOM_CONTEXT_WINDOW_FIELD]),
@@ -9015,7 +9204,7 @@ window.__ModuleLoader__.load({
9015
9204
  if (local.length <= 2) return `${local.slice(0, 1)}••@${domain}`;
9016
9205
  return `${local[0]}•••${local.at(-1)}@${domain}`;
9017
9206
  };
9018
- const hours = (seconds) => Math.round(seconds / 3600 * 10) / 10;
9207
+ const hours$1 = (seconds) => Math.round(seconds / 3600 * 10) / 10;
9019
9208
  const percent = (value) => Number(value).toLocaleString(void 0, { maximumFractionDigits: 1 });
9020
9209
  const isApproximateWindow = (seconds, expected) => seconds >= expected * .95 && seconds <= expected * 1.05;
9021
9210
  const windowLabel = (seconds, t) => {
@@ -9024,7 +9213,7 @@ window.__ModuleLoader__.load({
9024
9213
  if (isApproximateWindow(seconds, 604800)) return t("windowWeekly");
9025
9214
  if (isApproximateWindow(seconds, 2592e3)) return t("windowMonthly");
9026
9215
  if (isApproximateWindow(seconds, 31536e3)) return t("windowAnnual");
9027
- return seconds >= 86400 && seconds % 86400 === 0 ? fill(t("windowDays"), { value: seconds / 86400 }) : fill(t("windowHours"), { value: hours(seconds) });
9216
+ return seconds >= 86400 && seconds % 86400 === 0 ? fill(t("windowDays"), { value: seconds / 86400 }) : fill(t("windowHours"), { value: hours$1(seconds) });
9028
9217
  };
9029
9218
  const validDate = (value) => {
9030
9219
  const date = new Date(value);
@@ -9093,7 +9282,7 @@ window.__ModuleLoader__.load({
9093
9282
  }
9094
9283
  //#endregion
9095
9284
  //#region src/version.js
9096
- const PACKAGE_VERSION = "3.0.0-beta.4";
9285
+ const PACKAGE_VERSION = "3.0.0-beta.5";
9097
9286
  //#endregion
9098
9287
  //#region src/client-recovery.js
9099
9288
  async function recoveryCall(rpc, endpoint, payload = {}, timeoutMs = 1e4) {
@@ -9369,6 +9558,7 @@ window.__ModuleLoader__.load({
9369
9558
  const preferenceSnapshot = usePreferenceSnapshot(preference);
9370
9559
  const [open, setOpen] = (0, react.useState)(false);
9371
9560
  const [pane, setPane] = (0, react.useState)("root");
9561
+ const [query, setQuery] = (0, react.useState)("");
9372
9562
  const rootRef = (0, react.useRef)(null);
9373
9563
  const triggerRef = (0, react.useRef)(null);
9374
9564
  const id = (0, react.useId)();
@@ -9404,6 +9594,17 @@ window.__ModuleLoader__.load({
9404
9594
  ...effort.description === void 0 ? {} : { description: effort.description }
9405
9595
  }))], [reasoning, t]);
9406
9596
  const modelLabel = currentChoice?.model.name ?? t("selectModel");
9597
+ const searchable = visibleGroups.reduce((total, group) => total + group.models.length, 0) > 4;
9598
+ const needle = searchable ? query.trim().toLocaleLowerCase() : "";
9599
+ const shownGroups = needle === "" ? visibleGroups : visibleGroups.map((group) => ({
9600
+ ...group,
9601
+ models: group.models.filter((model) => [
9602
+ model.name,
9603
+ model.id,
9604
+ model.description,
9605
+ group.name
9606
+ ].some((text) => typeof text === "string" && text.toLocaleLowerCase().includes(needle)))
9607
+ })).filter((group) => group.models.length > 0);
9407
9608
  const speedSupported = state.current?.provider === "openai-codex" && (preferenceSnapshot.fastModels?.includes(state.current?.model) ?? supportsCodexFastMode(state.current?.model));
9408
9609
  const speedWritable = preferenceSnapshot.status === "ready" && preferenceSnapshot.writable === true;
9409
9610
  const ultrafastSupported = state.current?.provider === "openai-codex" && (preferenceSnapshot.ultrafastModels ?? []).includes(state.current?.model);
@@ -9445,11 +9646,15 @@ window.__ModuleLoader__.load({
9445
9646
  if (!rootRef.current?.contains(event.target)) {
9446
9647
  setOpen(false);
9447
9648
  setPane("root");
9649
+ setQuery("");
9448
9650
  }
9449
9651
  };
9450
9652
  document.addEventListener("mousedown", closeOutside);
9451
9653
  return () => document.removeEventListener("mousedown", closeOutside);
9452
9654
  }, [open]);
9655
+ (0, react.useEffect)(() => {
9656
+ if (pane !== "model") setQuery("");
9657
+ }, [pane]);
9453
9658
  (0, react.useEffect)(() => {
9454
9659
  if (!speedSupported && pane === "speed") setPane("root");
9455
9660
  if (!verbositySupported && pane === "verbosity") setPane("root");
@@ -9462,6 +9667,7 @@ window.__ModuleLoader__.load({
9462
9667
  const close = (restoreFocus = false) => {
9463
9668
  setOpen(false);
9464
9669
  setPane("root");
9670
+ setQuery("");
9465
9671
  if (restoreFocus) queueMicrotask(() => triggerRef.current?.focus());
9466
9672
  };
9467
9673
  const settleSelection = (accepted) => {
@@ -9537,7 +9743,7 @@ window.__ModuleLoader__.load({
9537
9743
  });
9538
9744
  let submenu = null;
9539
9745
  if (pane === "model") submenu = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9540
- className: "codexModelSelectSubmenu",
9746
+ className: "codexModelSelectSubmenu codexModelSelectModelMenu",
9541
9747
  role: "menu",
9542
9748
  "aria-label": t("modelLabel"),
9543
9749
  children: [
@@ -9561,9 +9767,18 @@ window.__ModuleLoader__.load({
9561
9767
  value: failure.message
9562
9768
  })
9563
9769
  }, failure.id)),
9770
+ searchable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
9771
+ className: "codexModelSelectSearch",
9772
+ type: "search",
9773
+ value: query,
9774
+ autoFocus: true,
9775
+ placeholder: t("modelSearch"),
9776
+ "aria-label": t("modelSearch"),
9777
+ onChange: (event) => setQuery(event.target.value)
9778
+ }) : null,
9564
9779
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9565
9780
  className: "codexModelSelectGroups scrollable",
9566
- children: visibleGroups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
9781
+ children: shownGroups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
9567
9782
  className: "codexModelSelectGroup",
9568
9783
  role: "group",
9569
9784
  "aria-labelledby": `${id}-${group.id}`,
@@ -9594,6 +9809,10 @@ window.__ModuleLoader__.load({
9594
9809
  state.status === "ready" && visibleGroups.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9595
9810
  className: "codexModelSelectEmpty",
9596
9811
  children: t(choices.length === 0 ? "modelsEmpty" : "modelsHidden")
9812
+ }) : null,
9813
+ state.status === "ready" && visibleGroups.length > 0 && shownGroups.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9814
+ className: "codexModelSelectEmpty",
9815
+ children: t("modelNoMatch")
9597
9816
  }) : null
9598
9817
  ]
9599
9818
  });
@@ -12861,6 +13080,115 @@ window.__ModuleLoader__.load({
12861
13080
  })]
12862
13081
  });
12863
13082
  }
13083
+ function ReasoningSummaryPreference({ preference, t }) {
13084
+ const snapshot = usePreferenceSnapshot(preference);
13085
+ const writable = snapshot.status === "ready" && snapshot.writable === true;
13086
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13087
+ className: "codexSubscriptionPreference",
13088
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13089
+ className: "codexSubscriptionPreferenceCopy",
13090
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13091
+ className: "codexSubscriptionPreferenceLabel",
13092
+ children: t("reasoningSummary")
13093
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13094
+ className: "codexSubscriptionPreferenceHint",
13095
+ children: t("reasoningSummaryHint")
13096
+ })]
13097
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13098
+ className: "codexSubscriptionQuotaModes",
13099
+ "data-saving": snapshot.saving || void 0,
13100
+ "aria-busy": snapshot.saving || void 0,
13101
+ role: "radiogroup",
13102
+ "aria-label": t("reasoningSummary"),
13103
+ children: REASONING_SUMMARIES.map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13104
+ className: "codexSubscriptionQuotaMode",
13105
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13106
+ type: "radio",
13107
+ name: "codex-reasoning-summary",
13108
+ checked: snapshot.reasoningSummary === value,
13109
+ disabled: !writable,
13110
+ onChange: () => {
13111
+ preference.set({ [REASONING_SUMMARY_FIELD]: value });
13112
+ }
13113
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`reasoningSummary_${value}`) })]
13114
+ }, value))
13115
+ })]
13116
+ });
13117
+ }
13118
+ function RetryPolicyPreference({ preference, t }) {
13119
+ const snapshot = usePreferenceSnapshot(preference);
13120
+ const writable = snapshot.status === "ready" && snapshot.writable === true;
13121
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13122
+ className: "codexSubscriptionPreference",
13123
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13124
+ className: "codexSubscriptionPreferenceCopy",
13125
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13126
+ className: "codexSubscriptionPreferenceLabel",
13127
+ children: t("retryPolicy")
13128
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13129
+ className: "codexSubscriptionPreferenceHint",
13130
+ children: t("retryPolicyHint")
13131
+ })]
13132
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13133
+ className: "codexSubscriptionQuotaModes",
13134
+ "data-saving": snapshot.saving || void 0,
13135
+ "aria-busy": snapshot.saving || void 0,
13136
+ role: "radiogroup",
13137
+ "aria-label": t("retryPolicy"),
13138
+ children: RETRY_POLICIES.map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13139
+ className: "codexSubscriptionQuotaMode",
13140
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13141
+ type: "radio",
13142
+ name: "codex-retry-policy",
13143
+ checked: snapshot.retryPolicy === value,
13144
+ disabled: !writable,
13145
+ onChange: () => {
13146
+ preference.set({ [RETRY_POLICY_FIELD]: value });
13147
+ }
13148
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`retryPolicy_${value}`) })]
13149
+ }, value))
13150
+ })]
13151
+ });
13152
+ }
13153
+ function ConnectorsPreference({ preference, t }) {
13154
+ const snapshot = usePreferenceSnapshot(preference);
13155
+ const writable = snapshot.status === "ready" && snapshot.writable === true;
13156
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13157
+ className: "codexSubscriptionPreference",
13158
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13159
+ className: "codexSubscriptionPreferenceCopy",
13160
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13161
+ className: "codexSubscriptionPreferenceLabel",
13162
+ children: [
13163
+ t("connectors"),
13164
+ " ",
13165
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13166
+ ]
13167
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13168
+ className: "codexSubscriptionPreferenceHint",
13169
+ children: t("connectorsHint")
13170
+ })]
13171
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13172
+ className: "codexSubscriptionQuotaModes",
13173
+ "data-saving": snapshot.saving || void 0,
13174
+ "aria-busy": snapshot.saving || void 0,
13175
+ role: "radiogroup",
13176
+ "aria-label": t("connectors"),
13177
+ children: CONNECTOR_MODES.map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13178
+ className: "codexSubscriptionQuotaMode",
13179
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13180
+ type: "radio",
13181
+ name: "codex-connectors",
13182
+ checked: snapshot.connectors === value,
13183
+ disabled: !writable,
13184
+ onChange: () => {
13185
+ preference.set({ [CONNECTORS_FIELD]: value });
13186
+ }
13187
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`connectors_${value}`) })]
13188
+ }, value))
13189
+ })]
13190
+ });
13191
+ }
12864
13192
  function StreamIdleTimeoutPreference({ preference, t }) {
12865
13193
  const snapshot = usePreferenceSnapshot(preference);
12866
13194
  const writable = snapshot.status === "ready" && snapshot.writable === true;
@@ -13135,245 +13463,267 @@ window.__ModuleLoader__.load({
13135
13463
  const snapshot = usePreferenceSnapshot(preference);
13136
13464
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13137
13465
  className: section === "advanced" ? "codexSubscriptionAdvancedPreferences" : "codexSubscriptionCard codexSubscriptionPreferencesCard",
13138
- children: [section === "advanced" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
13139
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13140
- className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13141
- "aria-label": t("modelsSectionTitle"),
13142
- children: [
13143
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("modelsSectionTitle") }),
13144
- defaultModel === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultModelPreference, {
13145
- preference,
13146
- defaultModel,
13147
- t
13148
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" })] }),
13149
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogStatus, {
13150
- preference,
13151
- t
13152
- }),
13153
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13154
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerModelsPreference, {
13155
- preference,
13156
- t
13157
- }),
13158
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13159
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextWindowPreference, {
13160
- preference,
13161
- t
13162
- }),
13163
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13164
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InputImageDetailPreference, {
13466
+ children: [
13467
+ snapshot.restartRequired ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
13468
+ className: "codexSubscriptionError",
13469
+ role: "status",
13470
+ children: t("settingsRestartRequired")
13471
+ }) : null,
13472
+ section === "advanced" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
13473
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13474
+ className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13475
+ "aria-label": t("modelsSectionTitle"),
13476
+ children: [
13477
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("modelsSectionTitle") }),
13478
+ defaultModel === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultModelPreference, {
13479
+ preference,
13480
+ defaultModel,
13481
+ t
13482
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" })] }),
13483
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogStatus, {
13484
+ preference,
13485
+ t
13486
+ }),
13487
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13488
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerModelsPreference, {
13489
+ preference,
13490
+ t
13491
+ }),
13492
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13493
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextWindowPreference, {
13494
+ preference,
13495
+ t
13496
+ }),
13497
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13498
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InputImageDetailPreference, {
13499
+ preference,
13500
+ t
13501
+ }),
13502
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13503
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningSummaryPreference, {
13504
+ preference,
13505
+ t
13506
+ }),
13507
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13508
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RetryPolicyPreference, {
13509
+ preference,
13510
+ t
13511
+ }),
13512
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectorsPreference, {
13513
+ preference,
13514
+ t
13515
+ })
13516
+ ]
13517
+ }),
13518
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13519
+ className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13520
+ "aria-label": t("searchSectionTitle"),
13521
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("searchSectionTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchProviderPreference, {
13165
13522
  preference,
13166
13523
  t
13524
+ })]
13525
+ }),
13526
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13527
+ className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13528
+ "aria-label": t("connectionTitle"),
13529
+ children: [
13530
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13531
+ className: "codexSubscriptionPreference",
13532
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13533
+ className: "codexSubscriptionPreferenceCopy",
13534
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13535
+ className: "codexSubscriptionPreferenceLabel",
13536
+ children: [
13537
+ t("connectionTitle"),
13538
+ " ",
13539
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13540
+ ]
13541
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13542
+ className: "codexSubscriptionPreferenceHint",
13543
+ children: t("connectionHint")
13544
+ })]
13545
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13546
+ className: "codexSubscriptionQuotaModes",
13547
+ role: "radiogroup",
13548
+ "aria-label": t("connectionTitle"),
13549
+ "aria-busy": snapshot.saving || void 0,
13550
+ children: ["sse", "websocket"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13551
+ className: "codexSubscriptionQuotaMode",
13552
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13553
+ type: "radio",
13554
+ name: "codex-connection-mode",
13555
+ checked: snapshot.connectionMode === value,
13556
+ disabled: !snapshot.writable,
13557
+ onChange: () => {
13558
+ preference.set({ connectionMode: value });
13559
+ }
13560
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: value === "sse" ? "SSE" : "WebSocket" })]
13561
+ }, value))
13562
+ })]
13563
+ }),
13564
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13565
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StreamIdleTimeoutPreference, {
13566
+ preference,
13567
+ t
13568
+ })
13569
+ ]
13570
+ }),
13571
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
13572
+ className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13573
+ "aria-label": t("reviewModelTitle"),
13574
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13575
+ className: "codexSubscriptionPreference",
13576
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13577
+ className: "codexSubscriptionPreferenceCopy",
13578
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13579
+ className: "codexSubscriptionPreferenceLabel",
13580
+ children: [
13581
+ t("reviewModelTitle"),
13582
+ " ",
13583
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13584
+ ]
13585
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13586
+ className: "codexSubscriptionPreferenceHint",
13587
+ children: t("reviewModelHint")
13588
+ })]
13589
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13590
+ className: "codexSubscriptionQuotaModes",
13591
+ role: "radiogroup",
13592
+ "aria-label": t("reviewModelTitle"),
13593
+ "aria-busy": snapshot.saving || void 0,
13594
+ children: ["session", "official"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13595
+ className: "codexSubscriptionQuotaMode",
13596
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13597
+ type: "radio",
13598
+ name: "codex-review-model",
13599
+ checked: snapshot.reviewModel === value,
13600
+ disabled: !snapshot.writable,
13601
+ onChange: () => {
13602
+ preference.set({ reviewModel: value });
13603
+ }
13604
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`reviewModel_${value}`) })]
13605
+ }, value))
13606
+ })]
13167
13607
  })
13168
- ]
13169
- }),
13170
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13171
- className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13172
- "aria-label": t("searchSectionTitle"),
13173
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: t("searchSectionTitle") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchProviderPreference, {
13608
+ }),
13609
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RemoteControlCard, {
13610
+ rpc,
13174
13611
  preference,
13612
+ snapshot,
13175
13613
  t
13176
- })]
13177
- }),
13178
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13179
- className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13180
- "aria-label": t("connectionTitle"),
13181
- children: [
13182
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13614
+ }),
13615
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
13616
+ className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13617
+ "aria-label": t("compactionTitle"),
13618
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13183
13619
  className: "codexSubscriptionPreference",
13184
13620
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13185
13621
  className: "codexSubscriptionPreferenceCopy",
13186
13622
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13187
13623
  className: "codexSubscriptionPreferenceLabel",
13188
13624
  children: [
13189
- t("connectionTitle"),
13625
+ t("compactionTitle"),
13190
13626
  " ",
13191
13627
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13192
13628
  ]
13193
13629
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13194
13630
  className: "codexSubscriptionPreferenceHint",
13195
- children: t("connectionHint")
13631
+ children: t("compactionHint")
13196
13632
  })]
13197
13633
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13198
13634
  className: "codexSubscriptionQuotaModes",
13199
13635
  role: "radiogroup",
13200
- "aria-label": t("connectionTitle"),
13636
+ "aria-label": t("compactionTitle"),
13201
13637
  "aria-busy": snapshot.saving || void 0,
13202
- children: ["sse", "websocket"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13638
+ children: ["dsh", "cloud"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13203
13639
  className: "codexSubscriptionQuotaMode",
13204
13640
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13205
13641
  type: "radio",
13206
- name: "codex-connection-mode",
13207
- checked: snapshot.connectionMode === value,
13642
+ name: "codex-compaction-mode",
13643
+ checked: snapshot.compactionMode === value,
13208
13644
  disabled: !snapshot.writable,
13209
13645
  onChange: () => {
13210
- preference.set({ connectionMode: value });
13646
+ preference.set({ compactionMode: value });
13211
13647
  }
13212
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: value === "sse" ? "SSE" : "WebSocket" })]
13648
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`compaction_${value}`) })]
13213
13649
  }, value))
13214
13650
  })]
13215
- }),
13216
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13217
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StreamIdleTimeoutPreference, {
13218
- preference,
13219
- t
13220
13651
  })
13221
- ]
13222
- }),
13223
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
13224
- className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13225
- "aria-label": t("reviewModelTitle"),
13226
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13227
- className: "codexSubscriptionPreference",
13228
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13229
- className: "codexSubscriptionPreferenceCopy",
13230
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13231
- className: "codexSubscriptionPreferenceLabel",
13232
- children: [
13233
- t("reviewModelTitle"),
13234
- " ",
13235
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13236
- ]
13237
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13238
- className: "codexSubscriptionPreferenceHint",
13239
- children: t("reviewModelHint")
13240
- })]
13241
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13242
- className: "codexSubscriptionQuotaModes",
13243
- role: "radiogroup",
13244
- "aria-label": t("reviewModelTitle"),
13245
- "aria-busy": snapshot.saving || void 0,
13246
- children: ["session", "official"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13247
- className: "codexSubscriptionQuotaMode",
13248
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13249
- type: "radio",
13250
- name: "codex-review-model",
13251
- checked: snapshot.reviewModel === value,
13252
- disabled: !snapshot.writable,
13253
- onChange: () => {
13254
- preference.set({ reviewModel: value });
13255
- }
13256
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`reviewModel_${value}`) })]
13257
- }, value))
13258
- })]
13259
- })
13260
- }),
13261
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RemoteControlCard, {
13262
- rpc,
13263
- preference,
13264
- snapshot,
13265
- t
13266
- }),
13267
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
13268
- className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13269
- "aria-label": t("compactionTitle"),
13270
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13271
- className: "codexSubscriptionPreference",
13652
+ }),
13653
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13654
+ className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13655
+ "aria-label": t("subagentBackendTitle"),
13272
13656
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13273
- className: "codexSubscriptionPreferenceCopy",
13274
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13275
- className: "codexSubscriptionPreferenceLabel",
13276
- children: [
13277
- t("compactionTitle"),
13278
- " ",
13279
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13280
- ]
13281
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13282
- className: "codexSubscriptionPreferenceHint",
13283
- children: t("compactionHint")
13657
+ className: "codexSubscriptionPreference",
13658
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13659
+ className: "codexSubscriptionPreferenceCopy",
13660
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13661
+ className: "codexSubscriptionPreferenceLabel",
13662
+ children: [
13663
+ t("subagentBackendTitle"),
13664
+ " ",
13665
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13666
+ ]
13667
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13668
+ className: "codexSubscriptionPreferenceHint",
13669
+ children: t(snapshot.subagentBackendAvailable ? "subagentBackendHint" : "subagentBackendUnavailable")
13670
+ })]
13671
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13672
+ className: "codexSubscriptionQuotaModes",
13673
+ role: "radiogroup",
13674
+ "aria-label": t("subagentBackendTitle"),
13675
+ "aria-busy": snapshot.saving || void 0,
13676
+ children: ["dsh", "codex"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13677
+ className: "codexSubscriptionQuotaMode",
13678
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13679
+ type: "radio",
13680
+ name: "codex-subagent-backend",
13681
+ checked: snapshot.subagentBackend === value,
13682
+ disabled: !snapshot.writable || !snapshot.subagentBackendAvailable || value === "codex" && !snapshot.subagentRuntimeInstalled,
13683
+ onChange: () => {
13684
+ preference.set({ subagentBackend: value });
13685
+ }
13686
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`subagentBackend_${value}`) })]
13687
+ }, value))
13284
13688
  })]
13285
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13286
- className: "codexSubscriptionQuotaModes",
13287
- role: "radiogroup",
13288
- "aria-label": t("compactionTitle"),
13289
- "aria-busy": snapshot.saving || void 0,
13290
- children: ["dsh", "cloud"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13291
- className: "codexSubscriptionQuotaMode",
13292
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13293
- type: "radio",
13294
- name: "codex-compaction-mode",
13295
- checked: snapshot.compactionMode === value,
13296
- disabled: !snapshot.writable,
13297
- onChange: () => {
13298
- preference.set({ compactionMode: value });
13299
- }
13300
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`compaction_${value}`) })]
13301
- }, value))
13689
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeManagement, {
13690
+ rpc,
13691
+ preference,
13692
+ t
13302
13693
  })]
13303
13694
  })
13304
- }),
13305
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
13306
- className: "codexSubscriptionCard codexSubscriptionPreferencesCard",
13307
- "aria-label": t("subagentBackendTitle"),
13308
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13309
- className: "codexSubscriptionPreference",
13310
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13311
- className: "codexSubscriptionPreferenceCopy",
13312
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
13313
- className: "codexSubscriptionPreferenceLabel",
13314
- children: [
13315
- t("subagentBackendTitle"),
13316
- " ",
13317
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: "Beta" })
13318
- ]
13319
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13320
- className: "codexSubscriptionPreferenceHint",
13321
- children: t(snapshot.subagentBackendAvailable ? "subagentBackendHint" : "subagentBackendUnavailable")
13322
- })]
13323
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
13324
- className: "codexSubscriptionQuotaModes",
13325
- role: "radiogroup",
13326
- "aria-label": t("subagentBackendTitle"),
13327
- "aria-busy": snapshot.saving || void 0,
13328
- children: ["dsh", "codex"].map((value) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
13329
- className: "codexSubscriptionQuotaMode",
13330
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
13331
- type: "radio",
13332
- name: "codex-subagent-backend",
13333
- checked: snapshot.subagentBackend === value,
13334
- disabled: !snapshot.writable || !snapshot.subagentBackendAvailable || value === "codex" && !snapshot.subagentRuntimeInstalled,
13335
- onChange: () => {
13336
- preference.set({ subagentBackend: value });
13337
- }
13338
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(`subagentBackend_${value}`) })]
13339
- }, value))
13340
- })]
13341
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RuntimeManagement, {
13342
- rpc,
13695
+ ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
13696
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickQuotaPreference, {
13697
+ preference,
13698
+ t
13699
+ }),
13700
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CapabilityPreferences, {
13701
+ preference,
13702
+ t,
13703
+ section: "quota"
13704
+ }),
13705
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13706
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoQuotaRetryPreference, {
13343
13707
  preference,
13344
13708
  t
13709
+ })
13710
+ ] }),
13711
+ snapshot.error ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13712
+ className: "codexSubscriptionRecover",
13713
+ role: "alert",
13714
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
13715
+ className: "codexSubscriptionError",
13716
+ children: t("preferenceFailed")
13717
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
13718
+ type: "button",
13719
+ variant: "outline",
13720
+ onClick: () => {
13721
+ preference.retry();
13722
+ },
13723
+ children: t("preferenceRetry")
13345
13724
  })]
13346
- })
13347
- ] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
13348
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickQuotaPreference, {
13349
- preference,
13350
- t
13351
- }),
13352
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CapabilityPreferences, {
13353
- preference,
13354
- t,
13355
- section: "quota"
13356
- }),
13357
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "codexSubscriptionDivider" }),
13358
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoQuotaRetryPreference, {
13359
- preference,
13360
- t
13361
- })
13362
- ] }), snapshot.error ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
13363
- className: "codexSubscriptionRecover",
13364
- role: "alert",
13365
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
13366
- className: "codexSubscriptionError",
13367
- children: t("preferenceFailed")
13368
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
13369
- type: "button",
13370
- variant: "outline",
13371
- onClick: () => {
13372
- preference.retry();
13373
- },
13374
- children: t("preferenceRetry")
13375
- })]
13376
- }) : null]
13725
+ }) : null
13726
+ ]
13377
13727
  });
13378
13728
  }
13379
13729
  //#endregion
@@ -13419,6 +13769,12 @@ window.__ModuleLoader__.load({
13419
13769
  }
13420
13770
  //#endregion
13421
13771
  //#region src/client-account.jsx
13772
+ const LOGIN_FAILURES = [
13773
+ "account-claim",
13774
+ "network",
13775
+ "token-exchange",
13776
+ "callback"
13777
+ ];
13422
13778
  function AccountEmail({ candidate, fallback, t, emailVisible, onClick }) {
13423
13779
  if (typeof candidate?.email !== "string" || candidate.email.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
13424
13780
  title: t("emailUnavailable"),
@@ -13778,7 +14134,7 @@ window.__ModuleLoader__.load({
13778
14134
  flow?.phase === "failed" || error !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
13779
14135
  className: "codexSubscriptionError",
13780
14136
  role: "alert",
13781
- children: error ?? t("failed")
14137
+ children: error ?? (LOGIN_FAILURES.includes(flow?.failure) ? t(`failed_${flow.failure.replace("-", "_")}`) : t("failed"))
13782
14138
  }) : null
13783
14139
  ]
13784
14140
  });
@@ -14231,6 +14587,276 @@ window.__ModuleLoader__.load({
14231
14587
  };
14232
14588
  }
14233
14589
  //#endregion
14590
+ //#region src/client-usage-overview.jsx
14591
+ const uiLocale = () => typeof document === "undefined" ? void 0 : document.documentElement.lang || void 0;
14592
+ const WEEKS = 26;
14593
+ const compact = (value) => new Intl.NumberFormat(uiLocale(), {
14594
+ notation: "compact",
14595
+ maximumFractionDigits: 1
14596
+ }).format(value);
14597
+ const hours = (seconds) => seconds >= 3600 ? `${Math.round(seconds / 360) / 10} h` : `${Math.max(1, Math.round(seconds / 60))} min`;
14598
+ const key = (date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
14599
+ function UsageHeatmap({ days, t }) {
14600
+ const byDate = new Map(days.map((day) => [day.date, day.tokens]));
14601
+ const today = /* @__PURE__ */ new Date();
14602
+ today.setHours(0, 0, 0, 0);
14603
+ const start = new Date(today);
14604
+ start.setDate(start.getDate() - ((WEEKS - 1) * 7 + today.getDay()));
14605
+ const cells = [];
14606
+ for (let index = 0; index < WEEKS * 7; index += 1) {
14607
+ const date = new Date(start);
14608
+ date.setDate(start.getDate() + index);
14609
+ if (date > today) break;
14610
+ cells.push({
14611
+ date: key(date),
14612
+ tokens: byDate.get(key(date)) ?? 0,
14613
+ column: Math.floor(index / 7),
14614
+ row: index % 7
14615
+ });
14616
+ }
14617
+ const busy = cells.map((cell) => cell.tokens).filter((tokens) => tokens > 0).sort((a, b) => a - b);
14618
+ const level = (tokens) => tokens === 0 ? 0 : 1 + [
14619
+ .25,
14620
+ .5,
14621
+ .75
14622
+ ].filter((point) => tokens > busy[Math.floor((busy.length - 1) * point)]).length;
14623
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
14624
+ className: "codexSubscriptionHeatmap",
14625
+ viewBox: `0 0 ${WEEKS * 14} 98`,
14626
+ role: "img",
14627
+ "aria-label": t("overviewHeatmap"),
14628
+ children: cells.map((cell) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
14629
+ x: cell.column * 14,
14630
+ y: cell.row * 14,
14631
+ width: "11",
14632
+ height: "11",
14633
+ rx: "2",
14634
+ "data-level": level(cell.tokens),
14635
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("title", { children: `${cell.date}: ${cell.tokens === 0 ? t("overviewNoUse") : fill(t("overviewTokens"), { value: compact(cell.tokens) })}` })
14636
+ }, cell.date))
14637
+ });
14638
+ }
14639
+ function UsageOverview({ rpc, t, signedIn, resetKey }) {
14640
+ const [open, setOpen] = (0, react.useState)(false);
14641
+ const [state, setState] = (0, react.useState)({ status: "idle" });
14642
+ const request = (0, react.useRef)(0);
14643
+ (0, react.useEffect)(() => {
14644
+ request.current += 1;
14645
+ setState({ status: "idle" });
14646
+ }, [signedIn, resetKey]);
14647
+ (0, react.useEffect)(() => {
14648
+ if (!open || !signedIn || state.status !== "idle") return;
14649
+ const id = ++request.current;
14650
+ setState({ status: "loading" });
14651
+ recoveryCall(rpc, "usage/profile", {}).then((value) => {
14652
+ if (request.current === id) setState({
14653
+ status: "ready",
14654
+ value
14655
+ });
14656
+ }).catch((error) => {
14657
+ if (request.current === id) setState({
14658
+ status: "error",
14659
+ message: error.message
14660
+ });
14661
+ });
14662
+ }, [
14663
+ open,
14664
+ signedIn,
14665
+ state.status,
14666
+ rpc
14667
+ ]);
14668
+ if (!signedIn) return null;
14669
+ const value = state.value;
14670
+ const stats = value === void 0 || value.available === false ? [] : [
14671
+ [t("overviewLifetime"), value.lifetimeTokens === void 0 ? void 0 : compact(value.lifetimeTokens)],
14672
+ [t("overviewPeak"), value.peakDailyTokens === void 0 ? void 0 : compact(value.peakDailyTokens)],
14673
+ [t("overviewStreak"), value.currentStreakDays === void 0 ? void 0 : fill(t("overviewDays"), { value: value.currentStreakDays })],
14674
+ [t("overviewLongestStreak"), value.longestStreakDays === void 0 ? void 0 : fill(t("overviewDays"), { value: value.longestStreakDays })],
14675
+ [t("overviewThreads"), value.totalThreads === void 0 ? void 0 : value.totalThreads.toLocaleString(uiLocale())],
14676
+ [t("overviewEffort"), value.mostUsedReasoningEffort === void 0 ? void 0 : `${value.mostUsedReasoningEffort}${value.mostUsedReasoningEffortPercent === void 0 ? "" : ` · ${value.mostUsedReasoningEffortPercent}%`}`],
14677
+ [t("overviewFast"), value.fastModePercent === void 0 ? void 0 : `${value.fastModePercent}%`],
14678
+ [t("overviewLongestTurn"), value.longestRunningTurnSeconds === void 0 ? void 0 : hours(value.longestRunningTurnSeconds)]
14679
+ ].filter(([, text]) => text !== void 0);
14680
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
14681
+ className: "codexSubscriptionHistory",
14682
+ onToggle: (event) => setOpen(event.currentTarget.open),
14683
+ children: [
14684
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("overviewTitle") }),
14685
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14686
+ "aria-live": "polite",
14687
+ children: [
14688
+ state.status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14689
+ className: "codexSubscriptionEmpty",
14690
+ role: "status",
14691
+ children: t("overviewLoading")
14692
+ }) : null,
14693
+ state.status === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14694
+ className: "codexSubscriptionError",
14695
+ role: "alert",
14696
+ children: state.message
14697
+ }) : null,
14698
+ state.status === "ready" && stats.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14699
+ className: "codexSubscriptionEmpty",
14700
+ role: "status",
14701
+ children: t("overviewUnavailable")
14702
+ }) : null
14703
+ ]
14704
+ }),
14705
+ stats.length === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dl", {
14706
+ className: "codexSubscriptionOverviewStats",
14707
+ children: stats.map(([label, text]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: text })] }, label))
14708
+ }), value.days.length === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageHeatmap, {
14709
+ days: value.days,
14710
+ t
14711
+ })] })
14712
+ ]
14713
+ });
14714
+ }
14715
+ //#endregion
14716
+ //#region src/client-usage-history.jsx
14717
+ const DIMENSIONS = [
14718
+ "model",
14719
+ "surface",
14720
+ "thread_source",
14721
+ "turn_trigger"
14722
+ ];
14723
+ const LABELS = /* @__PURE__ */ new Map([
14724
+ ["desktop_app", "historyDesktopApp"],
14725
+ ["cli", "historyCli"],
14726
+ ["ide_extension", "historyIde"],
14727
+ ["web", "historyWeb"],
14728
+ ["mobile", "historyMobile"],
14729
+ ["user", "historyUser"],
14730
+ ["subagent", "historySubagent"],
14731
+ ["memory_consolidation", "historyMemory"],
14732
+ ["review", "historyReview"],
14733
+ ["composer", "historyComposer"],
14734
+ ["automation", "historyAutomation"]
14735
+ ]);
14736
+ const day = (value) => new Date(value).toLocaleDateString(uiLocale(), {
14737
+ month: "numeric",
14738
+ day: "numeric"
14739
+ });
14740
+ const amount = (value) => value > 0 && value < .1 ? "<0.1" : (value >= 10 ? Math.round(value) : Math.round(value * 10) / 10).toLocaleString(uiLocale());
14741
+ const labelOf = (dimension, key, t) => dimension === "model" ? key : LABELS.has(key) ? t(LABELS.get(key)) : key.replaceAll("_", " ");
14742
+ function Rows({ dimension, rows, total, t }) {
14743
+ const top = Math.max(total, ...rows.map((row) => row.percent));
14744
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14745
+ className: "codexSubscriptionHistoryGroup",
14746
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", { children: t(`historyBy_${dimension}`) }), rows.toSorted((a, b) => b.percent - a.percent).map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14747
+ className: "codexSubscriptionHistoryRow",
14748
+ children: [
14749
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
14750
+ className: "codexSubscriptionHistoryKey",
14751
+ children: labelOf(dimension, row.key, t)
14752
+ }),
14753
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("progress", {
14754
+ max: top,
14755
+ value: row.percent,
14756
+ "aria-label": `${labelOf(dimension, row.key, t)} ${amount(row.percent)}%`
14757
+ }),
14758
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [amount(row.percent), "%"] })
14759
+ ]
14760
+ }, row.key))]
14761
+ });
14762
+ }
14763
+ function UsageHistory({ rpc, t, signedIn, resetKey }) {
14764
+ const [open, setOpen] = (0, react.useState)(false);
14765
+ const [state, setState] = (0, react.useState)({ status: "idle" });
14766
+ const [selected, setSelected] = (0, react.useState)(0);
14767
+ const request = (0, react.useRef)(0);
14768
+ (0, react.useEffect)(() => {
14769
+ request.current += 1;
14770
+ setState({ status: "idle" });
14771
+ setSelected(0);
14772
+ }, [signedIn, resetKey]);
14773
+ (0, react.useEffect)(() => {
14774
+ if (!open || !signedIn || state.status !== "idle") return;
14775
+ const id = ++request.current;
14776
+ setState({ status: "loading" });
14777
+ recoveryCall(rpc, "usage/history", {}).then((value) => {
14778
+ if (request.current === id) setState({
14779
+ status: "ready",
14780
+ value
14781
+ });
14782
+ }).catch((error) => {
14783
+ if (request.current === id) setState({
14784
+ status: "error",
14785
+ message: error.message
14786
+ });
14787
+ });
14788
+ }, [
14789
+ open,
14790
+ signedIn,
14791
+ state.status,
14792
+ rpc
14793
+ ]);
14794
+ if (!signedIn) return null;
14795
+ const value = state.value;
14796
+ const periods = (value?.periods ?? []).filter((period) => period.usedPercent !== void 0);
14797
+ const period = periods[Math.min(selected, Math.max(0, periods.length - 1))];
14798
+ const present = DIMENSIONS.filter((dimension) => period?.breakdowns?.[dimension]?.length > 0);
14799
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
14800
+ className: "codexSubscriptionHistory",
14801
+ onToggle: (event) => setOpen(event.currentTarget.open),
14802
+ children: [
14803
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("historyTitle") }),
14804
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
14805
+ "aria-live": "polite",
14806
+ children: [
14807
+ state.status === "loading" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14808
+ className: "codexSubscriptionEmpty",
14809
+ role: "status",
14810
+ children: t("historyLoading")
14811
+ }) : null,
14812
+ state.status === "error" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14813
+ className: "codexSubscriptionError",
14814
+ role: "alert",
14815
+ children: state.message
14816
+ }) : null,
14817
+ state.status === "ready" && value.available === false ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14818
+ className: "codexSubscriptionEmpty",
14819
+ role: "status",
14820
+ children: t("historyUnavailable")
14821
+ }) : null,
14822
+ state.status === "ready" && value.available !== false && period === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14823
+ className: "codexSubscriptionEmpty",
14824
+ role: "status",
14825
+ children: t("historyEmpty")
14826
+ }) : null
14827
+ ]
14828
+ }),
14829
+ period === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
14830
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14831
+ className: "codexSubscriptionHistoryPeriods",
14832
+ role: "group",
14833
+ "aria-label": t("historyPeriods"),
14834
+ children: periods.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
14835
+ type: "button",
14836
+ "aria-pressed": item === period,
14837
+ onClick: () => setSelected(index),
14838
+ children: `${day(item.startsAt)}–${day(item.endsAt)}`
14839
+ }, item.startsAt))
14840
+ }),
14841
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
14842
+ className: "codexSubscriptionHistorySummary",
14843
+ children: [fill(t("historyUsed"), { value: amount(period.usedPercent) }), period.complete ? "" : ` ${t("historyPartial")}`]
14844
+ }),
14845
+ present.map((dimension) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Rows, {
14846
+ dimension,
14847
+ rows: period.breakdowns[dimension],
14848
+ total: period.usedPercent,
14849
+ t
14850
+ }, dimension)),
14851
+ value.approximate ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
14852
+ className: "codexSubscriptionCreditNote",
14853
+ children: t("historyApproximate")
14854
+ }) : null
14855
+ ] })
14856
+ ]
14857
+ });
14858
+ }
14859
+ //#endregion
14234
14860
  //#region src/client-usage.jsx
14235
14861
  const count = (value) => Number(value).toLocaleString();
14236
14862
  const creditAmount = (value) => Number.isFinite(Number(value)) && String(value).trim() !== "" ? Number(value).toLocaleString(void 0, { maximumFractionDigits: 2 }) : value;
@@ -14596,6 +15222,18 @@ window.__ModuleLoader__.load({
14596
15222
  ]
14597
15223
  }, `${limit.id}-${window.windowSeconds}-${index}`)))
14598
15224
  }),
15225
+ limits.length === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageOverview, {
15226
+ rpc,
15227
+ t,
15228
+ signedIn,
15229
+ resetKey
15230
+ }),
15231
+ limits.length === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageHistory, {
15232
+ rpc,
15233
+ t,
15234
+ signedIn,
15235
+ resetKey
15236
+ }),
14599
15237
  visibleUsage?.chatPass === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
14600
15238
  className: "codexSubscriptionLimits",
14601
15239
  children: visibleUsage.chatPass.windows.map((window, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {