pushary 1.9.34 → 1.9.35

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.35
4
+
5
+ - When you run setup yourself in a terminal and your phone cannot get notifications yet, it no longer stops with exit code 6. It asks you to open the Pushary app and allow notifications, waits up to 10 minutes for your phone, then sends a test notification. Press Enter to skip the wait. Runs with `--yes`, `--agents` or `--json`, and computers with the Pushary Mac app, keep the single check.
6
+
3
7
  ## 1.9.34
4
8
 
5
9
  - Live questions keep waiting when a tool poll ends; agent instructions no longer cancel them after one retry.
@@ -3,7 +3,7 @@ import {
3
3
  connectDevice,
4
4
  connectExistingApp,
5
5
  printConnectInstructions
6
- } from "../chunk-3FOPVVNO.js";
6
+ } from "../chunk-43H2FUNN.js";
7
7
  import "../chunk-3EGEA4KH.js";
8
8
  import "../chunk-QCGNGEGE.js";
9
9
  import {
@@ -79,7 +79,7 @@ import {
79
79
  reachVerdict,
80
80
  roundTripEvidence,
81
81
  verifyRoundTrip
82
- } from "../chunk-3FOPVVNO.js";
82
+ } from "../chunk-43H2FUNN.js";
83
83
  import "../chunk-3EGEA4KH.js";
84
84
  import "../chunk-QCGNGEGE.js";
85
85
  import {
@@ -129,8 +129,9 @@ import {
129
129
  pairingEscapeApplies,
130
130
  printConnectInstructions,
131
131
  roundTripEvidence,
132
- verifyRoundTrip
133
- } from "../chunk-3FOPVVNO.js";
132
+ verifyRoundTrip,
133
+ waitForYourPhone
134
+ } from "../chunk-43H2FUNN.js";
134
135
  import "../chunk-3EGEA4KH.js";
135
136
  import {
136
137
  setHumanStream
@@ -325,6 +326,20 @@ import { parse as parseTOML, stringify as stringifyTOML } from "smol-toml";
325
326
  // src/cli/exit.ts
326
327
  var isExitPromptError = (err) => err instanceof Error && (err.name === "ExitPromptError" || err.message.includes("User force closed") || /force closed the prompt/i.test(err.message));
327
328
 
329
+ // src/cli/enter-key.ts
330
+ var enterKeyListener = (input2 = process.stdin) => {
331
+ if (input2.isTTY !== true) return null;
332
+ return (onEnter) => {
333
+ const onLine = () => onEnter();
334
+ input2.on("data", onLine);
335
+ input2.resume();
336
+ return () => {
337
+ input2.off("data", onLine);
338
+ input2.pause();
339
+ };
340
+ };
341
+ };
342
+
328
343
  // ../contracts/src/billing.ts
329
344
  var PARTNER_SELF_SERVE_PLANS = ["partner_launch", "partner_growth", "partner_scale"];
330
345
  var PARTNER_PLAN_TYPES = ["partner", ...PARTNER_SELF_SERVE_PLANS];
@@ -602,7 +617,7 @@ var planPhoneCheck = (context) => {
602
617
  if (context.verify === "none") return "verify-none";
603
618
  if (!context.stdoutIsTty) return "instructions";
604
619
  if (context.paired) return "confirm-pairing";
605
- if (context.connectMode === "app") return "reuse-app";
620
+ if (context.connectMode === "app") return context.interactive && !context.macAppInstalled ? "wait-for-app" : "reuse-app";
606
621
  return "connect";
607
622
  };
608
623
 
@@ -2765,7 +2780,9 @@ var main = async () => {
2765
2780
  verify: verifyMode,
2766
2781
  stdoutIsTty: process.stdout.isTTY === true,
2767
2782
  paired: keyFromPairing,
2768
- connectMode
2783
+ connectMode,
2784
+ interactive: !options.nonInteractive,
2785
+ macAppInstalled: appBridgeAvailable
2769
2786
  });
2770
2787
  switch (phoneCheck) {
2771
2788
  case "unverified":
@@ -2793,6 +2810,11 @@ var main = async () => {
2793
2810
  case "reuse-app":
2794
2811
  phone = await printConnectInstructions(trimmedKey);
2795
2812
  break;
2813
+ case "wait-for-app": {
2814
+ const skip = enterKeyListener();
2815
+ phone = skip === null ? await printConnectInstructions(trimmedKey) : await waitForYourPhone(trimmedKey, { skip });
2816
+ break;
2817
+ }
2796
2818
  case "connect":
2797
2819
  phone = await connectDevice(trimmedKey, { showCapabilities: !options.connectExplicit });
2798
2820
  break;
@@ -11,7 +11,7 @@ import {
11
11
  describeReach,
12
12
  fetchChannels,
13
13
  reachVerdict
14
- } from "../chunk-3FOPVVNO.js";
14
+ } from "../chunk-43H2FUNN.js";
15
15
  import "../chunk-3EGEA4KH.js";
16
16
  import "../chunk-QCGNGEGE.js";
17
17
  import {
@@ -950,6 +950,80 @@ var connectViaAppPairing = async (options = {}) => {
950
950
  process.off("SIGTERM", onTerminate);
951
951
  }
952
952
  };
953
+ var PHONE_WAIT_TIMEOUT_MS = 10 * 6e4;
954
+ var PHONE_WAIT_SKIP_LINE = "Press Enter to skip. Setup finishes without the phone check.";
955
+ var describePhoneWait = (skipOffered) => [
956
+ bold("Connect your phone"),
957
+ "Open the Pushary app on your phone and allow notifications.",
958
+ dim("Sign in with the same account you use here. No app yet? Get it at pushary.com/download"),
959
+ ...skipOffered ? [dim(PHONE_WAIT_SKIP_LINE)] : []
960
+ ];
961
+ var watchSkip = (listener) => {
962
+ let skipped = false;
963
+ let wake = () => {
964
+ };
965
+ const woken = new Promise((resolve) => {
966
+ wake = resolve;
967
+ });
968
+ const stop = listener?.(() => {
969
+ skipped = true;
970
+ wake();
971
+ }) ?? (() => {
972
+ });
973
+ return { skipped: () => skipped, woken, stop };
974
+ };
975
+ var PHONE_WAIT_REPAIR_LINE = `Open the Pushary app, sign in with the same account, and allow notifications. Then run ${NPX_LATEST_COMMAND} doctor.`;
976
+ var phoneWaitRepair = (verdict) => verdict.kind === "nobody" ? [PHONE_WAIT_REPAIR_LINE] : describeAppRepair(verdict) ?? [];
977
+ var pollForYourPhone = async (apiKey, firstSeen, options) => {
978
+ const clock = options.clock ?? SYSTEM_PAIR_CLOCK;
979
+ const deadline = clock.now() + PHONE_WAIT_TIMEOUT_MS;
980
+ const skip = watchSkip(options.skip);
981
+ const minutesLeft = () => Math.max(0, Math.ceil((deadline - clock.now()) / 6e4));
982
+ const stop = startSpinner(() => `Waiting for your phone ${dim(`(${minutesLeft()}m left)`)}`);
983
+ let lastSeen = firstSeen;
984
+ try {
985
+ while (clock.now() < deadline && !skip.skipped()) {
986
+ const probe = await fetchChannels(apiKey);
987
+ if (probe.kind === "unauthorized") {
988
+ stop(yellow("!"), "The server stopped accepting this key");
989
+ return { kind: "unauthorized" };
990
+ }
991
+ if (probe.kind === "locked") {
992
+ stop(yellow("!"), "This workspace has no active plan");
993
+ return { kind: "locked" };
994
+ }
995
+ if (probe.kind === "ok") {
996
+ lastSeen = probe.status;
997
+ if (reachesYou(probe.status)) {
998
+ stop(check, "Phone connected");
999
+ return { kind: "connected", channels: probe.status };
1000
+ }
1001
+ }
1002
+ await Promise.race([clock.sleep(CONNECT_POLL_INTERVAL_MS), skip.woken]);
1003
+ }
1004
+ stop(yellow("!"), skip.skipped() ? "Skipped the phone check" : "No phone connected yet");
1005
+ return { kind: "not_yet", lastSeen };
1006
+ } finally {
1007
+ skip.stop();
1008
+ }
1009
+ };
1010
+ var waitForYourPhone = async (apiKey, options = {}) => {
1011
+ const probe = await fetchChannels(apiKey);
1012
+ if (probe.kind !== "ok") return describeProbeFailure(probe);
1013
+ if (reachesYou(probe.status)) {
1014
+ console.log(` ${check} ${describeExistingConnection(probe.status)}`);
1015
+ return sendAndConfirm(apiKey, probe.status);
1016
+ }
1017
+ console.log();
1018
+ for (const line of describePhoneWait(options.skip !== void 0)) console.log(` ${line}`);
1019
+ console.log();
1020
+ const waited = await pollForYourPhone(apiKey, probe.status, options);
1021
+ if (waited.kind === "connected") return sendAndConfirm(apiKey, waited.channels);
1022
+ if (waited.kind === "unauthorized" || waited.kind === "locked") return describeProbeFailure(waited);
1023
+ const repair = phoneWaitRepair(reachVerdict(waited.lastSeen));
1024
+ for (const line of repair) console.log(` ${dim(line)}`);
1025
+ return phoneFailure("no_device", repair);
1026
+ };
953
1027
 
954
1028
  export {
955
1029
  reachVerdict,
@@ -965,5 +1039,6 @@ export {
965
1039
  printConnectInstructions,
966
1040
  BROWSER_CONNECT_COMMAND,
967
1041
  pairingEscapeApplies,
968
- connectViaAppPairing
1042
+ connectViaAppPairing,
1043
+ waitForYourPhone
969
1044
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pushary",
3
- "version": "1.9.34",
3
+ "version": "1.9.35",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "keywords": [
6
6
  "pushary",