@dexto/tui 1.6.11 → 1.6.13

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.
Files changed (66) hide show
  1. package/dist/InkCLIRefactored.cjs +39 -29
  2. package/dist/InkCLIRefactored.d.ts.map +1 -1
  3. package/dist/InkCLIRefactored.js +39 -29
  4. package/dist/components/Footer.cjs +9 -2
  5. package/dist/components/Footer.d.ts +3 -2
  6. package/dist/components/Footer.d.ts.map +1 -1
  7. package/dist/components/Footer.js +17 -3
  8. package/dist/components/modes/AlternateBufferCLI.cjs +2 -1
  9. package/dist/components/modes/AlternateBufferCLI.d.ts.map +1 -1
  10. package/dist/components/modes/AlternateBufferCLI.js +2 -1
  11. package/dist/components/modes/StaticCLI.cjs +2 -1
  12. package/dist/components/modes/StaticCLI.d.ts.map +1 -1
  13. package/dist/components/modes/StaticCLI.js +2 -1
  14. package/dist/components/overlays/ChatGPTUsageCapOverlay.cjs +90 -0
  15. package/dist/components/overlays/ChatGPTUsageCapOverlay.d.ts +19 -0
  16. package/dist/components/overlays/ChatGPTUsageCapOverlay.d.ts.map +1 -0
  17. package/dist/components/overlays/ChatGPTUsageCapOverlay.js +70 -0
  18. package/dist/components/overlays/ModelSelectorRefactored.cjs +263 -38
  19. package/dist/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
  20. package/dist/components/overlays/ModelSelectorRefactored.js +267 -38
  21. package/dist/components/overlays/ReasoningOverlay.cjs +1 -1
  22. package/dist/components/overlays/ReasoningOverlay.js +1 -1
  23. package/dist/containers/OverlayContainer.cjs +104 -13
  24. package/dist/containers/OverlayContainer.d.ts.map +1 -1
  25. package/dist/containers/OverlayContainer.js +104 -13
  26. package/dist/hooks/useAgentEvents.cjs +33 -2
  27. package/dist/hooks/useAgentEvents.d.ts.map +1 -1
  28. package/dist/hooks/useAgentEvents.js +35 -3
  29. package/dist/hooks/useCLIState.cjs +1 -0
  30. package/dist/hooks/useCLIState.d.ts.map +1 -1
  31. package/dist/hooks/useCLIState.js +1 -0
  32. package/dist/interactive-commands/exit-stats.cjs +16 -0
  33. package/dist/interactive-commands/exit-stats.d.ts +4 -0
  34. package/dist/interactive-commands/exit-stats.d.ts.map +1 -1
  35. package/dist/interactive-commands/exit-stats.js +15 -0
  36. package/dist/interactive-commands/general-commands.cjs +13 -2
  37. package/dist/interactive-commands/general-commands.d.ts.map +1 -1
  38. package/dist/interactive-commands/general-commands.js +14 -3
  39. package/dist/interactive-commands/general-commands.test.cjs +152 -0
  40. package/dist/interactive-commands/general-commands.test.d.ts +2 -0
  41. package/dist/interactive-commands/general-commands.test.d.ts.map +1 -0
  42. package/dist/interactive-commands/general-commands.test.js +151 -0
  43. package/dist/services/processStream.test.cjs +1 -0
  44. package/dist/services/processStream.test.js +1 -0
  45. package/dist/state/initialState.cjs +1 -0
  46. package/dist/state/initialState.d.ts.map +1 -1
  47. package/dist/state/initialState.js +1 -0
  48. package/dist/state/types.d.ts +4 -2
  49. package/dist/state/types.d.ts.map +1 -1
  50. package/dist/utils/chatgpt-rate-limit.cjs +72 -0
  51. package/dist/utils/chatgpt-rate-limit.d.ts +11 -0
  52. package/dist/utils/chatgpt-rate-limit.d.ts.map +1 -0
  53. package/dist/utils/chatgpt-rate-limit.js +49 -0
  54. package/dist/utils/chatgpt-rate-limit.test.cjs +46 -0
  55. package/dist/utils/chatgpt-rate-limit.test.d.ts +2 -0
  56. package/dist/utils/chatgpt-rate-limit.test.d.ts.map +1 -0
  57. package/dist/utils/chatgpt-rate-limit.test.js +49 -0
  58. package/dist/utils/llm-provider-display.cjs +11 -1
  59. package/dist/utils/llm-provider-display.d.ts +2 -2
  60. package/dist/utils/llm-provider-display.d.ts.map +1 -1
  61. package/dist/utils/llm-provider-display.js +11 -1
  62. package/dist/utils/llm-provider-display.test.cjs +15 -0
  63. package/dist/utils/llm-provider-display.test.d.ts +2 -0
  64. package/dist/utils/llm-provider-display.test.d.ts.map +1 -0
  65. package/dist/utils/llm-provider-display.test.js +14 -0
  66. package/package.json +4 -4
@@ -55,6 +55,9 @@ var import_SessionSubcommandSelector = __toESM(require("../components/overlays/S
55
55
  var import_McpCustomTypeSelector = __toESM(require("../components/overlays/McpCustomTypeSelector.js"), 1);
56
56
  var import_McpCustomWizard = __toESM(require("../components/overlays/McpCustomWizard.js"), 1);
57
57
  var import_CustomModelWizard = __toESM(require("../components/overlays/CustomModelWizard.js"), 1);
58
+ var import_ChatGPTUsageCapOverlay = __toESM(require("../components/overlays/ChatGPTUsageCapOverlay.js"), 1);
59
+ var import_llm_provider_display = require("../utils/llm-provider-display.js");
60
+ var import_chatgpt_rate_limit = require("../utils/chatgpt-rate-limit.js");
58
61
  var import_agent_management = require("@dexto/agent-management");
59
62
  var import_ApiKeyInput = __toESM(require("../components/overlays/ApiKeyInput.js"), 1);
60
63
  var import_SearchOverlay = __toESM(require("../components/overlays/SearchOverlay.js"), 1);
@@ -138,6 +141,7 @@ const OverlayContainer = (0, import_react.forwardRef)(
138
141
  const mcpCustomWizardRef = (0, import_react.useRef)(null);
139
142
  const customModelWizardRef = (0, import_react.useRef)(null);
140
143
  const sessionSubcommandSelectorRef = (0, import_react.useRef)(null);
144
+ const chatGPTUsageCapRef = (0, import_react.useRef)(null);
141
145
  const apiKeyInputRef = (0, import_react.useRef)(null);
142
146
  const loginOverlayRef = (0, import_react.useRef)(null);
143
147
  const logoutOverlayRef = (0, import_react.useRef)(null);
@@ -217,6 +221,8 @@ const OverlayContainer = (0, import_react.forwardRef)(
217
221
  return customModelWizardRef.current?.handleInput(inputStr, key) ?? false;
218
222
  case "session-subcommand-selector":
219
223
  return sessionSubcommandSelectorRef.current?.handleInput(inputStr, key) ?? false;
224
+ case "chatgpt-usage-cap":
225
+ return chatGPTUsageCapRef.current?.handleInput(inputStr, key) ?? false;
220
226
  case "api-key-input":
221
227
  return apiKeyInputRef.current?.handleInput(inputStr, key) ?? false;
222
228
  case "login":
@@ -337,12 +343,17 @@ const OverlayContainer = (0, import_react.forwardRef)(
337
343
  return null;
338
344
  };
339
345
  const persistRecentModel = (0, import_react.useCallback)(
340
- async (provider, model) => {
346
+ async (provider, model, baseURL) => {
341
347
  try {
342
- await (0, import_agent_management.recordRecentModel)({ provider, model });
348
+ await (0, import_agent_management.recordRecentModel)({
349
+ provider,
350
+ model,
351
+ ...baseURL ? { baseURL } : {}
352
+ });
343
353
  } catch (error) {
354
+ const modelKey = baseURL ? `${provider}/${model} (${baseURL})` : `${provider}/${model}`;
344
355
  agent.logger.debug(
345
- `Failed to persist recent model (${provider}/${model}): ${error instanceof Error ? error.message : String(error)}`
356
+ `Failed to persist recent model (${modelKey}): ${error instanceof Error ? error.message : String(error)}`
346
357
  );
347
358
  }
348
359
  },
@@ -350,6 +361,7 @@ const OverlayContainer = (0, import_react.forwardRef)(
350
361
  );
351
362
  const handleModelSelect = (0, import_react.useCallback)(
352
363
  async (provider, model, displayName, baseURL, reasoningVariant) => {
364
+ const providerLabel = (0, import_llm_provider_display.getLLMProviderDisplayName)(provider, baseURL);
353
365
  if (provider === "dexto-nova") {
354
366
  try {
355
367
  const canUse = await (0, import_host.canUseDextoProvider)();
@@ -387,7 +399,7 @@ const OverlayContainer = (0, import_react.forwardRef)(
387
399
  {
388
400
  id: (0, import_idGenerator.generateMessageId)("system"),
389
401
  role: "system",
390
- content: `\u{1F504} Switching to ${displayName || model} (${provider})...`,
402
+ content: `\u{1F504} Switching to ${displayName || model} (${providerLabel})...`,
391
403
  timestamp: /* @__PURE__ */ new Date()
392
404
  }
393
405
  ]);
@@ -400,20 +412,24 @@ const OverlayContainer = (0, import_react.forwardRef)(
400
412
  },
401
413
  session.id || void 0
402
414
  );
403
- await persistRecentModel(provider, model);
415
+ await persistRecentModel(provider, model, baseURL);
404
416
  setSession((prev) => ({ ...prev, modelName: displayName || model }));
405
417
  setMessages((prev) => [
406
418
  ...prev,
407
419
  {
408
420
  id: (0, import_idGenerator.generateMessageId)("system"),
409
421
  role: "system",
410
- content: `\u2705 Successfully switched to ${displayName || model} (${provider})`,
422
+ content: `\u2705 Successfully switched to ${displayName || model} (${providerLabel})`,
411
423
  timestamp: /* @__PURE__ */ new Date()
412
424
  }
413
425
  ]);
414
426
  } catch (error) {
415
427
  const missingProvider = isApiKeyMissingError(error);
416
428
  if (missingProvider) {
429
+ const missingProviderLabel = (0, import_llm_provider_display.getLLMProviderDisplayName)(
430
+ missingProvider,
431
+ missingProvider === provider ? baseURL : void 0
432
+ );
417
433
  setUi((prev) => ({
418
434
  ...prev,
419
435
  activeOverlay: "api-key-input",
@@ -430,7 +446,7 @@ const OverlayContainer = (0, import_react.forwardRef)(
430
446
  {
431
447
  id: (0, import_idGenerator.generateMessageId)("system"),
432
448
  role: "system",
433
- content: `\u{1F511} API key required for ${provider}`,
449
+ content: `\u{1F511} API key required for ${missingProviderLabel}`,
434
450
  timestamp: /* @__PURE__ */ new Date()
435
451
  }
436
452
  ]);
@@ -460,6 +476,7 @@ const OverlayContainer = (0, import_react.forwardRef)(
460
476
  );
461
477
  const handleSetDefaultModel = (0, import_react.useCallback)(
462
478
  async (provider, model, displayName, baseURL, reasoningVariant) => {
479
+ const providerLabel = (0, import_llm_provider_display.getLLMProviderDisplayName)(provider, baseURL);
463
480
  try {
464
481
  let providerEnvVar;
465
482
  try {
@@ -511,20 +528,24 @@ const OverlayContainer = (0, import_react.forwardRef)(
511
528
  },
512
529
  session.id || void 0
513
530
  );
514
- await persistRecentModel(provider, model);
531
+ await persistRecentModel(provider, model, baseURL);
515
532
  setSession((prev) => ({ ...prev, modelName: displayName || model }));
516
533
  setMessages((prev) => [
517
534
  ...prev,
518
535
  {
519
536
  id: (0, import_idGenerator.generateMessageId)("system"),
520
537
  role: "system",
521
- content: `\u2705 Default model set to ${displayName || model} (${provider})`,
538
+ content: `\u2705 Default model set to ${displayName || model} (${providerLabel})`,
522
539
  timestamp: /* @__PURE__ */ new Date()
523
540
  }
524
541
  ]);
525
542
  } catch (error) {
526
543
  const missingProvider = isApiKeyMissingError(error);
527
544
  if (missingProvider) {
545
+ const missingProviderLabel = (0, import_llm_provider_display.getLLMProviderDisplayName)(
546
+ missingProvider,
547
+ missingProvider === provider ? baseURL : void 0
548
+ );
528
549
  setUi((prev) => ({
529
550
  ...prev,
530
551
  activeOverlay: "api-key-input",
@@ -541,7 +562,7 @@ const OverlayContainer = (0, import_react.forwardRef)(
541
562
  {
542
563
  id: (0, import_idGenerator.generateMessageId)("system"),
543
564
  role: "system",
544
- content: `\u{1F511} API key required for ${provider}`,
565
+ content: `\u{1F511} API key required for ${missingProviderLabel}`,
545
566
  timestamp: /* @__PURE__ */ new Date()
546
567
  }
547
568
  ]);
@@ -612,6 +633,51 @@ const OverlayContainer = (0, import_react.forwardRef)(
612
633
  },
613
634
  [setUi, setInput, setMessages, buffer, editingModel, handleModelSelect]
614
635
  );
636
+ const handleChatGPTUsageCapClose = (0, import_react.useCallback)(() => {
637
+ setUi((prev) => ({
638
+ ...prev,
639
+ activeOverlay: "none"
640
+ }));
641
+ }, [setUi]);
642
+ const handleChatGPTUsageCapConfirm = (0, import_react.useCallback)(async () => {
643
+ const currentLLMConfig2 = session.id ? agent.getCurrentLLMConfig(session.id) : agent.getCurrentLLMConfig();
644
+ const fallbackTarget = (0, import_chatgpt_rate_limit.resolveChatGPTFallbackModel)(currentLLMConfig2.model);
645
+ const providerKeyStatus = (0, import_agent_management.getProviderKeyStatus)(fallbackTarget.provider);
646
+ const reasoningVariant = fallbackTarget.usedDefaultFallback ? void 0 : currentLLMConfig2.reasoning?.variant;
647
+ if (providerKeyStatus.hasApiKey) {
648
+ setUi((prev) => ({
649
+ ...prev,
650
+ activeOverlay: "none"
651
+ }));
652
+ await handleModelSelect(
653
+ fallbackTarget.provider,
654
+ fallbackTarget.model,
655
+ fallbackTarget.displayName,
656
+ void 0,
657
+ reasoningVariant
658
+ );
659
+ return;
660
+ }
661
+ setUi((prev) => ({
662
+ ...prev,
663
+ activeOverlay: "api-key-input",
664
+ pendingModelSwitch: {
665
+ provider: fallbackTarget.provider,
666
+ model: fallbackTarget.model,
667
+ displayName: fallbackTarget.displayName,
668
+ ...reasoningVariant !== void 0 ? { reasoningVariant } : {}
669
+ }
670
+ }));
671
+ setMessages((prev) => [
672
+ ...prev,
673
+ {
674
+ id: (0, import_idGenerator.generateMessageId)("system"),
675
+ role: "system",
676
+ content: "\u{1F511} ChatGPT Login hit its usage cap. Add an OpenAI API key to continue with the API provider.",
677
+ timestamp: /* @__PURE__ */ new Date()
678
+ }
679
+ ]);
680
+ }, [agent, handleModelSelect, session.id, setMessages, setUi]);
615
681
  const handleApiKeySaved = (0, import_react.useCallback)(
616
682
  async (meta) => {
617
683
  const pending = ui.pendingModelSwitch;
@@ -639,12 +705,16 @@ const OverlayContainer = (0, import_react.forwardRef)(
639
705
  ]);
640
706
  try {
641
707
  const pendingDisplayName = pending.displayName || pending.model;
708
+ const pendingProviderLabel = (0, import_llm_provider_display.getLLMProviderDisplayName)(
709
+ pending.provider,
710
+ pending.baseURL
711
+ );
642
712
  setMessages((prev) => [
643
713
  ...prev,
644
714
  {
645
715
  id: (0, import_idGenerator.generateMessageId)("system"),
646
716
  role: "system",
647
- content: `\u{1F504} Retrying switch to ${pendingDisplayName} (${pending.provider})...`,
717
+ content: `\u{1F504} Retrying switch to ${pendingDisplayName} (${pendingProviderLabel})...`,
648
718
  timestamp: /* @__PURE__ */ new Date()
649
719
  }
650
720
  ]);
@@ -661,14 +731,18 @@ const OverlayContainer = (0, import_react.forwardRef)(
661
731
  },
662
732
  session.id || void 0
663
733
  );
664
- await persistRecentModel(pending.provider, pending.model);
734
+ await persistRecentModel(
735
+ pending.provider,
736
+ pending.model,
737
+ pending.baseURL
738
+ );
665
739
  setSession((prev) => ({ ...prev, modelName: pendingDisplayName }));
666
740
  setMessages((prev) => [
667
741
  ...prev,
668
742
  {
669
743
  id: (0, import_idGenerator.generateMessageId)("system"),
670
744
  role: "system",
671
- content: `\u2705 Successfully switched to ${pendingDisplayName} (${pending.provider})`,
745
+ content: `\u2705 Successfully switched to ${pendingDisplayName} (${pendingProviderLabel})`,
672
746
  timestamp: /* @__PURE__ */ new Date()
673
747
  }
674
748
  ]);
@@ -2033,6 +2107,9 @@ Use /${data.name} to run it.`,
2033
2107
  const handleSessionRenameClose = (0, import_react.useCallback)(() => {
2034
2108
  setUi((prev) => ({ ...prev, activeOverlay: "none" }));
2035
2109
  }, [setUi]);
2110
+ const currentLLMConfig = session.id ? agent.getCurrentLLMConfig(session.id) : agent.getCurrentLLMConfig();
2111
+ const chatGPTFallbackTarget = (0, import_chatgpt_rate_limit.resolveChatGPTFallbackModel)(currentLLMConfig.model);
2112
+ const chatGPTFallbackKeyStatus = (0, import_agent_management.getProviderKeyStatus)(chatGPTFallbackTarget.provider);
2036
2113
  const hideCliChrome = (0, import_overlayPresentation.shouldHideCliChrome)(ui.activeOverlay, approval);
2037
2114
  const overlayContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2038
2115
  approval && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -2288,6 +2365,20 @@ Use /${data.name} to run it.`,
2288
2365
  onClose: handleClose
2289
2366
  }
2290
2367
  ) }),
2368
+ ui.activeOverlay === "chatgpt-usage-cap" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2369
+ import_ChatGPTUsageCapOverlay.default,
2370
+ {
2371
+ ref: chatGPTUsageCapRef,
2372
+ isVisible: true,
2373
+ currentModelDisplayName: session.modelName,
2374
+ fallbackModelDisplayName: chatGPTFallbackTarget.displayName,
2375
+ usedDefaultFallback: chatGPTFallbackTarget.usedDefaultFallback,
2376
+ apiKeyConfigured: chatGPTFallbackKeyStatus.hasApiKey,
2377
+ status: ui.chatgptRateLimitStatus,
2378
+ onConfirm: handleChatGPTUsageCapConfirm,
2379
+ onClose: handleChatGPTUsageCapClose
2380
+ }
2381
+ ) }),
2291
2382
  ui.activeOverlay === "login" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2292
2383
  import_LoginOverlay.default,
2293
2384
  {
@@ -1 +1 @@
1
- {"version":3,"file":"OverlayContainer.d.ts","sourceRoot":"","sources":["../../src/containers/OverlayContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAyE,MAAM,OAAO,CAAC;AAG9F,OAAO,KAAK,EAAE,UAAU,EAAmD,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAGH,KAAK,eAAe,EACvB,MAAM,iCAAiC,CAAC;AAuIzC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAsC3D,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,qBAAqB;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,mDAAmD;IACnD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,sGA6vF5B,CAAC"}
1
+ {"version":3,"file":"OverlayContainer.d.ts","sourceRoot":"","sources":["../../src/containers/OverlayContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAyE,MAAM,OAAO,CAAC;AAG9F,OAAO,KAAK,EAAE,UAAU,EAAmD,MAAM,aAAa,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAGH,KAAK,eAAe,EACvB,MAAM,iCAAiC,CAAC;AA4IzC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAsC3D,MAAM,WAAW,sBAAsB;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED,UAAU,qBAAqB;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,mDAAmD;IACnD,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,4EAA4E;IAC5E,qBAAqB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,sGAy2F5B,CAAC"}
@@ -30,6 +30,9 @@ import SessionSubcommandSelector from "../components/overlays/SessionSubcommandS
30
30
  import McpCustomTypeSelector from "../components/overlays/McpCustomTypeSelector.js";
31
31
  import McpCustomWizard from "../components/overlays/McpCustomWizard.js";
32
32
  import CustomModelWizard from "../components/overlays/CustomModelWizard.js";
33
+ import ChatGPTUsageCapOverlay from "../components/overlays/ChatGPTUsageCapOverlay.js";
34
+ import { getLLMProviderDisplayName } from "../utils/llm-provider-display.js";
35
+ import { resolveChatGPTFallbackModel } from "../utils/chatgpt-rate-limit.js";
33
36
  import {
34
37
  getProviderKeyStatus,
35
38
  loadGlobalPreferences,
@@ -124,6 +127,7 @@ const OverlayContainer = forwardRef(
124
127
  const mcpCustomWizardRef = useRef(null);
125
128
  const customModelWizardRef = useRef(null);
126
129
  const sessionSubcommandSelectorRef = useRef(null);
130
+ const chatGPTUsageCapRef = useRef(null);
127
131
  const apiKeyInputRef = useRef(null);
128
132
  const loginOverlayRef = useRef(null);
129
133
  const logoutOverlayRef = useRef(null);
@@ -203,6 +207,8 @@ const OverlayContainer = forwardRef(
203
207
  return customModelWizardRef.current?.handleInput(inputStr, key) ?? false;
204
208
  case "session-subcommand-selector":
205
209
  return sessionSubcommandSelectorRef.current?.handleInput(inputStr, key) ?? false;
210
+ case "chatgpt-usage-cap":
211
+ return chatGPTUsageCapRef.current?.handleInput(inputStr, key) ?? false;
206
212
  case "api-key-input":
207
213
  return apiKeyInputRef.current?.handleInput(inputStr, key) ?? false;
208
214
  case "login":
@@ -323,12 +329,17 @@ const OverlayContainer = forwardRef(
323
329
  return null;
324
330
  };
325
331
  const persistRecentModel = useCallback(
326
- async (provider, model) => {
332
+ async (provider, model, baseURL) => {
327
333
  try {
328
- await recordRecentModel({ provider, model });
334
+ await recordRecentModel({
335
+ provider,
336
+ model,
337
+ ...baseURL ? { baseURL } : {}
338
+ });
329
339
  } catch (error) {
340
+ const modelKey = baseURL ? `${provider}/${model} (${baseURL})` : `${provider}/${model}`;
330
341
  agent.logger.debug(
331
- `Failed to persist recent model (${provider}/${model}): ${error instanceof Error ? error.message : String(error)}`
342
+ `Failed to persist recent model (${modelKey}): ${error instanceof Error ? error.message : String(error)}`
332
343
  );
333
344
  }
334
345
  },
@@ -336,6 +347,7 @@ const OverlayContainer = forwardRef(
336
347
  );
337
348
  const handleModelSelect = useCallback(
338
349
  async (provider, model, displayName, baseURL, reasoningVariant) => {
350
+ const providerLabel = getLLMProviderDisplayName(provider, baseURL);
339
351
  if (provider === "dexto-nova") {
340
352
  try {
341
353
  const canUse = await canUseDextoProvider();
@@ -373,7 +385,7 @@ const OverlayContainer = forwardRef(
373
385
  {
374
386
  id: generateMessageId("system"),
375
387
  role: "system",
376
- content: `\u{1F504} Switching to ${displayName || model} (${provider})...`,
388
+ content: `\u{1F504} Switching to ${displayName || model} (${providerLabel})...`,
377
389
  timestamp: /* @__PURE__ */ new Date()
378
390
  }
379
391
  ]);
@@ -386,20 +398,24 @@ const OverlayContainer = forwardRef(
386
398
  },
387
399
  session.id || void 0
388
400
  );
389
- await persistRecentModel(provider, model);
401
+ await persistRecentModel(provider, model, baseURL);
390
402
  setSession((prev) => ({ ...prev, modelName: displayName || model }));
391
403
  setMessages((prev) => [
392
404
  ...prev,
393
405
  {
394
406
  id: generateMessageId("system"),
395
407
  role: "system",
396
- content: `\u2705 Successfully switched to ${displayName || model} (${provider})`,
408
+ content: `\u2705 Successfully switched to ${displayName || model} (${providerLabel})`,
397
409
  timestamp: /* @__PURE__ */ new Date()
398
410
  }
399
411
  ]);
400
412
  } catch (error) {
401
413
  const missingProvider = isApiKeyMissingError(error);
402
414
  if (missingProvider) {
415
+ const missingProviderLabel = getLLMProviderDisplayName(
416
+ missingProvider,
417
+ missingProvider === provider ? baseURL : void 0
418
+ );
403
419
  setUi((prev) => ({
404
420
  ...prev,
405
421
  activeOverlay: "api-key-input",
@@ -416,7 +432,7 @@ const OverlayContainer = forwardRef(
416
432
  {
417
433
  id: generateMessageId("system"),
418
434
  role: "system",
419
- content: `\u{1F511} API key required for ${provider}`,
435
+ content: `\u{1F511} API key required for ${missingProviderLabel}`,
420
436
  timestamp: /* @__PURE__ */ new Date()
421
437
  }
422
438
  ]);
@@ -446,6 +462,7 @@ const OverlayContainer = forwardRef(
446
462
  );
447
463
  const handleSetDefaultModel = useCallback(
448
464
  async (provider, model, displayName, baseURL, reasoningVariant) => {
465
+ const providerLabel = getLLMProviderDisplayName(provider, baseURL);
449
466
  try {
450
467
  let providerEnvVar;
451
468
  try {
@@ -497,20 +514,24 @@ const OverlayContainer = forwardRef(
497
514
  },
498
515
  session.id || void 0
499
516
  );
500
- await persistRecentModel(provider, model);
517
+ await persistRecentModel(provider, model, baseURL);
501
518
  setSession((prev) => ({ ...prev, modelName: displayName || model }));
502
519
  setMessages((prev) => [
503
520
  ...prev,
504
521
  {
505
522
  id: generateMessageId("system"),
506
523
  role: "system",
507
- content: `\u2705 Default model set to ${displayName || model} (${provider})`,
524
+ content: `\u2705 Default model set to ${displayName || model} (${providerLabel})`,
508
525
  timestamp: /* @__PURE__ */ new Date()
509
526
  }
510
527
  ]);
511
528
  } catch (error) {
512
529
  const missingProvider = isApiKeyMissingError(error);
513
530
  if (missingProvider) {
531
+ const missingProviderLabel = getLLMProviderDisplayName(
532
+ missingProvider,
533
+ missingProvider === provider ? baseURL : void 0
534
+ );
514
535
  setUi((prev) => ({
515
536
  ...prev,
516
537
  activeOverlay: "api-key-input",
@@ -527,7 +548,7 @@ const OverlayContainer = forwardRef(
527
548
  {
528
549
  id: generateMessageId("system"),
529
550
  role: "system",
530
- content: `\u{1F511} API key required for ${provider}`,
551
+ content: `\u{1F511} API key required for ${missingProviderLabel}`,
531
552
  timestamp: /* @__PURE__ */ new Date()
532
553
  }
533
554
  ]);
@@ -598,6 +619,51 @@ const OverlayContainer = forwardRef(
598
619
  },
599
620
  [setUi, setInput, setMessages, buffer, editingModel, handleModelSelect]
600
621
  );
622
+ const handleChatGPTUsageCapClose = useCallback(() => {
623
+ setUi((prev) => ({
624
+ ...prev,
625
+ activeOverlay: "none"
626
+ }));
627
+ }, [setUi]);
628
+ const handleChatGPTUsageCapConfirm = useCallback(async () => {
629
+ const currentLLMConfig2 = session.id ? agent.getCurrentLLMConfig(session.id) : agent.getCurrentLLMConfig();
630
+ const fallbackTarget = resolveChatGPTFallbackModel(currentLLMConfig2.model);
631
+ const providerKeyStatus = getProviderKeyStatus(fallbackTarget.provider);
632
+ const reasoningVariant = fallbackTarget.usedDefaultFallback ? void 0 : currentLLMConfig2.reasoning?.variant;
633
+ if (providerKeyStatus.hasApiKey) {
634
+ setUi((prev) => ({
635
+ ...prev,
636
+ activeOverlay: "none"
637
+ }));
638
+ await handleModelSelect(
639
+ fallbackTarget.provider,
640
+ fallbackTarget.model,
641
+ fallbackTarget.displayName,
642
+ void 0,
643
+ reasoningVariant
644
+ );
645
+ return;
646
+ }
647
+ setUi((prev) => ({
648
+ ...prev,
649
+ activeOverlay: "api-key-input",
650
+ pendingModelSwitch: {
651
+ provider: fallbackTarget.provider,
652
+ model: fallbackTarget.model,
653
+ displayName: fallbackTarget.displayName,
654
+ ...reasoningVariant !== void 0 ? { reasoningVariant } : {}
655
+ }
656
+ }));
657
+ setMessages((prev) => [
658
+ ...prev,
659
+ {
660
+ id: generateMessageId("system"),
661
+ role: "system",
662
+ content: "\u{1F511} ChatGPT Login hit its usage cap. Add an OpenAI API key to continue with the API provider.",
663
+ timestamp: /* @__PURE__ */ new Date()
664
+ }
665
+ ]);
666
+ }, [agent, handleModelSelect, session.id, setMessages, setUi]);
601
667
  const handleApiKeySaved = useCallback(
602
668
  async (meta) => {
603
669
  const pending = ui.pendingModelSwitch;
@@ -625,12 +691,16 @@ const OverlayContainer = forwardRef(
625
691
  ]);
626
692
  try {
627
693
  const pendingDisplayName = pending.displayName || pending.model;
694
+ const pendingProviderLabel = getLLMProviderDisplayName(
695
+ pending.provider,
696
+ pending.baseURL
697
+ );
628
698
  setMessages((prev) => [
629
699
  ...prev,
630
700
  {
631
701
  id: generateMessageId("system"),
632
702
  role: "system",
633
- content: `\u{1F504} Retrying switch to ${pendingDisplayName} (${pending.provider})...`,
703
+ content: `\u{1F504} Retrying switch to ${pendingDisplayName} (${pendingProviderLabel})...`,
634
704
  timestamp: /* @__PURE__ */ new Date()
635
705
  }
636
706
  ]);
@@ -647,14 +717,18 @@ const OverlayContainer = forwardRef(
647
717
  },
648
718
  session.id || void 0
649
719
  );
650
- await persistRecentModel(pending.provider, pending.model);
720
+ await persistRecentModel(
721
+ pending.provider,
722
+ pending.model,
723
+ pending.baseURL
724
+ );
651
725
  setSession((prev) => ({ ...prev, modelName: pendingDisplayName }));
652
726
  setMessages((prev) => [
653
727
  ...prev,
654
728
  {
655
729
  id: generateMessageId("system"),
656
730
  role: "system",
657
- content: `\u2705 Successfully switched to ${pendingDisplayName} (${pending.provider})`,
731
+ content: `\u2705 Successfully switched to ${pendingDisplayName} (${pendingProviderLabel})`,
658
732
  timestamp: /* @__PURE__ */ new Date()
659
733
  }
660
734
  ]);
@@ -2019,6 +2093,9 @@ Use /${data.name} to run it.`,
2019
2093
  const handleSessionRenameClose = useCallback(() => {
2020
2094
  setUi((prev) => ({ ...prev, activeOverlay: "none" }));
2021
2095
  }, [setUi]);
2096
+ const currentLLMConfig = session.id ? agent.getCurrentLLMConfig(session.id) : agent.getCurrentLLMConfig();
2097
+ const chatGPTFallbackTarget = resolveChatGPTFallbackModel(currentLLMConfig.model);
2098
+ const chatGPTFallbackKeyStatus = getProviderKeyStatus(chatGPTFallbackTarget.provider);
2022
2099
  const hideCliChrome = shouldHideCliChrome(ui.activeOverlay, approval);
2023
2100
  const overlayContent = /* @__PURE__ */ jsxs(Fragment, { children: [
2024
2101
  approval && /* @__PURE__ */ jsx(
@@ -2274,6 +2351,20 @@ Use /${data.name} to run it.`,
2274
2351
  onClose: handleClose
2275
2352
  }
2276
2353
  ) }),
2354
+ ui.activeOverlay === "chatgpt-usage-cap" && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
2355
+ ChatGPTUsageCapOverlay,
2356
+ {
2357
+ ref: chatGPTUsageCapRef,
2358
+ isVisible: true,
2359
+ currentModelDisplayName: session.modelName,
2360
+ fallbackModelDisplayName: chatGPTFallbackTarget.displayName,
2361
+ usedDefaultFallback: chatGPTFallbackTarget.usedDefaultFallback,
2362
+ apiKeyConfigured: chatGPTFallbackKeyStatus.hasApiKey,
2363
+ status: ui.chatgptRateLimitStatus,
2364
+ onConfirm: handleChatGPTUsageCapConfirm,
2365
+ onClose: handleChatGPTUsageCapClose
2366
+ }
2367
+ ) }),
2277
2368
  ui.activeOverlay === "login" && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(
2278
2369
  LoginOverlay,
2279
2370
  {
@@ -58,6 +58,28 @@ function useAgentEvents({
58
58
  )
59
59
  }));
60
60
  }
61
+ const nextIsChatGPTLogin = payload.newConfig?.provider === "openai-compatible" && (0, import_core.parseCodexBaseURL)(payload.newConfig?.baseURL)?.authMode === "chatgpt";
62
+ if (!nextIsChatGPTLogin) {
63
+ setUi((prev) => ({
64
+ ...prev,
65
+ chatgptRateLimitStatus: null,
66
+ ...prev.activeOverlay === "chatgpt-usage-cap" ? { activeOverlay: "none" } : {}
67
+ }));
68
+ }
69
+ },
70
+ { signal }
71
+ );
72
+ agent.on(
73
+ "llm:rate-limit-status",
74
+ (payload) => {
75
+ if (payload.sessionId !== currentSessionId) {
76
+ return;
77
+ }
78
+ setUi((prev) => ({
79
+ ...prev,
80
+ chatgptRateLimitStatus: payload.snapshot,
81
+ ...payload.snapshot.exceeded && prev.activeOverlay === "none" ? { activeOverlay: "chatgpt-usage-cap" } : {}
82
+ }));
61
83
  },
62
84
  { signal }
63
85
  );
@@ -142,7 +164,11 @@ function useAgentEvents({
142
164
  setApproval(null);
143
165
  setApprovalQueue([]);
144
166
  setQueuedMessages([]);
145
- setUi((prev) => ({ ...prev, activeOverlay: "none" }));
167
+ setUi((prev) => ({
168
+ ...prev,
169
+ activeOverlay: "none",
170
+ chatgptRateLimitStatus: null
171
+ }));
146
172
  },
147
173
  { signal }
148
174
  );
@@ -181,6 +207,7 @@ function useAgentEvents({
181
207
  setUi((prev) => ({
182
208
  ...prev,
183
209
  activeOverlay: "none",
210
+ chatgptRateLimitStatus: null,
184
211
  historySearch: {
185
212
  isActive: false,
186
213
  query: "",
@@ -199,7 +226,11 @@ function useAgentEvents({
199
226
  setApproval(null);
200
227
  setApprovalQueue([]);
201
228
  setQueuedMessages([]);
202
- setUi((prev) => ({ ...prev, activeOverlay: "none" }));
229
+ setUi((prev) => ({
230
+ ...prev,
231
+ activeOverlay: "none",
232
+ chatgptRateLimitStatus: null
233
+ }));
203
234
  },
204
235
  { signal }
205
236
  );
@@ -1 +1 @@
1
- {"version":3,"file":"useAgentEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useAgentEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAEH,KAAK,UAAU,EACf,KAAK,aAAa,EAErB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAEtE,UAAU,mBAAmB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,iFAAiF;IACjF,MAAM,EAAE,UAAU,CAAC;CACtB;AAYD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,GACT,EAAE,mBAAmB,GAAG,IAAI,CA6d5B"}
1
+ {"version":3,"file":"useAgentEvents.d.ts","sourceRoot":"","sources":["../../src/hooks/useAgentEvents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAGH,KAAK,UAAU,EACf,KAAK,aAAa,EAErB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAEvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAEtE,UAAU,mBAAmB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7D,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpE,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/D,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAC3D,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IAC1E,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAC1E,iBAAiB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACzE,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,iFAAiF;IACjF,MAAM,EAAE,UAAU,CAAC;CACtB;AAYD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,kBAAkB,EAClB,KAAK,EACL,UAAU,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,GACT,EAAE,mBAAmB,GAAG,IAAI,CAsgB5B"}
@@ -1,7 +1,8 @@
1
1
  import { useEffect, useRef } from "react";
2
2
  import { setMaxListeners } from "events";
3
3
  import {
4
- getModelDisplayName
4
+ getModelDisplayName,
5
+ parseCodexBaseURL
5
6
  } from "@dexto/core";
6
7
  import { generateMessageId } from "../utils/idGenerator.js";
7
8
  function extractTextContent(content) {
@@ -37,6 +38,28 @@ function useAgentEvents({
37
38
  )
38
39
  }));
39
40
  }
41
+ const nextIsChatGPTLogin = payload.newConfig?.provider === "openai-compatible" && parseCodexBaseURL(payload.newConfig?.baseURL)?.authMode === "chatgpt";
42
+ if (!nextIsChatGPTLogin) {
43
+ setUi((prev) => ({
44
+ ...prev,
45
+ chatgptRateLimitStatus: null,
46
+ ...prev.activeOverlay === "chatgpt-usage-cap" ? { activeOverlay: "none" } : {}
47
+ }));
48
+ }
49
+ },
50
+ { signal }
51
+ );
52
+ agent.on(
53
+ "llm:rate-limit-status",
54
+ (payload) => {
55
+ if (payload.sessionId !== currentSessionId) {
56
+ return;
57
+ }
58
+ setUi((prev) => ({
59
+ ...prev,
60
+ chatgptRateLimitStatus: payload.snapshot,
61
+ ...payload.snapshot.exceeded && prev.activeOverlay === "none" ? { activeOverlay: "chatgpt-usage-cap" } : {}
62
+ }));
40
63
  },
41
64
  { signal }
42
65
  );
@@ -121,7 +144,11 @@ function useAgentEvents({
121
144
  setApproval(null);
122
145
  setApprovalQueue([]);
123
146
  setQueuedMessages([]);
124
- setUi((prev) => ({ ...prev, activeOverlay: "none" }));
147
+ setUi((prev) => ({
148
+ ...prev,
149
+ activeOverlay: "none",
150
+ chatgptRateLimitStatus: null
151
+ }));
125
152
  },
126
153
  { signal }
127
154
  );
@@ -160,6 +187,7 @@ function useAgentEvents({
160
187
  setUi((prev) => ({
161
188
  ...prev,
162
189
  activeOverlay: "none",
190
+ chatgptRateLimitStatus: null,
163
191
  historySearch: {
164
192
  isActive: false,
165
193
  query: "",
@@ -178,7 +206,11 @@ function useAgentEvents({
178
206
  setApproval(null);
179
207
  setApprovalQueue([]);
180
208
  setQueuedMessages([]);
181
- setUi((prev) => ({ ...prev, activeOverlay: "none" }));
209
+ setUi((prev) => ({
210
+ ...prev,
211
+ activeOverlay: "none",
212
+ chatgptRateLimitStatus: null
213
+ }));
182
214
  },
183
215
  { signal }
184
216
  );