@pushary/agent-hooks 0.67.1 → 0.69.0
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 +89 -0
- package/data/cursor-plugin/scripts/pushary-gate.mjs +36 -10
- package/data/vscode-plugin/scripts/pushary-gate.mjs +32 -9
- package/dist/bin/pushary-claude.js +21 -11
- package/dist/bin/pushary-clean.js +58 -20
- package/dist/bin/pushary-codex-hook.js +38 -23
- package/dist/bin/pushary-codex.js +1 -1
- package/dist/bin/pushary-connect.js +1 -1
- package/dist/bin/pushary-doctor.js +139 -26
- package/dist/bin/pushary-gemini-hook.js +32 -16
- package/dist/bin/pushary-hook.js +3 -3
- package/dist/bin/pushary-notification-hook.js +1 -1
- package/dist/bin/pushary-permission-denied-hook.js +3 -3
- package/dist/bin/pushary-permission-hook.js +3 -3
- package/dist/bin/pushary-post-hook.js +1 -1
- package/dist/bin/pushary-prompt-hook.js +1 -1
- package/dist/bin/pushary-session-end-hook.js +1 -1
- package/dist/bin/pushary-session-start-hook.js +1 -1
- package/dist/bin/pushary-setup.js +16 -6
- package/dist/bin/pushary-status.js +1 -1
- package/dist/bin/pushary-stop-hook.js +1 -1
- package/dist/bin/pushary-stopfailure-hook.js +1 -1
- package/dist/chunk-3USMXNVB.js +64 -0
- package/dist/{chunk-SONXGCZY.js → chunk-C5I2RAMT.js} +45 -27
- package/dist/{chunk-XOUYM27W.js → chunk-H46LSQRT.js} +182 -103
- package/dist/{chunk-KB4ODLGB.js → chunk-I4BYZIX4.js} +2 -0
- package/dist/{chunk-V6OA4VPU.js → chunk-P7VBAYQO.js} +76 -2
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-YHG74UFF.js +0 -12
|
@@ -266,6 +266,29 @@ var writeStatusLine = (text) => {
|
|
|
266
266
|
` : ` ${text}
|
|
267
267
|
`);
|
|
268
268
|
};
|
|
269
|
+
var visibleLength = (text) => text.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
270
|
+
var clipToRow = (text, columns) => {
|
|
271
|
+
const budget = columns - 4;
|
|
272
|
+
if (budget <= 1 || visibleLength(text) <= budget) return text;
|
|
273
|
+
let visible = 0;
|
|
274
|
+
let out = "";
|
|
275
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
276
|
+
const escape = /^\x1b\[[0-9;]*m/.exec(text.slice(i));
|
|
277
|
+
if (escape) {
|
|
278
|
+
out += escape[0];
|
|
279
|
+
i += escape[0].length - 1;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (visible >= budget - 1) break;
|
|
283
|
+
out += text[i];
|
|
284
|
+
visible += 1;
|
|
285
|
+
}
|
|
286
|
+
return `${out}\u2026`;
|
|
287
|
+
};
|
|
288
|
+
var terminalColumns = () => {
|
|
289
|
+
const columns = process.stdout.columns;
|
|
290
|
+
return typeof columns === "number" && columns > 0 ? columns : 80;
|
|
291
|
+
};
|
|
269
292
|
var startSpinner = (getLabel) => {
|
|
270
293
|
if (!humanIsTty()) {
|
|
271
294
|
writeHuman(` ${getLabel()}
|
|
@@ -283,7 +306,8 @@ var startSpinner = (getLabel) => {
|
|
|
283
306
|
const frames = [" ", ". ", ".. ", "..."];
|
|
284
307
|
let i = 0;
|
|
285
308
|
const interval = setInterval(() => {
|
|
286
|
-
|
|
309
|
+
const line = `${dim(frames[i++ % frames.length])} ${getLabel()}`;
|
|
310
|
+
writeHuman(`\r ${clipToRow(line, terminalColumns())}\x1B[K`);
|
|
287
311
|
}, SPINNER_FRAME_MS);
|
|
288
312
|
return (finalGlyph, finalLabel) => {
|
|
289
313
|
clearInterval(interval);
|
|
@@ -338,6 +362,8 @@ var waitForDevice = async (apiKey, baseline) => {
|
|
|
338
362
|
await sleep(CONNECT_POLL_INTERVAL_MS);
|
|
339
363
|
}
|
|
340
364
|
stop(yellow("!"), "Didn't detect a connection yet");
|
|
365
|
+
console.log(` ${dim("Signed in on the app already? Open it and allow notifications.")}`);
|
|
366
|
+
console.log(` ${dim("Signing in alone does not connect the phone. Then run")} ${cyan("pushary doctor")}${dim(".")}`);
|
|
341
367
|
return { kind: "timeout" };
|
|
342
368
|
} catch (err) {
|
|
343
369
|
stop(yellow("!"), `Couldn't check connection ${dim(`(${err instanceof Error ? err.message : "network error"})`)}`);
|
|
@@ -484,6 +510,18 @@ var startPairing = async (cliPublicKey) => {
|
|
|
484
510
|
return null;
|
|
485
511
|
}
|
|
486
512
|
};
|
|
513
|
+
var describePairFailure = (reason) => {
|
|
514
|
+
switch (reason) {
|
|
515
|
+
case "no_site":
|
|
516
|
+
return "Couldn't set up your workspace. Try again, or finish setup at pushary.com/dashboard";
|
|
517
|
+
case "blocked":
|
|
518
|
+
return "Finish setting up in the Pushary app, then run setup again";
|
|
519
|
+
case "authorize_failed":
|
|
520
|
+
return "The app could not authorize this terminal. Re-run setup to try again";
|
|
521
|
+
default:
|
|
522
|
+
return "Pairing failed. Re-run setup to try again";
|
|
523
|
+
}
|
|
524
|
+
};
|
|
487
525
|
var cancelPairing = async (pairId) => {
|
|
488
526
|
try {
|
|
489
527
|
await fetch(`${apiBase()}/api/mobile/pair/start`, {
|
|
@@ -495,6 +533,7 @@ var cancelPairing = async (pairId) => {
|
|
|
495
533
|
} catch {
|
|
496
534
|
}
|
|
497
535
|
};
|
|
536
|
+
var PAIR_MAX_CONSECUTIVE_FAILURES = 8;
|
|
498
537
|
var claimPairing = async (pairId) => {
|
|
499
538
|
try {
|
|
500
539
|
const res = await fetch(`${apiBase()}/api/mobile/pair/claim?id=${encodeURIComponent(pairId)}`, {
|
|
@@ -506,6 +545,17 @@ var claimPairing = async (pairId) => {
|
|
|
506
545
|
return null;
|
|
507
546
|
}
|
|
508
547
|
};
|
|
548
|
+
var ackPairing = async (pairId) => {
|
|
549
|
+
try {
|
|
550
|
+
await fetch(`${apiBase()}/api/mobile/pair/ack`, {
|
|
551
|
+
method: "POST",
|
|
552
|
+
headers: { "Content-Type": "application/json" },
|
|
553
|
+
body: JSON.stringify({ pairId }),
|
|
554
|
+
signal: AbortSignal.timeout(5e3)
|
|
555
|
+
});
|
|
556
|
+
} catch {
|
|
557
|
+
}
|
|
558
|
+
};
|
|
509
559
|
var buildPairLinks = (pairId, publicKeyB64, baseUrl = apiBase()) => {
|
|
510
560
|
const id = encodeURIComponent(pairId);
|
|
511
561
|
const pk = encodeURIComponent(publicKeyB64);
|
|
@@ -533,12 +583,19 @@ var connectViaAppPairing = async (options = {}) => {
|
|
|
533
583
|
console.log();
|
|
534
584
|
const startedAt = Date.now();
|
|
535
585
|
const deadline = startedAt + PAIR_TIMEOUT_MS;
|
|
586
|
+
let hintShown = false;
|
|
536
587
|
const stop = startSpinner(() => {
|
|
537
588
|
const left = Math.max(0, Math.ceil((deadline - Date.now()) / 6e4));
|
|
538
589
|
if (Date.now() - startedAt < PAIR_HINT_AFTER_MS) {
|
|
539
590
|
return "Waiting for the app to authorize";
|
|
540
591
|
}
|
|
541
|
-
|
|
592
|
+
if (!hintShown) {
|
|
593
|
+
hintShown = true;
|
|
594
|
+
writeStatusLine(
|
|
595
|
+
`${dim("No app yet? Install it, sign in with this account, then scan. Ctrl-C to stop.")}`
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
return `Waiting for the app ${dim(`(${left}m left)`)}`;
|
|
542
599
|
});
|
|
543
600
|
let cancelled = false;
|
|
544
601
|
const onInterrupt = () => {
|
|
@@ -548,10 +605,22 @@ var connectViaAppPairing = async (options = {}) => {
|
|
|
548
605
|
void Promise.allSettled([Promise.resolve(flushed), cancelPairing(pairId)]).finally(() => process.exit(EXIT_ABORTED));
|
|
549
606
|
};
|
|
550
607
|
process.once("SIGINT", onInterrupt);
|
|
608
|
+
let consecutiveFailures = 0;
|
|
551
609
|
try {
|
|
552
610
|
while (Date.now() < deadline) {
|
|
553
611
|
if (cancelled) return null;
|
|
554
612
|
const claim = await claimPairing(pairId);
|
|
613
|
+
if (claim === null) {
|
|
614
|
+
consecutiveFailures += 1;
|
|
615
|
+
if (consecutiveFailures >= PAIR_MAX_CONSECUTIVE_FAILURES) {
|
|
616
|
+
stop(yellow("!"), "Can't reach pushary.com to finish pairing. Check your connection, then re-run setup.");
|
|
617
|
+
await cancelPairing(pairId);
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
await sleep(PAIR_POLL_INTERVAL_MS);
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
consecutiveFailures = 0;
|
|
555
624
|
if (claim?.status === "authorized") {
|
|
556
625
|
let apiKey;
|
|
557
626
|
try {
|
|
@@ -561,6 +630,7 @@ var connectViaAppPairing = async (options = {}) => {
|
|
|
561
630
|
await cancelPairing(pairId);
|
|
562
631
|
return null;
|
|
563
632
|
}
|
|
633
|
+
await ackPairing(pairId);
|
|
564
634
|
stop(check, "App connected");
|
|
565
635
|
return { apiKey, handle: claim.siteSlug };
|
|
566
636
|
}
|
|
@@ -568,6 +638,10 @@ var connectViaAppPairing = async (options = {}) => {
|
|
|
568
638
|
stop(yellow("!"), "Pairing expired \u2014 re-run setup to try again");
|
|
569
639
|
return null;
|
|
570
640
|
}
|
|
641
|
+
if (claim?.status === "failed") {
|
|
642
|
+
stop(yellow("!"), describePairFailure(claim.reason));
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
571
645
|
await sleep(PAIR_POLL_INTERVAL_MS);
|
|
572
646
|
}
|
|
573
647
|
stop(yellow("!"), "Timed out waiting for the app");
|
package/dist/src/index.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ interface ModeState {
|
|
|
36
36
|
readonly relayUrl: string | null;
|
|
37
37
|
readonly trainingConsent?: boolean;
|
|
38
38
|
readonly scope?: ScopeContract | null;
|
|
39
|
+
readonly degraded?: boolean;
|
|
39
40
|
}
|
|
40
41
|
declare const fetchModeState: (apiKey: string, sessionId?: string) => Promise<ModeState>;
|
|
41
42
|
declare const fetchModeOverride: (apiKey: string) => Promise<ApprovalMode | null>;
|
package/dist/src/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handlePreToolUse
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-C5I2RAMT.js";
|
|
4
4
|
import "../chunk-CAJZAFVS.js";
|
|
5
|
-
import "../chunk-
|
|
5
|
+
import "../chunk-3USMXNVB.js";
|
|
6
6
|
import {
|
|
7
7
|
askUser,
|
|
8
8
|
cancelQuestion,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
reportEvent,
|
|
16
16
|
resolvePolicy,
|
|
17
17
|
waitForAnswer
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-H46LSQRT.js";
|
|
19
19
|
import "../chunk-WLGEY4UX.js";
|
|
20
20
|
import "../chunk-BSZYIAZL.js";
|
|
21
21
|
import "../chunk-SAF6HGAA.js";
|
package/package.json
CHANGED
package/dist/chunk-YHG74UFF.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// src/answer.ts
|
|
2
|
-
var denyReasonFrom = (value, note) => {
|
|
3
|
-
const trimmed = note?.trim();
|
|
4
|
-
if (trimmed) return `Denied from your phone: ${trimmed}`;
|
|
5
|
-
return value && value !== "no" && value !== "yes" ? `Denied from your phone: ${value}` : "Denied via push notification";
|
|
6
|
-
};
|
|
7
|
-
var isDeferAnswer = (value) => value === "defer";
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
denyReasonFrom,
|
|
11
|
-
isDeferAnswer
|
|
12
|
-
};
|