@dosu/cli 0.11.0-alpha.5 → 0.11.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/dosu.js +304 -50
  2. package/package.json +1 -1
package/bin/dosu.js CHANGED
@@ -4341,7 +4341,7 @@ function getSupabaseAnonKey() {
4341
4341
  function getVersionString() {
4342
4342
  return `v${VERSION}`;
4343
4343
  }
4344
- var VERSION = "0.11.0-alpha.5";
4344
+ var VERSION = "0.11.0-alpha.7";
4345
4345
 
4346
4346
  // src/debug/logger.ts
4347
4347
  import {
@@ -6439,12 +6439,13 @@ function visibleOptions(cursor, options, maxItems) {
6439
6439
  return { kind: "option", index: start + index };
6440
6440
  });
6441
6441
  }
6442
- var import_picocolors22, ACTION_ARROW, ADD_REPOSITORIES_VALUE = "__add_repositories__", GitHubRepoPrompt;
6442
+ var import_picocolors22, ACTION_ARROW, SEPARATOR_LINE, ADD_REPOSITORIES_VALUE = "__add_repositories__", REFRESH_LIST_VALUE = "__refresh_list__", GitHubRepoPrompt;
6443
6443
  var init_github_repo_prompt = __esm(() => {
6444
6444
  init_dist5();
6445
6445
  init_prompt_symbols();
6446
6446
  import_picocolors22 = __toESM(require_picocolors(), 1);
6447
6447
  ACTION_ARROW = symbol("→", ">");
6448
+ SEPARATOR_LINE = "─".repeat(30);
6448
6449
  GitHubRepoPrompt = class GitHubRepoPrompt extends x {
6449
6450
  options;
6450
6451
  message;
@@ -6461,7 +6462,8 @@ var init_github_repo_prompt = __esm(() => {
6461
6462
  this.options = options;
6462
6463
  this.maxItems = maxItems;
6463
6464
  this.selected = initialValues.filter((value) => options.some((option) => option.kind === "repo" && option.value === value));
6464
- this.cursor = Math.max(this.options.findIndex((option) => option.kind === "repo" && this.selected.includes(option.value)), 0);
6465
+ const initialCursor = this.options.findIndex((option) => option.kind === "repo" && this.selected.includes(option.value));
6466
+ this.cursor = initialCursor >= 0 ? initialCursor : this.firstFocusableIndex();
6465
6467
  this.syncValue();
6466
6468
  this.on("key", (key) => {
6467
6469
  if (key === "a") {
@@ -6473,11 +6475,11 @@ var init_github_repo_prompt = __esm(() => {
6473
6475
  switch (key) {
6474
6476
  case "left":
6475
6477
  case "up":
6476
- this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
6478
+ this.cursor = this.advanceCursor(-1);
6477
6479
  break;
6478
6480
  case "down":
6479
6481
  case "right":
6480
- this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
6482
+ this.cursor = this.advanceCursor(1);
6481
6483
  break;
6482
6484
  case "space":
6483
6485
  this.toggleCurrent();
@@ -6486,6 +6488,22 @@ var init_github_repo_prompt = __esm(() => {
6486
6488
  this.syncValue();
6487
6489
  });
6488
6490
  }
6491
+ firstFocusableIndex() {
6492
+ const idx = this.options.findIndex((option) => option.kind !== "separator");
6493
+ return idx >= 0 ? idx : 0;
6494
+ }
6495
+ advanceCursor(direction) {
6496
+ const total = this.options.length;
6497
+ if (total === 0)
6498
+ return 0;
6499
+ let next = this.cursor;
6500
+ for (let i = 0;i < total; i++) {
6501
+ next = (next + direction + total) % total;
6502
+ if (this.options[next].kind !== "separator")
6503
+ return next;
6504
+ }
6505
+ return this.cursor;
6506
+ }
6489
6507
  get currentOption() {
6490
6508
  return this.options[this.cursor] ?? this.options[0];
6491
6509
  }
@@ -6493,10 +6511,11 @@ var init_github_repo_prompt = __esm(() => {
6493
6511
  this.value = this.currentOption.kind === "action" ? this.currentOption.value : [...this.selected];
6494
6512
  }
6495
6513
  toggleCurrent() {
6496
- if (this.currentOption.kind !== "repo")
6514
+ const current = this.currentOption;
6515
+ if (current.kind !== "repo")
6497
6516
  return;
6498
- const selected = this.selected.includes(this.currentOption.value);
6499
- this.selected = selected ? this.selected.filter((value) => value !== this.currentOption.value) : [...this.selected, this.currentOption.value];
6517
+ const selected = this.selected.includes(current.value);
6518
+ this.selected = selected ? this.selected.filter((value) => value !== current.value) : [...this.selected, current.value];
6500
6519
  }
6501
6520
  toggleAll() {
6502
6521
  const repoValues = this.options.filter((option) => option.kind === "repo").map((option) => option.value);
@@ -6514,12 +6533,14 @@ ${symbolByState} ${this.message}
6514
6533
  return `${header}${import_picocolors22.default.gray(BAR)}`;
6515
6534
  }
6516
6535
  const body = visibleOptions(this.cursor, this.options, this.maxItems).map((option) => {
6517
- const actualIndex = option.kind === "ellipsis" ? -1 : option.index;
6518
6536
  if (option.kind === "ellipsis") {
6519
6537
  return `${import_picocolors22.default.gray(BAR)} ${import_picocolors22.default.dim(ELLIPSIS)}`;
6520
6538
  }
6521
- const isActive = actualIndex === this.cursor;
6522
- const current = this.options[actualIndex];
6539
+ const current = this.options[option.index];
6540
+ if (current.kind === "separator") {
6541
+ return `${import_picocolors22.default.gray(BAR)} ${import_picocolors22.default.dim(SEPARATOR_LINE)}`;
6542
+ }
6543
+ const isActive = option.index === this.cursor;
6523
6544
  const marker = current.kind === "action" ? isActive ? import_picocolors22.default.cyan(ACTION_ARROW) : import_picocolors22.default.dim(ACTION_ARROW) : this.selected.includes(current.value) ? isActive ? import_picocolors22.default.cyan(CHECKBOX_ON) : CHECKBOX_ON : isActive ? import_picocolors22.default.cyan(CHECKBOX_OFF) : CHECKBOX_OFF;
6524
6545
  const label = isActive ? import_picocolors22.default.cyan(current.label) : current.label;
6525
6546
  const hint = current.hint ? ` ${import_picocolors22.default.dim(`(${current.hint})`)}` : "";
@@ -6530,9 +6551,12 @@ ${symbolByState} ${this.message}
6530
6551
  ${import_picocolors22.default.cyan(FOOTER)}`;
6531
6552
  }
6532
6553
  submitLabel() {
6533
- if (this.value === ADD_REPOSITORIES_VALUE) {
6534
- const action = this.options.find((option) => option.kind === "action");
6535
- return action?.label ?? "Add repositories...";
6554
+ if (typeof this.value === "string") {
6555
+ const matched = this.options.find((option) => option.kind === "action" && option.value === this.value);
6556
+ if (matched && matched.kind === "action")
6557
+ return matched.label;
6558
+ const fallback = this.options.find((option) => option.kind === "action");
6559
+ return fallback && fallback.kind === "action" ? fallback.label : "Add repositories...";
6536
6560
  }
6537
6561
  const selectedValues = Array.isArray(this.value) ? this.value : [];
6538
6562
  if (selectedValues.length === 0) {
@@ -6593,19 +6617,167 @@ var SUCCESS_HTML = `<!DOCTYPE html>
6593
6617
  * { margin: 0; padding: 0; box-sizing: border-box; }
6594
6618
  body {
6595
6619
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
6596
- background: #fafafa; color: #171717; min-height: 100vh;
6597
- display: flex; align-items: center; justify-content: center; padding: 20px;
6620
+ background: #fafafa;
6621
+ color: #171717;
6622
+ min-height: 100vh;
6623
+ position: relative;
6624
+ padding: 20px;
6625
+ }
6626
+ .container {
6627
+ position: absolute;
6628
+ top: 50%;
6629
+ left: 50%;
6630
+ transform: translate(-50%, -50%);
6631
+ max-width: 520px;
6632
+ width: 100%;
6633
+ text-align: center;
6634
+ }
6635
+ .connection-visual {
6636
+ display: flex;
6637
+ align-items: center;
6638
+ justify-content: center;
6639
+ gap: 16px;
6640
+ margin-bottom: 34px;
6641
+ }
6642
+ .logo-node {
6643
+ width: 64px;
6644
+ height: 64px;
6645
+ display: grid;
6646
+ place-items: center;
6647
+ border-radius: 12px;
6648
+ background: #f7f7f7;
6649
+ }
6650
+ .dosu-node {
6651
+ box-shadow:
6652
+ 0 0 0 1px rgba(132, 204, 22, 0.2),
6653
+ 0 2px 4px rgba(132, 204, 22, 0.12),
6654
+ 0 0 0 4px rgba(132, 204, 22, 0.2);
6655
+ }
6656
+ .github-node {
6657
+ box-shadow:
6658
+ 0 0 0 1px rgba(0, 0, 0, 0.1),
6659
+ 0 2px 4px rgba(0, 0, 0, 0.6),
6660
+ 0 0 0 4px rgba(0, 0, 0, 0.1);
6661
+ }
6662
+ .logo-node svg {
6663
+ display: block;
6664
+ }
6665
+ .dosu-mark {
6666
+ width: 40px;
6667
+ height: 42px;
6668
+ }
6669
+ .connect-icon {
6670
+ width: 96px;
6671
+ height: 40px;
6672
+ color: #171717;
6673
+ }
6674
+ .github-mark {
6675
+ width: 40px;
6676
+ height: 40px;
6677
+ fill: #171717;
6678
+ }
6679
+ h1 {
6680
+ font-size: 24px;
6681
+ font-weight: 600;
6682
+ letter-spacing: -0.02em;
6683
+ margin-bottom: 18px;
6684
+ }
6685
+ .msg {
6686
+ font-size: 16px;
6687
+ color: #666;
6688
+ }
6689
+ .tip {
6690
+ position: fixed;
6691
+ left: 50%;
6692
+ bottom: 28px;
6693
+ transform: translateX(-50%);
6694
+ width: calc(100vw - 48px);
6695
+ text-align: center;
6696
+ font-size: 14px;
6697
+ line-height: 1.5;
6698
+ color: #666;
6699
+ white-space: nowrap;
6700
+ }
6701
+ .tip-rule {
6702
+ display: flex;
6703
+ align-items: center;
6704
+ gap: 12px;
6705
+ width: min(720px, 100%);
6706
+ margin-bottom: 14px;
6707
+ margin-left: auto;
6708
+ margin-right: auto;
6709
+ }
6710
+ .tip-rule::before,
6711
+ .tip-rule::after {
6712
+ content: "";
6713
+ flex: 1;
6714
+ height: 1px;
6715
+ background: #eeeeee;
6716
+ }
6717
+ .tip-dot {
6718
+ width: 3px;
6719
+ height: 3px;
6720
+ border-radius: 999px;
6721
+ background: #dddddd;
6722
+ }
6723
+ .tip-label {
6724
+ font-weight: 600;
6725
+ color: #171717;
6726
+ }
6727
+ @media (max-width: 900px) {
6728
+ .tip {
6729
+ white-space: normal;
6730
+ }
6598
6731
  }
6599
- .container { max-width: 420px; width: 100%; text-align: center; }
6600
- h1 { font-size: 24px; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 8px; }
6601
- .msg { font-size: 16px; color: #666; }
6602
6732
  </style>
6603
6733
  </head>
6604
6734
  <body>
6605
6735
  <div class="container">
6736
+ <div class="connection-visual" aria-hidden="true">
6737
+ <div class="logo-node dosu-node">
6738
+ <svg class="dosu-mark" viewBox="0 0 86 89" fill="none" xmlns="http://www.w3.org/2000/svg">
6739
+ <path d="M5.29236 12.7928L17.7593 6.68188V72.5667L5.29236 84.0618V12.7928Z" fill="#B4BB91"/>
6740
+ <path d="M18.2575 73.1196L59.1329 72.748L51.7011 82.4095L29.0338 86.291L6.23962 85.1554L18.2575 73.1196Z" fill="#778561"/>
6741
+ <path d="M17.4916 3.73633L3.58557 12.7099V83.5792C3.58557 84.7542 4.98563 85.3652 5.84705 84.566L19.6296 71.7801" stroke="black" stroke-width="6.42844" stroke-linecap="round"/>
6742
+ <mask id="github-success-dosu-mask" fill="white">
6743
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M40.704 0.518066H17.0439V76.2221H40.704H42.5805H47.8013C68.7064 76.2221 85.6533 59.2752 85.6533 38.3701C85.6533 17.465 68.7063 0.518066 47.8013 0.518066H42.5805H40.704Z"/>
6744
+ </mask>
6745
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M40.704 0.518066H17.0439V76.2221H40.704H42.5805H47.8013C68.7064 76.2221 85.6533 59.2752 85.6533 38.3701C85.6533 17.465 68.7063 0.518066 47.8013 0.518066H42.5805H40.704Z" fill="#F3F6F1"/>
6746
+ <path d="M17.0439 0.518066V-6.57919H9.94669V0.518066H17.0439ZM17.0439 76.2221H9.94669V83.3194H17.0439V76.2221ZM17.0439 7.61532H40.704V-6.57919H17.0439V7.61532ZM24.1412 76.2221V0.518066H9.94669V76.2221H24.1412ZM40.704 69.1249H17.0439V83.3194H40.704V69.1249ZM42.5805 69.1249H40.704V83.3194H42.5805V69.1249ZM47.8013 69.1249H42.5805V83.3194H47.8013V69.1249ZM78.556 38.3701C78.556 55.3555 64.7867 69.1249 47.8013 69.1249V83.3194C72.6261 83.3194 92.7505 63.1949 92.7505 38.3701H78.556ZM47.8013 7.61532C64.7866 7.61532 78.556 21.3847 78.556 38.3701H92.7505C92.7505 13.5453 72.626 -6.57919 47.8013 -6.57919V7.61532ZM42.5805 7.61532H47.8013V-6.57919H42.5805V7.61532ZM40.704 7.61532H42.5805V-6.57919H40.704V7.61532Z" fill="black" mask="url(#github-success-dosu-mask)"/>
6747
+ <path d="M68.9215 36.0135C68.9215 36.0135 65.7369 49.4738 51.4231 49.4738C37.1093 49.4738 32.5787 37.3596 32.5787 36.0135" stroke="black" stroke-width="7.69161" stroke-linecap="round" stroke-linejoin="round"/>
6748
+ <path d="M0.348633 85.4946C0.348633 85.4946 29.4856 85.8309 34.809 85.698C44.8337 85.4477 51.2872 84.402 57.5269 78.9724C62.8129 74.3727 75.1342 59.6836 75.1342 59.6836" stroke="black" stroke-width="6.16482"/>
6749
+ </svg>
6750
+ </div>
6751
+ <svg class="connect-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 98 35" fill="none">
6752
+ <path d="M0.219664 27.9926C-0.0732364 28.2855 -0.0732364 28.7604 0.219664 29.0533L4.99263 33.8262C5.28553 34.1191 5.7604 34.1191 6.05329 33.8262C6.34618 33.5334 6.34618 33.0585 6.05329 32.7656L1.81065 28.5229L6.05329 24.2803C6.34618 23.9874 6.34618 23.5125 6.05329 23.2196C5.7604 22.9268 5.28553 22.9268 4.99263 23.2196L0.219664 27.9926ZM23.4637 20.5306L23.9334 21.1154L23.4637 20.5306ZM36.7859 9.83041L37.2556 10.4151L36.7859 9.83041ZM75.0238 20.8781L75.4935 20.2934L61.7387 9.24567L61.269 9.83041L60.7993 10.4151L74.5542 21.4629L75.0238 20.8781ZM36.7859 9.83041L36.3162 9.24567L22.9941 19.9459L23.4637 20.5306L23.9334 21.1154L37.2556 10.4151L36.7859 9.83041ZM23.4637 20.5306L22.9941 19.9459C16.687 25.0117 8.83963 27.7729 0.74999 27.7729V28.5229V29.2729C9.18123 29.2729 17.3599 26.3951 23.9334 21.1154L23.4637 20.5306ZM49.0275 5.52295V4.77295C44.4047 4.77295 39.9204 6.35084 36.3162 9.24567L36.7859 9.83041L37.2556 10.4151C40.5934 7.73424 44.7463 6.27295 49.0275 6.27295V5.52295ZM61.269 9.83041L61.7387 9.24567C58.1345 6.35084 53.6502 4.77295 49.0275 4.77295V5.52295V6.27295C53.3086 6.27295 57.4615 7.73424 60.7993 10.4151L61.269 9.83041ZM96.75 28.5229V27.7729C89.0195 27.7729 81.5206 25.1343 75.4935 20.2934L75.0238 20.8781L74.5542 21.4629C80.8476 26.5177 88.6779 29.2729 96.75 29.2729V28.5229Z" fill="currentColor" fill-opacity="0.2"/>
6753
+ <path d="M19.7805 23.1111L37.5316 9.15351C40.5229 6.8015 44.2177 5.52285 48.0229 5.52285" stroke="url(#paint0_linear_cli_connect)" stroke-width="1.5"/>
6754
+ <path d="M97.2803 6.05328C97.5732 5.76039 97.5732 5.28551 97.2803 4.99262L92.5074 0.219649C92.2145 -0.0732447 91.7396 -0.0732447 91.4467 0.219649C91.1538 0.512542 91.1538 0.987416 91.4467 1.28031L95.6893 5.52295L91.4467 9.76559C91.1538 10.0585 91.1538 10.5334 91.4467 10.8262C91.7396 11.1191 92.2145 11.1191 92.5074 10.8262L97.2803 6.05328ZM36.1431 23.369L36.6005 22.7746L36.1431 23.369ZM22.6322 12.9693L22.1748 13.5637L35.6856 23.9633L36.1431 23.369L36.6005 22.7746L23.0897 12.375L22.6322 12.9693ZM60.802 23.369L61.2595 23.9633L74.3306 13.9022L73.8731 13.3078L73.4157 12.7135L60.3446 22.7746L60.802 23.369ZM73.8731 13.3078L74.3306 13.9022C80.7574 8.95531 88.6398 6.27295 96.75 6.27295V5.52295V4.77295C88.3089 4.77295 80.1047 7.56478 73.4157 12.7135L73.8731 13.3078ZM48.4725 27.5646V28.3146C53.0982 28.3146 57.594 26.7847 61.2595 23.9633L60.802 23.369L60.3446 22.7746C56.9413 25.3942 52.7672 26.8146 48.4725 26.8146V27.5646ZM36.1431 23.369L35.6856 23.9633C39.3511 26.7847 43.8469 28.3146 48.4725 28.3146V27.5646V26.8146C44.1779 26.8146 40.0038 25.3942 36.6005 22.7746L36.1431 23.369ZM0.75 5.52295V6.27295C8.50036 6.27295 16.0331 8.8363 22.1748 13.5637L22.6322 12.9693L23.0897 12.375C16.6858 7.44577 8.83133 4.77295 0.75 4.77295V5.52295Z" fill="currentColor" fill-opacity="0.2"/>
6755
+ <path d="M77.3279 11.0334L69.669 16.5439L63.01 22.0543" stroke="url(#paint1_linear_cli_connect)" stroke-width="1.5"/>
6756
+ <defs>
6757
+ <linearGradient id="paint0_linear_cli_connect" x1="46.0229" y1="14.317" x2="19.7805" y2="14.317" gradientUnits="userSpaceOnUse">
6758
+ <stop stop-color="#4285F4" stop-opacity="0"/>
6759
+ <stop offset="1" stop-color="#4285F4"/>
6760
+ </linearGradient>
6761
+ <linearGradient id="paint1_linear_cli_connect" x1="77.1134" y1="10.9348" x2="62.4434" y2="18.8207" gradientUnits="userSpaceOnUse">
6762
+ <stop stop-color="#5CB712"/>
6763
+ <stop offset="1" stop-color="#5CB712" stop-opacity="0"/>
6764
+ </linearGradient>
6765
+ </defs>
6766
+ </svg>
6767
+ <div class="logo-node github-node">
6768
+ <svg class="github-mark" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
6769
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z"/>
6770
+ </svg>
6771
+ </div>
6772
+ </div>
6606
6773
  <h1>GitHub App connected</h1>
6607
6774
  <p class="msg">You can close this tab and return to your terminal.</p>
6608
6775
  </div>
6776
+ <div class="tip">
6777
+ <div class="tip-rule" aria-hidden="true"><span class="tip-dot"></span></div>
6778
+ <span class="tip-label">Did you know?</span>
6779
+ You can use Dosu to make your coding agents faster and cheaper. Just ask your agent to use Dosu to update your AGENTS.md.
6780
+ </div>
6609
6781
  </body>
6610
6782
  </html>`;
6611
6783
  var init_installation_server = __esm(() => {
@@ -7206,8 +7378,15 @@ function buildPromptOptions(repos) {
7206
7378
  kind: "action",
7207
7379
  label: "Add repositories...",
7208
7380
  value: ADD_REPOSITORIES_VALUE,
7209
- hint: "Open GitHub and refresh this list"
7381
+ hint: "Open GitHub to install/update access"
7382
+ },
7383
+ {
7384
+ kind: "action",
7385
+ label: "Refresh list",
7386
+ value: REFRESH_LIST_VALUE,
7387
+ hint: "Re-check Dosu for new repos"
7210
7388
  },
7389
+ { kind: "separator" },
7211
7390
  ...repos.map((r) => ({ kind: "repo", label: r.slug, value: r.slug }))
7212
7391
  ];
7213
7392
  }
@@ -7218,20 +7397,23 @@ function hasNewVisibleRepository(previousRepos, nextRepos) {
7218
7397
  function sleep2(ms) {
7219
7398
  return new Promise((resolve) => setTimeout(resolve, ms));
7220
7399
  }
7221
- async function waitForRepositoryRefresh(trpc, orgID, previousRepos) {
7400
+ async function waitForRepositoryRefresh(trpc, orgID, previousRepos, opts) {
7401
+ const timeoutMs = opts?.timeoutMs ?? REPO_REFRESH_POLL_TIMEOUT_MS;
7402
+ const intervalMs = opts?.intervalMs ?? REPO_REFRESH_POLL_INTERVAL_MS;
7222
7403
  const startedAt = Date.now();
7223
7404
  let latestRepos = previousRepos;
7224
- while (Date.now() - startedAt < REPO_REFRESH_POLL_TIMEOUT_MS) {
7405
+ while (Date.now() - startedAt < timeoutMs) {
7225
7406
  const polledRepos = await fetchListForOrg(trpc, orgID);
7226
7407
  latestRepos = polledRepos.length === 0 && previousRepos.length > 0 ? previousRepos : polledRepos;
7227
7408
  if (hasNewVisibleRepository(previousRepos, latestRepos)) {
7228
- return latestRepos;
7409
+ return { repos: latestRepos, foundNew: true };
7229
7410
  }
7230
- await sleep2(REPO_REFRESH_POLL_INTERVAL_MS);
7411
+ await sleep2(intervalMs);
7231
7412
  }
7232
- return latestRepos;
7413
+ return { repos: latestRepos, foundNew: false };
7233
7414
  }
7234
- async function openGitHubInstallFlow(onInstalled) {
7415
+ async function openGitHubInstallFlow(onInstalled, opts) {
7416
+ const timeoutMs = opts?.timeoutMs ?? INSTALLATION_TIMEOUT_MS;
7235
7417
  const { server, installationPromise } = await startInstallationCallbackServer();
7236
7418
  let timeoutId;
7237
7419
  try {
@@ -7251,9 +7433,9 @@ async function openGitHubInstallFlow(onInstalled) {
7251
7433
  }
7252
7434
  const timeout = new Promise((resolve) => {
7253
7435
  timeoutId = setTimeout(() => {
7254
- logger.warn("setup", `GitHub install timed out after ${INSTALLATION_TIMEOUT_MS / 1000}s`);
7436
+ logger.warn("setup", `GitHub install timed out after ${timeoutMs / 1000}s`);
7255
7437
  resolve(null);
7256
- }, INSTALLATION_TIMEOUT_MS);
7438
+ }, timeoutMs);
7257
7439
  });
7258
7440
  const s = Y2();
7259
7441
  s.start("Waiting for GitHub install to complete...");
@@ -7263,7 +7445,7 @@ async function openGitHubInstallFlow(onInstalled) {
7263
7445
  ]);
7264
7446
  if (result === null) {
7265
7447
  s.stop("Timed out");
7266
- M2.warn(`Didn't hear back from the browser after ${Math.floor(INSTALLATION_TIMEOUT_MS / 1000)}s. Run \`dosu setup\` again once you've completed the install.`);
7448
+ M2.warn(`Didn't hear back from the browser after ${Math.floor(timeoutMs / 1000)}s. Run \`dosu setup\` again once you've completed the install.`);
7267
7449
  return null;
7268
7450
  }
7269
7451
  if (onInstalled) {
@@ -7399,14 +7581,26 @@ ${lines}`);
7399
7581
  return { advance: false, has_connected_repo: deployed.length > 0 };
7400
7582
  }
7401
7583
  if (selected === ADD_REPOSITORIES_VALUE) {
7402
- let refreshedRepos = repos;
7584
+ let refresh = { repos, foundNew: false };
7403
7585
  const installationID = await openGitHubInstallFlow(async () => {
7404
- refreshedRepos = await waitForRepositoryRefresh(trpc, orgID, repos);
7405
- });
7586
+ refresh = await waitForRepositoryRefresh(trpc, orgID, repos, opts.refresh);
7587
+ }, opts.install);
7406
7588
  if (installationID === null) {
7407
7589
  return { advance: false, has_connected_repo: deployed.length > 0 };
7408
7590
  }
7409
- repos = refreshedRepos;
7591
+ repos = refresh.repos;
7592
+ if (!refresh.foundNew) {
7593
+ M2.warn("GitHub may still be syncing. Pick 'Refresh list' in a moment to re-check — sync usually completes within a minute.");
7594
+ }
7595
+ continue;
7596
+ }
7597
+ if (selected === REFRESH_LIST_VALUE) {
7598
+ const s2 = Y2();
7599
+ s2.start("Refreshing repository list...");
7600
+ const previousIds = new Set(repos.map((r) => r.repository_id));
7601
+ repos = await fetchListForOrg(trpc, orgID);
7602
+ const newCount = repos.filter((r) => !previousIds.has(r.repository_id)).length;
7603
+ s2.stop(newCount > 0 ? `Found ${newCount} new repo${newCount === 1 ? "" : "s"}` : "List refreshed — no new repos yet");
7410
7604
  continue;
7411
7605
  }
7412
7606
  const slugs = selected;
@@ -8102,12 +8296,14 @@ body {
8102
8296
  background: #fafafa;
8103
8297
  color: #171717;
8104
8298
  min-height: 100vh;
8105
- display: flex;
8106
- align-items: center;
8107
- justify-content: center;
8299
+ position: relative;
8108
8300
  padding: 20px;
8109
8301
  }
8110
8302
  .container {
8303
+ position: absolute;
8304
+ top: 50%;
8305
+ left: 50%;
8306
+ transform: translate(-50%, -50%);
8111
8307
  max-width: 420px;
8112
8308
  width: 100%;
8113
8309
  text-align: center;
@@ -8122,23 +8318,60 @@ h1 {
8122
8318
  font-weight: 600;
8123
8319
  color: #171717;
8124
8320
  letter-spacing: -0.02em;
8125
- margin-bottom: 8px;
8126
- }
8127
- .subtitle {
8128
- font-size: 16px;
8129
- color: #666;
8130
- margin-bottom: 8px;
8321
+ margin-bottom: 18px;
8131
8322
  }
8132
8323
  .email {
8133
8324
  font-size: 14px;
8134
8325
  color: #999;
8135
- margin-bottom: 28px;
8326
+ margin-bottom: 18px;
8136
8327
  }
8137
8328
  .close-msg {
8138
- margin-top: 4px;
8139
8329
  font-size: 16px;
8140
8330
  color: #666;
8141
8331
  }
8332
+ .tip {
8333
+ position: fixed;
8334
+ left: 50%;
8335
+ bottom: 28px;
8336
+ transform: translateX(-50%);
8337
+ width: calc(100vw - 48px);
8338
+ text-align: center;
8339
+ font-size: 14px;
8340
+ line-height: 1.5;
8341
+ color: #666;
8342
+ white-space: nowrap;
8343
+ }
8344
+ .tip-rule {
8345
+ display: flex;
8346
+ align-items: center;
8347
+ gap: 12px;
8348
+ width: min(720px, 100%);
8349
+ margin-bottom: 14px;
8350
+ margin-left: auto;
8351
+ margin-right: auto;
8352
+ }
8353
+ .tip-rule::before,
8354
+ .tip-rule::after {
8355
+ content: "";
8356
+ flex: 1;
8357
+ height: 1px;
8358
+ background: #eeeeee;
8359
+ }
8360
+ .tip-dot {
8361
+ width: 3px;
8362
+ height: 3px;
8363
+ border-radius: 999px;
8364
+ background: #dddddd;
8365
+ }
8366
+ .tip-label {
8367
+ font-weight: 600;
8368
+ color: #171717;
8369
+ }
8370
+ @media (max-width: 900px) {
8371
+ .tip {
8372
+ white-space: normal;
8373
+ }
8374
+ }
8142
8375
  </style>
8143
8376
  </head>
8144
8377
  <body>
@@ -8158,10 +8391,14 @@ h1 {
8158
8391
  </svg>
8159
8392
  </div>
8160
8393
  <h1>Authentication Successful</h1>
8161
- <p class="subtitle">You're all set. The CLI is now authenticated.</p>
8162
8394
  ${emailLine}
8163
8395
  <p class="close-msg">You can close this tab and return to your terminal.</p>
8164
8396
  </div>
8397
+ <div class="tip">
8398
+ <div class="tip-rule" aria-hidden="true"><span class="tip-dot"></span></div>
8399
+ <span class="tip-label">Did you know?</span>
8400
+ You can use Dosu to make your coding agents faster and cheaper. Just ask your agent to use Dosu to update your AGENTS.md.
8401
+ </div>
8165
8402
  </body>
8166
8403
  </html>`;
8167
8404
  }
@@ -8349,6 +8586,8 @@ __export(exports_flow2, {
8349
8586
  runInstallSkill: () => runInstallSkill,
8350
8587
  isStdioOnly: () => isStdioOnly
8351
8588
  });
8589
+ import { existsSync as existsSync9 } from "node:fs";
8590
+ import { join as join19 } from "node:path";
8352
8591
  async function runSetup(opts = {}) {
8353
8592
  logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
8354
8593
  Ie("Dosu CLI Setup");
@@ -8439,7 +8678,11 @@ async function runSetup(opts = {}) {
8439
8678
  }
8440
8679
  }
8441
8680
  if (mcpConfiguredThisRun) {
8442
- showTryItOutPrompt(cfg.mode);
8681
+ showTryItOutPrompt({
8682
+ mode: cfg.mode,
8683
+ docsImported: choices.connectGitHub && githubOnboardingDone,
8684
+ hasAgentsMd: existsSync9(join19(process.cwd(), "AGENTS.md"))
8685
+ });
8443
8686
  }
8444
8687
  if (cfg.mode === MODE_OSS) {
8445
8688
  Se("Setup complete! Using open-source libraries only.\n\nTips: Run `dosu setup --mode cloud` to connect your own repos.");
@@ -8799,12 +9042,12 @@ async function stepSelectTools(detected) {
8799
9042
  return {
8800
9043
  label: p2.name(),
8801
9044
  value: p2.id(),
8802
- hint: configured ? "configured" : undefined
9045
+ hint: configured ? "configured — untick to remove" : undefined
8803
9046
  };
8804
9047
  });
8805
9048
  const preselected = detected.filter((p2) => configuredMap.get(p2.id())).map((p2) => p2.id());
8806
9049
  const selected = await fe({
8807
- message: "Select agents to configure or update",
9050
+ message: "Select agents — tick to configure, untick to remove",
8808
9051
  options,
8809
9052
  initialValues: preselected
8810
9053
  });
@@ -8875,8 +9118,19 @@ ${lines}`);
8875
9118
  M2.success("All agents already configured. No changes needed.");
8876
9119
  }
8877
9120
  }
8878
- function showTryItOutPrompt(mode) {
8879
- const prompt = mode === MODE_OSS ? `What can Dosu help me with? Pick an open source library related to my project and explain how it works.` : `Please use Dosu to host my AGENTS.md`;
9121
+ function showTryItOutPrompt(opts = {}) {
9122
+ const prompt = (() => {
9123
+ if (opts.mode === MODE_OSS) {
9124
+ return `What can Dosu help me with? Pick an open source library related to my project and explain how it works.`;
9125
+ }
9126
+ if (opts.docsImported) {
9127
+ return `Use Dosu to summarize the most important docs in my repo.`;
9128
+ }
9129
+ if (opts.hasAgentsMd) {
9130
+ return `Please use Dosu to host my AGENTS.md`;
9131
+ }
9132
+ return `Ask Dosu to draft an AGENTS.md for this project.`;
9133
+ })();
8880
9134
  M2.message(`Try it out! Paste this into your agent:
8881
9135
 
8882
9136
  ${info(prompt)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.11.0-alpha.5",
3
+ "version": "0.11.0-alpha.7",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",