pushary 1.9.83 → 1.9.84

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 (127) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{api-EKLKVJQG.js → api-4WEMR2G3.js} +10 -10
  3. package/dist/bin/pushary-bell-hook.js +26 -26
  4. package/dist/bin/pushary-bell.js +10 -10
  5. package/dist/bin/pushary-claude.js +32 -31
  6. package/dist/bin/pushary-clean.js +34 -33
  7. package/dist/bin/pushary-codex-bridge.js +21 -21
  8. package/dist/bin/pushary-codex-hook.js +44 -43
  9. package/dist/bin/pushary-codex-session.js +8 -8
  10. package/dist/bin/pushary-codex.js +14 -13
  11. package/dist/bin/pushary-connect.js +27 -26
  12. package/dist/bin/pushary-cowork.js +5 -5
  13. package/dist/bin/pushary-daemon.js +70 -43
  14. package/dist/bin/pushary-disconnect.js +26 -25
  15. package/dist/bin/pushary-display-hook.js +17 -17
  16. package/dist/bin/pushary-doctor.js +42 -41
  17. package/dist/bin/pushary-elicitation-hook.js +26 -26
  18. package/dist/bin/pushary-gemini-bridge.js +15 -15
  19. package/dist/bin/pushary-gemini-hook.js +35 -34
  20. package/dist/bin/pushary-hook.js +30 -30
  21. package/dist/bin/pushary-login.js +20 -20
  22. package/dist/bin/pushary-logout.js +25 -24
  23. package/dist/bin/pushary-mcp.js +11 -11
  24. package/dist/bin/pushary-mode.js +15 -15
  25. package/dist/bin/pushary-notification-hook.js +25 -25
  26. package/dist/bin/pushary-opencode-hook.js +35 -34
  27. package/dist/bin/pushary-permission-denied-hook.js +30 -30
  28. package/dist/bin/pushary-permission-hook.js +30 -30
  29. package/dist/bin/pushary-post-hook.js +25 -25
  30. package/dist/bin/pushary-prompt-hook.js +25 -25
  31. package/dist/bin/pushary-session-end-hook.js +27 -27
  32. package/dist/bin/pushary-session-start-hook.js +35 -35
  33. package/dist/bin/pushary-setup.js +48 -47
  34. package/dist/bin/pushary-stats.js +5 -5
  35. package/dist/bin/pushary-status.js +32 -31
  36. package/dist/bin/pushary-stop-hook.js +25 -25
  37. package/dist/bin/pushary-stopfailure-hook.js +25 -25
  38. package/dist/bin/pushary-suggestions.js +15 -15
  39. package/dist/bin/pushary-transcript-register.js +21 -20
  40. package/dist/bin/pushary-transcripts.js +30 -20
  41. package/dist/bin/pushary-upgrade.js +40 -39
  42. package/dist/bin/pushary-wait.js +15 -15
  43. package/dist/bin/pushary.js +7 -7
  44. package/dist/{chunk-BLM6O2QL.js → chunk-254B34JU.js} +1 -1
  45. package/dist/{chunk-XYEGVQST.js → chunk-2VZY5XQ5.js} +7 -7
  46. package/dist/chunk-3MWQZKIO.js +843 -0
  47. package/dist/{chunk-46P53RBT.js → chunk-42DNYOC4.js} +23 -21
  48. package/dist/{chunk-7YYJASRF.js → chunk-4J3NGYHG.js} +2 -2
  49. package/dist/{chunk-ZGZ2L3QN.js → chunk-4OP5GWHQ.js} +5 -5
  50. package/dist/{chunk-5UPZR3C3.js → chunk-4QGV3II7.js} +4 -4
  51. package/dist/{chunk-MHUKYYYR.js → chunk-4TMKTLQX.js} +44 -1
  52. package/dist/{chunk-2B7YU4EK.js → chunk-5Z43EFX2.js} +2 -2
  53. package/dist/{chunk-YIAJOV2X.js → chunk-64XK7DLE.js} +3 -3
  54. package/dist/{chunk-VRHVOMH2.js → chunk-6HBWJXU6.js} +3 -3
  55. package/dist/{chunk-IUZCERPQ.js → chunk-7GYDMVHV.js} +2 -2
  56. package/dist/{chunk-BG4YJEFE.js → chunk-7ZYVX2KN.js} +1 -1
  57. package/dist/{chunk-KR3KVDXD.js → chunk-BGMYSRMY.js} +1 -1
  58. package/dist/{chunk-OUYFUUWB.js → chunk-BS5MTP34.js} +2 -2
  59. package/dist/{chunk-VCMDY6YL.js → chunk-BUS7MXEE.js} +3 -3
  60. package/dist/{chunk-EMT7I74E.js → chunk-CIICMXVH.js} +3 -3
  61. package/dist/{chunk-4P256ZAU.js → chunk-CSOVOAX5.js} +6 -6
  62. package/dist/{chunk-VBY2AHSX.js → chunk-CZ7C5AJT.js} +1 -1
  63. package/dist/{chunk-HCLP2QBX.js → chunk-DNBBWBYA.js} +5 -5
  64. package/dist/{chunk-BJN7LMMK.js → chunk-EKWDNEPN.js} +3 -3
  65. package/dist/{chunk-TNWQ6SKS.js → chunk-EX33ZFJ6.js} +3 -3
  66. package/dist/{chunk-TMBLBDPB.js → chunk-FNC4SPOD.js} +2 -2
  67. package/dist/{chunk-IBULUTHA.js → chunk-FRPR4OTH.js} +4 -4
  68. package/dist/{chunk-ACM4OINM.js → chunk-FSSA76HW.js} +1 -1
  69. package/dist/{chunk-J2PAQ3HF.js → chunk-G2GOVKBU.js} +6 -6
  70. package/dist/{chunk-2KVELJZX.js → chunk-GGGOFJBL.js} +1 -1
  71. package/dist/{chunk-GKWPIE6R.js → chunk-GWHZUHIK.js} +1 -1
  72. package/dist/{chunk-BUXMFD5C.js → chunk-H6IJOGDH.js} +4 -4
  73. package/dist/{chunk-SN22OXY3.js → chunk-HARHFDZM.js} +1 -1
  74. package/dist/{chunk-44R5ATBR.js → chunk-HLAW7HUT.js} +2 -2
  75. package/dist/{chunk-G4HTRKCP.js → chunk-HVZJ2EEI.js} +6 -6
  76. package/dist/{chunk-6BD5ZZLL.js → chunk-HWT42Z4O.js} +5 -5
  77. package/dist/{chunk-L4THAI7Q.js → chunk-JHWOM55B.js} +2 -0
  78. package/dist/{chunk-NDLOWIYO.js → chunk-JJCMQRBF.js} +3 -3
  79. package/dist/{chunk-7MRX5JYA.js → chunk-JLJWVKMJ.js} +54 -835
  80. package/dist/{chunk-TBU4WXA4.js → chunk-JSZT4Q23.js} +1 -1
  81. package/dist/{chunk-MA6FJ7U3.js → chunk-LUSWC2MV.js} +3 -3
  82. package/dist/{chunk-C5EWCNJF.js → chunk-OGTZ7JR7.js} +1 -1
  83. package/dist/{chunk-FGWRVOBP.js → chunk-OKWHHDV5.js} +5 -5
  84. package/dist/{chunk-XHHX63PY.js → chunk-OSEGZLCO.js} +3 -3
  85. package/dist/{chunk-B2RDWRKR.js → chunk-PHBZK4SC.js} +2 -2
  86. package/dist/{chunk-S55CXRFD.js → chunk-POKCUYIQ.js} +1 -1
  87. package/dist/{chunk-YZVAAY6B.js → chunk-QF6OJUWQ.js} +1 -1
  88. package/dist/{chunk-5FM4BQOM.js → chunk-QG5Y5A36.js} +10 -10
  89. package/dist/{chunk-UNEJNC6X.js → chunk-QSDZE2B7.js} +5 -5
  90. package/dist/{chunk-Y32CL7XZ.js → chunk-RPNT4D3K.js} +1 -1
  91. package/dist/{chunk-6CJ4MSZU.js → chunk-SAPRO7FI.js} +6 -6
  92. package/dist/{chunk-LLQBPDFQ.js → chunk-SBK7WGSE.js} +2 -2
  93. package/dist/{chunk-GMZTABMV.js → chunk-TD5PW2VI.js} +6 -6
  94. package/dist/{chunk-VUI4HK5O.js → chunk-TFJQAPIA.js} +2 -2
  95. package/dist/{chunk-OKZC4FHN.js → chunk-TNPKYKXU.js} +166 -24
  96. package/dist/{chunk-2BDGGE2G.js → chunk-TSCFJJIB.js} +6 -6
  97. package/dist/{chunk-MND7HQ4P.js → chunk-TZDEHPYZ.js} +1 -1
  98. package/dist/{chunk-FEF3ILT6.js → chunk-UGELL4RB.js} +2 -2
  99. package/dist/{chunk-6WOG2SCC.js → chunk-UIDWJ24H.js} +6 -13
  100. package/dist/{chunk-ZS27XXDA.js → chunk-UWL6VVE3.js} +4 -4
  101. package/dist/{chunk-JIC5PGNI.js → chunk-V4JZHAOY.js} +2 -2
  102. package/dist/{chunk-35ABA2JQ.js → chunk-VD24OIWR.js} +1 -1
  103. package/dist/{chunk-GGI6GTBL.js → chunk-VJZGR4N3.js} +7 -5
  104. package/dist/{chunk-CVPVP4KP.js → chunk-VVWL6AB4.js} +5 -5
  105. package/dist/{chunk-A3TMREYJ.js → chunk-W2IRYDG5.js} +4 -4
  106. package/dist/{chunk-SSNLMIFR.js → chunk-WRKRZJCW.js} +10 -8
  107. package/dist/{chunk-ASEHRBD4.js → chunk-YQCCJ6U5.js} +3 -3
  108. package/dist/{chunk-42RQG2VG.js → chunk-YU5ACKJP.js} +4 -4
  109. package/dist/{chunk-HIMEVTA5.js → chunk-Z75D2NJN.js} +3 -3
  110. package/dist/{chunk-6PWU2LBT.js → chunk-ZHL6F2KC.js} +3 -3
  111. package/dist/{chunk-SVAGMJOH.js → chunk-ZNFAF74M.js} +1 -1
  112. package/dist/{chunk-ELYJNNXG.js → chunk-ZUZ7NTWO.js} +181 -75
  113. package/dist/{chunk-QPJQAE2L.js → chunk-ZWKF7WE4.js} +4 -4
  114. package/dist/{codex-app-cards-switch-CTAOTOCH.js → codex-app-cards-switch-26N5XSSZ.js} +11 -11
  115. package/dist/{codex-desktop-launch-2DZVA5C7.js → codex-desktop-launch-UU6CPB2I.js} +1 -1
  116. package/dist/{codex-session-launch-TMOSTWEH.js → codex-session-launch-66LBR4MG.js} +18 -18
  117. package/dist/{config-OV6WLZXO.js → config-ESAAVJWO.js} +3 -3
  118. package/dist/{global-upgrade-FI42NJNL.js → global-upgrade-QJONTWQI.js} +10 -10
  119. package/dist/{identity-PCA25OI5.js → identity-IZVPSC7B.js} +4 -4
  120. package/dist/{live-capabilities-CYFXHTOI.js → live-capabilities-OEUPZX67.js} +5 -5
  121. package/dist/{paths-4YFDMUK6.js → paths-GDWS3B46.js} +3 -3
  122. package/dist/{reapply-PBQ46BPS.js → reapply-P2VOZGWQ.js} +28 -27
  123. package/dist/src/index.js +29 -29
  124. package/dist/{upgrade-lock-22J2AMVY.js → upgrade-lock-3QABNXBZ.js} +4 -4
  125. package/dist/{usage-7KTINNRK.js → usage-KDRZPUZS.js} +3 -3
  126. package/package.json +1 -1
  127. package/dist/chunk-7EIMASAA.js +0 -74
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NPX_LATEST_COMMAND
3
- } from "./chunk-2KVELJZX.js";
3
+ } from "./chunk-GGGOFJBL.js";
4
4
 
5
5
  // src/config.ts
6
6
  import { readFileSync } from "fs";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  findNativeClaudeInstall
3
- } from "./chunk-BG4YJEFE.js";
3
+ } from "./chunk-7ZYVX2KN.js";
4
4
  import {
5
5
  parseVersion
6
- } from "./chunk-YIAJOV2X.js";
6
+ } from "./chunk-64XK7DLE.js";
7
7
  import {
8
8
  isRecord
9
- } from "./chunk-L4THAI7Q.js";
9
+ } from "./chunk-JHWOM55B.js";
10
10
 
11
11
  // src/setup/agent-probe.ts
12
12
  import { execSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  localRepoKey,
3
3
  normalizeRepoRemote
4
- } from "./chunk-L4THAI7Q.js";
4
+ } from "./chunk-JHWOM55B.js";
5
5
 
6
6
  // src/repo.ts
7
7
  import { existsSync, readFileSync, statSync } from "fs";
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  openCodeConfigDirFrom
3
- } from "./chunk-2BDGGE2G.js";
3
+ } from "./chunk-TSCFJJIB.js";
4
4
  import {
5
5
  nativeClaudeInstallPath
6
- } from "./chunk-BG4YJEFE.js";
6
+ } from "./chunk-7ZYVX2KN.js";
7
7
  import {
8
8
  grokHome
9
- } from "./chunk-GGI6GTBL.js";
9
+ } from "./chunk-VJZGR4N3.js";
10
10
  import {
11
11
  claudeConfigDir,
12
12
  clineDataDirectory,
13
13
  codexHomeFrom
14
- } from "./chunk-B2RDWRKR.js";
14
+ } from "./chunk-PHBZK4SC.js";
15
15
  import {
16
16
  HOOK_COMPATIBLE_PROFILES
17
- } from "./chunk-L4THAI7Q.js";
17
+ } from "./chunk-JHWOM55B.js";
18
18
 
19
19
  // src/vscode-config.ts
20
20
  import { homedir } from "os";
@@ -9,20 +9,20 @@ import {
9
9
  installedCodexApp,
10
10
  readCodexAppRuntime,
11
11
  shellQuoted
12
- } from "./chunk-TMBLBDPB.js";
12
+ } from "./chunk-FNC4SPOD.js";
13
13
  import {
14
14
  writeHuman
15
15
  } from "./chunk-QCGNGEGE.js";
16
16
  import {
17
17
  xml
18
- } from "./chunk-6CJ4MSZU.js";
18
+ } from "./chunk-SAPRO7FI.js";
19
19
  import {
20
20
  CODEX_APP_LAUNCH_AT_LOGIN_VERB,
21
21
  CODEX_APP_LAUNCH_VARIABLE
22
22
  } from "./chunk-E46NE7FB.js";
23
23
  import {
24
24
  writeFileAtomic
25
- } from "./chunk-YIAJOV2X.js";
25
+ } from "./chunk-64XK7DLE.js";
26
26
 
27
27
  // src/codex-app-cards-switch.ts
28
28
  import { execFileSync as execFileSync2 } from "child_process";
@@ -4,7 +4,7 @@ import {
4
4
  quoteIfNeeded,
5
5
  shellDoubleQuoted,
6
6
  writeFileAtomic
7
- } from "./chunk-YIAJOV2X.js";
7
+ } from "./chunk-64XK7DLE.js";
8
8
  import {
9
9
  cmdShimScriptOf
10
10
  } from "./chunk-ZVU6WMMU.js";
@@ -15,7 +15,7 @@ import {
15
15
  HOOK_LOCATOR_BINARY,
16
16
  PRETOOLUSE_GATED_TOOLS,
17
17
  withHookHoldBudget
18
- } from "./chunk-L4THAI7Q.js";
18
+ } from "./chunk-JHWOM55B.js";
19
19
 
20
20
  // src/setup/paths.ts
21
21
  import { createHash as createHash2 } from "crypto";
@@ -7,7 +7,7 @@ import {
7
7
  recordSealerFor,
8
8
  uploadTranscriptRecords,
9
9
  wrapSessionKey
10
- } from "./chunk-IUZCERPQ.js";
10
+ } from "./chunk-7GYDMVHV.js";
11
11
 
12
12
  // src/live-session.ts
13
13
  var MAX_TRANSCRIPT_QUEUE = 100;
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KZERVKTD.js";
4
4
  import {
5
5
  renderCommandHelp
6
- } from "./chunk-2KVELJZX.js";
6
+ } from "./chunk-GGGOFJBL.js";
7
7
  import {
8
8
  getPackageVersion
9
9
  } from "./chunk-ZVU6WMMU.js";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  ensureCodexTrustsPusharyHooks
3
- } from "./chunk-2B7YU4EK.js";
3
+ } from "./chunk-5Z43EFX2.js";
4
4
  import {
5
5
  hermesReceiptPaths,
6
6
  hermesSetupPredatesThePluginFolder,
7
7
  installHermesPlugin,
8
8
  refreshHermesPluginFiles,
9
9
  shippedHermesPlugin
10
- } from "./chunk-OKZC4FHN.js";
10
+ } from "./chunk-TNPKYKXU.js";
11
11
  import {
12
12
  fxIgnoresInstructionsFile,
13
13
  fxInstructionsBody,
@@ -16,7 +16,7 @@ import {
16
16
  macAppFxBridge,
17
17
  refreshClineKey,
18
18
  switchFxHttpEntryToBridge
19
- } from "./chunk-ZGZ2L3QN.js";
19
+ } from "./chunk-4OP5GWHQ.js";
20
20
  import {
21
21
  OPENCODE_HOOK_BINARY,
22
22
  agentHookOwner,
@@ -28,16 +28,16 @@ import {
28
28
  openCodePluginDir,
29
29
  openCodeWired,
30
30
  withOpenCodeAskRules
31
- } from "./chunk-2BDGGE2G.js";
31
+ } from "./chunk-TSCFJJIB.js";
32
32
  import {
33
33
  detectClaudeVersion
34
- } from "./chunk-MA6FJ7U3.js";
34
+ } from "./chunk-LUSWC2MV.js";
35
35
  import {
36
36
  addCompatibleHooks,
37
37
  compatibleConfigFile,
38
38
  compatibleInstructionsFile,
39
39
  hasCompatibleHooks
40
- } from "./chunk-GGI6GTBL.js";
40
+ } from "./chunk-VJZGR4N3.js";
41
41
  import {
42
42
  GEMINI_HOOK_BINARY,
43
43
  addGeminiHooks,
@@ -49,7 +49,7 @@ import {
49
49
  geminiWired,
50
50
  hasGeminiHooks,
51
51
  planHooks
52
- } from "./chunk-42RQG2VG.js";
52
+ } from "./chunk-YU5ACKJP.js";
53
53
  import {
54
54
  CLAUDE_HOOK_BINARY,
55
55
  CLAUDE_HOOK_EVENTS,
@@ -95,7 +95,7 @@ import {
95
95
  renderAgentInstructions,
96
96
  supportedClaudeEvents,
97
97
  vscodePluginMcp
98
- } from "./chunk-B2RDWRKR.js";
98
+ } from "./chunk-PHBZK4SC.js";
99
99
  import {
100
100
  formatVersion,
101
101
  hookCommandsUseBareNames,
@@ -104,12 +104,12 @@ import {
104
104
  resolveGlobalBinary,
105
105
  writeFileAtomic,
106
106
  writeJsonAtomic
107
- } from "./chunk-YIAJOV2X.js";
107
+ } from "./chunk-64XK7DLE.js";
108
108
  import {
109
109
  HOOK_COMPATIBLE_PROFILES,
110
110
  isCompatibleAgentType,
111
111
  isRecord
112
- } from "./chunk-L4THAI7Q.js";
112
+ } from "./chunk-JHWOM55B.js";
113
113
 
114
114
  // src/reapply.ts
115
115
  import { dirname, join } from "path";
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  macAppBridgeAvailable
3
- } from "./chunk-2BDGGE2G.js";
3
+ } from "./chunk-TSCFJJIB.js";
4
4
  import {
5
5
  keyPrefix
6
- } from "./chunk-IBULUTHA.js";
6
+ } from "./chunk-FRPR4OTH.js";
7
7
  import {
8
8
  bridgeAgentKey
9
- } from "./chunk-B2RDWRKR.js";
9
+ } from "./chunk-PHBZK4SC.js";
10
10
  import {
11
11
  readJsonSafe
12
- } from "./chunk-YIAJOV2X.js";
12
+ } from "./chunk-64XK7DLE.js";
13
13
  import {
14
14
  isRecord,
15
15
  isValidApiKey
16
- } from "./chunk-L4THAI7Q.js";
16
+ } from "./chunk-JHWOM55B.js";
17
17
 
18
18
  // src/shared-mcp-key.ts
19
19
  var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guardBinary
3
- } from "./chunk-B2RDWRKR.js";
3
+ } from "./chunk-PHBZK4SC.js";
4
4
 
5
5
  // src/bell/install.ts
6
6
  import { join } from "path";
@@ -4,23 +4,23 @@ import {
4
4
  } from "./chunk-XHKBHWLX.js";
5
5
  import {
6
6
  readControlMode
7
- } from "./chunk-IBULUTHA.js";
7
+ } from "./chunk-FRPR4OTH.js";
8
8
  import {
9
9
  getMachineId
10
- } from "./chunk-JIC5PGNI.js";
10
+ } from "./chunk-V4JZHAOY.js";
11
11
  import {
12
12
  pusharyDir
13
- } from "./chunk-B2RDWRKR.js";
13
+ } from "./chunk-PHBZK4SC.js";
14
14
  import {
15
15
  readJsonSafe,
16
16
  resolveGlobalBinary,
17
17
  writeFileAtomic,
18
18
  writeJsonAtomic,
19
19
  writeJsonAtomicDurable
20
- } from "./chunk-YIAJOV2X.js";
20
+ } from "./chunk-64XK7DLE.js";
21
21
  import {
22
22
  getApiKey
23
- } from "./chunk-TBU4WXA4.js";
23
+ } from "./chunk-JSZT4Q23.js";
24
24
  import {
25
25
  CLI_PACKAGE_NAMES,
26
26
  cmdShimScriptOf,
@@ -30,7 +30,7 @@ import {
30
30
  } from "./chunk-ZVU6WMMU.js";
31
31
  import {
32
32
  isRecord
33
- } from "./chunk-L4THAI7Q.js";
33
+ } from "./chunk-JHWOM55B.js";
34
34
 
35
35
  // src/daemon-lifecycle.ts
36
36
  import { dirname, join, win32 as win32Path } from "path";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  autoUpdateLock
3
- } from "./chunk-B2RDWRKR.js";
3
+ } from "./chunk-PHBZK4SC.js";
4
4
  import {
5
5
  installPackageGlobally,
6
6
  npmErrorMessage,
7
7
  writeJsonAtomic
8
- } from "./chunk-YIAJOV2X.js";
8
+ } from "./chunk-64XK7DLE.js";
9
9
 
10
10
  // src/upgrade-lock.ts
11
11
  import { fork } from "child_process";
@@ -3,10 +3,10 @@ import {
3
3
  forkFinishWithUpgradeLock,
4
4
  installWithUpgradeLock,
5
5
  releaseAutoUpdateLock
6
- } from "./chunk-LLQBPDFQ.js";
6
+ } from "./chunk-SBK7WGSE.js";
7
7
  import {
8
8
  phoneStartIsRequired
9
- } from "./chunk-5UPZR3C3.js";
9
+ } from "./chunk-4QGV3II7.js";
10
10
  import {
11
11
  describeAutoUpdateCheck,
12
12
  globalInstallLocation,
@@ -18,25 +18,25 @@ import {
18
18
  readAutoUpdateState,
19
19
  updateAutoUpdateState,
20
20
  upgradeEntryFor
21
- } from "./chunk-6PWU2LBT.js";
21
+ } from "./chunk-ZHL6F2KC.js";
22
22
  import {
23
23
  autoUpdateLock,
24
24
  autoUpdateLog,
25
25
  autoUpdateState
26
- } from "./chunk-B2RDWRKR.js";
26
+ } from "./chunk-PHBZK4SC.js";
27
27
  import {
28
28
  execNpm,
29
29
  fetchLatestPublishedVersion,
30
30
  npmErrorMessage,
31
31
  readGlobalCliInstallAt,
32
32
  readGlobalPrefix
33
- } from "./chunk-YIAJOV2X.js";
33
+ } from "./chunk-64XK7DLE.js";
34
34
  import {
35
35
  EXIT
36
36
  } from "./chunk-KZERVKTD.js";
37
37
  import {
38
38
  NPX_LATEST_COMMAND
39
- } from "./chunk-2KVELJZX.js";
39
+ } from "./chunk-GGGOFJBL.js";
40
40
  import {
41
41
  commandsPackage,
42
42
  globalUpgradeEntry,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  findNativeClaudeInstall
3
- } from "./chunk-BG4YJEFE.js";
3
+ } from "./chunk-7ZYVX2KN.js";
4
4
  import {
5
5
  isFile
6
- } from "./chunk-YIAJOV2X.js";
6
+ } from "./chunk-64XK7DLE.js";
7
7
 
8
8
  // src/wrapper/claudeBinary.ts
9
9
  import { homedir } from "os";
@@ -5,19 +5,19 @@ import {
5
5
  hermesAppWiringRecord,
6
6
  hermesConfigReceipt,
7
7
  hermesSetupReceipt
8
- } from "./chunk-B2RDWRKR.js";
8
+ } from "./chunk-PHBZK4SC.js";
9
9
  import {
10
10
  readJsonSafe,
11
11
  resolvePathBinary,
12
12
  writeJsonAtomic
13
- } from "./chunk-YIAJOV2X.js";
13
+ } from "./chunk-64XK7DLE.js";
14
14
  import {
15
15
  isNewerVersion,
16
16
  isReleaseVersion
17
17
  } from "./chunk-ZVU6WMMU.js";
18
18
  import {
19
19
  isRecord
20
- } from "./chunk-L4THAI7Q.js";
20
+ } from "./chunk-JHWOM55B.js";
21
21
 
22
22
  // src/hermes/plugin-payload.ts
23
23
  import { createHash } from "crypto";
@@ -571,11 +571,14 @@ def _configured_key():
571
571
  return _key_in_pushary_config()
572
572
 
573
573
 
574
+ def pushary_config_path():
575
+ configured = os.environ.get("PUSHARY_CONFIG_FILE")
576
+ return Path(configured).expanduser() if configured else Path.home() / ".pushary" / "config.json"
577
+
578
+
574
579
  def _key_in_pushary_config():
575
- path = Path(os.environ.get("PUSHARY_CONFIG_FILE", "")).expanduser() \\
576
- if os.environ.get("PUSHARY_CONFIG_FILE") else Path.home() / ".pushary" / "config.json"
577
580
  try:
578
- value = json.loads(path.read_text(encoding="utf-8")).get("apiKey")
581
+ value = json.loads(pushary_config_path().read_text(encoding="utf-8")).get("apiKey")
579
582
  return value if isinstance(value, str) and value else None
580
583
  except Exception:
581
584
  return None
@@ -951,6 +954,7 @@ import threading
951
954
  import time
952
955
  from datetime import datetime, timezone
953
956
  from pathlib import Path
957
+ from typing import NamedTuple
954
958
 
955
959
  from . import api
956
960
 
@@ -958,8 +962,26 @@ logger = logging.getLogger(__name__)
958
962
  MAX_MESSAGES = 5000
959
963
  MAX_SOURCE_BYTES = 20_000_000
960
964
  POLL_SECONDS = 5
965
+ SNAPSHOT_REFRESH_SECONDS = 60
966
+ AUTHORIZATION_LIFETIME_SECONDS = 60
967
+ SNAPSHOT_RETENTION_SECONDS = 48 * 60 * 60
968
+ SNAPSHOT_PRUNE_INTERVAL_SECONDS = 60 * 60
969
+ SOURCE_UNAVAILABLE = "source_unavailable"
970
+ HISTORY_NOT_ALLOWED_WARNING = ("[pushary] Hermes session history is not saved on this computer; it needs "
971
+ "\`npx pushary@latest setup\` with the key Hermes uses, or Session history turned on in the Pushary Mac app")
972
+
973
+
974
+ class _Authorization(NamedTuple):
975
+ inputs: tuple[object, ...]
976
+ expires_at: float
977
+ command: list[str] | None
978
+
979
+
961
980
  _workers: dict[tuple[str, str], tuple[threading.Event, threading.Thread]] = {}
981
+ _authorizations: dict[str, _Authorization] = {}
962
982
  _lock = threading.Lock()
983
+ _next_prune_at = 0.0
984
+ _history_not_allowed_reported = False
963
985
 
964
986
 
965
987
  def _text_blocks(content: object) -> list[dict[str, object]]:
@@ -1088,8 +1110,7 @@ def _registration_command(key: str) -> list[str] | None:
1088
1110
  command = [helper, "hermes"]
1089
1111
  result = subprocess.run([helper, "authorize-export"],
1090
1112
  input=json.dumps({"apiKey": key, "baseUrl": api.BASE_URL}), text=True,
1091
- stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, timeout=5, check=False,
1092
- env={**os.environ, "PUSHARY_API_KEY": key, "PUSHARY_BASE_URL": api.BASE_URL})
1113
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, timeout=5, check=False)
1093
1114
  if result.returncode != 0:
1094
1115
  return None
1095
1116
  authorization = json.loads(result.stdout)
@@ -1100,27 +1121,146 @@ def _registration_command(key: str) -> list[str] | None:
1100
1121
  return None
1101
1122
 
1102
1123
 
1124
+ def _file_state(path: Path | None) -> tuple[int, ...] | None:
1125
+ if path is None:
1126
+ return None
1127
+ try:
1128
+ info = os.lstat(path)
1129
+ except OSError:
1130
+ return None
1131
+ return (info.st_ino, info.st_mode, info.st_nlink, info.st_uid, info.st_size, info.st_mtime_ns, info.st_ctime_ns)
1132
+
1133
+
1134
+ def _authorization_inputs(key: str) -> tuple[object, ...]:
1135
+ root = Path.home() / ".pushary"
1136
+ helper = shutil.which("pushary-transcript-register")
1137
+ sources = (root / "native-transcript-consent.json", root / "bridge-auth", root / "bridge-auth" / "agent-key.json",
1138
+ root / "machine-id", root / "bin" / "pushary-bridge", api.pushary_config_path(),
1139
+ Path(helper) if helper else None)
1140
+ return (key, api.BASE_URL, os.environ.get("PUSHARY_TRANSCRIPTS"), helper, *(_file_state(source) for source in sources))
1141
+
1142
+
1143
+ def _authorized_command(key: str) -> list[str] | None:
1144
+ inputs = _authorization_inputs(key)
1145
+ now = time.monotonic()
1146
+ with _lock:
1147
+ cached = _authorizations.get(key)
1148
+ if cached is not None and cached.inputs == inputs and now < cached.expires_at:
1149
+ return cached.command
1150
+ command = _registration_command(key)
1151
+ with _lock:
1152
+ _authorizations[key] = _Authorization(inputs, now + AUTHORIZATION_LIFETIME_SECONDS, command)
1153
+ return command
1154
+
1155
+
1156
+ def _report_history_not_allowed_once() -> None:
1157
+ global _history_not_allowed_reported
1158
+ with _lock:
1159
+ if _history_not_allowed_reported:
1160
+ return
1161
+ _history_not_allowed_reported = True
1162
+ logger.warning(HISTORY_NOT_ALLOWED_WARNING)
1163
+
1164
+
1165
+ def _history_root() -> Path:
1166
+ return Path.home() / ".pushary" / "hermes-history"
1167
+
1168
+
1169
+ def _snapshot_expired(path: Path, now: float) -> bool:
1170
+ return now - path.lstat().st_mtime > SNAPSHOT_RETENTION_SECONDS
1171
+
1172
+
1173
+ def _prune_expired_snapshots(root: Path, now: float) -> None:
1174
+ try:
1175
+ bindings = [entry for entry in root.iterdir() if not entry.is_symlink() and entry.is_dir()]
1176
+ except OSError:
1177
+ return
1178
+ for binding in bindings:
1179
+ try:
1180
+ snapshots = list(binding.iterdir())
1181
+ except OSError:
1182
+ continue
1183
+ for snapshot in snapshots:
1184
+ try:
1185
+ if _snapshot_expired(snapshot, now):
1186
+ snapshot.unlink()
1187
+ except OSError:
1188
+ continue
1189
+
1190
+
1191
+ def _prune_expired_snapshots_periodically() -> None:
1192
+ global _next_prune_at
1193
+ now = time.monotonic()
1194
+ with _lock:
1195
+ if now < _next_prune_at:
1196
+ return
1197
+ _next_prune_at = now + SNAPSHOT_PRUNE_INTERVAL_SECONDS
1198
+ _prune_expired_snapshots(_history_root(), time.time())
1199
+
1200
+
1201
+ def _source_state(database_path: Path) -> tuple[object, ...]:
1202
+ return (_file_state(database_path), _file_state(database_path.with_name(database_path.name + "-wal")))
1203
+
1204
+
1205
+ def _snapshot_refresh_due(written_at: float | None, now: float) -> bool:
1206
+ return written_at is None or not 0 <= now - written_at < SNAPSHOT_REFRESH_SECONDS
1207
+
1208
+
1209
+ def _is_permanent_source_failure(failure: Exception) -> bool:
1210
+ return isinstance(failure, ValueError)
1211
+
1212
+
1213
+ def _snapshot_digest(messages: list[dict[str, object]], error: str | None, completed: bool) -> str:
1214
+ encoded = json.dumps([messages, error, completed], ensure_ascii=True, allow_nan=False).encode("utf-8")
1215
+ return hashlib.sha256(encoded).hexdigest()
1216
+
1217
+
1218
+ def _write_changed_snapshot(path: Path, session_id: str, messages: list[dict[str, object]], error: str | None,
1219
+ completed: bool, written: str | None, refresh_due: bool) -> str | None:
1220
+ digest = _snapshot_digest(messages, error, completed)
1221
+ if not refresh_due and digest == written:
1222
+ return None
1223
+ write_snapshot(path, session_id, messages, error=error, completed=completed)
1224
+ return digest
1225
+
1226
+
1103
1227
  def _export_loop(database_path: Path, session_id: str, key: str, command: list[str], stop: threading.Event) -> None:
1104
1228
  binding = hashlib.sha256((api.BASE_URL.rstrip("/") + "\\0" + key + "\\0" + str(database_path)).encode()).hexdigest()
1105
- path = Path.home() / ".pushary" / "hermes-history" / binding / f"{session_id}.json"
1229
+ path = _history_root() / binding / f"{session_id}.json"
1106
1230
  next_registration = 0
1231
+ written_at = None
1232
+ source_state = None
1233
+ written = None
1107
1234
  warned = False
1108
1235
  revoked = False
1109
1236
  try:
1110
1237
  while True:
1111
- if api._get_api_key() != key or _registration_command(key) != command:
1238
+ if api._get_api_key() != key or _authorized_command(key) != command:
1112
1239
  revoked = True
1113
1240
  break
1114
1241
  ending = stop.is_set()
1115
- try:
1116
- messages = read_display_history(database_path, session_id)
1117
- write_snapshot(path, session_id, messages, completed=ending)
1118
- warned = False
1119
- except Exception:
1120
- if not warned:
1242
+ now = time.time()
1243
+ refresh_due = ending or _snapshot_refresh_due(written_at, now)
1244
+ current_state = _source_state(database_path)
1245
+ if refresh_due or current_state != source_state:
1246
+ source_state = current_state
1247
+ error = None
1248
+ try:
1249
+ messages = read_display_history(database_path, session_id)
1250
+ except Exception as failure:
1251
+ messages, error = [], SOURCE_UNAVAILABLE
1252
+ if not _is_permanent_source_failure(failure):
1253
+ source_state = None
1254
+ try:
1255
+ digest = _write_changed_snapshot(path, session_id, messages, error, ending and error is None, written, refresh_due)
1256
+ except ValueError:
1257
+ messages, error = [], SOURCE_UNAVAILABLE
1258
+ digest = _write_changed_snapshot(path, session_id, messages, error, False, written, refresh_due)
1259
+ if digest is not None:
1260
+ written, written_at = digest, now
1261
+ if error is not None and not warned:
1121
1262
  logger.warning("[pushary] Hermes history source is unavailable; existing phone history is preserved")
1122
- warned = True
1123
- write_snapshot(path, session_id, [], error="source_unavailable")
1263
+ warned = error is not None
1124
1264
  if ending or time.monotonic() >= next_registration:
1125
1265
  payload = {"session_id": session_id, "cwd": str(database_path.parent), "transcript_path": str(path),
1126
1266
  "hook_event_name": "SessionEnd" if ending else "SessionStart"}
@@ -1148,16 +1288,18 @@ def start_history(session_id: object, parent_session_id: object = None) -> None:
1148
1288
  try:
1149
1289
  from hermes_constants import get_hermes_home
1150
1290
 
1151
- key = api._get_api_key()
1152
- command = _registration_command(key)
1153
- if command is None:
1154
- return
1291
+ _prune_expired_snapshots_periodically()
1155
1292
  database_path = (get_hermes_home() / "state.db").resolve()
1156
1293
  identity = (str(database_path), session_id)
1157
1294
  with _lock:
1158
1295
  if identity in _workers or len(_workers) >= 32:
1159
1296
  return
1160
- stop = threading.Event()
1297
+ key = api._get_api_key()
1298
+ command = _authorized_command(key)
1299
+ if command is None:
1300
+ _report_history_not_allowed_once()
1301
+ return
1302
+ stop = threading.Event()
1161
1303
  context = contextvars.copy_context()
1162
1304
  thread = threading.Thread(target=context.run, args=(_export_loop, database_path, session_id, key, command, stop),
1163
1305
  name="pushary-history", daemon=True)
@@ -1321,7 +1463,7 @@ def record_plugin_load(approval_transport_registered, home=None, pid=None, now=N
1321
1463
  logger.debug("[pushary] could not record the plugin load: %s", exc)
1322
1464
  return None
1323
1465
  ` },
1324
- { path: "plugin.yaml", contents: "name: pushary\nversion: 0.9.0\ndescription: Push notifications and human-in-the-loop for Hermes Agent via Pushary\nauthor: RalphNex OU\nrequires_env:\n - name: PUSHARY_API_KEY\n description: Your Pushary API key\n url: https://pushary.com/sign-up?from=hermes\n secret: true\nprovides_tools:\n - pushary_remind\n - pushary_notify\n - pushary_ask\n - pushary_wait\n - pushary_cancel\n - pushary_propose_scope\n - pushary_enroll\n - pushary_ask_end_user\nprovides_hooks:\n - pre_llm_call\n - pre_tool_call\n - post_tool_call\n - on_session_start\n - on_session_end\n - on_session_finalize\nprovides_approval_transports:\n - pushary\n" },
1466
+ { path: "plugin.yaml", contents: "name: pushary\nversion: 0.9.1\ndescription: Push notifications and human-in-the-loop for Hermes Agent via Pushary\nauthor: RalphNex OU\nrequires_env:\n - name: PUSHARY_API_KEY\n description: Your Pushary API key\n url: https://pushary.com/sign-up?from=hermes\n secret: true\nprovides_tools:\n - pushary_remind\n - pushary_notify\n - pushary_ask\n - pushary_wait\n - pushary_cancel\n - pushary_propose_scope\n - pushary_enroll\n - pushary_ask_end_user\nprovides_hooks:\n - pre_llm_call\n - pre_tool_call\n - post_tool_call\n - on_session_start\n - on_session_end\n - on_session_finalize\nprovides_approval_transports:\n - pushary\n" },
1325
1467
  { path: "schemas.py", contents: `PUSHARY_REMIND = {
1326
1468
  "name": "pushary_remind",
1327
1469
  "description": "Schedule a one-time personal reminder on Pushary, even after Hermes exits. Use body plus in_minutes or at (ISO timestamp with explicit UTC offset, within 30 days). Never guess the user's timezone. Confirm the returned time. No arguments lists pending reminders; cancel_reminder_id cancels a scheduled one. Use Hermes cron for agent work; use this for reminding the operator.",
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  compatibleConfigFile
3
- } from "./chunk-GGI6GTBL.js";
3
+ } from "./chunk-VJZGR4N3.js";
4
4
  import {
5
5
  hookOwnerOf,
6
6
  hookOwnerOfCommands,
7
7
  liveBridgeProbe,
8
8
  resolveBridgeStub
9
- } from "./chunk-42RQG2VG.js";
9
+ } from "./chunk-YU5ACKJP.js";
10
10
  import {
11
11
  AGENT_CHOICES
12
- } from "./chunk-SN22OXY3.js";
12
+ } from "./chunk-HARHFDZM.js";
13
13
  import {
14
14
  claudeSettings,
15
15
  codexHooksJson,
@@ -19,10 +19,10 @@ import {
19
19
  pusharyDir,
20
20
  vscodePluginDir,
21
21
  windowsNodeLauncherFor
22
- } from "./chunk-B2RDWRKR.js";
22
+ } from "./chunk-PHBZK4SC.js";
23
23
  import {
24
24
  readJsonSafe
25
- } from "./chunk-YIAJOV2X.js";
25
+ } from "./chunk-64XK7DLE.js";
26
26
  import {
27
27
  HOOK_BUDGETS,
28
28
  HOOK_COMPATIBLE_PROFILES,
@@ -30,7 +30,7 @@ import {
30
30
  OPENCODE_APPROVAL_EVENT,
31
31
  hookCompatibleProfile,
32
32
  isRecord
33
- } from "./chunk-L4THAI7Q.js";
33
+ } from "./chunk-JHWOM55B.js";
34
34
 
35
35
  // src/opencode-plugin.ts
36
36
  var OPENCODE_PLUGIN_MARKER = "pushary-opencode-plugin w1";
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-KZERVKTD.js";
8
8
  import {
9
9
  redactSecretsFromContent
10
- } from "./chunk-L4THAI7Q.js";
10
+ } from "./chunk-JHWOM55B.js";
11
11
 
12
12
  // src/cli/json.ts
13
13
  var writeStdoutFully = (text) => new Promise((resolve, reject) => {