@pushary/agent-hooks 1.9.7 → 1.9.9

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 (111) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +3 -3
  3. package/data/cursor-plugin/README.md +3 -7
  4. package/data/vscode-plugin/README.md +1 -1
  5. package/dist/bin/pushary-bell-hook.js +22 -24
  6. package/dist/bin/pushary-bell.js +13 -13
  7. package/dist/bin/pushary-claude.js +28 -30
  8. package/dist/bin/pushary-clean.js +113 -94
  9. package/dist/bin/pushary-codex-bridge.js +20 -20
  10. package/dist/bin/pushary-codex-hook.js +36 -38
  11. package/dist/bin/pushary-codex.js +13 -13
  12. package/dist/bin/pushary-connect.js +48 -22
  13. package/dist/bin/pushary-cowork.js +5 -5
  14. package/dist/bin/pushary-daemon.js +50 -40
  15. package/dist/bin/pushary-disconnect.js +188 -56
  16. package/dist/bin/pushary-doctor.js +105 -85
  17. package/dist/bin/pushary-elicitation-hook.js +25 -27
  18. package/dist/bin/pushary-gemini-bridge.js +13 -13
  19. package/dist/bin/pushary-gemini-hook.js +31 -33
  20. package/dist/bin/pushary-hook.js +36 -39
  21. package/dist/bin/pushary-login.js +12 -12
  22. package/dist/bin/pushary-logout.js +105 -42
  23. package/dist/bin/pushary-mcp.js +9 -9
  24. package/dist/bin/pushary-mode.js +28 -31
  25. package/dist/bin/pushary-notification-hook.js +29 -32
  26. package/dist/bin/pushary-opencode-hook.js +30 -32
  27. package/dist/bin/pushary-permission-denied-hook.js +30 -33
  28. package/dist/bin/pushary-permission-hook.js +33 -36
  29. package/dist/bin/pushary-post-hook.js +30 -33
  30. package/dist/bin/pushary-prompt-hook.js +29 -32
  31. package/dist/bin/pushary-session-end-hook.js +29 -32
  32. package/dist/bin/pushary-session-start-hook.js +33 -36
  33. package/dist/bin/pushary-setup.js +168 -160
  34. package/dist/bin/pushary-stats.js +5 -5
  35. package/dist/bin/pushary-status.js +65 -19
  36. package/dist/bin/pushary-stop-hook.js +29 -32
  37. package/dist/bin/pushary-stopfailure-hook.js +29 -32
  38. package/dist/bin/pushary-suggestions.js +19 -21
  39. package/dist/bin/pushary-transcript-register.js +18 -20
  40. package/dist/bin/pushary-transcripts.js +7 -7
  41. package/dist/bin/pushary-upgrade.js +50 -26
  42. package/dist/bin/pushary-wait.js +23 -19
  43. package/dist/bin/pushary.js +15 -14
  44. package/dist/{chunk-4FK6RZVJ.js → chunk-462EQA6K.js} +1 -1
  45. package/dist/{chunk-STQRUH3S.js → chunk-5DCDQ5VW.js} +59 -15
  46. package/dist/{chunk-JXISQ7DT.js → chunk-5N5L6DNN.js} +3 -3
  47. package/dist/{chunk-QR6VE5ME.js → chunk-5RGA636G.js} +79 -17
  48. package/dist/{chunk-L76HTPU6.js → chunk-6AYSKVLL.js} +3 -3
  49. package/dist/{chunk-NIBFSARF.js → chunk-6EBGOHDJ.js} +33 -13
  50. package/dist/{chunk-QQ4HBXZC.js → chunk-6W5M3MSE.js} +84 -673
  51. package/dist/{chunk-R3YW55MY.js → chunk-AI7RMFVV.js} +29 -26
  52. package/dist/{chunk-AUUXS44H.js → chunk-APP43AW7.js} +1 -1
  53. package/dist/{chunk-RQGODFQN.js → chunk-AZOKPWVI.js} +1 -1
  54. package/dist/{chunk-3GNUXXDZ.js → chunk-B5NMSP3V.js} +2 -2
  55. package/dist/{chunk-4D2AYNSE.js → chunk-BNSKVIAW.js} +2 -2
  56. package/dist/chunk-BYLKCZ2G.js +367 -0
  57. package/dist/{chunk-X5NXPCIC.js → chunk-BZLHTMT6.js} +89 -7
  58. package/dist/{chunk-BTQGAXZ3.js → chunk-COQ64C4F.js} +10 -10
  59. package/dist/{chunk-N4EUSDKX.js → chunk-DCCSULXK.js} +14 -14
  60. package/dist/{chunk-JWKBDSPF.js → chunk-DP3WX7FW.js} +2 -2
  61. package/dist/chunk-E5HOHIUV.js +52 -0
  62. package/dist/{chunk-GU3EJCVV.js → chunk-EA5NWDK7.js} +4 -0
  63. package/dist/chunk-EIAEUG7G.js +46 -0
  64. package/dist/{chunk-EB4XGVBG.js → chunk-EUW7JL2K.js} +0 -32
  65. package/dist/{chunk-T7Y5EADL.js → chunk-F7R3SZ4Q.js} +2 -2
  66. package/dist/{chunk-H37L7TT3.js → chunk-G7RIDXAT.js} +2 -2
  67. package/dist/{chunk-W2KI5KPD.js → chunk-H5T27W7M.js} +2 -2
  68. package/dist/chunk-HBWYMRR5.js +94 -0
  69. package/dist/{chunk-CBQACHKY.js → chunk-IIVZZMSO.js} +1 -1
  70. package/dist/{chunk-Z6HPS67T.js → chunk-IRHABAQT.js} +1 -1
  71. package/dist/{chunk-QTO6HEZD.js → chunk-K545B734.js} +2 -2
  72. package/dist/{chunk-KYO45G5L.js → chunk-KOWFRUIT.js} +1 -1
  73. package/dist/{chunk-QFEM7R6T.js → chunk-KQFTBQ66.js} +11 -11
  74. package/dist/chunk-LENBKYRB.js +50 -0
  75. package/dist/{chunk-JCWZ23MJ.js → chunk-M3STIAGU.js} +3 -3
  76. package/dist/{chunk-6DJTDHBI.js → chunk-MD4SVNT6.js} +1 -1
  77. package/dist/{chunk-7264S5HZ.js → chunk-MLGIVVSG.js} +1 -1
  78. package/dist/{chunk-H7MMU64M.js → chunk-NGKUXZID.js} +2 -2
  79. package/dist/{chunk-JWQZSYCK.js → chunk-NUVGDBZC.js} +1 -1
  80. package/dist/{chunk-AQ55ZSSS.js → chunk-OAYWO5NP.js} +1 -1
  81. package/dist/chunk-Q6C6ILUS.js +49 -0
  82. package/dist/{chunk-MBK7N46B.js → chunk-QIOIO7VN.js} +6 -6
  83. package/dist/{chunk-KFKL3FHS.js → chunk-QRXPWW3M.js} +4 -3
  84. package/dist/{chunk-7OIWWZAD.js → chunk-QTIUJZRX.js} +3 -3
  85. package/dist/{chunk-XWAYAO3V.js → chunk-R5RIVOPL.js} +2 -2
  86. package/dist/{chunk-ADSQDYYG.js → chunk-REU2VQPH.js} +54 -5
  87. package/dist/{chunk-GKI6LFAV.js → chunk-RQ32ADJP.js} +2 -2
  88. package/dist/{chunk-VXRXFU6Q.js → chunk-SZ4Q6ZVS.js} +14 -7
  89. package/dist/{chunk-KT5E2RLS.js → chunk-T6ZN4TEF.js} +1 -1
  90. package/dist/{chunk-UFVGSEWH.js → chunk-TO3PS646.js} +2 -2
  91. package/dist/chunk-UAP5DS6P.js +599 -0
  92. package/dist/{chunk-MZPXVH4A.js → chunk-UF6RBP5V.js} +204 -28
  93. package/dist/{chunk-AVNKVF7N.js → chunk-UPIZSCYD.js} +4 -4
  94. package/dist/{chunk-3PVDOCFI.js → chunk-VHPFNLRS.js} +5 -5
  95. package/dist/{chunk-HPRZJKRO.js → chunk-VIIHC42X.js} +1 -1
  96. package/dist/{chunk-D6S5EKXA.js → chunk-WRPYCIV2.js} +8 -12
  97. package/dist/{chunk-ZUTU43FT.js → chunk-Z23ZBYDW.js} +6 -4
  98. package/dist/{chunk-SBLPHUEB.js → chunk-ZGADIZDS.js} +8 -6
  99. package/dist/{global-upgrade-E2HUEB4B.js → global-upgrade-H272QOGD.js} +6 -6
  100. package/dist/{paths-QVTEGNZV.js → paths-HMVOTFUN.js} +2 -2
  101. package/dist/reapply-Q5NHDTVU.js +55 -0
  102. package/dist/src/index.d.ts +1 -0
  103. package/dist/src/index.js +19 -20
  104. package/dist/{upgrade-lock-JCIDZMHF.js → upgrade-lock-L3GHFIRW.js} +3 -3
  105. package/package.json +1 -1
  106. package/dist/chunk-4YO4T5FV.js +0 -149
  107. package/dist/chunk-ANEAA37E.js +0 -197
  108. package/dist/chunk-MNWRUGMH.js +0 -86
  109. package/dist/chunk-RQSOEB4S.js +0 -44
  110. package/dist/chunk-SD3272LS.js +0 -143
  111. package/dist/reapply-5QVKM6LA.js +0 -38
@@ -1,14 +1,36 @@
1
1
  import {
2
- guardedArgv
3
- } from "./chunk-ZUTU43FT.js";
2
+ compatibleConfigFile
3
+ } from "./chunk-UF6RBP5V.js";
4
+ import {
5
+ hookOwnerOf,
6
+ hookOwnerOfCommands,
7
+ liveBridgeProbe,
8
+ resolveBridgeStub
9
+ } from "./chunk-BYLKCZ2G.js";
10
+ import {
11
+ claudeSettings,
12
+ codexHooksJson,
13
+ cursorUserHooks,
14
+ geminiSettings,
15
+ guardedArgv,
16
+ pusharyDir,
17
+ vscodePluginDir
18
+ } from "./chunk-Z23ZBYDW.js";
19
+ import {
20
+ readJsonSafe
21
+ } from "./chunk-T7E75EKA.js";
4
22
  import {
5
23
  HOOK_BUDGETS,
6
- OPENCODE_APPROVAL_EVENT
7
- } from "./chunk-QR6VE5ME.js";
24
+ HOOK_COMPATIBLE_PROFILES,
25
+ HOOK_LOCATOR_BINARY,
26
+ OPENCODE_APPROVAL_EVENT,
27
+ hookCompatibleProfile
28
+ } from "./chunk-5RGA636G.js";
8
29
 
9
30
  // src/opencode-plugin.ts
10
31
  var OPENCODE_PLUGIN_MARKER = "pushary-opencode-plugin w1";
11
32
  var OPENCODE_PLUGIN_PLACEHOLDER = "__PUSHARY_COMMAND__";
33
+ var OPENCODE_APPROVAL_EVENTS_PLACEHOLDER = "__PUSHARY_APPROVAL_EVENTS__";
12
34
  var OPENCODE_PLUGIN_FILE = "pushary.js";
13
35
  var OPENCODE_PLUGIN_DIR = "plugins";
14
36
  var OPENCODE_PLUGIN_SIBLING = "package.json";
@@ -262,7 +284,7 @@ export const PusharyPlugin = async ({ client, directory, worktree }) => {
262
284
  try {
263
285
  const type = event && event.type
264
286
  const properties = event && event.properties
265
- if (${JSON.stringify(OPENCODE_ASKED_EVENTS)}.includes(type)) {
287
+ if (${OPENCODE_APPROVAL_EVENTS_PLACEHOLDER}.includes(type)) {
266
288
  const asked = askedFrom(properties)
267
289
  if (asked) void gate(asked)
268
290
  return
@@ -295,12 +317,29 @@ var openCodePluginModule = () => ({
295
317
  marker: OPENCODE_PLUGIN_MARKER,
296
318
  source: openCodePluginSource(),
297
319
  placeholder: OPENCODE_PLUGIN_PLACEHOLDER,
320
+ approvalEvents: {
321
+ placeholder: OPENCODE_APPROVAL_EVENTS_PLACEHOLDER,
322
+ events: OPENCODE_ASKED_EVENTS
323
+ },
298
324
  sibling: {
299
325
  path: OPENCODE_PLUGIN_SIBLING,
300
326
  contents: OPENCODE_PLUGIN_SIBLING_CONTENTS
301
327
  }
302
328
  });
303
- var renderOpenCodePlugin = (module, argv) => module.source.replace(module.placeholder, JSON.stringify(argv));
329
+ var renderOpenCodePlugin = (module, argv, holdsApprovals = true) => module.source.replace(module.placeholder, JSON.stringify(argv)).replace(module.approvalEvents.placeholder, JSON.stringify(holdsApprovals ? module.approvalEvents.events : []));
330
+ var COMMAND_LINE = /^const COMMAND = (.*)$/m;
331
+ var isArgv = (value) => Array.isArray(value) && value.every((item) => typeof item === "string");
332
+ var openCodePluginArgv = (contents) => {
333
+ if (!isOpenCodePluginOurs(contents)) return null;
334
+ const line = contents.match(COMMAND_LINE)?.[1];
335
+ if (line === void 0) return null;
336
+ try {
337
+ const parsed = JSON.parse(line);
338
+ return isArgv(parsed) ? parsed : null;
339
+ } catch {
340
+ return null;
341
+ }
342
+ };
304
343
  var isOpenCodePluginOurs = (contents) => contents.includes(OPENCODE_PLUGIN_MARKER);
305
344
 
306
345
  // src/opencode-config.ts
@@ -362,6 +401,46 @@ var removeOpenCodeMcpServer = (config) => {
362
401
  return true;
363
402
  };
364
403
 
404
+ // src/setup/agent-hook-owner.ts
405
+ import { readFileSync as readFileSync2 } from "fs";
406
+ import { join as join2 } from "path";
407
+ var COMPATIBLE_HOOK_FILES = Object.fromEntries(
408
+ HOOK_COMPATIBLE_PROFILES.map((profile) => [profile.agentType, () => compatibleConfigFile(profile)])
409
+ );
410
+ var HOOK_FILES = {
411
+ claude_code: claudeSettings,
412
+ codex: codexHooksJson,
413
+ gemini_cli: geminiSettings,
414
+ cursor: cursorUserHooks,
415
+ vscode: () => join2(vscodePluginDir(), "hooks", "hooks.json"),
416
+ ...COMPATIBLE_HOOK_FILES
417
+ };
418
+ var agentHookFile = (agent) => HOOK_FILES[agent]?.() ?? null;
419
+ var readTextOrNull = (path) => {
420
+ try {
421
+ return readFileSync2(path, "utf-8");
422
+ } catch {
423
+ return null;
424
+ }
425
+ };
426
+ var openCodePluginOwner = (appAvailable) => {
427
+ const contents = readTextOrNull(openCodePluginFile());
428
+ return hookOwnerOfCommands(contents === null ? [] : openCodePluginArgv(contents) ?? [], appAvailable);
429
+ };
430
+ var agentHookOwner = (agent, appAvailable) => {
431
+ if (agent === "opencode") return openCodePluginOwner(appAvailable);
432
+ const file = agentHookFile(agent);
433
+ if (!file) return "none";
434
+ const document = readJsonSafe(file);
435
+ const profile = hookCompatibleProfile(agent);
436
+ return hookOwnerOf(
437
+ document.kind === "ok" ? document.value : null,
438
+ appAvailable,
439
+ profile ? profile.hooksKeyPath : void 0
440
+ );
441
+ };
442
+ var macAppBridgeAvailable = () => resolveBridgeStub(join2(pusharyDir(), "bin", HOOK_LOCATOR_BINARY), liveBridgeProbe()).kind === "bundle";
443
+
365
444
  export {
366
445
  OPENCODE_PLUGIN_PLACEHOLDER,
367
446
  OPENCODE_PLUGIN_SIBLING,
@@ -379,5 +458,8 @@ export {
379
458
  openCodeConfigFile,
380
459
  openCodeInstructionsFile,
381
460
  addOpenCodeMcpServer,
382
- removeOpenCodeMcpServer
461
+ removeOpenCodeMcpServer,
462
+ agentHookFile,
463
+ agentHookOwner,
464
+ macAppBridgeAvailable
383
465
  };
@@ -4,40 +4,40 @@ import {
4
4
  savePin,
5
5
  verifyRecipients
6
6
  } from "./chunk-SGZJ5LYH.js";
7
- import {
8
- hookOwnerOf
9
- } from "./chunk-SD3272LS.js";
10
7
  import {
11
8
  ensureDaemonRunning
12
- } from "./chunk-VXRXFU6Q.js";
9
+ } from "./chunk-SZ4Q6ZVS.js";
13
10
  import {
14
11
  buildTranscriptRecords,
15
12
  decodePublicKey,
16
13
  generateSessionKey,
17
14
  wrapSessionKey
18
- } from "./chunk-AUUXS44H.js";
15
+ } from "./chunk-APP43AW7.js";
19
16
  import {
20
17
  fetchTranscriptRecipients,
21
18
  uploadTranscriptRecords
22
- } from "./chunk-4FK6RZVJ.js";
19
+ } from "./chunk-462EQA6K.js";
23
20
  import {
24
21
  transcriptEnvironmentPreference,
25
22
  transcriptsEnabled
26
- } from "./chunk-HPRZJKRO.js";
23
+ } from "./chunk-VIIHC42X.js";
24
+ import {
25
+ hookOwnerOf
26
+ } from "./chunk-BYLKCZ2G.js";
27
27
  import {
28
28
  readTranscriptPreference
29
- } from "./chunk-ADSQDYYG.js";
29
+ } from "./chunk-REU2VQPH.js";
30
30
  import {
31
31
  codexHome,
32
32
  pusharyDir
33
- } from "./chunk-ZUTU43FT.js";
33
+ } from "./chunk-Z23ZBYDW.js";
34
34
  import {
35
35
  writeJsonAtomic
36
36
  } from "./chunk-T7E75EKA.js";
37
37
  import {
38
38
  getApiKey,
39
39
  getBaseUrl
40
- } from "./chunk-Z6HPS67T.js";
40
+ } from "./chunk-IRHABAQT.js";
41
41
 
42
42
  // src/transcript-registration.ts
43
43
  import { createHash } from "crypto";
@@ -14,19 +14,19 @@ import {
14
14
  } from "./chunk-U4TMAANR.js";
15
15
  import {
16
16
  callMcpTool
17
- } from "./chunk-L76HTPU6.js";
17
+ } from "./chunk-6AYSKVLL.js";
18
18
  import {
19
19
  reportedInstallSource
20
- } from "./chunk-4D2AYNSE.js";
20
+ } from "./chunk-BNSKVIAW.js";
21
21
  import {
22
22
  NPX_LATEST_COMMAND
23
- } from "./chunk-STQRUH3S.js";
23
+ } from "./chunk-5DCDQ5VW.js";
24
24
  import {
25
25
  NO_PAIRING_COMPUTER,
26
26
  PAIR_TTL_SECONDS,
27
27
  classifyConfirmResponse,
28
28
  isAnswerSource
29
- } from "./chunk-QR6VE5ME.js";
29
+ } from "./chunk-5RGA636G.js";
30
30
 
31
31
  // src/reach.ts
32
32
  var reachVerdict = (channels) => {
@@ -155,7 +155,7 @@ var describeVerifyOutcome = (outcome) => {
155
155
  ok: false,
156
156
  message: "Nothing to deliver to. Agents are configured; approvals will fall back to the terminal.",
157
157
  next: [
158
- "Run pushary connect to add your phone.",
158
+ "Run pushary pair to pair your phone.",
159
159
  "Then pushary doctor --roundtrip to test a synthetic question and answer."
160
160
  ]
161
161
  };
@@ -165,7 +165,7 @@ var describeVerifyOutcome = (outcome) => {
165
165
  message: `Delivered to ${plural2(outcome.recipients, "device")} on this site, none of them yours.`,
166
166
  next: [
167
167
  `Approvals for your agent would wake one of your ${plural2(outcome.otherMembers, "teammate")}.`,
168
- "Run pushary connect to add your own phone."
168
+ "Run pushary pair to pair your own phone."
169
169
  ]
170
170
  };
171
171
  case "unattributable":
@@ -174,7 +174,7 @@ var describeVerifyOutcome = (outcome) => {
174
174
  message: `Delivered to ${plural2(outcome.recipients, "device")} on this site, and no way to tell whose.`,
175
175
  next: [
176
176
  "Browser subscriptions carry no owner, and this site has other members.",
177
- "Install the Pushary app with pushary connect, or run pushary doctor --roundtrip to prove it reaches you."
177
+ "Install the Pushary app and pair it with pushary pair, or run pushary doctor --roundtrip to prove it reaches you."
178
178
  ]
179
179
  };
180
180
  case "error":
@@ -319,8 +319,8 @@ var describeRoundTripOutcome = (outcome) => {
319
319
  ok: false,
320
320
  message: "Nothing to ask. No phone or browser is connected to this site.",
321
321
  next: [
322
- "Run pushary connect to add your phone.",
323
- "Or pushary connect --app if you already have the Pushary app."
322
+ "Run pushary pair to pair your phone.",
323
+ "Or pushary pair --app if you already have the Pushary app."
324
324
  ]
325
325
  };
326
326
  case "error":
@@ -538,14 +538,14 @@ var waitForDevice = async (apiKey, baseline) => {
538
538
  consecutiveFailures = 0;
539
539
  const channels = probe.status;
540
540
  if (reachesYou(channels) || channels.webActive > baseline.webActive) {
541
- stop(check, "Phone connected");
541
+ stop(check, "Phone paired");
542
542
  return { kind: "connected", channels };
543
543
  }
544
544
  await sleep(CONNECT_POLL_INTERVAL_MS);
545
545
  }
546
546
  stop(yellow("!"), "Didn't detect a connection yet");
547
547
  console.log(` ${dim("Signed in on the app already? Open it and allow notifications.")}`);
548
- console.log(` ${dim("Signing in alone does not connect the phone. Then run")} ${cyan("pushary doctor")}${dim(".")}`);
548
+ console.log(` ${dim("Signing in alone does not pair the phone. Then run")} ${cyan("pushary doctor")}${dim(".")}`);
549
549
  return { kind: "timeout" };
550
550
  } catch (err) {
551
551
  stop(yellow("!"), `Couldn't check connection ${dim(`(${err instanceof Error ? err.message : "network error"})`)}`);
@@ -588,14 +588,14 @@ var connectDevice = async (apiKey, options = {}) => {
588
588
  }
589
589
  const site = await fetchSite(apiKey);
590
590
  if (!site) {
591
- console.log(` ${yellow("!")} Couldn't load your subscribe link. Connect your phone later at ${cyan("pushary.com/download")}.`);
591
+ console.log(` ${yellow("!")} Couldn't load your subscribe link. Pair your phone later at ${cyan("pushary.com/download")}.`);
592
592
  return phoneFailure("no_subscribe_link");
593
593
  }
594
594
  console.log();
595
595
  if (channels.site !== null && channels.site.otherMembers > 0 && channels.phoneReachable) {
596
596
  printSiteOnlyWarning(channels);
597
597
  } else {
598
- console.log(` ${bold("Connect your phone")}`);
598
+ console.log(` ${bold("Pair your phone")}`);
599
599
  if (channels.webDesktop > 0) {
600
600
  console.log(` ${dim("A browser on this computer is subscribed, but no phone is connected yet.")}`);
601
601
  }
@@ -727,7 +727,7 @@ var printConnectInstructions = async (apiKey) => {
727
727
  }
728
728
  const site = await fetchSite(apiKey);
729
729
  const target = site?.subscribeUrl ?? "https://pushary.com/download";
730
- console.log(` ${dim("Connect your phone for push notifications at")} ${cyan(target)}`);
730
+ console.log(` ${dim("Pair your phone for push notifications at")} ${cyan(target)}`);
731
731
  console.log(` ${dim("or get the Pushary app at")} ${cyan("https://pushary.com/download")}`);
732
732
  return phoneFailure("no_device");
733
733
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  CODEX_HOOK_STATUS
3
- } from "./chunk-H7MMU64M.js";
3
+ } from "./chunk-NGKUXZID.js";
4
4
  import {
5
5
  NPX_LATEST_COMMAND
6
- } from "./chunk-STQRUH3S.js";
6
+ } from "./chunk-5DCDQ5VW.js";
7
7
 
8
8
  // src/setup/codex-trust.ts
9
9
  var CODEX_TRUST_TELEMETRY = {
@@ -0,0 +1,52 @@
1
+ import {
2
+ macAppBridgeAvailable
3
+ } from "./chunk-BZLHTMT6.js";
4
+ import {
5
+ keyPrefix
6
+ } from "./chunk-REU2VQPH.js";
7
+ import {
8
+ bridgeAgentKey
9
+ } from "./chunk-Z23ZBYDW.js";
10
+ import {
11
+ readJsonSafe
12
+ } from "./chunk-T7E75EKA.js";
13
+ import {
14
+ isValidApiKey
15
+ } from "./chunk-5RGA636G.js";
16
+
17
+ // src/shared-mcp-key.ts
18
+ var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
19
+ var pusharyKey = (value) => typeof value === "string" && isValidApiKey(value.trim()) ? value.trim() : null;
20
+ var bearerKey = (authorization) => typeof authorization === "string" && authorization.startsWith("Bearer ") ? pusharyKey(authorization.slice("Bearer ".length)) : null;
21
+ var mcpServerBearer = (mcpServers) => bearerKey(asRecord(asRecord(asRecord(mcpServers)?.pushary)?.headers)?.Authorization);
22
+ var appAgentKey = (bridgeAgentKey2) => pusharyKey(asRecord(bridgeAgentKey2)?.key);
23
+ var setupReceiptKey = (claudeMcpReceipt) => bearerKey(asRecord(asRecord(asRecord(claudeMcpReceipt)?.installedPushary)?.headers)?.Authorization);
24
+ var macAppKeepsMcpEntry = (entryKey, keys) => {
25
+ if (!entryKey) return true;
26
+ if (keys.appKey) return entryKey === keys.appKey;
27
+ return entryKey !== keys.setupKey;
28
+ };
29
+
30
+ // src/mac-app-key.ts
31
+ var NOT_CONNECTED = { kind: "not_connected" };
32
+ var CONNECTED_THROUGH_MAC_APP = "This computer is connected through the Pushary Mac app";
33
+ var PAIR_FROM_MAC_APP = "Pair a phone from the Pushary Mac app: Settings > Phone > Pair.";
34
+ var readMacAppAgentKey = () => {
35
+ const stored = readJsonSafe(bridgeAgentKey());
36
+ return stored.kind === "ok" ? appAgentKey(stored.value) : null;
37
+ };
38
+ var macAppConnectionOf = (appKey, appInstalled) => appKey !== null && appInstalled() ? { kind: "connected", keyPrefix: keyPrefix(appKey) } : NOT_CONNECTED;
39
+ var readMacAppConnection = () => macAppConnectionOf(readMacAppAgentKey(), macAppBridgeAvailable);
40
+ var readMacAppConnectionWhenKeyless = (cliKey) => cliKey ? NOT_CONNECTED : readMacAppConnection();
41
+
42
+ export {
43
+ pusharyKey,
44
+ mcpServerBearer,
45
+ setupReceiptKey,
46
+ macAppKeepsMcpEntry,
47
+ CONNECTED_THROUGH_MAC_APP,
48
+ PAIR_FROM_MAC_APP,
49
+ readMacAppAgentKey,
50
+ readMacAppConnection,
51
+ readMacAppConnectionWhenKeyless
52
+ };
@@ -1,3 +1,6 @@
1
+ // src/hooks-spec.ts
2
+ var CURSOR_GATE_SCRIPT = "pushary-gate.mjs";
3
+
1
4
  // src/diagnostics/service-runtime.ts
2
5
  var unescapeXml = (value) => value.replaceAll("&quot;", '"').replaceAll("&apos;", "'").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&");
3
6
  var unquoteSystemd = (value) => value.replaceAll('\\"', '"').replaceAll("\\\\", "\\").replaceAll("%%", "%");
@@ -37,6 +40,7 @@ var versionManagerOf = (execPath) => {
37
40
  var describeVersionManagerPin = (execPath, manager) => `The background service is pinned to ${execPath}, which ${manager} manages. Switching Node versions strands it; run pushary daemon install afterwards.`;
38
41
 
39
42
  export {
43
+ CURSOR_GATE_SCRIPT,
40
44
  readServiceExecPath,
41
45
  versionManagerOf,
42
46
  describeVersionManagerPin
@@ -0,0 +1,46 @@
1
+ import {
2
+ pusharyDir
3
+ } from "./chunk-Z23ZBYDW.js";
4
+ import {
5
+ readJsonSafe,
6
+ writeFileAtomic
7
+ } from "./chunk-T7E75EKA.js";
8
+ import {
9
+ DECLINED_AGENTS_FILE,
10
+ HOOK_SOURCES,
11
+ normalizeAgentId,
12
+ parseDeclinedAgents,
13
+ serializeDeclinedAgents,
14
+ withDeclinedAgent,
15
+ withoutDeclinedAgent
16
+ } from "./chunk-5RGA636G.js";
17
+
18
+ // src/declined-agents-file.ts
19
+ import { join } from "path";
20
+ var DECLINED_AGENTS_MODE = 384;
21
+ var declinedAgentsFile = () => join(pusharyDir(), DECLINED_AGENTS_FILE);
22
+ var readDeclinedAgents = (file = declinedAgentsFile()) => {
23
+ const stored = readJsonSafe(file);
24
+ return stored.kind === "ok" ? parseDeclinedAgents(stored.value) : [];
25
+ };
26
+ var writeDeclinedAgents = (agents, file) => writeFileAtomic(file, serializeDeclinedAgents(agents), DECLINED_AGENTS_MODE, "utf-8");
27
+ var changeDeclinedAgents = (file, applies, next) => {
28
+ const current = readDeclinedAgents(file);
29
+ if (!applies(current)) return "unchanged";
30
+ try {
31
+ writeDeclinedAgents(next(current), file);
32
+ return "changed";
33
+ } catch {
34
+ return "unwritable";
35
+ }
36
+ };
37
+ var recordDeclinedAgent = (agent, file = declinedAgentsFile()) => changeDeclinedAgents(file, (current) => !current.includes(agent), (current) => withDeclinedAgent(current, agent));
38
+ var clearDeclinedAgent = (agent, file = declinedAgentsFile()) => changeDeclinedAgents(file, (current) => current.includes(agent), (current) => withoutDeclinedAgent(current, agent));
39
+ var declinedAgentForSetupChoice = (choice) => normalizeAgentId(choice, HOOK_SOURCES);
40
+
41
+ export {
42
+ declinedAgentsFile,
43
+ recordDeclinedAgent,
44
+ clearDeclinedAgent,
45
+ declinedAgentForSetupChoice
46
+ };
@@ -1,11 +1,3 @@
1
- import {
2
- pusharyHookExecutable
3
- } from "./chunk-4YO4T5FV.js";
4
- import {
5
- isProtectedByScope,
6
- registerHookEntry
7
- } from "./chunk-ZUTU43FT.js";
8
-
9
1
  // src/skills-cli.ts
10
2
  import { execSync } from "child_process";
11
3
  var PUSHARY_SKILL_SOURCE = "Pushary/pushary-skill";
@@ -33,28 +25,6 @@ var installAgentSkill = async (request, effects) => {
33
25
  return "packaged-copy";
34
26
  };
35
27
 
36
- // src/cursor-config.ts
37
- var hookCommandOf = (entry) => {
38
- const command = entry && typeof entry === "object" && !Array.isArray(entry) ? entry.command : void 0;
39
- return typeof command === "string" ? command : "";
40
- };
41
- var isPusharyCursorEntry = (entry) => pusharyHookExecutable(hookCommandOf(entry)) !== null;
42
- var registerCursorGate = (existing, entry) => registerHookEntry(existing, isPusharyCursorEntry, entry);
43
- var withoutPusharyCursorHooks = (hooks, scope) => {
44
- let removed = 0;
45
- const kept = {};
46
- for (const [event, entries] of Object.entries(hooks)) {
47
- if (!Array.isArray(entries)) {
48
- kept[event] = entries;
49
- continue;
50
- }
51
- const others = entries.filter((entry) => !isPusharyCursorEntry(entry) || isProtectedByScope(hookCommandOf(entry), scope));
52
- removed += entries.length - others.length;
53
- if (others.length > 0 || entries.length === 0) kept[event] = others;
54
- }
55
- return { hooks: kept, removed };
56
- };
57
-
58
28
  // src/cli/dry-run.ts
59
29
  import { execFileSync } from "child_process";
60
30
  import { rmSync, writeFileSync } from "fs";
@@ -92,8 +62,6 @@ export {
92
62
  PUSHARY_SKILL_NAME,
93
63
  installSkillViaSkillsCli,
94
64
  installAgentSkill,
95
- registerCursorGate,
96
- withoutPusharyCursorHooks,
97
65
  createGuards,
98
66
  describeSetupSideEffects
99
67
  };
@@ -10,10 +10,10 @@ import {
10
10
  resolvePackageVersionFromBinary,
11
11
  resolvePathBinary,
12
12
  resolvePathBinaryAsync
13
- } from "./chunk-ZUTU43FT.js";
13
+ } from "./chunk-Z23ZBYDW.js";
14
14
  import {
15
15
  MANAGED_PROVIDERS
16
- } from "./chunk-QR6VE5ME.js";
16
+ } from "./chunk-5RGA636G.js";
17
17
 
18
18
  // src/setup/codex-install.ts
19
19
  var NATIVE_BINARY_MIN_BYTES = 20 * 1024 * 1024;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readConfigFileKey
3
- } from "./chunk-ADSQDYYG.js";
3
+ } from "./chunk-REU2VQPH.js";
4
4
 
5
5
  // src/bell/fleet.ts
6
6
  import { closeSync, constants, futimesSync, lstatSync, mkdirSync, openSync, readdirSync, unlinkSync } from "fs";
@@ -141,7 +141,7 @@ var writeLastShown = (at) => {
141
141
  }
142
142
  };
143
143
  var upgradeLine = (context) => ` ${context.liveAgents} agents running. A bell can't tell you which one needs you, and it can't reach your pocket.
144
- pushary connect`;
144
+ pushary pair`;
145
145
  var upgradeNotice = (context, deps = {}) => {
146
146
  const env = deps.env ?? process.env;
147
147
  if (env.PUSHARY_BELL_QUIET === "1" || env.PUSHARY_BELL_QUIET === "true") return null;
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSseMessages
3
- } from "./chunk-L76HTPU6.js";
3
+ } from "./chunk-6AYSKVLL.js";
4
4
  import {
5
5
  NPX_LATEST_COMMAND
6
- } from "./chunk-STQRUH3S.js";
6
+ } from "./chunk-5DCDQ5VW.js";
7
7
 
8
8
  // src/mcp-stdio-bridge.ts
9
9
  var MCP_BRIDGE_BINARY = "pushary-mcp";
@@ -0,0 +1,94 @@
1
+ import {
2
+ SIGNED_OUT_ON_MAC_MESSAGE,
3
+ describeSignedOutKey,
4
+ readSignedOutDiagnosis
5
+ } from "./chunk-Q6C6ILUS.js";
6
+ import {
7
+ createIo
8
+ } from "./chunk-U4TMAANR.js";
9
+ import {
10
+ readKeySource
11
+ } from "./chunk-REU2VQPH.js";
12
+ import {
13
+ absoluteUrl,
14
+ checkApiKey,
15
+ describeKeyCheck,
16
+ keyCheckFromResponse
17
+ } from "./chunk-QRXPWW3M.js";
18
+ import {
19
+ EXIT
20
+ } from "./chunk-KZERVKTD.js";
21
+ import {
22
+ getBaseUrl
23
+ } from "./chunk-IRHABAQT.js";
24
+
25
+ // src/cli/report-key.ts
26
+ var { dim, yellow } = createIo();
27
+ var printReport = (report) => {
28
+ console.log(` ${yellow("!")} ${report.message}`);
29
+ for (const line of report.next) console.log(` ${dim(line)}`);
30
+ };
31
+ var signedOutKeyReport = (check) => {
32
+ if (check.kind !== "rejected") return null;
33
+ const diagnosis = readSignedOutDiagnosis(readKeySource().key, "rejected");
34
+ if (diagnosis.kind !== "signed_out_on_mac") return null;
35
+ return { message: SIGNED_OUT_ON_MAC_MESSAGE, next: describeSignedOutKey(diagnosis), exitCode: EXIT.UNAUTHENTICATED, fatal: true };
36
+ };
37
+ var printKeyCheck = (check, baseUrl) => {
38
+ const report = signedOutKeyReport(check) ?? describeKeyCheck(check, baseUrl);
39
+ printReport(report);
40
+ return report;
41
+ };
42
+ var exitIfKeyFailure = async (response, baseUrl) => {
43
+ const check = await keyCheckFromResponse(response, baseUrl);
44
+ if (!check) return;
45
+ const report = printKeyCheck(check, baseUrl);
46
+ process.exit(report.exitCode);
47
+ };
48
+ var responseDetail = async (response) => {
49
+ try {
50
+ const body = await response.json();
51
+ const text = [body.error, body.message].find((part) => typeof part === "string" && part);
52
+ if (typeof text === "string") return text;
53
+ } catch {
54
+ }
55
+ return response.statusText || `HTTP ${response.status}`;
56
+ };
57
+ var exitOnFailedResponse = async (response, baseUrl) => {
58
+ await exitIfKeyFailure(response, baseUrl);
59
+ console.log(` ${yellow("!")} Failed: ${await responseDetail(response)}`);
60
+ process.exit(EXIT.FAILED);
61
+ };
62
+ var REFUSED_SETTINGS_ACTION = {
63
+ mode: "change the approval mode",
64
+ wait: "change how long approvals wait for you",
65
+ suggestions: "read or accept rule suggestions"
66
+ };
67
+ var APPROVAL_SETTINGS_PATH = "/dashboard/agent/settings";
68
+ var AGENT_KEY_SCOPE = "agent";
69
+ var isAgentKeyRefusal = (status, check) => status === 401 && check.kind === "ok" && check.identity.keyScope === AGENT_KEY_SCOPE;
70
+ var describeAgentKeyRefusal = (request, baseUrl = getBaseUrl()) => ({
71
+ message: `This computer's key cannot ${REFUSED_SETTINGS_ACTION[request]}. Keys from pushary login, phone pairing and the Mac app run approvals and notifications, not account settings.`,
72
+ next: [
73
+ `Change it from the Pushary app, your phone, or the dashboard: ${absoluteUrl(baseUrl, APPROVAL_SETTINGS_PATH)}`,
74
+ "The key itself is valid. Nothing on this computer needs fixing."
75
+ ],
76
+ exitCode: EXIT.USAGE,
77
+ fatal: true
78
+ });
79
+ var exitOnFailedSettingsRequest = async (response, settings) => {
80
+ if (response.status === 401) {
81
+ const check = await checkApiKey(settings.apiKey, { baseUrl: settings.baseUrl });
82
+ if (isAgentKeyRefusal(response.status, check)) {
83
+ const report = describeAgentKeyRefusal(settings.request, settings.baseUrl);
84
+ printReport(report);
85
+ process.exit(report.exitCode);
86
+ }
87
+ }
88
+ return exitOnFailedResponse(response, settings.baseUrl);
89
+ };
90
+
91
+ export {
92
+ printKeyCheck,
93
+ exitOnFailedSettingsRequest
94
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isSafeReadOnlyCommand
3
- } from "./chunk-QR6VE5ME.js";
3
+ } from "./chunk-5RGA636G.js";
4
4
 
5
5
  // src/ledger.ts
6
6
  import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync } from "fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NPX_LATEST_COMMAND
3
- } from "./chunk-STQRUH3S.js";
3
+ } from "./chunk-5DCDQ5VW.js";
4
4
 
5
5
  // src/config.ts
6
6
  import { readFileSync } from "fs";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-POFBE6ZY.js";
4
4
  import {
5
5
  autoUpdateState
6
- } from "./chunk-ZUTU43FT.js";
6
+ } from "./chunk-Z23ZBYDW.js";
7
7
  import {
8
8
  readJsonSafe,
9
9
  writeJsonAtomic
@@ -14,7 +14,7 @@ import {
14
14
  cliPackagePathSegments,
15
15
  globalUpgradeEntry,
16
16
  ownPackageRoot
17
- } from "./chunk-QR6VE5ME.js";
17
+ } from "./chunk-5RGA636G.js";
18
18
 
19
19
  // src/auto-update.ts
20
20
  import { spawn } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-ZUTU43FT.js";
3
+ } from "./chunk-Z23ZBYDW.js";
4
4
  import {
5
5
  writeFileAtomic
6
6
  } from "./chunk-T7E75EKA.js";