@codexhost/cli-win32-arm64 0.12.1 → 0.12.2

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.
@@ -71,6 +71,15 @@
71
71
  get(composer) {
72
72
  return this.#state(composer);
73
73
  }
74
+ /** Release the DOM identity while retaining configuration owned by a target.
75
+ * A cloud composer may reuse this element before a different native draft.
76
+ * A successful replacement transfer retains the shared submission marker.
77
+ */
78
+ detach(composer, preservePendingSubmission = false) {
79
+ const state = this.#states.get(composer);
80
+ if (state && !preservePendingSubmission) this.#pendingSubmissions.delete(state);
81
+ this.#states.delete(composer);
82
+ }
74
83
  mount(composer, target, preferredNewThreadAgent) {
75
84
  const bound = this.#targetState(target);
76
85
  if (bound) {
@@ -661,6 +670,111 @@
661
670
  return control;
662
671
  }
663
672
 
673
+ // ../desktop-control/dist/renderer-react-ownership.js
674
+ var REACT_FIBER_WALK_LIMIT_EVENT = "codexhost:react-fiber-walk-limit";
675
+ function committedReactAncestors(value) {
676
+ const MAX_VISITED_FIBERS = 2e5;
677
+ const fiber = (value2) => typeof value2 === "object" && value2 !== null ? value2 : null;
678
+ const exhausted = () => {
679
+ const target = globalThis;
680
+ if (typeof target.dispatchEvent === "function" && typeof CustomEvent === "function")
681
+ target.dispatchEvent(new CustomEvent("codexhost:react-fiber-walk-limit", {
682
+ detail: { limit: MAX_VISITED_FIBERS }
683
+ }));
684
+ return [];
685
+ };
686
+ const first = fiber(value);
687
+ if (!first)
688
+ return [];
689
+ const previous = [];
690
+ const seen = /* @__PURE__ */ new Set();
691
+ for (let node2 = first; node2; node2 = fiber(node2.return)) {
692
+ if (seen.has(node2))
693
+ return [];
694
+ if (seen.size >= MAX_VISITED_FIBERS)
695
+ return exhausted();
696
+ seen.add(node2);
697
+ previous.push(node2);
698
+ }
699
+ const rootState = fiber(previous.at(-1)?.stateNode);
700
+ if (!rootState || !("current" in rootState))
701
+ return previous;
702
+ const current = fiber(rootState.current);
703
+ if (!current)
704
+ return [];
705
+ const alternate = fiber(first.alternate);
706
+ const path = [current];
707
+ seen.clear();
708
+ seen.add(current);
709
+ for (let index = previous.length - 2; index >= 0; index -= 1) {
710
+ const expected = previous[index];
711
+ const expectedAlternate = fiber(expected?.alternate);
712
+ let child = fiber(path.at(-1)?.child);
713
+ let matched = false;
714
+ while (child && !seen.has(child) && seen.size < MAX_VISITED_FIBERS) {
715
+ seen.add(child);
716
+ if (child === expected || child === expectedAlternate) {
717
+ matched = true;
718
+ break;
719
+ }
720
+ child = fiber(child.sibling);
721
+ }
722
+ if (!matched || !child)
723
+ break;
724
+ path.push(child);
725
+ }
726
+ if (path.length === previous.length && (path.at(-1) === first || path.at(-1) === alternate)) {
727
+ return path.reverse();
728
+ }
729
+ const stack = [{ node: current, parent: null }];
730
+ seen.clear();
731
+ while (stack.length > 0 && seen.size < MAX_VISITED_FIBERS) {
732
+ const entry = stack.pop();
733
+ if (!entry)
734
+ break;
735
+ if (seen.has(entry.node))
736
+ return [];
737
+ seen.add(entry.node);
738
+ if (entry.node === first || entry.node === alternate) {
739
+ const ancestors = [];
740
+ for (let cursor = entry; cursor; cursor = cursor.parent)
741
+ ancestors.push(cursor.node);
742
+ return ancestors;
743
+ }
744
+ const sibling = entry.parent && fiber(entry.node.sibling);
745
+ if (sibling)
746
+ stack.push({ node: sibling, parent: entry.parent });
747
+ const child = fiber(entry.node.child);
748
+ if (child)
749
+ stack.push({ node: child, parent: entry });
750
+ }
751
+ return stack.length > 0 ? exhausted() : [];
752
+ }
753
+
754
+ // src/renderer-composer-kind.ts
755
+ function isOrbitComposer(composer) {
756
+ let element = composer.querySelector('[contenteditable="true"], textarea, [role="textbox"]') ?? composer;
757
+ for (let depth = 0; element && depth < 12; depth += 1) {
758
+ const key = Object.getOwnPropertyNames(element).find(
759
+ (name) => name.startsWith("__reactFiber$")
760
+ );
761
+ if (key) {
762
+ for (const fiber of committedReactAncestors(
763
+ Object.getOwnPropertyDescriptor(element, key)?.value
764
+ )) {
765
+ const props = fiber.memoizedProps;
766
+ if (typeof props === "object" && props !== null && "isOrbit" in props) {
767
+ const value = props.isOrbit;
768
+ if (typeof value === "boolean") return value;
769
+ }
770
+ }
771
+ return false;
772
+ }
773
+ element = element.parentElement;
774
+ }
775
+ return false;
776
+ }
777
+
664
778
  // ../../node_modules/zod/v4/classic/external.js
665
779
  var external_exports = {};
666
780
  __export(external_exports, {
@@ -16807,6 +16921,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16807
16921
  ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }]
16808
16922
  ];
16809
16923
 
16924
+ // ../../node_modules/lucide/dist/esm/icons/eye.mjs
16925
+ var Eye = [
16926
+ [
16927
+ "path",
16928
+ {
16929
+ d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"
16930
+ }
16931
+ ],
16932
+ ["circle", { cx: "12", cy: "12", r: "3" }]
16933
+ ];
16934
+
16935
+ // ../../node_modules/lucide/dist/esm/icons/eye-off.mjs
16936
+ var EyeOff = [
16937
+ [
16938
+ "path",
16939
+ {
16940
+ d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"
16941
+ }
16942
+ ],
16943
+ ["path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }],
16944
+ [
16945
+ "path",
16946
+ {
16947
+ d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"
16948
+ }
16949
+ ],
16950
+ ["path", { d: "m2 2 20 20" }]
16951
+ ];
16952
+
16810
16953
  // ../../node_modules/lucide/dist/esm/icons/ellipsis.mjs
16811
16954
  var Ellipsis = [
16812
16955
  ["circle", { cx: "12", cy: "12", r: "1" }],
@@ -17041,6 +17184,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17041
17184
  "info",
17042
17185
  "external-link",
17043
17186
  "refresh",
17187
+ "eye",
17188
+ "eye-off",
17044
17189
  "unavailable",
17045
17190
  "alert",
17046
17191
  "check",
@@ -17090,6 +17235,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17090
17235
  info: Info,
17091
17236
  "external-link": ExternalLink,
17092
17237
  refresh: RefreshCw,
17238
+ eye: Eye,
17239
+ "eye-off": EyeOff,
17093
17240
  unavailable: CircleOff,
17094
17241
  alert: TriangleAlert,
17095
17242
  check: CircleCheck,
@@ -17674,9 +17821,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17674
17821
  }
17675
17822
  };
17676
17823
  update.addEventListener("click", () => void run("update"));
17677
- signal.addEventListener("abort", render, { once: true });
17824
+ const owner = document2.defaultView;
17825
+ let checkFrame = null;
17826
+ let checkTimer = null;
17827
+ signal.addEventListener(
17828
+ "abort",
17829
+ () => {
17830
+ if (checkFrame !== null) owner?.cancelAnimationFrame(checkFrame);
17831
+ if (checkTimer !== null) owner?.clearTimeout(checkTimer);
17832
+ render();
17833
+ },
17834
+ { once: true }
17835
+ );
17836
+ status.textContent = messages.harnessVersionChecking;
17678
17837
  render();
17679
- void run("check");
17838
+ if (!signal.aborted && owner?.requestAnimationFrame) {
17839
+ checkFrame = owner.requestAnimationFrame(() => {
17840
+ checkFrame = null;
17841
+ if (signal.aborted) return;
17842
+ checkTimer = owner.setTimeout(() => {
17843
+ checkTimer = null;
17844
+ void run("check");
17845
+ }, 0);
17846
+ });
17847
+ } else {
17848
+ void run("check");
17849
+ }
17680
17850
  return panel;
17681
17851
  }
17682
17852
 
@@ -18158,6 +18328,30 @@ ${error51.stderrTail}`] : []
18158
18328
  const hostNames = /* @__PURE__ */ new Map();
18159
18329
  let latestSnapshot = null;
18160
18330
  let disposeHostScroller = () => void 0;
18331
+ let disposed = false;
18332
+ let renderQueued = false;
18333
+ let renderFrame = null;
18334
+ const scheduleRender = () => {
18335
+ if (disposed || context.signal.aborted || renderQueued) return;
18336
+ renderQueued = true;
18337
+ const flush = () => {
18338
+ renderFrame = null;
18339
+ renderQueued = false;
18340
+ if (!disposed && !context.signal.aborted) {
18341
+ render(diagnostics?.snapshot() ?? latestSnapshot);
18342
+ }
18343
+ };
18344
+ if (document2.defaultView?.requestAnimationFrame) {
18345
+ renderFrame = document2.defaultView.requestAnimationFrame(flush);
18346
+ } else {
18347
+ queueMicrotask(flush);
18348
+ }
18349
+ };
18350
+ const cancelRender = () => {
18351
+ disposed = true;
18352
+ if (renderFrame !== null) document2.defaultView?.cancelAnimationFrame(renderFrame);
18353
+ renderFrame = null;
18354
+ };
18161
18355
  const diagnostics = getDiagnostics();
18162
18356
  const installs = diagnostics ? harnessInstallStore(diagnostics) : null;
18163
18357
  const runRefresh = () => {
@@ -18551,20 +18745,20 @@ ${error51.stderrTail}`] : []
18551
18745
  () => {
18552
18746
  }
18553
18747
  );
18554
- const unsubscribeGroup = groupPreference.subscribe(
18555
- () => render(diagnostics?.snapshot() ?? latestSnapshot)
18556
- );
18748
+ const unsubscribeGroup = groupPreference.subscribe(scheduleRender);
18557
18749
  if (!diagnostics) {
18558
18750
  refresh.disabled = true;
18559
18751
  return () => {
18752
+ cancelRender();
18560
18753
  disposeHostScroller();
18561
18754
  unsubscribeGroup();
18562
18755
  };
18563
18756
  }
18564
18757
  refresh.addEventListener("click", runRefresh);
18565
- const unsubscribe = diagnostics.subscribe(() => render(diagnostics.snapshot()));
18566
- const unsubscribeInstalls = installs?.subscribe(() => render(diagnostics.snapshot()));
18758
+ const unsubscribe = diagnostics.subscribe(scheduleRender);
18759
+ const unsubscribeInstalls = installs?.subscribe(scheduleRender);
18567
18760
  return () => {
18761
+ cancelRender();
18568
18762
  disposeHostScroller();
18569
18763
  unsubscribeInstalls?.();
18570
18764
  unsubscribe();
@@ -18576,9 +18770,10 @@ ${error51.stderrTail}`] : []
18576
18770
 
18577
18771
  // src/settings/credential-import-messages.ts
18578
18772
  var credentialImportEnglish = {
18579
- column: "Use in Harness",
18580
18773
  sectionTitle: "Accounts in Pi",
18581
- sectionEmpty: "No logins in Pi yet. Use the Pi mark on a Codex or Grok account above to import one.",
18774
+ sectionHint: "Copy a local Codex or Grok login into a Pi model entry.",
18775
+ sectionImport: "Import account",
18776
+ sectionEmpty: "No logins in Pi yet. Use \u201CImport account\u201D, or \u201CImport into Pi\u201D on a Codex or Grok account above.",
18582
18777
  rowReimport: "Copy again",
18583
18778
  rowRemove: "Remove",
18584
18779
  othersTitle: "Pi's own logins",
@@ -18591,6 +18786,8 @@ ${error51.stderrTail}`] : []
18591
18786
  entry: "Entry in Pi",
18592
18787
  name: "Model entry name",
18593
18788
  source: "Source account",
18789
+ sourceCurrent: "Current login",
18790
+ sourceImported: "Already in Pi as {name}/\u2026; another entry can be added",
18594
18791
  preview: "Creates {name}/\u2026 in Pi. Existing Provider configurations remain unchanged.",
18595
18792
  warning: "Copies the current authorization once; it does not synchronize logins or add quota. Pi and the original app may refresh the same token, which can require signing in again. Usage follows this Provider's billing rules.",
18596
18793
  confirm: "Confirm import",
@@ -18606,9 +18803,10 @@ ${error51.stderrTail}`] : []
18606
18803
  close: "Done"
18607
18804
  };
18608
18805
  var credentialImportChinese = {
18609
- column: "\u7528\u4E8E Harness",
18610
18806
  sectionTitle: "Pi \u4E2D\u7684\u8D26\u53F7",
18611
- sectionEmpty: "Pi \u4E2D\u8FD8\u6CA1\u6709\u767B\u5F55\u3002\u70B9\u51FB\u4E0A\u65B9 Codex \u6216 Grok \u8D26\u53F7\u884C\u7684 Pi \u56FE\u6807\u5373\u53EF\u5BFC\u5165\u3002",
18807
+ sectionHint: "\u628A Codex\u3001Grok \u7684\u672C\u5730\u767B\u5F55\u590D\u5236\u6210 Pi \u7684\u6A21\u578B\u5165\u53E3",
18808
+ sectionImport: "\u5BFC\u5165\u8D26\u53F7",
18809
+ sectionEmpty: "Pi \u4E2D\u8FD8\u6CA1\u6709\u767B\u5F55\u3002\u70B9\u51FB\u300C\u5BFC\u5165\u8D26\u53F7\u300D\uFF0C\u6216\u4E0A\u65B9 Codex\u3001Grok \u8D26\u53F7\u884C\u7684\u300C\u5BFC\u5165\u5230 Pi\u300D\u5373\u53EF\u5BFC\u5165\u3002",
18612
18810
  rowReimport: "\u91CD\u65B0\u5BFC\u5165",
18613
18811
  rowRemove: "\u79FB\u9664",
18614
18812
  othersTitle: "Pi \u81EA\u6709\u914D\u7F6E",
@@ -18621,6 +18819,8 @@ ${error51.stderrTail}`] : []
18621
18819
  entry: "Pi \u4E2D\u7684\u5165\u53E3",
18622
18820
  name: "\u6A21\u578B\u5165\u53E3\u540D\u79F0",
18623
18821
  source: "\u6765\u6E90\u8D26\u53F7",
18822
+ sourceCurrent: "\u5F53\u524D\u767B\u5F55",
18823
+ sourceImported: "\u5DF2\u5BFC\u5165\u4E3A {name}/\u2026\uFF0C\u53EF\u518D\u65B0\u589E\u4E00\u4E2A\u5165\u53E3",
18624
18824
  preview: "\u5C06\u5728 Pi \u4E2D\u65B0\u589E {name}/\u2026\uFF0C\u4FDD\u7559\u5168\u90E8\u5DF2\u6709 Provider \u914D\u7F6E\u3002",
18625
18825
  warning: "\u4EC5\u590D\u5236\u5F53\u524D\u6388\u6743\uFF0C\u4E0D\u6301\u7EED\u540C\u6B65\u767B\u5F55\uFF0C\u4E5F\u4E0D\u589E\u52A0\u989D\u5EA6\u3002Pi \u4E0E\u539F\u751F\u5DE5\u5177\u5206\u522B\u5237\u65B0\u540C\u4E00\u51ED\u8BC1\u65F6\uFF0C\u53EF\u80FD\u9700\u8981\u91CD\u65B0\u767B\u5F55\u3002\u5B9E\u9645\u7528\u91CF\u9075\u5FAA\u8BE5 Provider \u7684\u8BA1\u8D39\u89C4\u5219\u3002",
18626
18826
  confirm: "\u786E\u8BA4\u5BFC\u5165",
@@ -18746,6 +18946,8 @@ ${error51.stderrTail}`] : []
18746
18946
  accountCreditsFailed: "Could not load limits",
18747
18947
  accountCreditsRetry: "Retry",
18748
18948
  accountCreditsRefresh: "Refresh limits",
18949
+ accountEmailsHide: "Hide emails",
18950
+ accountEmailsShow: "Show emails",
18749
18951
  accountLoadFailed: "Could not load Codex Accounts.",
18750
18952
  accountCreditsUsed: "Used",
18751
18953
  accountCreditsResetAt: "Quota resets: {time}",
@@ -19016,6 +19218,8 @@ ${error51.stderrTail}`] : []
19016
19218
  accountCreditsFailed: "\u989D\u5EA6\u8BFB\u53D6\u5931\u8D25",
19017
19219
  accountCreditsRetry: "\u91CD\u8BD5",
19018
19220
  accountCreditsRefresh: "\u5237\u65B0\u989D\u5EA6",
19221
+ accountEmailsHide: "\u9690\u85CF\u90AE\u7BB1",
19222
+ accountEmailsShow: "\u663E\u793A\u90AE\u7BB1",
19019
19223
  accountLoadFailed: "\u65E0\u6CD5\u52A0\u8F7D Codex \u8D26\u53F7\u3002",
19020
19224
  accountCreditsUsed: "\u5DF2\u7528",
19021
19225
  accountCreditsResetAt: "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4\uFF1A{time}",
@@ -22270,10 +22474,11 @@ Codex Fast mode prioritizes requests and may increase usage.`
22270
22474
  return event.key === "Enter" && !event.shiftKey && !event.isComposing;
22271
22475
  }
22272
22476
  function composerForEditor(editor) {
22273
- return editor.closest(CODEX_COMPOSER_SELECTOR);
22477
+ return composerForElement(editor);
22274
22478
  }
22275
22479
  function composerForElement(element) {
22276
- return element.closest(CODEX_COMPOSER_SELECTOR);
22480
+ const composer = element.closest(CODEX_COMPOSER_SELECTOR);
22481
+ return composer && !isOrbitComposer(composer) ? composer : null;
22277
22482
  }
22278
22483
  function isRecord(value) {
22279
22484
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -22759,87 +22964,6 @@ Codex Fast mode prioritizes requests and may increase usage.`
22759
22964
  }
22760
22965
  };
22761
22966
 
22762
- // ../desktop-control/dist/renderer-react-ownership.js
22763
- var REACT_FIBER_WALK_LIMIT_EVENT = "codexhost:react-fiber-walk-limit";
22764
- function committedReactAncestors(value) {
22765
- const MAX_VISITED_FIBERS = 2e5;
22766
- const fiber = (value2) => typeof value2 === "object" && value2 !== null ? value2 : null;
22767
- const exhausted = () => {
22768
- const target = globalThis;
22769
- if (typeof target.dispatchEvent === "function" && typeof CustomEvent === "function")
22770
- target.dispatchEvent(new CustomEvent("codexhost:react-fiber-walk-limit", {
22771
- detail: { limit: MAX_VISITED_FIBERS }
22772
- }));
22773
- return [];
22774
- };
22775
- const first = fiber(value);
22776
- if (!first)
22777
- return [];
22778
- const previous = [];
22779
- const seen = /* @__PURE__ */ new Set();
22780
- for (let node2 = first; node2; node2 = fiber(node2.return)) {
22781
- if (seen.has(node2))
22782
- return [];
22783
- if (seen.size >= MAX_VISITED_FIBERS)
22784
- return exhausted();
22785
- seen.add(node2);
22786
- previous.push(node2);
22787
- }
22788
- const rootState = fiber(previous.at(-1)?.stateNode);
22789
- if (!rootState || !("current" in rootState))
22790
- return previous;
22791
- const current = fiber(rootState.current);
22792
- if (!current)
22793
- return [];
22794
- const alternate = fiber(first.alternate);
22795
- const path = [current];
22796
- seen.clear();
22797
- seen.add(current);
22798
- for (let index = previous.length - 2; index >= 0; index -= 1) {
22799
- const expected = previous[index];
22800
- const expectedAlternate = fiber(expected?.alternate);
22801
- let child = fiber(path.at(-1)?.child);
22802
- let matched = false;
22803
- while (child && !seen.has(child) && seen.size < MAX_VISITED_FIBERS) {
22804
- seen.add(child);
22805
- if (child === expected || child === expectedAlternate) {
22806
- matched = true;
22807
- break;
22808
- }
22809
- child = fiber(child.sibling);
22810
- }
22811
- if (!matched || !child)
22812
- break;
22813
- path.push(child);
22814
- }
22815
- if (path.length === previous.length && (path.at(-1) === first || path.at(-1) === alternate)) {
22816
- return path.reverse();
22817
- }
22818
- const stack = [{ node: current, parent: null }];
22819
- seen.clear();
22820
- while (stack.length > 0 && seen.size < MAX_VISITED_FIBERS) {
22821
- const entry = stack.pop();
22822
- if (!entry)
22823
- break;
22824
- if (seen.has(entry.node))
22825
- return [];
22826
- seen.add(entry.node);
22827
- if (entry.node === first || entry.node === alternate) {
22828
- const ancestors = [];
22829
- for (let cursor = entry; cursor; cursor = cursor.parent)
22830
- ancestors.push(cursor.node);
22831
- return ancestors;
22832
- }
22833
- const sibling = entry.parent && fiber(entry.node.sibling);
22834
- if (sibling)
22835
- stack.push({ node: sibling, parent: entry.parent });
22836
- const child = fiber(entry.node.child);
22837
- if (child)
22838
- stack.push({ node: child, parent: entry });
22839
- }
22840
- return stack.length > 0 ? exhausted() : [];
22841
- }
22842
-
22843
22967
  // src/renderer-codex-usage-gate.ts
22844
22968
  var EDITOR_SELECTOR2 = '[contenteditable="true"][role="textbox"]';
22845
22969
  var MAX_HOOKS = 4096;
@@ -25070,6 +25194,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
25070
25194
  return draftIds;
25071
25195
  }
25072
25196
  function findComposerModelTarget(composer) {
25197
+ if (isOrbitComposer(composer)) return null;
25073
25198
  const draftIds = findComposerDraftIds(composer);
25074
25199
  const domIdentity = findComposerDomIdentity(composer);
25075
25200
  if (domIdentity.kind === "ambiguous") return null;
@@ -25261,7 +25386,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
25261
25386
  window.addEventListener("codexhost:draft-prewarm-policy-changed", handleRoutingPolicyChange);
25262
25387
  currentRequestRoute();
25263
25388
  const applyAgent = (agent, model, thinkingOptionId, permissionModeId, composer) => {
25264
- if (disposed) return false;
25389
+ if (disposed || composer && isOrbitComposer(composer)) return false;
25265
25390
  const selection = modelSelectionForAgent(
25266
25391
  null,
25267
25392
  null,
@@ -28006,8 +28131,28 @@ Codex Fast mode prioritizes requests and may increase usage.`
28006
28131
  }
28007
28132
  }
28008
28133
 
28134
+ // src/settings/account-privacy.ts
28135
+ var EMAIL_PATTERN = /([^\s@]+)@([^\s@]+\.[^\s@]+)/gu;
28136
+ var MASK = "****";
28137
+ function maskEmailLocalPart(local) {
28138
+ const chars = Array.from(local);
28139
+ if (chars.length <= 1) return MASK;
28140
+ if (chars.length <= 4) return `${chars[0]}${MASK}${chars.length > 2 ? chars.at(-1) : ""}`;
28141
+ return `${chars.slice(0, 2).join("")}${MASK}${chars.slice(-2).join("")}`;
28142
+ }
28143
+ function maskEmails(text) {
28144
+ return text.replace(
28145
+ EMAIL_PATTERN,
28146
+ (_match, local, domain2) => `${maskEmailLocalPart(local)}@${domain2}`
28147
+ );
28148
+ }
28149
+ function accountDisplayText(text, hideEmails) {
28150
+ return hideEmails ? maskEmails(text) : text;
28151
+ }
28152
+
28009
28153
  // src/settings/credential-imports.ts
28010
28154
  var TARGET_HARNESS_ID = "pi";
28155
+ var SECTION_IMPORT_KEY = "section:import";
28011
28156
  var VENDOR_AGENTS = {
28012
28157
  "openai-codex": "codex",
28013
28158
  xai: "grok"
@@ -28042,9 +28187,17 @@ Codex Fast mode prioritizes requests and may increase usage.`
28042
28187
  let busy = false;
28043
28188
  let dialog;
28044
28189
  let othersExpanded = false;
28190
+ let sectionExpanded = true;
28191
+ let hideEmails = false;
28192
+ const shown = (text) => accountDisplayText(text, hideEmails);
28045
28193
  const targetButtons = /* @__PURE__ */ new Map();
28046
28194
  const importedRecords = () => snapshot.targets.find((target) => target.harnessId === TARGET_HARNESS_ID)?.imports ?? [];
28047
28195
  const sourceOf = (record4) => snapshot.sources.find((source) => source.id === record4.source.id);
28196
+ const piTarget = () => snapshot.targets.find((candidate) => candidate.harnessId === TARGET_HARNESS_ID);
28197
+ const compatibleSources = () => {
28198
+ const target = piTarget();
28199
+ return target ? snapshot.sources.filter((source) => target.providers.includes(source.provider)) : [];
28200
+ };
28048
28201
  const section = document2.createElement("section");
28049
28202
  section.className = "settings-pi-accounts";
28050
28203
  section.hidden = true;
@@ -28052,12 +28205,46 @@ Codex Fast mode prioritizes requests and may increase usage.`
28052
28205
  section.setAttribute("aria-label", messages.sectionTitle);
28053
28206
  const sectionHeader = document2.createElement("div");
28054
28207
  sectionHeader.className = "settings-pi-accounts__header";
28208
+ const sectionToggle = document2.createElement("button");
28209
+ sectionToggle.type = "button";
28210
+ sectionToggle.className = "settings-pi-accounts__fold";
28211
+ sectionToggle.setAttribute("aria-expanded", "true");
28055
28212
  const sectionTitle = document2.createElement("strong");
28056
28213
  sectionTitle.textContent = messages.sectionTitle;
28057
28214
  const sectionCount = document2.createElement("span");
28058
- sectionHeader.append(createRendererAgentIcon("pi", 16, document2), sectionTitle, sectionCount);
28215
+ sectionCount.className = "settings-pi-accounts__count";
28216
+ sectionToggle.append(
28217
+ createRendererSettingsIcon("chevron-right", 14),
28218
+ createRendererAgentIcon("pi", 16, document2),
28219
+ sectionTitle,
28220
+ sectionCount
28221
+ );
28222
+ const sectionHint = document2.createElement("span");
28223
+ sectionHint.className = "settings-pi-accounts__hint";
28224
+ sectionHint.textContent = messages.sectionHint;
28225
+ const sectionImport = document2.createElement("button");
28226
+ sectionImport.type = "button";
28227
+ sectionImport.className = "settings-pi-accounts__import";
28228
+ sectionImport.setAttribute("aria-haspopup", "dialog");
28229
+ sectionImport.append(createRendererSettingsIcon("add", 14), messages.sectionImport);
28230
+ sectionImport.addEventListener("click", () => {
28231
+ const sources = compatibleSources();
28232
+ const free = sources.find(
28233
+ (source2) => !importedRecords().some((record4) => record4.source.id === source2.id)
28234
+ );
28235
+ const source = free ?? sources[0];
28236
+ if (source) openDialog("add", { source, choose: true }, SECTION_IMPORT_KEY);
28237
+ });
28238
+ sectionHeader.append(sectionToggle, sectionHint, sectionImport);
28059
28239
  const card = document2.createElement("div");
28060
28240
  card.className = "settings-pi-accounts__card";
28241
+ card.id = "settings-pi-accounts-card";
28242
+ sectionToggle.setAttribute("aria-controls", card.id);
28243
+ sectionToggle.addEventListener("click", () => {
28244
+ sectionExpanded = !sectionExpanded;
28245
+ card.hidden = !sectionExpanded;
28246
+ sectionToggle.setAttribute("aria-expanded", String(sectionExpanded));
28247
+ });
28061
28248
  const othersToggle = document2.createElement("button");
28062
28249
  othersToggle.type = "button";
28063
28250
  othersToggle.className = "settings-pi-accounts__toggle";
@@ -28098,15 +28285,15 @@ Codex Fast mode prioritizes requests and may increase usage.`
28098
28285
  row.className = "settings-pi-accounts__row";
28099
28286
  row.tabIndex = -1;
28100
28287
  row.dataset.importName = record4.name;
28101
- row.setAttribute("aria-label", record4.source.label);
28288
+ row.setAttribute("aria-label", shown(record4.source.label));
28102
28289
  const agent = KNOWN_RENDERER_AGENTS.find((candidate) => candidate === record4.source.harnessId);
28103
28290
  const mark = createMark(agent);
28104
28291
  const identity = document2.createElement("div");
28105
28292
  identity.className = "settings-pi-accounts__identity";
28106
28293
  const label = document2.createElement("strong");
28107
28294
  label.className = "settings-account-email";
28108
- label.textContent = record4.source.label;
28109
- label.title = record4.source.label;
28295
+ label.textContent = shown(record4.source.label);
28296
+ label.title = label.textContent;
28110
28297
  label.translate = false;
28111
28298
  const meta3 = document2.createElement("div");
28112
28299
  meta3.className = "settings-account-metadata";
@@ -28136,7 +28323,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28136
28323
  reimport.type = "button";
28137
28324
  reimport.className = "settings-account-action";
28138
28325
  reimport.textContent = messages.rowReimport;
28139
- reimport.setAttribute("aria-label", `${messages.reimport}: ${record4.source.label}`);
28326
+ reimport.setAttribute("aria-label", `${messages.reimport}: ${shown(record4.source.label)}`);
28140
28327
  reimport.disabled = busy || !source;
28141
28328
  reimport.title = messages.reimport;
28142
28329
  reimport.addEventListener("click", () => {
@@ -28146,7 +28333,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28146
28333
  remove.type = "button";
28147
28334
  remove.className = "settings-account-action settings-pi-accounts__remove";
28148
28335
  remove.textContent = messages.rowRemove;
28149
- remove.setAttribute("aria-label", `${messages.remove}: ${record4.source.label}`);
28336
+ remove.setAttribute("aria-label", `${messages.remove}: ${shown(record4.source.label)}`);
28150
28337
  remove.disabled = busy;
28151
28338
  remove.addEventListener("click", () => openDialog("remove", { record: record4 }, `row:${record4.name}`));
28152
28339
  if (source) actions.append(reimport);
@@ -28162,14 +28349,14 @@ Codex Fast mode prioritizes requests and may increase usage.`
28162
28349
  const agent = login.vendor ? VENDOR_AGENTS[login.vendor] : void 0;
28163
28350
  row.setAttribute(
28164
28351
  "aria-label",
28165
- [login.label ?? login.provider, agent && RENDERER_AGENT_LABELS[agent]].filter(Boolean).join(" \xB7 ")
28352
+ [shown(login.label ?? login.provider), agent && RENDERER_AGENT_LABELS[agent]].filter(Boolean).join(" \xB7 ")
28166
28353
  );
28167
28354
  const mark = createMark(agent);
28168
28355
  const identity = document2.createElement("div");
28169
28356
  identity.className = "settings-pi-accounts__identity";
28170
28357
  const title = document2.createElement("strong");
28171
28358
  title.className = "settings-account-email";
28172
- title.textContent = login.label ?? login.provider;
28359
+ title.textContent = shown(login.label ?? login.provider);
28173
28360
  title.title = title.textContent;
28174
28361
  title.translate = false;
28175
28362
  const meta3 = document2.createElement("div");
@@ -28190,11 +28377,14 @@ Codex Fast mode prioritizes requests and may increase usage.`
28190
28377
  return row;
28191
28378
  };
28192
28379
  const renderSection = () => {
28193
- const target = snapshot.targets.find((candidate) => candidate.harnessId === TARGET_HARNESS_ID);
28380
+ const target = piTarget();
28194
28381
  section.hidden = !target;
28195
28382
  const records = importedRecords();
28196
28383
  const others = target?.others ?? [];
28197
28384
  sectionCount.textContent = String(records.length + others.length);
28385
+ card.hidden = !sectionExpanded;
28386
+ sectionImport.hidden = compatibleSources().length === 0;
28387
+ sectionImport.disabled = busy;
28198
28388
  rows.clear();
28199
28389
  if (records.length + others.length === 0) {
28200
28390
  const empty = document2.createElement("p");
@@ -28257,6 +28447,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
28257
28447
  let state = initial;
28258
28448
  let mode = initialMode;
28259
28449
  let nameInput;
28450
+ let nameEdited = false;
28451
+ let sourceRadios = [];
28452
+ let refreshPreview = () => void 0;
28260
28453
  const command = (text, onClick, variant = "secondary") => {
28261
28454
  const button = document2.createElement("button");
28262
28455
  button.type = "button";
@@ -28280,9 +28473,50 @@ Codex Fast mode prioritizes requests and may increase usage.`
28280
28473
  paragraph.textContent = text;
28281
28474
  return paragraph;
28282
28475
  };
28476
+ const sourcePicker = (choices) => {
28477
+ const group = document2.createElement("fieldset");
28478
+ group.className = "settings-credential-dialog__sources";
28479
+ const legend = document2.createElement("legend");
28480
+ legend.textContent = messages.source;
28481
+ group.append(legend);
28482
+ for (const choice of choices) {
28483
+ const option = document2.createElement("label");
28484
+ option.className = "settings-credential-dialog__source";
28485
+ const radio = document2.createElement("input");
28486
+ radio.type = "radio";
28487
+ radio.name = "settings-credential-source";
28488
+ radio.value = choice.id;
28489
+ radio.checked = choice.id === state.source?.id;
28490
+ sourceRadios.push(radio);
28491
+ const copy = document2.createElement("span");
28492
+ const label = document2.createElement("strong");
28493
+ label.textContent = shown(choice.label);
28494
+ label.translate = false;
28495
+ const existing = importedRecords().find((record4) => record4.source.id === choice.id);
28496
+ const agent = KNOWN_RENDERER_AGENTS.find((candidate) => candidate === choice.harnessId);
28497
+ const detail = document2.createElement("span");
28498
+ detail.textContent = [
28499
+ agent && RENDERER_AGENT_LABELS[agent] || choice.harnessId,
28500
+ existing ? messages.sourceImported.replace("{name}", existing.name) : messages.sourceCurrent
28501
+ ].join(" \xB7 ");
28502
+ copy.append(label, detail);
28503
+ radio.addEventListener("change", () => {
28504
+ if (!radio.checked) return;
28505
+ state = { ...state, source: choice };
28506
+ if (nameInput && !nameEdited) {
28507
+ nameInput.value = defaultImportName(choice, importedRecords());
28508
+ }
28509
+ refreshPreview();
28510
+ });
28511
+ option.append(radio, copy);
28512
+ group.append(option);
28513
+ }
28514
+ return group;
28515
+ };
28283
28516
  const setBusy = (value) => {
28284
28517
  for (const child of controls.children) child.disabled = value;
28285
28518
  if (nameInput) nameInput.disabled = value;
28519
+ for (const radio of sourceRadios) radio.disabled = value;
28286
28520
  };
28287
28521
  const submit = async (request, next) => {
28288
28522
  error51.textContent = "";
@@ -28310,6 +28544,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28310
28544
  mode = next;
28311
28545
  error51.textContent = "";
28312
28546
  nameInput = void 0;
28547
+ sourceRadios = [];
28313
28548
  body.replaceChildren();
28314
28549
  controls.replaceChildren();
28315
28550
  const { source, record: record4 } = state;
@@ -28318,7 +28553,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
28318
28553
  title.textContent = mode === "add" ? messages.add : messages.reimport;
28319
28554
  modal.setAttribute("aria-label", title.textContent);
28320
28555
  const active = source ?? record4?.source;
28321
- if (active) body.append(line(messages.source, active.label));
28556
+ const choices = mode === "add" && state.choose ? compatibleSources() : [];
28557
+ if (choices.length > 1) body.append(sourcePicker(choices));
28558
+ else if (active) body.append(line(messages.source, shown(active.label)));
28322
28559
  const input = document2.createElement("input");
28323
28560
  input.type = "text";
28324
28561
  input.maxLength = 48;
@@ -28326,6 +28563,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
28326
28563
  input.spellcheck = false;
28327
28564
  input.value = record4?.name ?? (source ? defaultImportName(source, importedRecords()) : "codex");
28328
28565
  input.readOnly = Boolean(record4);
28566
+ input.addEventListener("input", () => {
28567
+ nameEdited = true;
28568
+ });
28329
28569
  nameInput = input;
28330
28570
  const label = document2.createElement("label");
28331
28571
  label.className = "settings-credential-dialog__field";
@@ -28337,6 +28577,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28337
28577
  preview.textContent = (mode === "reimport" ? messages.reimportPreview : messages.preview).replace("{name}", input.value);
28338
28578
  };
28339
28579
  input.addEventListener("input", update);
28580
+ refreshPreview = update;
28340
28581
  update();
28341
28582
  body.append(label, preview, note(messages.warning));
28342
28583
  controls.append(
@@ -28344,7 +28585,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
28344
28585
  command(
28345
28586
  messages.confirm,
28346
28587
  async () => {
28347
- if (!source) return;
28588
+ const source2 = state.source;
28589
+ if (!source2) return;
28348
28590
  if (!credentialImportNameSchema.safeParse(input.value).success) {
28349
28591
  error51.textContent = messages.invalidName;
28350
28592
  input.focus();
@@ -28353,7 +28595,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28353
28595
  await submit(
28354
28596
  {
28355
28597
  action: mode === "reimport" ? "reimport" : "import",
28356
- sourceId: source.id,
28598
+ sourceId: source2.id,
28357
28599
  name: record4?.name ?? input.value,
28358
28600
  confirmed: true
28359
28601
  },
@@ -28395,7 +28637,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28395
28637
  modal.addEventListener("close", () => {
28396
28638
  modal.remove();
28397
28639
  dialog = void 0;
28398
- const target = returnKey ? targetButtons.get(returnKey) ?? rows.get(returnKey.replace(/^row:/, "")) : void 0;
28640
+ const target = returnKey ? returnKey === SECTION_IMPORT_KEY ? sectionImport : targetButtons.get(returnKey) ?? rows.get(returnKey.replace(/^row:/, "")) : void 0;
28399
28641
  (target?.isConnected ? target : section).focus();
28400
28642
  });
28401
28643
  show(initialMode);
@@ -28405,6 +28647,12 @@ Codex Fast mode prioritizes requests and may increase usage.`
28405
28647
  signal.addEventListener("abort", () => dialog?.remove(), { once: true });
28406
28648
  renderSection();
28407
28649
  return {
28650
+ /** Mask the middle of email addresses in the section and dialogs (screen sharing). */
28651
+ setHideEmails(value) {
28652
+ if (hideEmails === value) return;
28653
+ hideEmails = value;
28654
+ renderSection();
28655
+ },
28408
28656
  /** Dedicated "imported into Pi" section, rendered below the account table. */
28409
28657
  section,
28410
28658
  refresh: async () => {
@@ -28426,20 +28674,33 @@ Codex Fast mode prioritizes requests and may increase usage.`
28426
28674
  const key = `${harnessId}:${accountLabel}:import`;
28427
28675
  const button = document2.createElement("button");
28428
28676
  button.type = "button";
28429
- button.className = "settings-icon-button settings-account-harness-target";
28677
+ button.className = "settings-account-pi-import";
28430
28678
  button.dataset.accountFocus = key;
28431
28679
  button.disabled = busy;
28432
- if (record4) button.dataset.state = "imported";
28433
28680
  const hint = record4 ? messages.importedHint.replace("{name}", record4.name) : messages.add;
28434
28681
  button.title = hint;
28435
28682
  button.setAttribute("aria-label", hint);
28436
- button.setAttribute("aria-haspopup", "dialog");
28437
- button.append(createRendererAgentIcon("pi", 16, document2));
28683
+ button.append(createRendererAgentIcon("pi", 12, document2));
28684
+ if (record4) {
28685
+ button.dataset.state = "imported";
28686
+ const name = document2.createElement("code");
28687
+ name.textContent = `${record4.name}/\u2026`;
28688
+ name.translate = false;
28689
+ button.append(name, createRendererSettingsIcon("check", 12));
28690
+ } else {
28691
+ button.setAttribute("aria-haspopup", "dialog");
28692
+ button.append(messages.add);
28693
+ }
28438
28694
  button.addEventListener("click", () => {
28439
28695
  if (!record4) {
28440
28696
  openDialog("add", { source }, key);
28441
28697
  return;
28442
28698
  }
28699
+ if (!sectionExpanded) {
28700
+ sectionExpanded = true;
28701
+ renderSection();
28702
+ sectionToggle.setAttribute("aria-expanded", "true");
28703
+ }
28443
28704
  const row = rows.get(record4.name);
28444
28705
  row?.scrollIntoView({ block: "nearest", behavior: "smooth" });
28445
28706
  row?.focus();
@@ -28731,37 +28992,35 @@ Codex Fast mode prioritizes requests and may increase usage.`
28731
28992
  return { cells: [cell], continuationCells: [] };
28732
28993
  }
28733
28994
  const { rows, additional } = splitUsageWindows(state.credits, messages, filter);
28734
- const onlyRow = rows.length === 1 ? rows[0] : void 0;
28735
- if (additional.length && onlyRow && !Object.keys(onlyRow.columns).length) rows.pop();
28736
- for (let index = 0; index < additional.length; index += 2) {
28737
- const first = additional[index];
28738
- const second = additional[index + 1];
28739
- rows.push({
28740
- columns: {
28741
- ...first ? { five_hour: first } : {},
28742
- ...second ? { seven_day: second } : {}
28743
- }
28744
- });
28995
+ const windows = [
28996
+ ...rows.flatMap(
28997
+ (row) => ["five_hour", "seven_day"].flatMap(
28998
+ (period) => row.columns[period] ? [row.columns[period]] : []
28999
+ )
29000
+ ),
29001
+ ...additional
29002
+ ];
29003
+ const packed = [];
29004
+ for (let index = 0; index < windows.length; index += 2) {
29005
+ const pair = windows.slice(index, index + 2);
29006
+ packed.push(
29007
+ pair.map((window2) => {
29008
+ const cell = document2.createElement("td");
29009
+ cell.className = "settings-account-usage-cell";
29010
+ if (pair.length === 1) cell.colSpan = 2;
29011
+ cell.append(renderUsageWindow(document2, window2, messages, display));
29012
+ return cell;
29013
+ })
29014
+ );
28745
29015
  }
28746
- const renderCells = (row) => ["five_hour", "seven_day"].map((period) => {
29016
+ if (packed.length === 0) {
28747
29017
  const cell = document2.createElement("td");
28748
- cell.className = "settings-account-usage-cell";
28749
- const window2 = row.columns[period];
28750
- if (window2) cell.append(renderUsageWindow(document2, window2, messages, display));
28751
- else {
28752
- const missing = document2.createElement("div");
28753
- missing.className = "settings-account-usage__missing";
28754
- const dash = document2.createElement("span");
28755
- dash.textContent = "\u2014";
28756
- dash.setAttribute("aria-hidden", "true");
28757
- missing.append(dash);
28758
- cell.append(missing);
28759
- }
28760
- return cell;
28761
- });
28762
- const [firstRow = { columns: {} }, ...continuations] = rows;
28763
- const cells = renderCells(firstRow);
28764
- const continuationCells = continuations.map(renderCells);
29018
+ cell.colSpan = 2;
29019
+ cell.className = "settings-account-usage-cell settings-account-usage-cell--message";
29020
+ cell.textContent = messages.accountCreditsEmpty;
29021
+ packed.push([cell]);
29022
+ }
29023
+ const [cells = [], ...continuationCells] = packed;
28765
29024
  return { cells, continuationCells };
28766
29025
  }
28767
29026
  function renderAccountResetCredits(document2, credits, messages) {
@@ -28855,14 +29114,14 @@ Codex Fast mode prioritizes requests and may increase usage.`
28855
29114
  table.className = "settings-account-table";
28856
29115
  table.setAttribute("aria-label", messages.pageLabels.accounts);
28857
29116
  const columns = document2.createElement("colgroup");
28858
- for (const width of [32, 24, 24, 20]) {
29117
+ for (const width of [36, 32, 32]) {
28859
29118
  const column = document2.createElement("col");
28860
29119
  column.style.width = `${width}%`;
28861
29120
  columns.append(column);
28862
29121
  }
28863
29122
  const head = document2.createElement("thead");
28864
29123
  const row = document2.createElement("tr");
28865
- const headers = Array.from({ length: 3 }, (_, index) => {
29124
+ const headers = Array.from({ length: 2 }, (_, index) => {
28866
29125
  const cell = document2.createElement("th");
28867
29126
  cell.scope = index === 1 ? "colgroup" : "col";
28868
29127
  if (index === 1) cell.colSpan = 2;
@@ -28870,11 +29129,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28870
29129
  return cell;
28871
29130
  });
28872
29131
  const updateDisplay = (display) => {
28873
- const labels = [
28874
- messages.accountColumnAccount,
28875
- accountUsageColumnLabel(display, messages),
28876
- messages.credentialImports.column
28877
- ];
29132
+ const labels = [messages.accountColumnAccount, accountUsageColumnLabel(display, messages)];
28878
29133
  headers.forEach((cell, index) => {
28879
29134
  cell.textContent = labels[index] ?? "";
28880
29135
  });
@@ -28926,11 +29181,13 @@ Codex Fast mode prioritizes requests and may increase usage.`
28926
29181
  person.append(input.mark, identity);
28927
29182
  return person;
28928
29183
  }
28929
- function createTargetCell(document2, action) {
28930
- const cell = document2.createElement("td");
28931
- cell.className = action ? "settings-account-management-cell" : "settings-account-management-cell settings-account-management-cell--empty";
28932
- if (action) cell.append(action);
28933
- return cell;
29184
+ function appendAccountExtras(cell, items) {
29185
+ const present = items.filter((item) => Boolean(item));
29186
+ if (present.length === 0) return;
29187
+ const extras = cell.ownerDocument.createElement("div");
29188
+ extras.className = "settings-account-row__extras";
29189
+ extras.append(...present);
29190
+ cell.append(extras);
28934
29191
  }
28935
29192
  function renderAccountBalance(document2, messages, balance) {
28936
29193
  const cell = document2.createElement("td");
@@ -28955,8 +29212,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
28955
29212
  row.dataset.accountId = account.accountId;
28956
29213
  row.dataset.accountFocus = `${account.accountId}:row`;
28957
29214
  row.tabIndex = -1;
28958
- const name = codexAccountDisplayName(account);
28959
- row.setAttribute("aria-label", name.full);
29215
+ const name = accountDisplayText(codexAccountDisplayName(account).full, input.hideEmails === true);
29216
+ row.setAttribute("aria-label", name);
28960
29217
  const personCell = document2.createElement("td");
28961
29218
  personCell.className = "settings-account-person-cell";
28962
29219
  const mark = document2.createElement("div");
@@ -28966,7 +29223,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
28966
29223
  mark.append(createRendererAgentIcon("codex", 26, document2));
28967
29224
  personCell.append(
28968
29225
  createAccountPerson(document2, messages, {
28969
- name: name.full,
29226
+ name,
28970
29227
  agent: "Codex",
28971
29228
  plan: accountPlanLabel(account.planType),
28972
29229
  highlighted: account.planType === "pro" || account.planType === "prolite",
@@ -28982,8 +29239,6 @@ Codex Fast mode prioritizes requests and may increase usage.`
28982
29239
  input.onRetry,
28983
29240
  account.planType === "pro" ? "weekly-only" : "all"
28984
29241
  );
28985
- const actionsCell = createTargetCell(document2, input.importAction);
28986
- if (input.importAction) row.className += " settings-account-row--targets";
28987
29242
  const continuationRows = usage.continuationCells.map((cells) => {
28988
29243
  const continuation = document2.createElement("tr");
28989
29244
  continuation.className = "settings-account-row settings-account-quota-continuation-row";
@@ -28994,18 +29249,19 @@ Codex Fast mode prioritizes requests and may increase usage.`
28994
29249
  if (continuationRows.length > 0) {
28995
29250
  personCell.rowSpan = continuationRows.length + 1;
28996
29251
  personCell.className += " settings-account-spanning-cell";
28997
- actionsCell.rowSpan = continuationRows.length + 1;
28998
- actionsCell.className += " settings-account-spanning-cell";
28999
29252
  }
29000
- row.append(personCell, ...usage.cells, actionsCell);
29253
+ row.append(personCell, ...usage.cells);
29001
29254
  const reset = input.usage?.status === "ready" ? renderAccountResetCredits(document2, input.usage.credits, messages) : null;
29002
- if (!reset) return [row, ...continuationRows];
29255
+ if (!reset) {
29256
+ appendAccountExtras(personCell, [input.importAction]);
29257
+ return [row, ...continuationRows];
29258
+ }
29003
29259
  const detailsRow = document2.createElement("tr");
29004
29260
  detailsRow.className = "settings-account-details-row";
29005
29261
  detailsRow.id = `settings-account-reset-${++resetDetailsSequence}`;
29006
29262
  detailsRow.hidden = !input.resetExpanded;
29007
29263
  const detailsCell = document2.createElement("td");
29008
- detailsCell.colSpan = 4;
29264
+ detailsCell.colSpan = 3;
29009
29265
  detailsCell.append(reset.details);
29010
29266
  detailsRow.append(detailsCell);
29011
29267
  reset.summary.dataset.accountFocus = `${account.accountId}:reset`;
@@ -29016,15 +29272,18 @@ Codex Fast mode prioritizes requests and may increase usage.`
29016
29272
  reset.summary.setAttribute("aria-expanded", String(!detailsRow.hidden));
29017
29273
  input.onResetExpanded(!detailsRow.hidden);
29018
29274
  });
29019
- personCell.append(reset.summary);
29275
+ appendAccountExtras(personCell, [reset.summary, input.importAction]);
29020
29276
  return [row, ...continuationRows, detailsRow];
29021
29277
  }
29022
- function renderHarnessAccountRows(document2, account, messages, display, importAction) {
29278
+ function renderHarnessAccountRows(document2, account, messages, display, importAction, hideEmails = false) {
29023
29279
  const row = document2.createElement("tr");
29024
29280
  row.className = "settings-account-row";
29025
29281
  row.dataset.harnessId = account.harnessId;
29026
29282
  row.tabIndex = -1;
29027
- const name = account.email ?? account.label ?? account.harnessName;
29283
+ const name = accountDisplayText(
29284
+ account.email ?? account.label ?? account.harnessName,
29285
+ hideEmails
29286
+ );
29028
29287
  row.setAttribute("aria-label", name);
29029
29288
  const personCell = document2.createElement("td");
29030
29289
  personCell.className = "settings-account-person-cell";
@@ -29049,9 +29308,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
29049
29308
  () => void 0,
29050
29309
  account.harnessId === "grok" ? "weekly-only" : "all"
29051
29310
  ) : renderAccountBalance(document2, messages, account.balance);
29052
- const managementCell = createTargetCell(document2, importAction);
29053
- if (importAction) row.className += " settings-account-row--targets";
29054
29311
  personCell.title = messages.accountNativeManagementHint.replace("{harness}", account.harnessName);
29312
+ appendAccountExtras(personCell, [importAction]);
29055
29313
  const continuationRows = usage.continuationCells.map((cells) => {
29056
29314
  const continuation = document2.createElement("tr");
29057
29315
  continuation.className = "settings-account-row settings-account-quota-continuation-row";
@@ -29062,10 +29320,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
29062
29320
  if (continuationRows.length > 0) {
29063
29321
  personCell.rowSpan = continuationRows.length + 1;
29064
29322
  personCell.className += " settings-account-spanning-cell";
29065
- managementCell.rowSpan = continuationRows.length + 1;
29066
- managementCell.className += " settings-account-spanning-cell";
29067
29323
  }
29068
- row.append(personCell, ...usage.cells, managementCell);
29324
+ row.append(personCell, ...usage.cells);
29069
29325
  return [row, ...continuationRows];
29070
29326
  }
29071
29327
 
@@ -29225,6 +29481,26 @@ Codex Fast mode prioritizes requests and may increase usage.`
29225
29481
  refreshUsage.title = messages.accountCreditsRefresh;
29226
29482
  refreshUsage.setAttribute("aria-label", messages.accountCreditsRefresh);
29227
29483
  refreshUsage.append(createRendererSettingsIcon("refresh", 16));
29484
+ let hideEmails = false;
29485
+ const privacyToggle = document2.createElement("button");
29486
+ privacyToggle.type = "button";
29487
+ privacyToggle.className = "settings-icon-button settings-account-privacy-toggle";
29488
+ const updatePrivacyToggle = () => {
29489
+ const label = hideEmails ? messages.accountEmailsShow : messages.accountEmailsHide;
29490
+ privacyToggle.title = label;
29491
+ privacyToggle.setAttribute("aria-label", label);
29492
+ privacyToggle.setAttribute("aria-pressed", String(hideEmails));
29493
+ privacyToggle.replaceChildren(
29494
+ createRendererSettingsIcon(hideEmails ? "eye-off" : "eye", 16)
29495
+ );
29496
+ };
29497
+ updatePrivacyToggle();
29498
+ privacyToggle.addEventListener("click", () => {
29499
+ hideEmails = !hideEmails;
29500
+ updatePrivacyToggle();
29501
+ credentialImports.setHideEmails(hideEmails);
29502
+ render();
29503
+ });
29228
29504
  refreshUsage.addEventListener("click", () => {
29229
29505
  usageByAccountId.clear();
29230
29506
  loadUsage(accounts);
@@ -29232,7 +29508,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
29232
29508
  void credentialImports.refresh();
29233
29509
  });
29234
29510
  search.addEventListener("input", () => render());
29235
- toolbar.append(connected, searchWrapper, displayControls, refreshUsage);
29511
+ toolbar.append(connected, privacyToggle, searchWrapper, displayControls, refreshUsage);
29236
29512
  const list = document2.createElement("div");
29237
29513
  list.className = "settings-account-list";
29238
29514
  const { table, body, updateDisplay } = createAccountsTable(document2, messages);
@@ -29277,7 +29553,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
29277
29553
  if (visibleAccounts.length + visibleHarnessAccounts.length === 0) {
29278
29554
  const emptyRow = document2.createElement("tr");
29279
29555
  const emptyCell = document2.createElement("td");
29280
- emptyCell.colSpan = 4;
29556
+ emptyCell.colSpan = 3;
29281
29557
  emptyCell.className = "settings-account-empty";
29282
29558
  emptyCell.textContent = query ? messages.accountNoMatches : messages.accountEmpty;
29283
29559
  emptyRow.append(emptyCell);
@@ -29287,10 +29563,6 @@ Codex Fast mode prioritizes requests and may increase usage.`
29287
29563
  body.append(
29288
29564
  ...renderAccountRows(document2, account, messages, {
29289
29565
  current: accountPhase === "ready" && account.accountId === currentAccountId,
29290
- importAction: credentialImports.button(
29291
- "codex",
29292
- codexAccountDisplayName(account).full
29293
- ),
29294
29566
  usage: usageByAccountId.get(account.accountId),
29295
29567
  display: usageDisplay,
29296
29568
  resetExpanded: expandedResetAccounts.has(account.accountId),
@@ -29301,7 +29573,12 @@ Codex Fast mode prioritizes requests and may increase usage.`
29301
29573
  onResetExpanded: (open) => {
29302
29574
  if (open) expandedResetAccounts.add(account.accountId);
29303
29575
  else expandedResetAccounts.delete(account.accountId);
29304
- }
29576
+ },
29577
+ importAction: credentialImports.button(
29578
+ "codex",
29579
+ codexAccountDisplayName(account).full
29580
+ ),
29581
+ hideEmails
29305
29582
  })
29306
29583
  );
29307
29584
  }
@@ -29315,7 +29592,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
29315
29592
  credentialImports.button(
29316
29593
  account.harnessId,
29317
29594
  account.email ?? account.label ?? account.harnessName
29318
- )
29595
+ ),
29596
+ hideEmails
29319
29597
  )
29320
29598
  );
29321
29599
  }
@@ -29422,8 +29700,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
29422
29700
  } catch {
29423
29701
  }
29424
29702
  const harnessAccounts = createHarnessAccounts(context.signal, getClient, render);
29425
- void credentialImports.refresh();
29426
29703
  void harnessAccounts.refresh();
29704
+ void credentialImports.refresh();
29427
29705
  load();
29428
29706
  return () => {
29429
29707
  stopCountdowns();
@@ -32622,6 +32900,15 @@ Codex Fast mode prioritizes requests and may increase usage.`
32622
32900
  color: var(--settings-muted);
32623
32901
  font-variant-numeric: tabular-nums;
32624
32902
  }
32903
+ /* Email privacy belongs to the identity column, so it sits beside the account count on the
32904
+ left; quota controls (used/remaining, refresh) stay together on the right. */
32905
+ .settings-account-privacy-toggle {
32906
+ margin-left: -8px;
32907
+ }
32908
+ .settings-account-privacy-toggle[aria-pressed="true"] {
32909
+ color: var(--settings-text);
32910
+ background: var(--settings-active);
32911
+ }
32625
32912
  .settings-account-search {
32626
32913
  display: flex;
32627
32914
  align-items: center;
@@ -32691,10 +32978,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
32691
32978
  background: light-dark(#f8f8fa, #202024);
32692
32979
  font-size: 11px;
32693
32980
  font-weight: 500;
32694
- text-align: left;
32695
- }
32696
- .settings-account-table th:last-child {
32697
- text-align: right;
32981
+ text-align: center;
32698
32982
  }
32699
32983
  .settings-account-table td {
32700
32984
  padding: 17px 16px;
@@ -33014,26 +33298,11 @@ Codex Fast mode prioritizes requests and may increase usage.`
33014
33298
  border: 0;
33015
33299
  }
33016
33300
  .settings-account-person-cell,
33017
- .settings-account-management-cell,
33301
+ .settings-account-usage-cell[colspan="2"],
33018
33302
  .settings-account-usage-cell--message,
33019
33303
  .settings-account-balance-cell {
33020
33304
  grid-column: 1 / -1;
33021
33305
  }
33022
- .settings-account-table .settings-account-row > td.settings-account-management-cell--empty {
33023
- display: none;
33024
- }
33025
- .settings-account-row--targets {
33026
- position: relative;
33027
- }
33028
- .settings-account-row--targets .settings-account-person-cell {
33029
- padding-right: 32px;
33030
- }
33031
- .settings-account-table .settings-account-row--targets > td.settings-account-management-cell {
33032
- position: absolute;
33033
- top: 14px;
33034
- right: 12px;
33035
- width: auto;
33036
- }
33037
33306
  .settings-account-email {
33038
33307
  font-size: 13px;
33039
33308
  }
@@ -33051,32 +33320,57 @@ Codex Fast mode prioritizes requests and may increase usage.`
33051
33320
  }
33052
33321
  }
33053
33322
 
33054
- /* Small Harness target mark: muted when nothing is copied, full-strength with a dot when it is. */
33055
- .settings-account-harness-target {
33056
- position: relative;
33057
- width: 26px;
33058
- height: 28px;
33059
- color: var(--settings-subtle);
33323
+ /* Identity extras: reset cards and the Pi import chip share one wrapping line. */
33324
+ .settings-account-row__extras {
33325
+ display: flex;
33326
+ flex-wrap: wrap;
33327
+ align-items: center;
33328
+ gap: 4px 10px;
33329
+ margin-top: 6px;
33060
33330
  }
33061
- .settings-account-harness-target:hover:not(:disabled) {
33331
+ /* Pi import chip: dashed "Import into Pi" until copied, then the entry name with a check. */
33332
+ .settings-account-pi-import {
33333
+ display: inline-flex;
33334
+ align-items: center;
33335
+ gap: 5px;
33336
+ min-height: 24px;
33337
+ padding: 2px 8px;
33338
+ color: var(--settings-muted);
33339
+ font: inherit;
33340
+ font-size: 11px;
33341
+ white-space: nowrap;
33342
+ background: transparent;
33343
+ border: 1px dashed var(--settings-border);
33344
+ border-radius: 6px;
33345
+ cursor: pointer;
33346
+ }
33347
+ .settings-account-pi-import:hover:not(:disabled) {
33062
33348
  color: var(--settings-text);
33349
+ border-style: solid;
33350
+ background: var(--settings-hover);
33063
33351
  }
33064
- .settings-account-harness-target:disabled {
33065
- opacity: 0.4;
33352
+ .settings-account-pi-import:disabled {
33353
+ opacity: 0.45;
33066
33354
  cursor: default;
33067
33355
  }
33068
- .settings-account-harness-target[data-state] {
33356
+ .settings-account-pi-import[data-state="imported"] {
33069
33357
  color: var(--settings-text);
33358
+ background: var(--settings-inset);
33359
+ border-style: solid;
33070
33360
  }
33071
- .settings-account-harness-target[data-state]::after {
33072
- content: "";
33073
- position: absolute;
33074
- top: 5px;
33075
- right: 3px;
33076
- width: 6px;
33077
- height: 6px;
33078
- border-radius: 50%;
33079
- background: var(--settings-text);
33361
+ .settings-account-pi-import code {
33362
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
33363
+ font-size: 11px;
33364
+ }
33365
+ .settings-account-pi-import > svg {
33366
+ flex: none;
33367
+ }
33368
+ .settings-account-pi-import[data-state="imported"] > svg:last-child {
33369
+ color: light-dark(#2f7d4f, #7fd19b);
33370
+ }
33371
+ .settings-account-pi-import:focus-visible {
33372
+ outline: 2px solid var(--settings-focus);
33373
+ outline-offset: 1px;
33080
33374
  }
33081
33375
  /* Dedicated "imported into Pi" section: same card language as the account table, lighter header. */
33082
33376
  .settings-pi-accounts {
@@ -33087,18 +33381,67 @@ Codex Fast mode prioritizes requests and may increase usage.`
33087
33381
  }
33088
33382
  .settings-pi-accounts__header {
33089
33383
  display: flex;
33384
+ flex-wrap: wrap;
33090
33385
  align-items: center;
33091
- gap: 8px;
33386
+ gap: 8px 12px;
33092
33387
  padding: 0 2px 12px;
33093
33388
  font-size: 13px;
33094
33389
  }
33095
- .settings-pi-accounts__header > svg {
33390
+ .settings-pi-accounts__fold {
33391
+ display: inline-flex;
33392
+ align-items: center;
33393
+ gap: 8px;
33394
+ padding: 4px 0;
33395
+ color: var(--settings-text);
33396
+ font: inherit;
33397
+ background: transparent;
33398
+ border: 0;
33399
+ cursor: pointer;
33400
+ }
33401
+ .settings-pi-accounts__fold > svg {
33096
33402
  flex: none;
33097
33403
  }
33098
- .settings-pi-accounts__header > :last-child {
33404
+ .settings-pi-accounts__fold > svg:first-child {
33405
+ color: var(--settings-muted);
33406
+ transition: transform 120ms ease;
33407
+ }
33408
+ .settings-pi-accounts__fold[aria-expanded="true"] > svg:first-child {
33409
+ transform: rotate(90deg);
33410
+ }
33411
+ .settings-pi-accounts__count {
33099
33412
  color: var(--settings-muted);
33100
33413
  font-variant-numeric: tabular-nums;
33101
33414
  }
33415
+ .settings-pi-accounts__hint {
33416
+ margin-right: auto;
33417
+ color: var(--settings-muted);
33418
+ font-size: 12px;
33419
+ }
33420
+ .settings-pi-accounts__import {
33421
+ display: inline-flex;
33422
+ align-items: center;
33423
+ gap: 6px;
33424
+ min-height: 30px;
33425
+ padding: 4px 10px;
33426
+ color: var(--settings-text);
33427
+ font: inherit;
33428
+ font-size: 12px;
33429
+ background: light-dark(#ffffff, #232326);
33430
+ border: 1px solid var(--settings-border);
33431
+ border-radius: 7px;
33432
+ cursor: pointer;
33433
+ }
33434
+ .settings-pi-accounts__import:hover:not(:disabled) {
33435
+ background: var(--settings-hover);
33436
+ }
33437
+ .settings-pi-accounts__import:disabled {
33438
+ opacity: 0.45;
33439
+ cursor: default;
33440
+ }
33441
+ .settings-pi-accounts__import[hidden],
33442
+ .settings-pi-accounts__card[hidden] {
33443
+ display: none;
33444
+ }
33102
33445
  .settings-pi-accounts__card {
33103
33446
  container-type: inline-size;
33104
33447
  overflow: hidden;
@@ -33235,6 +33578,54 @@ Codex Fast mode prioritizes requests and may increase usage.`
33235
33578
  color: var(--settings-muted);
33236
33579
  font-size: 12px;
33237
33580
  }
33581
+ .settings-credential-dialog__sources {
33582
+ display: grid;
33583
+ gap: 8px;
33584
+ margin: 0;
33585
+ padding: 0;
33586
+ border: 0;
33587
+ }
33588
+ .settings-credential-dialog__sources > legend {
33589
+ margin-bottom: 6px;
33590
+ padding: 0;
33591
+ color: var(--settings-muted);
33592
+ font-size: 12px;
33593
+ }
33594
+ .settings-credential-dialog__source {
33595
+ display: flex;
33596
+ align-items: center;
33597
+ gap: 10px;
33598
+ padding: 9px 12px;
33599
+ border: 1px solid var(--settings-border);
33600
+ border-radius: 8px;
33601
+ cursor: pointer;
33602
+ }
33603
+ .settings-credential-dialog__source:has(input:checked) {
33604
+ border-color: var(--settings-focus);
33605
+ background: var(--settings-hover);
33606
+ }
33607
+ .settings-credential-dialog__source > span {
33608
+ display: grid;
33609
+ gap: 2px;
33610
+ min-width: 0;
33611
+ }
33612
+ .settings-credential-dialog__source strong {
33613
+ font-size: 13px;
33614
+ font-weight: 500;
33615
+ overflow-wrap: anywhere;
33616
+ }
33617
+ .settings-credential-dialog__source > span > span {
33618
+ color: var(--settings-muted);
33619
+ font-size: 12px;
33620
+ }
33621
+ .settings-credential-dialog .settings-credential-dialog__source input {
33622
+ flex: none;
33623
+ width: auto;
33624
+ min-height: 0;
33625
+ margin: 0;
33626
+ padding: 0;
33627
+ accent-color: var(--settings-focus);
33628
+ }
33238
33629
  .settings-credential-dialog input {
33239
33630
  width: 100%;
33240
33631
  box-sizing: border-box;
@@ -33281,9 +33672,6 @@ Codex Fast mode prioritizes requests and may increase usage.`
33281
33672
  }
33282
33673
 
33283
33674
  @media (forced-colors: active) {
33284
- .settings-account-harness-target[data-state]::after {
33285
- background: Highlight;
33286
- }
33287
33675
  .settings-account-usage__bar {
33288
33676
  border: 1px solid CanvasText;
33289
33677
  }
@@ -35063,9 +35451,9 @@ ${accounts_default}`;
35063
35451
  const availabilityRetryDelays = [500, 1e3, 2e3, 4e3, 8e3];
35064
35452
  const usageRefreshTimers = /* @__PURE__ */ new Map();
35065
35453
  const usageRefreshAttempts = /* @__PURE__ */ new Map();
35066
- const isMountedComposer = (composer) => composer.isConnected && composer.matches(CODEX_COMPOSER_SELECTOR) && mountedByComposer.has(composer);
35454
+ const isMountedComposer = (composer) => composer.isConnected && composer.matches(CODEX_COMPOSER_SELECTOR) && !isOrbitComposer(composer) && mountedByComposer.has(composer);
35067
35455
  const isCurrentModelRequest = (mounted, generation) => isMountedComposer(mounted.composer) && mountedByComposer.get(mounted.composer) === mounted && controller.isCurrentModelRequest(mounted.composer, generation);
35068
- const isCurrentOwnershipRequest = (mounted, generation) => mounted.composer.isConnected && mountedByComposer.get(mounted.composer) === mounted && controller.isCurrentOwnershipRequest(mounted.composer, generation);
35456
+ const isCurrentOwnershipRequest = (mounted, generation) => isMountedComposer(mounted.composer) && mountedByComposer.get(mounted.composer) === mounted && controller.isCurrentOwnershipRequest(mounted.composer, generation);
35069
35457
  const notifySubmission = (composer, trigger) => {
35070
35458
  const state = controller.recordSubmission(composer);
35071
35459
  writeNewThreadAgentPreference(state.agent);
@@ -35098,6 +35486,7 @@ ${accounts_default}`;
35098
35486
  const composerAvailability = (mounted) => mounted.hostId ? hostHarnessAvailabilityState(mounted.hostId).availability : {};
35099
35487
  const composerAdapterState = (mounted) => composerClient(mounted) ? "ready" : "installing";
35100
35488
  const renderMounted = (mounted) => {
35489
+ if (!isMountedComposer(mounted.composer)) return;
35101
35490
  const accounts = composerCodexAccounts(mounted.composer);
35102
35491
  const currentCodexAccount = accounts?.accounts.find(
35103
35492
  ({ accountId }) => accountId === accounts.readyAccountId
@@ -35292,6 +35681,7 @@ ${accounts_default}`;
35292
35681
  await policy.clear();
35293
35682
  };
35294
35683
  const applyDraftAgentCarrier = (composer, agent) => {
35684
+ if (isOrbitComposer(composer)) return false;
35295
35685
  const model = controller.modelForAgent(composer, agent);
35296
35686
  const hasConcreteModel = model !== void 0;
35297
35687
  return applyAdapterAgent?.(
@@ -35309,6 +35699,7 @@ ${accounts_default}`;
35309
35699
  );
35310
35700
  };
35311
35701
  const loadThreadOwnership = async (mounted) => {
35702
+ if (!isMountedComposer(mounted.composer)) return;
35312
35703
  const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
35313
35704
  if (!threadId) {
35314
35705
  mounted.ownershipStatus = "not-required";
@@ -36387,7 +36778,7 @@ ${accounts_default}`;
36387
36778
  }
36388
36779
  };
36389
36780
  const mount = (composer) => {
36390
- if (mountedByComposer.has(composer) || !composer.isConnected || !composer.matches(CODEX_COMPOSER_SELECTOR)) {
36781
+ if (mountedByComposer.has(composer) || !composer.isConnected || isOrbitComposer(composer) || !composer.matches(CODEX_COMPOSER_SELECTOR)) {
36391
36782
  return;
36392
36783
  }
36393
36784
  const allButtons = [...composer.querySelectorAll("button")];
@@ -36475,11 +36866,12 @@ ${accounts_default}`;
36475
36866
  refreshTargetsOnNextScan = false;
36476
36867
  if (disposed) return;
36477
36868
  settingsLifecycle.refresh();
36869
+ const transferredComposers = /* @__PURE__ */ new Set();
36478
36870
  for (const [target, replacement] of pendingReplacements) {
36479
36871
  const sourceState = controller.get(replacement.source.composer);
36480
36872
  const replacementTarget = findComposerModelTarget(target);
36481
36873
  const replacementHostId = activeModelHostId(target);
36482
- if (!shouldTransferComposerState(
36874
+ if (isOrbitComposer(target) || !shouldTransferComposerState(
36483
36875
  replacement.sourceModelTarget,
36484
36876
  replacementTarget,
36485
36877
  sourceState.phase,
@@ -36490,10 +36882,12 @@ ${accounts_default}`;
36490
36882
  controllerTarget(replacementTarget, replacementHostId)
36491
36883
  )) {
36492
36884
  pendingReplacements.delete(target);
36885
+ } else {
36886
+ transferredComposers.add(replacement.source.composer);
36493
36887
  }
36494
36888
  }
36495
36889
  for (const [composer, mounted] of mountedByComposer) {
36496
- if (!composer.isConnected || !composer.matches(CODEX_COMPOSER_SELECTOR) || !mounted.control.root.isConnected) {
36890
+ if (!composer.isConnected || isOrbitComposer(composer) || !composer.matches(CODEX_COMPOSER_SELECTOR) || !mounted.control.root.isConnected) {
36497
36891
  mounted.usageRequestGeneration += 1;
36498
36892
  usageRefreshAttempts.delete(composer);
36499
36893
  const timer = usageRefreshTimers.get(composer);
@@ -36504,6 +36898,7 @@ ${accounts_default}`;
36504
36898
  mounted.codexUsageGate.dispose();
36505
36899
  disposeComposerAgentControl(mounted.control);
36506
36900
  mountedByComposer.delete(composer);
36901
+ controller.detach(composer, transferredComposers.has(composer));
36507
36902
  continue;
36508
36903
  }
36509
36904
  const state = controller.get(composer);
@@ -36575,6 +36970,7 @@ ${accounts_default}`;
36575
36970
  }
36576
36971
  };
36577
36972
  const applyComposerAgent = (composer) => {
36973
+ if (!isMountedComposer(composer)) return false;
36578
36974
  const state = controller.get(composer);
36579
36975
  const mounted = mountedByComposer.get(composer);
36580
36976
  if (mounted?.modelTarget?.[0] === "conversation") {
@@ -36768,7 +37164,7 @@ ${accounts_default}`;
36768
37164
  },
36769
37165
  isComposerEditor: (editor) => {
36770
37166
  const composer = composerForElement(editor);
36771
- return composer !== null && mountedByComposer.has(composer);
37167
+ return composer !== null && isMountedComposer(composer);
36772
37168
  },
36773
37169
  readLocale: () => settingsLifecycle.locale,
36774
37170
  // Desktop's own suggestion menu hugs the input card and covers the
@@ -36796,7 +37192,7 @@ ${accounts_default}`;
36796
37192
  }
36797
37193
  });
36798
37194
  const connectedComposers = () => [...mountedByComposer.values()].filter(
36799
- (mounted) => mounted.composer.isConnected && mounted.control.root.isConnected
37195
+ (mounted) => isMountedComposer(mounted.composer) && mounted.control.root.isConnected
36800
37196
  );
36801
37197
  const api = {
36802
37198
  remoteConnections: (request) => handleRemoteConnectionsRequest(remoteConnections, request),
@@ -36980,6 +37376,8 @@ lucide/dist/esm/icons/circle-off.mjs:
36980
37376
  lucide/dist/esm/icons/copy.mjs:
36981
37377
  lucide/dist/esm/icons/download.mjs:
36982
37378
  lucide/dist/esm/icons/external-link.mjs:
37379
+ lucide/dist/esm/icons/eye.mjs:
37380
+ lucide/dist/esm/icons/eye-off.mjs:
36983
37381
  lucide/dist/esm/icons/ellipsis.mjs:
36984
37382
  lucide/dist/esm/icons/folder-input.mjs:
36985
37383
  lucide/dist/esm/icons/grip-vertical.mjs: