@karlorz/codexhost-cli-win32-x64 0.13.3-0 → 0.13.3-3

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.
@@ -18807,6 +18807,14 @@ ${error51.stderrTail}`] : []
18807
18807
  otherSection: "Other",
18808
18808
  appearanceDescription: "Conversation display and local resource management.",
18809
18809
  appearanceGroup: "Appearance",
18810
+ hideCodexUsageBannerTitle: "Hide Codex usage warning",
18811
+ hideCodexUsageBannerDescription: "On by default. Hide the out-of-usage card on every Composer.",
18812
+ hideCodexUsageBannerHelpLabel: "About hiding the Codex usage warning",
18813
+ hideCodexUsageBannerHelp: Object.freeze([
18814
+ "The native card appears when the signed-in ChatGPT Codex quota is exhausted.",
18815
+ "When this is on, that card is hidden on every Composer, including Codex threads. Reset usage and Upgrade stay available in Settings.",
18816
+ "Turning this off only shows the native card again. Send on this Composer, including Codex threads, is already separated from that quota card."
18817
+ ]),
18810
18818
  cpaLiveVoiceTitle: "Override live voice",
18811
18819
  cpaLiveVoiceDescription: "On by default. Host creates the realtime call instead of ChatGPT.",
18812
18820
  cpaLiveVoiceHelpLabel: "About overriding live voice",
@@ -19090,6 +19098,14 @@ ${error51.stderrTail}`] : []
19090
19098
  otherSection: "\u5176\u4ED6",
19091
19099
  appearanceDescription: "\u4F1A\u8BDD\u663E\u793A\u4E0E\u672C\u5730\u8D44\u6E90\u7BA1\u7406\u3002",
19092
19100
  appearanceGroup: "\u5916\u89C2",
19101
+ hideCodexUsageBannerTitle: "\u9690\u85CF Codex \u989D\u5EA6\u8B66\u544A",
19102
+ hideCodexUsageBannerDescription: "\u9ED8\u8BA4\u5F00\u542F\u3002\u5728\u6240\u6709 Composer \u4E0A\u9690\u85CF\u989D\u5EA6\u8017\u5C3D\u5361\u7247\u3002",
19103
+ hideCodexUsageBannerHelpLabel: "\u9690\u85CF Codex \u989D\u5EA6\u8B66\u544A\u8BF4\u660E",
19104
+ hideCodexUsageBannerHelp: Object.freeze([
19105
+ "\u5DF2\u767B\u5F55\u7684 ChatGPT Codex \u989D\u5EA6\u8017\u5C3D\u65F6\uFF0CDesktop \u4F1A\u663E\u793A\u539F\u751F\u8B66\u544A\u5361\u7247\u3002",
19106
+ "\u5F00\u542F\u540E\uFF0C\u6240\u6709 Composer \u90FD\u9690\u85CF\u8BE5\u5361\u7247\uFF0C\u5305\u62EC Codex \u4F1A\u8BDD\u3002\u300C\u91CD\u7F6E\u7528\u91CF\u300D\u548C\u300C\u5347\u7EA7\u300D\u4ECD\u53EF\u5728\u8BBE\u7F6E\u4E2D\u4F7F\u7528\u3002",
19107
+ "\u5173\u95ED\u6B64\u5F00\u5173\u53EA\u4F1A\u91CD\u65B0\u663E\u793A\u539F\u751F\u5361\u7247\u3002\u5F53\u524D Composer \u7684\u53D1\u9001\uFF08\u5305\u62EC Codex \u4F1A\u8BDD\uFF09\u5DF2\u4E0E\u8BE5\u989D\u5EA6\u5361\u7247\u5206\u79BB\u3002"
19108
+ ]),
19093
19109
  cpaLiveVoiceTitle: "\u6539\u5199\u5B9E\u65F6\u8BED\u97F3",
19094
19110
  cpaLiveVoiceDescription: "\u9ED8\u8BA4\u5F00\u542F\u3002\u7531 Host \u521B\u5EFA realtime \u901A\u8BDD\uFF0C\u800C\u4E0D\u662F ChatGPT\u3002",
19095
19111
  cpaLiveVoiceHelpLabel: "\u6539\u5199\u5B9E\u65F6\u8BED\u97F3\u8BF4\u660E",
@@ -22541,6 +22557,27 @@ Codex Fast mode prioritizes requests and may increase usage.`
22541
22557
  };
22542
22558
  }
22543
22559
 
22560
+ // src/renderer-codex-usage-banner-preference.ts
22561
+ var CODEX_USAGE_BANNER_STORAGE_KEY = "codexhost.codex-usage-banner-hidden.v1";
22562
+ var CODEX_USAGE_BANNER_CHANGE_EVENT = "codexhost:codex-usage-banner-changed";
22563
+ function readCodexUsageBannerPreference(owner) {
22564
+ if (!owner) return true;
22565
+ try {
22566
+ return owner.localStorage.getItem(CODEX_USAGE_BANNER_STORAGE_KEY) !== "0";
22567
+ } catch {
22568
+ return true;
22569
+ }
22570
+ }
22571
+ function writeCodexUsageBannerPreference(owner, enabled) {
22572
+ try {
22573
+ owner.localStorage.setItem(CODEX_USAGE_BANNER_STORAGE_KEY, enabled ? "1" : "0");
22574
+ } catch {
22575
+ return false;
22576
+ }
22577
+ owner.dispatchEvent(new Event(CODEX_USAGE_BANNER_CHANGE_EVENT));
22578
+ return true;
22579
+ }
22580
+
22544
22581
  // src/renderer-composer-dom.ts
22545
22582
  var CODEX_COMPOSER_SELECTOR = "[data-codex-composer-root]";
22546
22583
  var EDITOR_SELECTOR = 'textarea, [contenteditable="true"], [role="textbox"]';
@@ -22713,6 +22750,17 @@ Codex Fast mode prioritizes requests and may increase usage.`
22713
22750
  ].filter(isNativeContextUsageControlCandidate);
22714
22751
  return candidates.length === 1 ? candidates[0] ?? null : null;
22715
22752
  }
22753
+ function isNativeUsageBannerCandidate(element) {
22754
+ if (element.localName !== "aside") return false;
22755
+ if (typeof element.querySelector !== "function") return false;
22756
+ return element.querySelector("h3") !== null && element.querySelector("button") !== null;
22757
+ }
22758
+ function nativeUsageBannerForComposer(composer) {
22759
+ const candidates = [...composer.querySelectorAll("aside")].filter(
22760
+ isNativeUsageBannerCandidate
22761
+ );
22762
+ return candidates.length === 1 ? candidates[0] ?? null : null;
22763
+ }
22716
22764
  function captureNativeControl(element) {
22717
22765
  return element ? {
22718
22766
  element,
@@ -22734,6 +22782,12 @@ Codex Fast mode prioritizes requests and may increase usage.`
22734
22782
  restoreNativeControl(control.nativeContextUsageControl);
22735
22783
  control.nativeContextUsageControl = captureNativeControl(candidate);
22736
22784
  }
22785
+ function refreshNativeUsageBanner(control) {
22786
+ const candidate = nativeUsageBannerForComposer(control.composer);
22787
+ if (candidate === control.nativeUsageBanner?.element) return;
22788
+ restoreNativeControl(control.nativeUsageBanner);
22789
+ control.nativeUsageBanner = captureNativeControl(candidate);
22790
+ }
22737
22791
  function refreshNativeModelControl(control) {
22738
22792
  const candidate = nativeModelControlForComposer(control.composer);
22739
22793
  if (!candidate) return;
@@ -22852,12 +22906,20 @@ Codex Fast mode prioritizes requests and may increase usage.`
22852
22906
  refreshNativeContextUsageControl(control);
22853
22907
  refreshNativeModelControl(control);
22854
22908
  refreshNativePermissionModeControl(control);
22909
+ refreshNativeUsageBanner(control);
22855
22910
  refreshTrailingClusterPlacement(control);
22856
22911
  refreshUsagePlacement(control);
22857
22912
  refreshCreditsPlacement(control);
22858
22913
  setNativeControlHidden(control.nativeModelControl, hideModel);
22859
22914
  setNativeControlHidden(control.nativeContextUsageControl, false);
22860
22915
  setNativeControlHidden(control.nativePermissionModeControl, hidePermissionMode);
22916
+ setNativeControlHidden(
22917
+ control.nativeUsageBanner,
22918
+ readCodexUsageBannerPreference(preferenceOwner(control))
22919
+ );
22920
+ }
22921
+ function preferenceOwner(control) {
22922
+ return control.composer.ownerDocument?.defaultView ?? (typeof document !== "undefined" ? document.defaultView : null);
22861
22923
  }
22862
22924
  function mountComposerAgentControl(composer, composerId, sendButton, enabledAgents, onSelect, onDownload, onOpenProviderPicker, onSelectModel, onSelectThinking, onSelectPermissionMode, onOpenCommandMenu) {
22863
22925
  if (composer instanceof HTMLElement) composer.style.minWidth = "0";
@@ -22865,6 +22927,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
22865
22927
  const nativeContextUsageControl = captureNativeControl(
22866
22928
  nativeContextUsageControlForComposer(composer)
22867
22929
  );
22930
+ const nativeUsageBanner = captureNativeControl(nativeUsageBannerForComposer(composer));
22868
22931
  const semanticNativePermissionModeControl = semanticNativePermissionModeControlForComposer(composer);
22869
22932
  const nativePermissionModeControl = captureNativeControl(semanticNativePermissionModeControl);
22870
22933
  const nativePermissionModeControlVerified = semanticNativePermissionModeControl !== null && nativePermissionModeControlForComposer(composer) === semanticNativePermissionModeControl;
@@ -22925,6 +22988,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
22925
22988
  nativeModelControl,
22926
22989
  nativePermissionModeControl,
22927
22990
  nativeContextUsageControl,
22991
+ nativeUsageBanner,
22928
22992
  nativePermissionModeControlVerified,
22929
22993
  credits,
22930
22994
  usage: null,
@@ -22999,7 +23063,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
22999
23063
  control.harnessCommands.root.hidden = state.agent === "codex";
23000
23064
  control.harnessCommands.root.style.display = state.agent === "codex" ? "none" : "inline-flex";
23001
23065
  renderRendererCreditsControl(control.credits, accountCredits, locale);
23002
- return state.agent !== "codex" && adapterState === "ready" && !submissionBlocked;
23066
+ return !submissionBlocked && (state.agent === "codex" || adapterState === "ready");
23003
23067
  }
23004
23068
  function disposeComposerAgentControl(control) {
23005
23069
  if (control.sendDisabledBeforeSwitch !== null) {
@@ -23010,6 +23074,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
23010
23074
  }
23011
23075
  restoreNativeControl(control.nativeModelControl);
23012
23076
  restoreNativeControl(control.nativeContextUsageControl);
23077
+ restoreNativeControl(control.nativeUsageBanner);
23013
23078
  restoreNativeControl(control.nativePermissionModeControl);
23014
23079
  control.credits.dispose();
23015
23080
  control.usage?.dispose();
@@ -23460,8 +23525,10 @@ Codex Fast mode prioritizes requests and may increase usage.`
23460
23525
  };
23461
23526
  const apply = () => {
23462
23527
  const status = applyGate();
23463
- if (status === "bypassed" && owner) banner.hide(owner.owner);
23464
- else banner.restore();
23528
+ const ownerWindow = composer.ownerDocument?.defaultView ?? (typeof document !== "undefined" ? document.defaultView : null);
23529
+ if (status === "bypassed" && owner && readCodexUsageBannerPreference(ownerWindow)) {
23530
+ banner.hide(owner.owner);
23531
+ } else banner.restore();
23465
23532
  return status;
23466
23533
  };
23467
23534
  const applyGate = () => {
@@ -31028,6 +31095,31 @@ ${detail}` : ""}`
31028
31095
  description.className = "settings-page-description";
31029
31096
  description.textContent = messages.appearanceDescription;
31030
31097
  const { group, card } = createPreferenceGroup(document2, messages.appearanceGroup);
31098
+ const usageBannerId = preferenceId("hide-codex-usage-banner");
31099
+ const usageBannerRow = createPreferenceItem(document2, {
31100
+ title: messages.hideCodexUsageBannerTitle,
31101
+ description: messages.hideCodexUsageBannerDescription,
31102
+ controlId: usageBannerId,
31103
+ help: {
31104
+ label: messages.hideCodexUsageBannerHelpLabel,
31105
+ lines: messages.hideCodexUsageBannerHelp
31106
+ }
31107
+ });
31108
+ const usageBanner = createPreferenceSwitch(
31109
+ document2,
31110
+ usageBannerId,
31111
+ usageBannerRow.description.id
31112
+ );
31113
+ usageBanner.checked = readCodexUsageBannerPreference(ownerWindow);
31114
+ usageBanner.addEventListener("change", () => {
31115
+ writeCodexUsageBannerPreference(ownerWindow, usageBanner.checked);
31116
+ });
31117
+ const syncUsageBanner = () => {
31118
+ usageBanner.checked = readCodexUsageBannerPreference(ownerWindow);
31119
+ };
31120
+ ownerWindow.addEventListener(CODEX_USAGE_BANNER_CHANGE_EVENT, syncUsageBanner);
31121
+ usageBannerRow.item.append(usageBanner);
31122
+ card.append(usageBannerRow.item);
31031
31123
  const liveVoiceId = preferenceId("cpa-live-voice");
31032
31124
  const liveVoiceRow = createPreferenceItem(document2, {
31033
31125
  title: messages.cpaLiveVoiceTitle,
@@ -31077,6 +31169,7 @@ ${detail}` : ""}`
31077
31169
  getLoadedSessionsClient
31078
31170
  );
31079
31171
  return () => {
31172
+ ownerWindow.removeEventListener(CODEX_USAGE_BANNER_CHANGE_EVENT, syncUsageBanner);
31080
31173
  ownerWindow.removeEventListener(CPA_LIVE_VOICE_CHANGE_EVENT, syncLiveVoice);
31081
31174
  ownerWindow.removeEventListener(REASONING_SOFT_WRAP_CHANGE_EVENT, sync);
31082
31175
  disposeIdleRelease();
@@ -38177,6 +38270,101 @@ th[aria-sort] .console-usage-sort__mark {
38177
38270
  };
38178
38271
  }
38179
38272
 
38273
+ // src/settings/back-navigation.ts
38274
+ var NATIVE_BACK_SELECTOR = '[data-app-shell-titlebar] button[aria-label="Back"]';
38275
+ var SETTINGS_BACK_ATTRIBUTE = "data-codexhost-settings-back";
38276
+ function attachSettingsBackNavigation(ownerDocument, onBack) {
38277
+ const ownerWindow = ownerDocument.defaultView;
38278
+ let source = null;
38279
+ let button2 = null;
38280
+ let disposed = false;
38281
+ const onClick = (event) => {
38282
+ event.preventDefault();
38283
+ event.stopPropagation();
38284
+ onBack();
38285
+ };
38286
+ const place = () => {
38287
+ if (disposed) return;
38288
+ const nextSource = [...ownerDocument.querySelectorAll(NATIVE_BACK_SELECTOR)].find(
38289
+ (candidate) => {
38290
+ const bounds2 = candidate.getBoundingClientRect();
38291
+ const parent = candidate.parentElement;
38292
+ return bounds2.width > 0 && bounds2.height > 0 && !candidate.closest('[aria-hidden="true"]') && parent !== null && ownerWindow?.getComputedStyle(parent).visibility !== "hidden";
38293
+ }
38294
+ ) ?? null;
38295
+ if (nextSource !== source) {
38296
+ button2?.removeEventListener("click", onClick);
38297
+ button2?.remove();
38298
+ source = nextSource;
38299
+ button2 = source?.cloneNode(true);
38300
+ if (button2) {
38301
+ for (const element of [button2, ...button2.querySelectorAll("[id]")]) {
38302
+ element.removeAttribute("id");
38303
+ }
38304
+ for (const attribute of [
38305
+ "disabled",
38306
+ "aria-disabled",
38307
+ "data-disabled",
38308
+ "tabindex",
38309
+ "aria-describedby"
38310
+ ]) {
38311
+ button2.removeAttribute(attribute);
38312
+ }
38313
+ button2.setAttribute(SETTINGS_BACK_ATTRIBUTE, "");
38314
+ button2.title = source?.getAttribute("aria-label") ?? "Back";
38315
+ button2.style.position = "fixed";
38316
+ button2.style.zIndex = "41";
38317
+ button2.style.margin = "0";
38318
+ button2.style.setProperty("-webkit-app-region", "no-drag");
38319
+ button2.addEventListener("click", onClick);
38320
+ ownerDocument.body.append(button2);
38321
+ }
38322
+ }
38323
+ if (!source || !button2) return;
38324
+ const bounds = source.getBoundingClientRect();
38325
+ Object.assign(button2.style, {
38326
+ left: `${bounds.left}px`,
38327
+ top: `${bounds.top}px`,
38328
+ width: `${bounds.width}px`,
38329
+ height: `${bounds.height}px`
38330
+ });
38331
+ };
38332
+ const onKeyDown = (event) => {
38333
+ if (event.defaultPrevented || event.shiftKey) return;
38334
+ const macBack = event.metaKey && !event.ctrlKey && !event.altKey && event.key === "[";
38335
+ const altBack = event.altKey && !event.metaKey && !event.ctrlKey && event.key === "ArrowLeft";
38336
+ if (!macBack && !altBack) return;
38337
+ event.preventDefault();
38338
+ event.stopPropagation();
38339
+ onBack();
38340
+ };
38341
+ const style = ownerDocument.createElement("style");
38342
+ style.textContent = `${NATIVE_BACK_SELECTOR} { visibility: hidden !important; }`;
38343
+ ownerDocument.head.append(style);
38344
+ place();
38345
+ const observer = ownerWindow ? new ownerWindow.MutationObserver((records) => {
38346
+ const titlebar = source?.closest("[data-app-shell-titlebar]");
38347
+ if (!source?.isConnected || records.some((record5) => titlebar?.contains(record5.target))) {
38348
+ place();
38349
+ }
38350
+ }) : null;
38351
+ observer?.observe(ownerDocument.body, { childList: true, subtree: true });
38352
+ ownerWindow?.addEventListener("resize", place);
38353
+ ownerDocument.addEventListener("keydown", onKeyDown, true);
38354
+ return {
38355
+ dispose() {
38356
+ if (disposed) return;
38357
+ disposed = true;
38358
+ observer?.disconnect();
38359
+ ownerWindow?.removeEventListener("resize", place);
38360
+ ownerDocument.removeEventListener("keydown", onKeyDown, true);
38361
+ button2?.removeEventListener("click", onClick);
38362
+ button2?.remove();
38363
+ style.remove();
38364
+ }
38365
+ };
38366
+ }
38367
+
38180
38368
  // src/settings/rail-page.ts
38181
38369
  var NAVIGATION_RAIL_SELECTOR = "nav[data-app-navigation-rail]";
38182
38370
  var RAIL_DESTINATION_SELECTOR = "[data-sidebar-destination]";
@@ -38222,6 +38410,7 @@ nav[data-app-navigation-rail][${RAIL_OPEN_ATTRIBUTE}] ${RAIL_DESTINATION_SELECTO
38222
38410
  if (disposed) return;
38223
38411
  onNavigateAway();
38224
38412
  };
38413
+ const backNavigation = attachSettingsBackNavigation(ownerDocument, navigateAway);
38225
38414
  const checkNavigation = () => {
38226
38415
  if (disposed) return;
38227
38416
  const nextRail = findRail(ownerDocument);
@@ -38276,6 +38465,7 @@ nav[data-app-navigation-rail][${RAIL_OPEN_ATTRIBUTE}] ${RAIL_DESTINATION_SELECTO
38276
38465
  dispose() {
38277
38466
  if (disposed) return;
38278
38467
  disposed = true;
38468
+ backNavigation.dispose();
38279
38469
  railMutations?.disconnect();
38280
38470
  railResize?.disconnect();
38281
38471
  bodyMutations?.disconnect();
@@ -39820,7 +40010,7 @@ ${usage_default}`;
39820
40010
  const currentCodexAccount = accounts?.accounts.find(
39821
40011
  ({ accountId }) => accountId === accounts.readyAccountId
39822
40012
  );
39823
- const externalSubmissionReady = renderComposerAgentControl(
40013
+ const usageGateAllowed = renderComposerAgentControl(
39824
40014
  mounted.control,
39825
40015
  controller.get(mounted.composer),
39826
40016
  composerAdapterState(mounted),
@@ -39834,7 +40024,7 @@ ${usage_default}`;
39834
40024
  currentCodexAccount ?? null,
39835
40025
  mounted.ownershipStatus === "error"
39836
40026
  );
39837
- showCodexUsageGateStatus(mounted, mounted.codexUsageGate.update(externalSubmissionReady));
40027
+ showCodexUsageGateStatus(mounted, mounted.codexUsageGate.update(usageGateAllowed));
39838
40028
  if (mounted.control.usage) {
39839
40029
  mounted.control.usage.onOpen = () => {
39840
40030
  void refreshThreadUsage(
@@ -41539,10 +41729,24 @@ ${usage_default}`;
41539
41729
  }
41540
41730
  }
41541
41731
  };
41732
+ const onUsageBannerPreference = () => {
41733
+ for (const mounted of mountedByComposer.values()) {
41734
+ const hideCodexControls = controller.isSwitching(mounted.composer) || controller.get(mounted.composer).agent !== "codex";
41735
+ reconcileComposerNativeControls(mounted.control, hideCodexControls, hideCodexControls);
41736
+ mounted.codexUsageGate.refresh();
41737
+ }
41738
+ };
41739
+ const onUsageBannerStorage = (event) => {
41740
+ if (event.key === CODEX_USAGE_BANNER_STORAGE_KEY || event.key === null) {
41741
+ onUsageBannerPreference();
41742
+ }
41743
+ };
41542
41744
  window.addEventListener("codexhost:draft-prewarm-policy-changed", onHostRouteChange);
41543
41745
  window.addEventListener("codexhost:draft-workspace", onDraftWorkspace);
41544
41746
  window.addEventListener("codexhost:renderer-adapter-status", onAdapterStatus);
41545
41747
  window.addEventListener("focus", onWindowFocus);
41748
+ window.addEventListener(CODEX_USAGE_BANNER_CHANGE_EVENT, onUsageBannerPreference);
41749
+ window.addEventListener("storage", onUsageBannerStorage);
41546
41750
  delegationMention = installRendererDelegationMention(document, {
41547
41751
  onOpen: (editor) => {
41548
41752
  const composer = composerForElement(editor);
@@ -41706,6 +41910,8 @@ ${usage_default}`;
41706
41910
  window.removeEventListener("codexhost:draft-workspace", onDraftWorkspace);
41707
41911
  window.removeEventListener("codexhost:renderer-adapter-status", onAdapterStatus);
41708
41912
  window.removeEventListener("focus", onWindowFocus);
41913
+ window.removeEventListener(CODEX_USAGE_BANNER_CHANGE_EVENT, onUsageBannerPreference);
41914
+ window.removeEventListener("storage", onUsageBannerStorage);
41709
41915
  for (const state of harnessAvailabilityByHost.values()) {
41710
41916
  state.requestGeneration += 1;
41711
41917
  state.codexAccounts?.dispose();
package/bin/codexhost.exe CHANGED
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karlorz/codexhost-cli-win32-x64",
3
- "version": "0.13.3-0",
3
+ "version": "0.13.3-3",
4
4
  "description": "Run Pi and Claude Code as first-class external harnesses inside Codex Desktop.",
5
5
  "type": "module",
6
6
  "files": [