premanmcp 0.16.0 → 0.16.1

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/integrations.js +104 -36
  2. package/package.json +1 -1
@@ -366,14 +366,6 @@ export async function slackCommand(args) {
366
366
  // The guided run
367
367
  // ---------------------------------------------------------------------------
368
368
 
369
- /**
370
- * "yes" | "no" | "back" -- back only offered once there is somewhere to go.
371
- *
372
- * `--yes` takes each step's own default rather than answering yes to all of
373
- * them, so a step that should not ride in on a keypress can say so. Every step
374
- * that asks defaults to yes today; the desktop app, which used to be the
375
- * exception, no longer asks at all.
376
- */
377
369
  /**
378
370
  * Ask, once, before PreMan writes into an SDK repository or a docs site.
379
371
  *
@@ -387,8 +379,14 @@ export async function slackCommand(args) {
387
379
  * which is the whole reason this moved out of the delivery run.
388
380
  */
389
381
  async function offerReleaseTargets(args, checkout, { assumeYes }) {
382
+ // SILENT is a step that did not happen rather than one that was skipped: no
383
+ // heading, and no line in the summary either. A repository with no SDK and no
384
+ // docs site has nothing to decide here, and saying so is worse than saying
385
+ // nothing.
386
+ const SILENT = { state: "skipped", silent: true };
387
+
390
388
  const integrationId = checkout?.match?.integration_id;
391
- if (!integrationId) return { state: "skipped" };
389
+ if (!integrationId) return SILENT;
392
390
 
393
391
  const token = resolveApiKey(args);
394
392
  const path = `/sdk/integrations/${integrationId}/distribution`;
@@ -399,18 +397,19 @@ async function offerReleaseTargets(args, checkout, { assumeYes }) {
399
397
  // Detection costs one root listing per repository in the installation. It
400
398
  // is the least important thing in this walk and never worth failing setup
401
399
  // over.
402
- return { state: "skipped" };
400
+ return SILENT;
403
401
  }
404
402
 
403
+ const sdkRepo = detected?.sdk_repo || "";
404
+ const docsRepo = detected?.docs_repo || "";
405
+ if (!sdkRepo && !docsRepo) return SILENT;
406
+
407
+ banner("Releases");
405
408
  if (detected?.confirmed) {
406
409
  process.stdout.write(`${MARK.ok()} Release targets already answered.\n`);
407
410
  return;
408
411
  }
409
412
 
410
- const sdkRepo = detected?.sdk_repo || "";
411
- const docsRepo = detected?.docs_repo || "";
412
- if (!sdkRepo && !docsRepo) return { state: "skipped" };
413
-
414
413
  const body = {};
415
414
  const decided = [];
416
415
  for (const [repo, field, flag, question] of [
@@ -474,6 +473,46 @@ async function askRelease(question, assumeYes) {
474
473
  return answer === "y" || answer === "yes";
475
474
  }
476
475
 
476
+ /**
477
+ * Put PreMan on screen, signed in as the account this walk just used.
478
+ *
479
+ * Returns whether the app is actually up, because that is what decides the last
480
+ * line of the walk and nothing downstream can work it out.
481
+ */
482
+ async function showDesktopSignedIn(openDesktopSignedIn, args, creds, stopOpening) {
483
+ // The same --dest the install honoured, or the launch would look for the app
484
+ // somewhere it was never copied to.
485
+ const destination = args.value("--dest", "/Applications");
486
+ const opened = await openDesktopSignedIn(creds, { destination });
487
+ stopOpening?.();
488
+ if (opened.state === "opened-signed-in") {
489
+ process.stdout.write("Opened PreMan, signed in as this account.\n");
490
+ } else if (opened.state === "not-installed") {
491
+ process.stdout.write(
492
+ `PreMan is not in ${destination} yet \u2014 open it once installed and sign in.\n`
493
+ );
494
+ } else {
495
+ // Either the session could not be handed over or this app is too old to take
496
+ // it up. Say so rather than let the customer wonder why they are looking at
497
+ // a login screen.
498
+ process.stdout.write("Opened PreMan \u2014 sign in with the account you just used.\n");
499
+ }
500
+ return opened.state !== "not-installed";
501
+ }
502
+
503
+ /** One step heading, in the one format the whole walk uses. */
504
+ function banner(name) {
505
+ process.stdout.write(`\n── ${name} ──\n`);
506
+ }
507
+
508
+ /**
509
+ * "yes" | "no" | "back" -- back only offered once there is somewhere to go.
510
+ *
511
+ * `--yes` takes each step's own default rather than answering yes to all of
512
+ * them, so a step that should not ride in on a keypress can say so. Every step
513
+ * that asks defaults to yes today; the desktop app, which used to be the
514
+ * exception, no longer asks at all.
515
+ */
477
516
  async function askStep(question, { assumeYes, canGoBack, defaultYes = true }) {
478
517
  const fallback = defaultYes ? "yes" : "no";
479
518
  if (assumeYes) return fallback;
@@ -599,6 +638,22 @@ export async function onboardCommand(
599
638
  process.stdout.write(
600
639
  `${checkout.slug} is still not shared. Add it at ${INSTALLATIONS_URL}.\n`
601
640
  );
641
+ // Nothing was connected, so this step did not finish. Returning nothing
642
+ // marks it done, which is how the walk came to print a tick directly
643
+ // under a line saying the repository is not shared — and why somebody
644
+ // would then open the app expecting to find GitHub set up and find
645
+ // "Continue with GitHub" instead. The sibling branch below already
646
+ // reports this correctly; this one simply never did.
647
+ return { state: "skipped" };
648
+ },
649
+ onSkip: () => {
650
+ // The one question in this walk that decides whether a fix from this
651
+ // code can ever land anywhere. Declining it in silence is how the gap
652
+ // stays invisible until a fix task finishes and produces nothing.
653
+ process.stdout.write(
654
+ `${MARK.skip()} ${checkout.slug} stays disconnected — fixes here cannot open pull requests.\n`
655
+ );
656
+ process.stdout.write(` Run '${cliInvocation()} github' here to change that.\n`);
602
657
  },
603
658
  });
604
659
  } else {
@@ -631,6 +686,10 @@ export async function onboardCommand(
631
686
  // inside a delivery run, on a screen most people never opened.
632
687
  steps.push({
633
688
  name: "Releases",
689
+ // Prints its own heading, and only once it knows there is a question. A
690
+ // walk that draws an empty section has told the customer something is
691
+ // missing when nothing is.
692
+ ownBanner: true,
634
693
  run: () => offerReleaseTargets(args, checkout, { assumeYes }),
635
694
  });
636
695
 
@@ -678,8 +737,21 @@ export async function onboardCommand(
678
737
  if (desktop?.state === "installed") {
679
738
  steps.push({
680
739
  name: "Desktop app",
681
- run: () => {
740
+ // Nothing to download, which is the point of this branch. It is not a
741
+ // reason to stop at the sentence: the step exists to leave the customer
742
+ // looking at PreMan, so the one run with nothing to install was also the
743
+ // only run that opened nothing, and it closed by sending someone to a
744
+ // website instead of the app already sitting on their machine.
745
+ run: async () => {
682
746
  process.stdout.write(`${MARK.ok()} PreMan desktop app already installed.\n`);
747
+ const stopOpening = showOpeningDesktop();
748
+ try {
749
+ return {
750
+ appOpened: await showDesktopSignedIn(openDesktopSignedIn, args, creds, stopOpening),
751
+ };
752
+ } finally {
753
+ stopOpening();
754
+ }
683
755
  },
684
756
  });
685
757
  } else if (!desktop) {
@@ -707,26 +779,15 @@ export async function onboardCommand(
707
779
  return installed;
708
780
  }
709
781
  stopOpening ??= showOpeningDesktop();
710
- // The same --dest the install honoured, or the launch would look
711
- // for the app somewhere it was never copied to.
712
- const destination = args.value("--dest", "/Applications");
713
- const opened = await openDesktopSignedIn(creds, { destination });
714
- stopOpening();
715
- if (opened.state === "opened-signed-in") {
716
- process.stdout.write("Opened PreMan, signed in as this account.\n");
717
- } else if (opened.state === "not-installed") {
718
- process.stdout.write(
719
- `PreMan is not in ${destination} yet \u2014 open it once installed and sign in.\n`
720
- );
721
- } else {
722
- // Either the session could not be handed over or this app is too
723
- // old to take it up. Say so rather than let the customer wonder
724
- // why they are looking at a login screen.
725
- process.stdout.write("Opened PreMan \u2014 sign in with the account you just used.\n");
726
- }
727
- // Whether the app is on screen decides what the last line of the walk
728
- // should say, and only this closure knows.
729
- return { ...installed, appOpened: opened.state !== "not-installed" };
782
+ return {
783
+ ...installed,
784
+ appOpened: await showDesktopSignedIn(
785
+ openDesktopSignedIn,
786
+ args,
787
+ creds,
788
+ stopOpening
789
+ ),
790
+ };
730
791
  } finally {
731
792
  stopOpening?.();
732
793
  }
@@ -745,7 +806,7 @@ export async function onboardCommand(
745
806
  let i = 0;
746
807
  while (i < steps.length) {
747
808
  const step = steps[i];
748
- process.stdout.write(`\n── ${step.name} ──\n`);
809
+ if (!step.ownBanner) banner(step.name);
749
810
 
750
811
  if (step.question) {
751
812
  // "back" goes to the last step that asked something, not simply to the
@@ -784,6 +845,13 @@ export async function onboardCommand(
784
845
  // at the end of a successful install: the install reports state "installed",
785
846
  // which is none of the three, so it printed as a failure with no detail.
786
847
  const reported = await step.run();
848
+ // A step that never announced itself does not belong in the summary
849
+ // either: a line reading "(skipped)" for work nobody was offered reads as
850
+ // something having gone wrong.
851
+ if (reported?.silent) {
852
+ i += 1;
853
+ continue;
854
+ }
787
855
  const state =
788
856
  { failed: "failed", skipped: "skipped", unsupported: "skipped" }[reported?.state] ||
789
857
  "done";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "premanmcp",
3
- "version": "0.16.0",
3
+ "version": "0.16.1",
4
4
  "description": "Turn APIs into agent-callable MCP tools with auth, testing, and audit logs",
5
5
  "type": "module",
6
6
  "bin": {