@codexhost/cli-linux-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.
@@ -15849,6 +15849,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15849
15849
  ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }]
15850
15850
  ];
15851
15851
 
15852
+ // ../../node_modules/lucide/dist/esm/icons/eye.mjs
15853
+ var Eye = [
15854
+ [
15855
+ "path",
15856
+ {
15857
+ 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"
15858
+ }
15859
+ ],
15860
+ ["circle", { cx: "12", cy: "12", r: "3" }]
15861
+ ];
15862
+
15863
+ // ../../node_modules/lucide/dist/esm/icons/eye-off.mjs
15864
+ var EyeOff = [
15865
+ [
15866
+ "path",
15867
+ {
15868
+ 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"
15869
+ }
15870
+ ],
15871
+ ["path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }],
15872
+ [
15873
+ "path",
15874
+ {
15875
+ 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"
15876
+ }
15877
+ ],
15878
+ ["path", { d: "m2 2 20 20" }]
15879
+ ];
15880
+
15852
15881
  // ../../node_modules/lucide/dist/esm/icons/ellipsis.mjs
15853
15882
  var Ellipsis = [
15854
15883
  ["circle", { cx: "12", cy: "12", r: "1" }],
@@ -16092,6 +16121,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16092
16121
  info: Info,
16093
16122
  "external-link": ExternalLink,
16094
16123
  refresh: RefreshCw,
16124
+ eye: Eye,
16125
+ "eye-off": EyeOff,
16095
16126
  unavailable: CircleOff,
16096
16127
  alert: TriangleAlert,
16097
16128
  check: CircleCheck,
@@ -17977,6 +18008,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17977
18008
  color: var(--settings-muted);
17978
18009
  font-variant-numeric: tabular-nums;
17979
18010
  }
18011
+ /* Email privacy belongs to the identity column, so it sits beside the account count on the
18012
+ left; quota controls (used/remaining, refresh) stay together on the right. */
18013
+ .settings-account-privacy-toggle {
18014
+ margin-left: -8px;
18015
+ }
18016
+ .settings-account-privacy-toggle[aria-pressed="true"] {
18017
+ color: var(--settings-text);
18018
+ background: var(--settings-active);
18019
+ }
17980
18020
  .settings-account-search {
17981
18021
  display: flex;
17982
18022
  align-items: center;
@@ -18046,10 +18086,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18046
18086
  background: light-dark(#f8f8fa, #202024);
18047
18087
  font-size: 11px;
18048
18088
  font-weight: 500;
18049
- text-align: left;
18050
- }
18051
- .settings-account-table th:last-child {
18052
- text-align: right;
18089
+ text-align: center;
18053
18090
  }
18054
18091
  .settings-account-table td {
18055
18092
  padding: 17px 16px;
@@ -18369,26 +18406,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18369
18406
  border: 0;
18370
18407
  }
18371
18408
  .settings-account-person-cell,
18372
- .settings-account-management-cell,
18409
+ .settings-account-usage-cell[colspan="2"],
18373
18410
  .settings-account-usage-cell--message,
18374
18411
  .settings-account-balance-cell {
18375
18412
  grid-column: 1 / -1;
18376
18413
  }
18377
- .settings-account-table .settings-account-row > td.settings-account-management-cell--empty {
18378
- display: none;
18379
- }
18380
- .settings-account-row--targets {
18381
- position: relative;
18382
- }
18383
- .settings-account-row--targets .settings-account-person-cell {
18384
- padding-right: 32px;
18385
- }
18386
- .settings-account-table .settings-account-row--targets > td.settings-account-management-cell {
18387
- position: absolute;
18388
- top: 14px;
18389
- right: 12px;
18390
- width: auto;
18391
- }
18392
18414
  .settings-account-email {
18393
18415
  font-size: 13px;
18394
18416
  }
@@ -18406,32 +18428,57 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18406
18428
  }
18407
18429
  }
18408
18430
 
18409
- /* Small Harness target mark: muted when nothing is copied, full-strength with a dot when it is. */
18410
- .settings-account-harness-target {
18411
- position: relative;
18412
- width: 26px;
18413
- height: 28px;
18414
- color: var(--settings-subtle);
18431
+ /* Identity extras: reset cards and the Pi import chip share one wrapping line. */
18432
+ .settings-account-row__extras {
18433
+ display: flex;
18434
+ flex-wrap: wrap;
18435
+ align-items: center;
18436
+ gap: 4px 10px;
18437
+ margin-top: 6px;
18438
+ }
18439
+ /* Pi import chip: dashed "Import into Pi" until copied, then the entry name with a check. */
18440
+ .settings-account-pi-import {
18441
+ display: inline-flex;
18442
+ align-items: center;
18443
+ gap: 5px;
18444
+ min-height: 24px;
18445
+ padding: 2px 8px;
18446
+ color: var(--settings-muted);
18447
+ font: inherit;
18448
+ font-size: 11px;
18449
+ white-space: nowrap;
18450
+ background: transparent;
18451
+ border: 1px dashed var(--settings-border);
18452
+ border-radius: 6px;
18453
+ cursor: pointer;
18415
18454
  }
18416
- .settings-account-harness-target:hover:not(:disabled) {
18455
+ .settings-account-pi-import:hover:not(:disabled) {
18417
18456
  color: var(--settings-text);
18457
+ border-style: solid;
18458
+ background: var(--settings-hover);
18418
18459
  }
18419
- .settings-account-harness-target:disabled {
18420
- opacity: 0.4;
18460
+ .settings-account-pi-import:disabled {
18461
+ opacity: 0.45;
18421
18462
  cursor: default;
18422
18463
  }
18423
- .settings-account-harness-target[data-state] {
18464
+ .settings-account-pi-import[data-state="imported"] {
18424
18465
  color: var(--settings-text);
18466
+ background: var(--settings-inset);
18467
+ border-style: solid;
18425
18468
  }
18426
- .settings-account-harness-target[data-state]::after {
18427
- content: "";
18428
- position: absolute;
18429
- top: 5px;
18430
- right: 3px;
18431
- width: 6px;
18432
- height: 6px;
18433
- border-radius: 50%;
18434
- background: var(--settings-text);
18469
+ .settings-account-pi-import code {
18470
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
18471
+ font-size: 11px;
18472
+ }
18473
+ .settings-account-pi-import > svg {
18474
+ flex: none;
18475
+ }
18476
+ .settings-account-pi-import[data-state="imported"] > svg:last-child {
18477
+ color: light-dark(#2f7d4f, #7fd19b);
18478
+ }
18479
+ .settings-account-pi-import:focus-visible {
18480
+ outline: 2px solid var(--settings-focus);
18481
+ outline-offset: 1px;
18435
18482
  }
18436
18483
  /* Dedicated "imported into Pi" section: same card language as the account table, lighter header. */
18437
18484
  .settings-pi-accounts {
@@ -18442,18 +18489,67 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18442
18489
  }
18443
18490
  .settings-pi-accounts__header {
18444
18491
  display: flex;
18492
+ flex-wrap: wrap;
18445
18493
  align-items: center;
18446
- gap: 8px;
18494
+ gap: 8px 12px;
18447
18495
  padding: 0 2px 12px;
18448
18496
  font-size: 13px;
18449
18497
  }
18450
- .settings-pi-accounts__header > svg {
18498
+ .settings-pi-accounts__fold {
18499
+ display: inline-flex;
18500
+ align-items: center;
18501
+ gap: 8px;
18502
+ padding: 4px 0;
18503
+ color: var(--settings-text);
18504
+ font: inherit;
18505
+ background: transparent;
18506
+ border: 0;
18507
+ cursor: pointer;
18508
+ }
18509
+ .settings-pi-accounts__fold > svg {
18451
18510
  flex: none;
18452
18511
  }
18453
- .settings-pi-accounts__header > :last-child {
18512
+ .settings-pi-accounts__fold > svg:first-child {
18513
+ color: var(--settings-muted);
18514
+ transition: transform 120ms ease;
18515
+ }
18516
+ .settings-pi-accounts__fold[aria-expanded="true"] > svg:first-child {
18517
+ transform: rotate(90deg);
18518
+ }
18519
+ .settings-pi-accounts__count {
18454
18520
  color: var(--settings-muted);
18455
18521
  font-variant-numeric: tabular-nums;
18456
18522
  }
18523
+ .settings-pi-accounts__hint {
18524
+ margin-right: auto;
18525
+ color: var(--settings-muted);
18526
+ font-size: 12px;
18527
+ }
18528
+ .settings-pi-accounts__import {
18529
+ display: inline-flex;
18530
+ align-items: center;
18531
+ gap: 6px;
18532
+ min-height: 30px;
18533
+ padding: 4px 10px;
18534
+ color: var(--settings-text);
18535
+ font: inherit;
18536
+ font-size: 12px;
18537
+ background: light-dark(#ffffff, #232326);
18538
+ border: 1px solid var(--settings-border);
18539
+ border-radius: 7px;
18540
+ cursor: pointer;
18541
+ }
18542
+ .settings-pi-accounts__import:hover:not(:disabled) {
18543
+ background: var(--settings-hover);
18544
+ }
18545
+ .settings-pi-accounts__import:disabled {
18546
+ opacity: 0.45;
18547
+ cursor: default;
18548
+ }
18549
+ .settings-pi-accounts__import[hidden],
18550
+ .settings-pi-accounts__card[hidden] {
18551
+ display: none;
18552
+ }
18457
18553
  .settings-pi-accounts__card {
18458
18554
  container-type: inline-size;
18459
18555
  overflow: hidden;
@@ -18590,6 +18686,54 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18590
18686
  color: var(--settings-muted);
18591
18687
  font-size: 12px;
18592
18688
  }
18689
+ .settings-credential-dialog__sources {
18690
+ display: grid;
18691
+ gap: 8px;
18692
+ margin: 0;
18693
+ padding: 0;
18694
+ border: 0;
18695
+ }
18696
+ .settings-credential-dialog__sources > legend {
18697
+ margin-bottom: 6px;
18698
+ padding: 0;
18699
+ color: var(--settings-muted);
18700
+ font-size: 12px;
18701
+ }
18702
+ .settings-credential-dialog__source {
18703
+ display: flex;
18704
+ align-items: center;
18705
+ gap: 10px;
18706
+ padding: 9px 12px;
18707
+ border: 1px solid var(--settings-border);
18708
+ border-radius: 8px;
18709
+ cursor: pointer;
18710
+ }
18711
+ .settings-credential-dialog__source:has(input:checked) {
18712
+ border-color: var(--settings-focus);
18713
+ background: var(--settings-hover);
18714
+ }
18715
+ .settings-credential-dialog__source > span {
18716
+ display: grid;
18717
+ gap: 2px;
18718
+ min-width: 0;
18719
+ }
18720
+ .settings-credential-dialog__source strong {
18721
+ font-size: 13px;
18722
+ font-weight: 500;
18723
+ overflow-wrap: anywhere;
18724
+ }
18725
+ .settings-credential-dialog__source > span > span {
18726
+ color: var(--settings-muted);
18727
+ font-size: 12px;
18728
+ }
18729
+ .settings-credential-dialog .settings-credential-dialog__source input {
18730
+ flex: none;
18731
+ width: auto;
18732
+ min-height: 0;
18733
+ margin: 0;
18734
+ padding: 0;
18735
+ accent-color: var(--settings-focus);
18736
+ }
18593
18737
  .settings-credential-dialog input {
18594
18738
  width: 100%;
18595
18739
  box-sizing: border-box;
@@ -18636,9 +18780,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18636
18780
  }
18637
18781
 
18638
18782
  @media (forced-colors: active) {
18639
- .settings-account-harness-target[data-state]::after {
18640
- background: Highlight;
18641
- }
18642
18783
  .settings-account-usage__bar {
18643
18784
  border: 1px solid CanvasText;
18644
18785
  }
@@ -18693,9 +18834,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18693
18834
 
18694
18835
  // src/settings/credential-import-messages.ts
18695
18836
  var credentialImportEnglish = {
18696
- column: "Use in Harness",
18697
18837
  sectionTitle: "Accounts in Pi",
18698
- sectionEmpty: "No logins in Pi yet. Use the Pi mark on a Codex or Grok account above to import one.",
18838
+ sectionHint: "Copy a local Codex or Grok login into a Pi model entry.",
18839
+ sectionImport: "Import account",
18840
+ sectionEmpty: "No logins in Pi yet. Use \u201CImport account\u201D, or \u201CImport into Pi\u201D on a Codex or Grok account above.",
18699
18841
  rowReimport: "Copy again",
18700
18842
  rowRemove: "Remove",
18701
18843
  othersTitle: "Pi's own logins",
@@ -18708,6 +18850,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18708
18850
  entry: "Entry in Pi",
18709
18851
  name: "Model entry name",
18710
18852
  source: "Source account",
18853
+ sourceCurrent: "Current login",
18854
+ sourceImported: "Already in Pi as {name}/\u2026; another entry can be added",
18711
18855
  preview: "Creates {name}/\u2026 in Pi. Existing Provider configurations remain unchanged.",
18712
18856
  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.",
18713
18857
  confirm: "Confirm import",
@@ -18723,9 +18867,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18723
18867
  close: "Done"
18724
18868
  };
18725
18869
  var credentialImportChinese = {
18726
- column: "\u7528\u4E8E Harness",
18727
18870
  sectionTitle: "Pi \u4E2D\u7684\u8D26\u53F7",
18728
- 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",
18871
+ sectionHint: "\u628A Codex\u3001Grok \u7684\u672C\u5730\u767B\u5F55\u590D\u5236\u6210 Pi \u7684\u6A21\u578B\u5165\u53E3",
18872
+ sectionImport: "\u5BFC\u5165\u8D26\u53F7",
18873
+ 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",
18729
18874
  rowReimport: "\u91CD\u65B0\u5BFC\u5165",
18730
18875
  rowRemove: "\u79FB\u9664",
18731
18876
  othersTitle: "Pi \u81EA\u6709\u914D\u7F6E",
@@ -18738,6 +18883,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18738
18883
  entry: "Pi \u4E2D\u7684\u5165\u53E3",
18739
18884
  name: "\u6A21\u578B\u5165\u53E3\u540D\u79F0",
18740
18885
  source: "\u6765\u6E90\u8D26\u53F7",
18886
+ sourceCurrent: "\u5F53\u524D\u767B\u5F55",
18887
+ sourceImported: "\u5DF2\u5BFC\u5165\u4E3A {name}/\u2026\uFF0C\u53EF\u518D\u65B0\u589E\u4E00\u4E2A\u5165\u53E3",
18741
18888
  preview: "\u5C06\u5728 Pi \u4E2D\u65B0\u589E {name}/\u2026\uFF0C\u4FDD\u7559\u5168\u90E8\u5DF2\u6709 Provider \u914D\u7F6E\u3002",
18742
18889
  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",
18743
18890
  confirm: "\u786E\u8BA4\u5BFC\u5165",
@@ -18911,6 +19058,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18911
19058
  accountCreditsFailed: "Could not load limits",
18912
19059
  accountCreditsRetry: "Retry",
18913
19060
  accountCreditsRefresh: "Refresh limits",
19061
+ accountEmailsHide: "Hide emails",
19062
+ accountEmailsShow: "Show emails",
18914
19063
  accountLoadFailed: "Could not load Codex Accounts.",
18915
19064
  accountCreditsUsed: "Used",
18916
19065
  accountCreditsResetAt: "Quota resets: {time}",
@@ -19181,6 +19330,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
19181
19330
  accountCreditsFailed: "\u989D\u5EA6\u8BFB\u53D6\u5931\u8D25",
19182
19331
  accountCreditsRetry: "\u91CD\u8BD5",
19183
19332
  accountCreditsRefresh: "\u5237\u65B0\u989D\u5EA6",
19333
+ accountEmailsHide: "\u9690\u85CF\u90AE\u7BB1",
19334
+ accountEmailsShow: "\u663E\u793A\u90AE\u7BB1",
19184
19335
  accountLoadFailed: "\u65E0\u6CD5\u52A0\u8F7D Codex \u8D26\u53F7\u3002",
19185
19336
  accountCreditsUsed: "\u5DF2\u7528",
19186
19337
  accountCreditsResetAt: "\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4\uFF1A{time}",
@@ -21188,9 +21339,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
21188
21339
  }
21189
21340
  };
21190
21341
  update.addEventListener("click", () => void run("update"));
21191
- signal.addEventListener("abort", render, { once: true });
21342
+ const owner = document2.defaultView;
21343
+ let checkFrame = null;
21344
+ let checkTimer = null;
21345
+ signal.addEventListener(
21346
+ "abort",
21347
+ () => {
21348
+ if (checkFrame !== null) owner?.cancelAnimationFrame(checkFrame);
21349
+ if (checkTimer !== null) owner?.clearTimeout(checkTimer);
21350
+ render();
21351
+ },
21352
+ { once: true }
21353
+ );
21354
+ status.textContent = messages.harnessVersionChecking;
21192
21355
  render();
21193
- void run("check");
21356
+ if (!signal.aborted && owner?.requestAnimationFrame) {
21357
+ checkFrame = owner.requestAnimationFrame(() => {
21358
+ checkFrame = null;
21359
+ if (signal.aborted) return;
21360
+ checkTimer = owner.setTimeout(() => {
21361
+ checkTimer = null;
21362
+ void run("check");
21363
+ }, 0);
21364
+ });
21365
+ } else {
21366
+ void run("check");
21367
+ }
21194
21368
  return panel;
21195
21369
  }
21196
21370
 
@@ -21669,6 +21843,30 @@ ${error51.stderrTail}`] : []
21669
21843
  const hostNames = /* @__PURE__ */ new Map();
21670
21844
  let latestSnapshot = null;
21671
21845
  let disposeHostScroller = () => void 0;
21846
+ let disposed = false;
21847
+ let renderQueued = false;
21848
+ let renderFrame = null;
21849
+ const scheduleRender = () => {
21850
+ if (disposed || context.signal.aborted || renderQueued) return;
21851
+ renderQueued = true;
21852
+ const flush = () => {
21853
+ renderFrame = null;
21854
+ renderQueued = false;
21855
+ if (!disposed && !context.signal.aborted) {
21856
+ render(diagnostics?.snapshot() ?? latestSnapshot);
21857
+ }
21858
+ };
21859
+ if (document2.defaultView?.requestAnimationFrame) {
21860
+ renderFrame = document2.defaultView.requestAnimationFrame(flush);
21861
+ } else {
21862
+ queueMicrotask(flush);
21863
+ }
21864
+ };
21865
+ const cancelRender = () => {
21866
+ disposed = true;
21867
+ if (renderFrame !== null) document2.defaultView?.cancelAnimationFrame(renderFrame);
21868
+ renderFrame = null;
21869
+ };
21672
21870
  const diagnostics = getDiagnostics();
21673
21871
  const installs = diagnostics ? harnessInstallStore(diagnostics) : null;
21674
21872
  const runRefresh = () => {
@@ -22062,20 +22260,20 @@ ${error51.stderrTail}`] : []
22062
22260
  () => {
22063
22261
  }
22064
22262
  );
22065
- const unsubscribeGroup = groupPreference.subscribe(
22066
- () => render(diagnostics?.snapshot() ?? latestSnapshot)
22067
- );
22263
+ const unsubscribeGroup = groupPreference.subscribe(scheduleRender);
22068
22264
  if (!diagnostics) {
22069
22265
  refresh.disabled = true;
22070
22266
  return () => {
22267
+ cancelRender();
22071
22268
  disposeHostScroller();
22072
22269
  unsubscribeGroup();
22073
22270
  };
22074
22271
  }
22075
22272
  refresh.addEventListener("click", runRefresh);
22076
- const unsubscribe = diagnostics.subscribe(() => render(diagnostics.snapshot()));
22077
- const unsubscribeInstalls = installs?.subscribe(() => render(diagnostics.snapshot()));
22273
+ const unsubscribe = diagnostics.subscribe(scheduleRender);
22274
+ const unsubscribeInstalls = installs?.subscribe(scheduleRender);
22078
22275
  return () => {
22276
+ cancelRender();
22079
22277
  disposeHostScroller();
22080
22278
  unsubscribeInstalls?.();
22081
22279
  unsubscribe();
@@ -22989,8 +23187,28 @@ ${error51.stderrTail}`] : []
22989
23187
  });
22990
23188
  }
22991
23189
 
23190
+ // src/settings/account-privacy.ts
23191
+ var EMAIL_PATTERN = /([^\s@]+)@([^\s@]+\.[^\s@]+)/gu;
23192
+ var MASK = "****";
23193
+ function maskEmailLocalPart(local) {
23194
+ const chars = Array.from(local);
23195
+ if (chars.length <= 1) return MASK;
23196
+ if (chars.length <= 4) return `${chars[0]}${MASK}${chars.length > 2 ? chars.at(-1) : ""}`;
23197
+ return `${chars.slice(0, 2).join("")}${MASK}${chars.slice(-2).join("")}`;
23198
+ }
23199
+ function maskEmails(text) {
23200
+ return text.replace(
23201
+ EMAIL_PATTERN,
23202
+ (_match, local, domain2) => `${maskEmailLocalPart(local)}@${domain2}`
23203
+ );
23204
+ }
23205
+ function accountDisplayText(text, hideEmails) {
23206
+ return hideEmails ? maskEmails(text) : text;
23207
+ }
23208
+
22992
23209
  // src/settings/credential-imports.ts
22993
23210
  var TARGET_HARNESS_ID = "pi";
23211
+ var SECTION_IMPORT_KEY = "section:import";
22994
23212
  var VENDOR_AGENTS = {
22995
23213
  "openai-codex": "codex",
22996
23214
  xai: "grok"
@@ -23025,9 +23243,17 @@ ${error51.stderrTail}`] : []
23025
23243
  let busy = false;
23026
23244
  let dialog;
23027
23245
  let othersExpanded = false;
23246
+ let sectionExpanded = true;
23247
+ let hideEmails = false;
23248
+ const shown = (text) => accountDisplayText(text, hideEmails);
23028
23249
  const targetButtons = /* @__PURE__ */ new Map();
23029
23250
  const importedRecords = () => snapshot.targets.find((target) => target.harnessId === TARGET_HARNESS_ID)?.imports ?? [];
23030
23251
  const sourceOf = (record2) => snapshot.sources.find((source) => source.id === record2.source.id);
23252
+ const piTarget = () => snapshot.targets.find((candidate) => candidate.harnessId === TARGET_HARNESS_ID);
23253
+ const compatibleSources = () => {
23254
+ const target = piTarget();
23255
+ return target ? snapshot.sources.filter((source) => target.providers.includes(source.provider)) : [];
23256
+ };
23031
23257
  const section = document2.createElement("section");
23032
23258
  section.className = "settings-pi-accounts";
23033
23259
  section.hidden = true;
@@ -23035,12 +23261,46 @@ ${error51.stderrTail}`] : []
23035
23261
  section.setAttribute("aria-label", messages.sectionTitle);
23036
23262
  const sectionHeader = document2.createElement("div");
23037
23263
  sectionHeader.className = "settings-pi-accounts__header";
23264
+ const sectionToggle = document2.createElement("button");
23265
+ sectionToggle.type = "button";
23266
+ sectionToggle.className = "settings-pi-accounts__fold";
23267
+ sectionToggle.setAttribute("aria-expanded", "true");
23038
23268
  const sectionTitle = document2.createElement("strong");
23039
23269
  sectionTitle.textContent = messages.sectionTitle;
23040
23270
  const sectionCount = document2.createElement("span");
23041
- sectionHeader.append(createRendererAgentIcon("pi", 16, document2), sectionTitle, sectionCount);
23271
+ sectionCount.className = "settings-pi-accounts__count";
23272
+ sectionToggle.append(
23273
+ createRendererSettingsIcon("chevron-right", 14),
23274
+ createRendererAgentIcon("pi", 16, document2),
23275
+ sectionTitle,
23276
+ sectionCount
23277
+ );
23278
+ const sectionHint = document2.createElement("span");
23279
+ sectionHint.className = "settings-pi-accounts__hint";
23280
+ sectionHint.textContent = messages.sectionHint;
23281
+ const sectionImport = document2.createElement("button");
23282
+ sectionImport.type = "button";
23283
+ sectionImport.className = "settings-pi-accounts__import";
23284
+ sectionImport.setAttribute("aria-haspopup", "dialog");
23285
+ sectionImport.append(createRendererSettingsIcon("add", 14), messages.sectionImport);
23286
+ sectionImport.addEventListener("click", () => {
23287
+ const sources = compatibleSources();
23288
+ const free = sources.find(
23289
+ (source2) => !importedRecords().some((record2) => record2.source.id === source2.id)
23290
+ );
23291
+ const source = free ?? sources[0];
23292
+ if (source) openDialog("add", { source, choose: true }, SECTION_IMPORT_KEY);
23293
+ });
23294
+ sectionHeader.append(sectionToggle, sectionHint, sectionImport);
23042
23295
  const card = document2.createElement("div");
23043
23296
  card.className = "settings-pi-accounts__card";
23297
+ card.id = "settings-pi-accounts-card";
23298
+ sectionToggle.setAttribute("aria-controls", card.id);
23299
+ sectionToggle.addEventListener("click", () => {
23300
+ sectionExpanded = !sectionExpanded;
23301
+ card.hidden = !sectionExpanded;
23302
+ sectionToggle.setAttribute("aria-expanded", String(sectionExpanded));
23303
+ });
23044
23304
  const othersToggle = document2.createElement("button");
23045
23305
  othersToggle.type = "button";
23046
23306
  othersToggle.className = "settings-pi-accounts__toggle";
@@ -23081,15 +23341,15 @@ ${error51.stderrTail}`] : []
23081
23341
  row.className = "settings-pi-accounts__row";
23082
23342
  row.tabIndex = -1;
23083
23343
  row.dataset.importName = record2.name;
23084
- row.setAttribute("aria-label", record2.source.label);
23344
+ row.setAttribute("aria-label", shown(record2.source.label));
23085
23345
  const agent = KNOWN_RENDERER_AGENTS.find((candidate) => candidate === record2.source.harnessId);
23086
23346
  const mark = createMark(agent);
23087
23347
  const identity = document2.createElement("div");
23088
23348
  identity.className = "settings-pi-accounts__identity";
23089
23349
  const label = document2.createElement("strong");
23090
23350
  label.className = "settings-account-email";
23091
- label.textContent = record2.source.label;
23092
- label.title = record2.source.label;
23351
+ label.textContent = shown(record2.source.label);
23352
+ label.title = label.textContent;
23093
23353
  label.translate = false;
23094
23354
  const meta3 = document2.createElement("div");
23095
23355
  meta3.className = "settings-account-metadata";
@@ -23119,7 +23379,7 @@ ${error51.stderrTail}`] : []
23119
23379
  reimport.type = "button";
23120
23380
  reimport.className = "settings-account-action";
23121
23381
  reimport.textContent = messages.rowReimport;
23122
- reimport.setAttribute("aria-label", `${messages.reimport}: ${record2.source.label}`);
23382
+ reimport.setAttribute("aria-label", `${messages.reimport}: ${shown(record2.source.label)}`);
23123
23383
  reimport.disabled = busy || !source;
23124
23384
  reimport.title = messages.reimport;
23125
23385
  reimport.addEventListener("click", () => {
@@ -23129,7 +23389,7 @@ ${error51.stderrTail}`] : []
23129
23389
  remove.type = "button";
23130
23390
  remove.className = "settings-account-action settings-pi-accounts__remove";
23131
23391
  remove.textContent = messages.rowRemove;
23132
- remove.setAttribute("aria-label", `${messages.remove}: ${record2.source.label}`);
23392
+ remove.setAttribute("aria-label", `${messages.remove}: ${shown(record2.source.label)}`);
23133
23393
  remove.disabled = busy;
23134
23394
  remove.addEventListener("click", () => openDialog("remove", { record: record2 }, `row:${record2.name}`));
23135
23395
  if (source) actions.append(reimport);
@@ -23145,14 +23405,14 @@ ${error51.stderrTail}`] : []
23145
23405
  const agent = login.vendor ? VENDOR_AGENTS[login.vendor] : void 0;
23146
23406
  row.setAttribute(
23147
23407
  "aria-label",
23148
- [login.label ?? login.provider, agent && RENDERER_AGENT_LABELS[agent]].filter(Boolean).join(" \xB7 ")
23408
+ [shown(login.label ?? login.provider), agent && RENDERER_AGENT_LABELS[agent]].filter(Boolean).join(" \xB7 ")
23149
23409
  );
23150
23410
  const mark = createMark(agent);
23151
23411
  const identity = document2.createElement("div");
23152
23412
  identity.className = "settings-pi-accounts__identity";
23153
23413
  const title = document2.createElement("strong");
23154
23414
  title.className = "settings-account-email";
23155
- title.textContent = login.label ?? login.provider;
23415
+ title.textContent = shown(login.label ?? login.provider);
23156
23416
  title.title = title.textContent;
23157
23417
  title.translate = false;
23158
23418
  const meta3 = document2.createElement("div");
@@ -23173,11 +23433,14 @@ ${error51.stderrTail}`] : []
23173
23433
  return row;
23174
23434
  };
23175
23435
  const renderSection = () => {
23176
- const target = snapshot.targets.find((candidate) => candidate.harnessId === TARGET_HARNESS_ID);
23436
+ const target = piTarget();
23177
23437
  section.hidden = !target;
23178
23438
  const records = importedRecords();
23179
23439
  const others = target?.others ?? [];
23180
23440
  sectionCount.textContent = String(records.length + others.length);
23441
+ card.hidden = !sectionExpanded;
23442
+ sectionImport.hidden = compatibleSources().length === 0;
23443
+ sectionImport.disabled = busy;
23181
23444
  rows.clear();
23182
23445
  if (records.length + others.length === 0) {
23183
23446
  const empty = document2.createElement("p");
@@ -23240,6 +23503,9 @@ ${error51.stderrTail}`] : []
23240
23503
  let state = initial;
23241
23504
  let mode = initialMode;
23242
23505
  let nameInput;
23506
+ let nameEdited = false;
23507
+ let sourceRadios = [];
23508
+ let refreshPreview = () => void 0;
23243
23509
  const command = (text, onClick, variant = "secondary") => {
23244
23510
  const button2 = document2.createElement("button");
23245
23511
  button2.type = "button";
@@ -23263,9 +23529,50 @@ ${error51.stderrTail}`] : []
23263
23529
  paragraph.textContent = text;
23264
23530
  return paragraph;
23265
23531
  };
23532
+ const sourcePicker = (choices) => {
23533
+ const group = document2.createElement("fieldset");
23534
+ group.className = "settings-credential-dialog__sources";
23535
+ const legend = document2.createElement("legend");
23536
+ legend.textContent = messages.source;
23537
+ group.append(legend);
23538
+ for (const choice of choices) {
23539
+ const option = document2.createElement("label");
23540
+ option.className = "settings-credential-dialog__source";
23541
+ const radio = document2.createElement("input");
23542
+ radio.type = "radio";
23543
+ radio.name = "settings-credential-source";
23544
+ radio.value = choice.id;
23545
+ radio.checked = choice.id === state.source?.id;
23546
+ sourceRadios.push(radio);
23547
+ const copy = document2.createElement("span");
23548
+ const label = document2.createElement("strong");
23549
+ label.textContent = shown(choice.label);
23550
+ label.translate = false;
23551
+ const existing = importedRecords().find((record2) => record2.source.id === choice.id);
23552
+ const agent = KNOWN_RENDERER_AGENTS.find((candidate) => candidate === choice.harnessId);
23553
+ const detail = document2.createElement("span");
23554
+ detail.textContent = [
23555
+ agent && RENDERER_AGENT_LABELS[agent] || choice.harnessId,
23556
+ existing ? messages.sourceImported.replace("{name}", existing.name) : messages.sourceCurrent
23557
+ ].join(" \xB7 ");
23558
+ copy.append(label, detail);
23559
+ radio.addEventListener("change", () => {
23560
+ if (!radio.checked) return;
23561
+ state = { ...state, source: choice };
23562
+ if (nameInput && !nameEdited) {
23563
+ nameInput.value = defaultImportName(choice, importedRecords());
23564
+ }
23565
+ refreshPreview();
23566
+ });
23567
+ option.append(radio, copy);
23568
+ group.append(option);
23569
+ }
23570
+ return group;
23571
+ };
23266
23572
  const setBusy = (value) => {
23267
23573
  for (const child of controls.children) child.disabled = value;
23268
23574
  if (nameInput) nameInput.disabled = value;
23575
+ for (const radio of sourceRadios) radio.disabled = value;
23269
23576
  };
23270
23577
  const submit = async (request, next) => {
23271
23578
  error51.textContent = "";
@@ -23293,6 +23600,7 @@ ${error51.stderrTail}`] : []
23293
23600
  mode = next;
23294
23601
  error51.textContent = "";
23295
23602
  nameInput = void 0;
23603
+ sourceRadios = [];
23296
23604
  body.replaceChildren();
23297
23605
  controls.replaceChildren();
23298
23606
  const { source, record: record2 } = state;
@@ -23301,7 +23609,9 @@ ${error51.stderrTail}`] : []
23301
23609
  title.textContent = mode === "add" ? messages.add : messages.reimport;
23302
23610
  modal.setAttribute("aria-label", title.textContent);
23303
23611
  const active = source ?? record2?.source;
23304
- if (active) body.append(line(messages.source, active.label));
23612
+ const choices = mode === "add" && state.choose ? compatibleSources() : [];
23613
+ if (choices.length > 1) body.append(sourcePicker(choices));
23614
+ else if (active) body.append(line(messages.source, shown(active.label)));
23305
23615
  const input = document2.createElement("input");
23306
23616
  input.type = "text";
23307
23617
  input.maxLength = 48;
@@ -23309,6 +23619,9 @@ ${error51.stderrTail}`] : []
23309
23619
  input.spellcheck = false;
23310
23620
  input.value = record2?.name ?? (source ? defaultImportName(source, importedRecords()) : "codex");
23311
23621
  input.readOnly = Boolean(record2);
23622
+ input.addEventListener("input", () => {
23623
+ nameEdited = true;
23624
+ });
23312
23625
  nameInput = input;
23313
23626
  const label = document2.createElement("label");
23314
23627
  label.className = "settings-credential-dialog__field";
@@ -23320,6 +23633,7 @@ ${error51.stderrTail}`] : []
23320
23633
  preview.textContent = (mode === "reimport" ? messages.reimportPreview : messages.preview).replace("{name}", input.value);
23321
23634
  };
23322
23635
  input.addEventListener("input", update);
23636
+ refreshPreview = update;
23323
23637
  update();
23324
23638
  body.append(label, preview, note(messages.warning));
23325
23639
  controls.append(
@@ -23327,7 +23641,8 @@ ${error51.stderrTail}`] : []
23327
23641
  command(
23328
23642
  messages.confirm,
23329
23643
  async () => {
23330
- if (!source) return;
23644
+ const source2 = state.source;
23645
+ if (!source2) return;
23331
23646
  if (!credentialImportNameSchema.safeParse(input.value).success) {
23332
23647
  error51.textContent = messages.invalidName;
23333
23648
  input.focus();
@@ -23336,7 +23651,7 @@ ${error51.stderrTail}`] : []
23336
23651
  await submit(
23337
23652
  {
23338
23653
  action: mode === "reimport" ? "reimport" : "import",
23339
- sourceId: source.id,
23654
+ sourceId: source2.id,
23340
23655
  name: record2?.name ?? input.value,
23341
23656
  confirmed: true
23342
23657
  },
@@ -23378,7 +23693,7 @@ ${error51.stderrTail}`] : []
23378
23693
  modal.addEventListener("close", () => {
23379
23694
  modal.remove();
23380
23695
  dialog = void 0;
23381
- const target = returnKey ? targetButtons.get(returnKey) ?? rows.get(returnKey.replace(/^row:/, "")) : void 0;
23696
+ const target = returnKey ? returnKey === SECTION_IMPORT_KEY ? sectionImport : targetButtons.get(returnKey) ?? rows.get(returnKey.replace(/^row:/, "")) : void 0;
23382
23697
  (target?.isConnected ? target : section).focus();
23383
23698
  });
23384
23699
  show(initialMode);
@@ -23388,6 +23703,12 @@ ${error51.stderrTail}`] : []
23388
23703
  signal.addEventListener("abort", () => dialog?.remove(), { once: true });
23389
23704
  renderSection();
23390
23705
  return {
23706
+ /** Mask the middle of email addresses in the section and dialogs (screen sharing). */
23707
+ setHideEmails(value) {
23708
+ if (hideEmails === value) return;
23709
+ hideEmails = value;
23710
+ renderSection();
23711
+ },
23391
23712
  /** Dedicated "imported into Pi" section, rendered below the account table. */
23392
23713
  section,
23393
23714
  refresh: async () => {
@@ -23409,20 +23730,33 @@ ${error51.stderrTail}`] : []
23409
23730
  const key = `${harnessId}:${accountLabel}:import`;
23410
23731
  const button2 = document2.createElement("button");
23411
23732
  button2.type = "button";
23412
- button2.className = "settings-icon-button settings-account-harness-target";
23733
+ button2.className = "settings-account-pi-import";
23413
23734
  button2.dataset.accountFocus = key;
23414
23735
  button2.disabled = busy;
23415
- if (record2) button2.dataset.state = "imported";
23416
23736
  const hint = record2 ? messages.importedHint.replace("{name}", record2.name) : messages.add;
23417
23737
  button2.title = hint;
23418
23738
  button2.setAttribute("aria-label", hint);
23419
- button2.setAttribute("aria-haspopup", "dialog");
23420
- button2.append(createRendererAgentIcon("pi", 16, document2));
23739
+ button2.append(createRendererAgentIcon("pi", 12, document2));
23740
+ if (record2) {
23741
+ button2.dataset.state = "imported";
23742
+ const name = document2.createElement("code");
23743
+ name.textContent = `${record2.name}/\u2026`;
23744
+ name.translate = false;
23745
+ button2.append(name, createRendererSettingsIcon("check", 12));
23746
+ } else {
23747
+ button2.setAttribute("aria-haspopup", "dialog");
23748
+ button2.append(messages.add);
23749
+ }
23421
23750
  button2.addEventListener("click", () => {
23422
23751
  if (!record2) {
23423
23752
  openDialog("add", { source }, key);
23424
23753
  return;
23425
23754
  }
23755
+ if (!sectionExpanded) {
23756
+ sectionExpanded = true;
23757
+ renderSection();
23758
+ sectionToggle.setAttribute("aria-expanded", "true");
23759
+ }
23426
23760
  const row = rows.get(record2.name);
23427
23761
  row?.scrollIntoView({ block: "nearest", behavior: "smooth" });
23428
23762
  row?.focus();
@@ -23803,37 +24137,35 @@ ${error51.stderrTail}`] : []
23803
24137
  return { cells: [cell], continuationCells: [] };
23804
24138
  }
23805
24139
  const { rows, additional } = splitUsageWindows(state.credits, messages, filter);
23806
- const onlyRow = rows.length === 1 ? rows[0] : void 0;
23807
- if (additional.length && onlyRow && !Object.keys(onlyRow.columns).length) rows.pop();
23808
- for (let index = 0; index < additional.length; index += 2) {
23809
- const first = additional[index];
23810
- const second = additional[index + 1];
23811
- rows.push({
23812
- columns: {
23813
- ...first ? { five_hour: first } : {},
23814
- ...second ? { seven_day: second } : {}
23815
- }
23816
- });
24140
+ const windows = [
24141
+ ...rows.flatMap(
24142
+ (row) => ["five_hour", "seven_day"].flatMap(
24143
+ (period) => row.columns[period] ? [row.columns[period]] : []
24144
+ )
24145
+ ),
24146
+ ...additional
24147
+ ];
24148
+ const packed = [];
24149
+ for (let index = 0; index < windows.length; index += 2) {
24150
+ const pair = windows.slice(index, index + 2);
24151
+ packed.push(
24152
+ pair.map((window2) => {
24153
+ const cell = document2.createElement("td");
24154
+ cell.className = "settings-account-usage-cell";
24155
+ if (pair.length === 1) cell.colSpan = 2;
24156
+ cell.append(renderUsageWindow(document2, window2, messages, display));
24157
+ return cell;
24158
+ })
24159
+ );
23817
24160
  }
23818
- const renderCells = (row) => ["five_hour", "seven_day"].map((period) => {
24161
+ if (packed.length === 0) {
23819
24162
  const cell = document2.createElement("td");
23820
- cell.className = "settings-account-usage-cell";
23821
- const window2 = row.columns[period];
23822
- if (window2) cell.append(renderUsageWindow(document2, window2, messages, display));
23823
- else {
23824
- const missing = document2.createElement("div");
23825
- missing.className = "settings-account-usage__missing";
23826
- const dash = document2.createElement("span");
23827
- dash.textContent = "\u2014";
23828
- dash.setAttribute("aria-hidden", "true");
23829
- missing.append(dash);
23830
- cell.append(missing);
23831
- }
23832
- return cell;
23833
- });
23834
- const [firstRow = { columns: {} }, ...continuations] = rows;
23835
- const cells = renderCells(firstRow);
23836
- const continuationCells = continuations.map(renderCells);
24163
+ cell.colSpan = 2;
24164
+ cell.className = "settings-account-usage-cell settings-account-usage-cell--message";
24165
+ cell.textContent = messages.accountCreditsEmpty;
24166
+ packed.push([cell]);
24167
+ }
24168
+ const [cells = [], ...continuationCells] = packed;
23837
24169
  return { cells, continuationCells };
23838
24170
  }
23839
24171
  function renderAccountResetCredits(document2, credits, messages) {
@@ -23927,14 +24259,14 @@ ${error51.stderrTail}`] : []
23927
24259
  table.className = "settings-account-table";
23928
24260
  table.setAttribute("aria-label", messages.pageLabels.accounts);
23929
24261
  const columns = document2.createElement("colgroup");
23930
- for (const width of [32, 24, 24, 20]) {
24262
+ for (const width of [36, 32, 32]) {
23931
24263
  const column = document2.createElement("col");
23932
24264
  column.style.width = `${width}%`;
23933
24265
  columns.append(column);
23934
24266
  }
23935
24267
  const head = document2.createElement("thead");
23936
24268
  const row = document2.createElement("tr");
23937
- const headers = Array.from({ length: 3 }, (_, index) => {
24269
+ const headers = Array.from({ length: 2 }, (_, index) => {
23938
24270
  const cell = document2.createElement("th");
23939
24271
  cell.scope = index === 1 ? "colgroup" : "col";
23940
24272
  if (index === 1) cell.colSpan = 2;
@@ -23942,11 +24274,7 @@ ${error51.stderrTail}`] : []
23942
24274
  return cell;
23943
24275
  });
23944
24276
  const updateDisplay = (display) => {
23945
- const labels = [
23946
- messages.accountColumnAccount,
23947
- accountUsageColumnLabel(display, messages),
23948
- messages.credentialImports.column
23949
- ];
24277
+ const labels = [messages.accountColumnAccount, accountUsageColumnLabel(display, messages)];
23950
24278
  headers.forEach((cell, index) => {
23951
24279
  cell.textContent = labels[index] ?? "";
23952
24280
  });
@@ -23998,11 +24326,13 @@ ${error51.stderrTail}`] : []
23998
24326
  person.append(input.mark, identity);
23999
24327
  return person;
24000
24328
  }
24001
- function createTargetCell(document2, action) {
24002
- const cell = document2.createElement("td");
24003
- cell.className = action ? "settings-account-management-cell" : "settings-account-management-cell settings-account-management-cell--empty";
24004
- if (action) cell.append(action);
24005
- return cell;
24329
+ function appendAccountExtras(cell, items) {
24330
+ const present = items.filter((item) => Boolean(item));
24331
+ if (present.length === 0) return;
24332
+ const extras = cell.ownerDocument.createElement("div");
24333
+ extras.className = "settings-account-row__extras";
24334
+ extras.append(...present);
24335
+ cell.append(extras);
24006
24336
  }
24007
24337
  function renderAccountBalance(document2, messages, balance) {
24008
24338
  const cell = document2.createElement("td");
@@ -24027,8 +24357,8 @@ ${error51.stderrTail}`] : []
24027
24357
  row.dataset.accountId = account.accountId;
24028
24358
  row.dataset.accountFocus = `${account.accountId}:row`;
24029
24359
  row.tabIndex = -1;
24030
- const name = codexAccountDisplayName(account);
24031
- row.setAttribute("aria-label", name.full);
24360
+ const name = accountDisplayText(codexAccountDisplayName(account).full, input.hideEmails === true);
24361
+ row.setAttribute("aria-label", name);
24032
24362
  const personCell = document2.createElement("td");
24033
24363
  personCell.className = "settings-account-person-cell";
24034
24364
  const mark = document2.createElement("div");
@@ -24038,7 +24368,7 @@ ${error51.stderrTail}`] : []
24038
24368
  mark.append(createRendererAgentIcon("codex", 26, document2));
24039
24369
  personCell.append(
24040
24370
  createAccountPerson(document2, messages, {
24041
- name: name.full,
24371
+ name,
24042
24372
  agent: "Codex",
24043
24373
  plan: accountPlanLabel(account.planType),
24044
24374
  highlighted: account.planType === "pro" || account.planType === "prolite",
@@ -24054,8 +24384,6 @@ ${error51.stderrTail}`] : []
24054
24384
  input.onRetry,
24055
24385
  account.planType === "pro" ? "weekly-only" : "all"
24056
24386
  );
24057
- const actionsCell = createTargetCell(document2, input.importAction);
24058
- if (input.importAction) row.className += " settings-account-row--targets";
24059
24387
  const continuationRows = usage.continuationCells.map((cells) => {
24060
24388
  const continuation = document2.createElement("tr");
24061
24389
  continuation.className = "settings-account-row settings-account-quota-continuation-row";
@@ -24066,18 +24394,19 @@ ${error51.stderrTail}`] : []
24066
24394
  if (continuationRows.length > 0) {
24067
24395
  personCell.rowSpan = continuationRows.length + 1;
24068
24396
  personCell.className += " settings-account-spanning-cell";
24069
- actionsCell.rowSpan = continuationRows.length + 1;
24070
- actionsCell.className += " settings-account-spanning-cell";
24071
24397
  }
24072
- row.append(personCell, ...usage.cells, actionsCell);
24398
+ row.append(personCell, ...usage.cells);
24073
24399
  const reset = input.usage?.status === "ready" ? renderAccountResetCredits(document2, input.usage.credits, messages) : null;
24074
- if (!reset) return [row, ...continuationRows];
24400
+ if (!reset) {
24401
+ appendAccountExtras(personCell, [input.importAction]);
24402
+ return [row, ...continuationRows];
24403
+ }
24075
24404
  const detailsRow = document2.createElement("tr");
24076
24405
  detailsRow.className = "settings-account-details-row";
24077
24406
  detailsRow.id = `settings-account-reset-${++resetDetailsSequence}`;
24078
24407
  detailsRow.hidden = !input.resetExpanded;
24079
24408
  const detailsCell = document2.createElement("td");
24080
- detailsCell.colSpan = 4;
24409
+ detailsCell.colSpan = 3;
24081
24410
  detailsCell.append(reset.details);
24082
24411
  detailsRow.append(detailsCell);
24083
24412
  reset.summary.dataset.accountFocus = `${account.accountId}:reset`;
@@ -24088,15 +24417,18 @@ ${error51.stderrTail}`] : []
24088
24417
  reset.summary.setAttribute("aria-expanded", String(!detailsRow.hidden));
24089
24418
  input.onResetExpanded(!detailsRow.hidden);
24090
24419
  });
24091
- personCell.append(reset.summary);
24420
+ appendAccountExtras(personCell, [reset.summary, input.importAction]);
24092
24421
  return [row, ...continuationRows, detailsRow];
24093
24422
  }
24094
- function renderHarnessAccountRows(document2, account, messages, display, importAction) {
24423
+ function renderHarnessAccountRows(document2, account, messages, display, importAction, hideEmails = false) {
24095
24424
  const row = document2.createElement("tr");
24096
24425
  row.className = "settings-account-row";
24097
24426
  row.dataset.harnessId = account.harnessId;
24098
24427
  row.tabIndex = -1;
24099
- const name = account.email ?? account.label ?? account.harnessName;
24428
+ const name = accountDisplayText(
24429
+ account.email ?? account.label ?? account.harnessName,
24430
+ hideEmails
24431
+ );
24100
24432
  row.setAttribute("aria-label", name);
24101
24433
  const personCell = document2.createElement("td");
24102
24434
  personCell.className = "settings-account-person-cell";
@@ -24121,9 +24453,8 @@ ${error51.stderrTail}`] : []
24121
24453
  () => void 0,
24122
24454
  account.harnessId === "grok" ? "weekly-only" : "all"
24123
24455
  ) : renderAccountBalance(document2, messages, account.balance);
24124
- const managementCell = createTargetCell(document2, importAction);
24125
- if (importAction) row.className += " settings-account-row--targets";
24126
24456
  personCell.title = messages.accountNativeManagementHint.replace("{harness}", account.harnessName);
24457
+ appendAccountExtras(personCell, [importAction]);
24127
24458
  const continuationRows = usage.continuationCells.map((cells) => {
24128
24459
  const continuation = document2.createElement("tr");
24129
24460
  continuation.className = "settings-account-row settings-account-quota-continuation-row";
@@ -24134,10 +24465,8 @@ ${error51.stderrTail}`] : []
24134
24465
  if (continuationRows.length > 0) {
24135
24466
  personCell.rowSpan = continuationRows.length + 1;
24136
24467
  personCell.className += " settings-account-spanning-cell";
24137
- managementCell.rowSpan = continuationRows.length + 1;
24138
- managementCell.className += " settings-account-spanning-cell";
24139
24468
  }
24140
- row.append(personCell, ...usage.cells, managementCell);
24469
+ row.append(personCell, ...usage.cells);
24141
24470
  return [row, ...continuationRows];
24142
24471
  }
24143
24472
 
@@ -24305,6 +24634,26 @@ ${error51.stderrTail}`] : []
24305
24634
  refreshUsage.title = messages.accountCreditsRefresh;
24306
24635
  refreshUsage.setAttribute("aria-label", messages.accountCreditsRefresh);
24307
24636
  refreshUsage.append(createRendererSettingsIcon("refresh", 16));
24637
+ let hideEmails = false;
24638
+ const privacyToggle = document2.createElement("button");
24639
+ privacyToggle.type = "button";
24640
+ privacyToggle.className = "settings-icon-button settings-account-privacy-toggle";
24641
+ const updatePrivacyToggle = () => {
24642
+ const label = hideEmails ? messages.accountEmailsShow : messages.accountEmailsHide;
24643
+ privacyToggle.title = label;
24644
+ privacyToggle.setAttribute("aria-label", label);
24645
+ privacyToggle.setAttribute("aria-pressed", String(hideEmails));
24646
+ privacyToggle.replaceChildren(
24647
+ createRendererSettingsIcon(hideEmails ? "eye-off" : "eye", 16)
24648
+ );
24649
+ };
24650
+ updatePrivacyToggle();
24651
+ privacyToggle.addEventListener("click", () => {
24652
+ hideEmails = !hideEmails;
24653
+ updatePrivacyToggle();
24654
+ credentialImports.setHideEmails(hideEmails);
24655
+ render();
24656
+ });
24308
24657
  refreshUsage.addEventListener("click", () => {
24309
24658
  usageByAccountId.clear();
24310
24659
  loadUsage(accounts);
@@ -24312,7 +24661,7 @@ ${error51.stderrTail}`] : []
24312
24661
  void credentialImports.refresh();
24313
24662
  });
24314
24663
  search.addEventListener("input", () => render());
24315
- toolbar.append(connected, searchWrapper, displayControls, refreshUsage);
24664
+ toolbar.append(connected, privacyToggle, searchWrapper, displayControls, refreshUsage);
24316
24665
  const list = document2.createElement("div");
24317
24666
  list.className = "settings-account-list";
24318
24667
  const { table, body, updateDisplay } = createAccountsTable(document2, messages);
@@ -24357,7 +24706,7 @@ ${error51.stderrTail}`] : []
24357
24706
  if (visibleAccounts.length + visibleHarnessAccounts.length === 0) {
24358
24707
  const emptyRow = document2.createElement("tr");
24359
24708
  const emptyCell = document2.createElement("td");
24360
- emptyCell.colSpan = 4;
24709
+ emptyCell.colSpan = 3;
24361
24710
  emptyCell.className = "settings-account-empty";
24362
24711
  emptyCell.textContent = query ? messages.accountNoMatches : messages.accountEmpty;
24363
24712
  emptyRow.append(emptyCell);
@@ -24367,10 +24716,6 @@ ${error51.stderrTail}`] : []
24367
24716
  body.append(
24368
24717
  ...renderAccountRows(document2, account, messages, {
24369
24718
  current: accountPhase === "ready" && account.accountId === currentAccountId,
24370
- importAction: credentialImports.button(
24371
- "codex",
24372
- codexAccountDisplayName(account).full
24373
- ),
24374
24719
  usage: usageByAccountId.get(account.accountId),
24375
24720
  display: usageDisplay,
24376
24721
  resetExpanded: expandedResetAccounts.has(account.accountId),
@@ -24381,7 +24726,12 @@ ${error51.stderrTail}`] : []
24381
24726
  onResetExpanded: (open) => {
24382
24727
  if (open) expandedResetAccounts.add(account.accountId);
24383
24728
  else expandedResetAccounts.delete(account.accountId);
24384
- }
24729
+ },
24730
+ importAction: credentialImports.button(
24731
+ "codex",
24732
+ codexAccountDisplayName(account).full
24733
+ ),
24734
+ hideEmails
24385
24735
  })
24386
24736
  );
24387
24737
  }
@@ -24395,7 +24745,8 @@ ${error51.stderrTail}`] : []
24395
24745
  credentialImports.button(
24396
24746
  account.harnessId,
24397
24747
  account.email ?? account.label ?? account.harnessName
24398
- )
24748
+ ),
24749
+ hideEmails
24399
24750
  )
24400
24751
  );
24401
24752
  }
@@ -24502,8 +24853,8 @@ ${error51.stderrTail}`] : []
24502
24853
  } catch {
24503
24854
  }
24504
24855
  const harnessAccounts = createHarnessAccounts(context.signal, getClient, render);
24505
- void credentialImports.refresh();
24506
24856
  void harnessAccounts.refresh();
24857
+ void credentialImports.refresh();
24507
24858
  load();
24508
24859
  return () => {
24509
24860
  stopCountdowns();
@@ -27892,6 +28243,8 @@ lucide/dist/esm/icons/circle-off.mjs:
27892
28243
  lucide/dist/esm/icons/copy.mjs:
27893
28244
  lucide/dist/esm/icons/download.mjs:
27894
28245
  lucide/dist/esm/icons/external-link.mjs:
28246
+ lucide/dist/esm/icons/eye.mjs:
28247
+ lucide/dist/esm/icons/eye-off.mjs:
27895
28248
  lucide/dist/esm/icons/ellipsis.mjs:
27896
28249
  lucide/dist/esm/icons/folder-input.mjs:
27897
28250
  lucide/dist/esm/icons/grip-vertical.mjs: