@pushary/agent-hooks 1.4.1 → 1.4.2

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 (78) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/bin/pushary-bell-hook.js +18 -18
  3. package/dist/bin/pushary-bell.js +6 -6
  4. package/dist/bin/pushary-claude.js +18 -18
  5. package/dist/bin/pushary-clean.js +24 -20
  6. package/dist/bin/pushary-codex-bridge.js +10 -10
  7. package/dist/bin/pushary-codex-hook.js +31 -26
  8. package/dist/bin/pushary-codex.js +6 -6
  9. package/dist/bin/pushary-connect.js +6 -6
  10. package/dist/bin/pushary-cowork.js +3 -3
  11. package/dist/bin/pushary-daemon.js +22 -22
  12. package/dist/bin/pushary-disconnect.js +10 -10
  13. package/dist/bin/pushary-doctor.js +20 -20
  14. package/dist/bin/pushary-elicitation-hook.js +17 -17
  15. package/dist/bin/pushary-gemini-bridge.js +9 -9
  16. package/dist/bin/pushary-gemini-hook.js +19 -19
  17. package/dist/bin/pushary-hook.js +23 -23
  18. package/dist/bin/pushary-login.js +7 -7
  19. package/dist/bin/pushary-logout.js +4 -4
  20. package/dist/bin/pushary-mode.js +3 -3
  21. package/dist/bin/pushary-notification-hook.js +20 -20
  22. package/dist/bin/pushary-opencode-hook.js +19 -19
  23. package/dist/bin/pushary-permission-denied-hook.js +24 -24
  24. package/dist/bin/pushary-permission-hook.js +23 -23
  25. package/dist/bin/pushary-post-hook.js +20 -20
  26. package/dist/bin/pushary-prompt-hook.js +20 -20
  27. package/dist/bin/pushary-session-end-hook.js +20 -20
  28. package/dist/bin/pushary-session-start-hook.js +22 -22
  29. package/dist/bin/pushary-setup.js +53 -32
  30. package/dist/bin/pushary-stats.js +2 -2
  31. package/dist/bin/pushary-status.js +10 -10
  32. package/dist/bin/pushary-stop-hook.js +20 -20
  33. package/dist/bin/pushary-stopfailure-hook.js +20 -20
  34. package/dist/bin/pushary-transcript-register.js +16 -16
  35. package/dist/bin/pushary-transcripts.js +4 -4
  36. package/dist/bin/pushary-upgrade.js +14 -14
  37. package/dist/bin/pushary-wait.js +3 -3
  38. package/dist/{chunk-BZBUPZC6.js → chunk-25RTLTQD.js} +1 -1
  39. package/dist/{chunk-SKXLIVFM.js → chunk-2V2IKOGJ.js} +1 -1
  40. package/dist/{chunk-MN3XOVRK.js → chunk-4BROEAKH.js} +1 -1
  41. package/dist/{chunk-KEMEBTCJ.js → chunk-4ZDKSDVW.js} +4 -4
  42. package/dist/{chunk-43JKGLZZ.js → chunk-55KW4FLG.js} +2 -2
  43. package/dist/{chunk-2GMI6JH6.js → chunk-ACYIZ3KH.js} +5 -5
  44. package/dist/{chunk-3BPB2HYZ.js → chunk-BZ4GDOJX.js} +3 -3
  45. package/dist/{chunk-R3AMKNIW.js → chunk-DY4ILT6L.js} +1 -1
  46. package/dist/{chunk-VYUDGQM7.js → chunk-F4UWL4NY.js} +1 -1
  47. package/dist/{chunk-TI3ZWXZG.js → chunk-FU2DFEAZ.js} +1 -1
  48. package/dist/{chunk-LNGYW6G4.js → chunk-G653QPTR.js} +17 -13
  49. package/dist/{chunk-CRNAXFQ6.js → chunk-GZ7E6VOB.js} +1 -1
  50. package/dist/{chunk-WIOXWUUH.js → chunk-II7PUMPB.js} +3 -3
  51. package/dist/{chunk-4FN6VV56.js → chunk-JVTOML54.js} +2 -2
  52. package/dist/{chunk-SWFF5U2N.js → chunk-LEAAERSQ.js} +1 -1
  53. package/dist/{chunk-ED5TA2FJ.js → chunk-LPYCPFBZ.js} +3 -3
  54. package/dist/{chunk-HK3IXIQJ.js → chunk-M5CTUFF3.js} +1 -1
  55. package/dist/{chunk-3UA6FPRC.js → chunk-MUVTZNJW.js} +3 -3
  56. package/dist/{chunk-JOVWYVSR.js → chunk-MW6ZPC6R.js} +1 -1
  57. package/dist/{chunk-3T52B2OF.js → chunk-NHTAHAIS.js} +1 -1
  58. package/dist/{chunk-D7ERHWYB.js → chunk-NOWZUGZW.js} +1 -1
  59. package/dist/{chunk-QBS6LGEK.js → chunk-NY6XQ6CA.js} +1 -1
  60. package/dist/{chunk-LUT2EZLG.js → chunk-PC6DU5C4.js} +1 -1
  61. package/dist/{chunk-FVKFDTN6.js → chunk-SOUZBGYJ.js} +4 -0
  62. package/dist/{chunk-ALFT7H5B.js → chunk-SUWRZYQG.js} +56 -5
  63. package/dist/{chunk-S3EP4B35.js → chunk-T5SZ4PML.js} +24 -10
  64. package/dist/{chunk-SAF6NNXY.js → chunk-TRLFZKVG.js} +1 -1
  65. package/dist/{chunk-KI36MAT6.js → chunk-TYEO6T5J.js} +2 -2
  66. package/dist/{chunk-TNS3YLFE.js → chunk-UJBZIKSY.js} +6 -6
  67. package/dist/{chunk-K6I5M2ME.js → chunk-UM5J3J4V.js} +1 -1
  68. package/dist/{chunk-HQLAZWJJ.js → chunk-VIOL2DJS.js} +5 -5
  69. package/dist/{chunk-PHHGHHOW.js → chunk-VOMOZ4D5.js} +1 -1
  70. package/dist/{chunk-I6HRQOMT.js → chunk-VW66JEGU.js} +4 -4
  71. package/dist/{chunk-TF4IOINR.js → chunk-WPVHRUDT.js} +3 -3
  72. package/dist/{chunk-GOFDGTEI.js → chunk-XDP3UYH5.js} +16 -43
  73. package/dist/{chunk-37VLIYLI.js → chunk-Y3MM6PYN.js} +1 -1
  74. package/dist/{chunk-WEO5JCB4.js → chunk-YXP3WPAI.js} +1 -1
  75. package/dist/{chunk-LYXX5NSB.js → chunk-ZVY25BMK.js} +1 -1
  76. package/dist/{reapply-BAWDJTG7.js → reapply-J527BCJG.js} +8 -8
  77. package/dist/src/index.js +12 -12
  78. package/package.json +1 -1
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  AGENT_CHOICES
3
- } from "./chunk-R3AMKNIW.js";
3
+ } from "./chunk-DY4ILT6L.js";
4
4
  import {
5
5
  isBridgeLocator
6
- } from "./chunk-LYXX5NSB.js";
6
+ } from "./chunk-ZVY25BMK.js";
7
7
  import {
8
8
  pusharyHookExecutable
9
- } from "./chunk-TF4IOINR.js";
9
+ } from "./chunk-WPVHRUDT.js";
10
10
  import {
11
11
  BELL_HOOK_BINARY
12
- } from "./chunk-JOVWYVSR.js";
12
+ } from "./chunk-MW6ZPC6R.js";
13
13
 
14
14
  // src/setup/hook-ownership.ts
15
15
  var commandsIn = (value) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SETUP_FLAGS
3
- } from "./chunk-R3AMKNIW.js";
3
+ } from "./chunk-DY4ILT6L.js";
4
4
  import {
5
5
  parseFlags
6
6
  } from "./chunk-GMXKITVA.js";
@@ -14,7 +14,7 @@ import {
14
14
  CLAUDE_CONNECTOR_URL,
15
15
  COWORK_CONNECTOR_LIMIT,
16
16
  COWORK_STANDING_INSTRUCTIONS
17
- } from "./chunk-FVKFDTN6.js";
17
+ } from "./chunk-SOUZBGYJ.js";
18
18
 
19
19
  // src/cli/cowork.ts
20
20
  import { readFileSync } from "fs";
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  detectClaudeVersion
3
- } from "./chunk-LUT2EZLG.js";
3
+ } from "./chunk-PC6DU5C4.js";
4
4
  import {
5
5
  addClaudeMcpServer,
6
6
  addPusharyHooks,
7
7
  addPusharyToolPermissions
8
- } from "./chunk-WIOXWUUH.js";
8
+ } from "./chunk-II7PUMPB.js";
9
9
  import {
10
10
  claudeUnprovenHolds,
11
11
  claudeWired,
12
12
  codexUnprovenHolds,
13
13
  codexWired,
14
14
  geminiWired
15
- } from "./chunk-TF4IOINR.js";
15
+ } from "./chunk-WPVHRUDT.js";
16
16
  import {
17
17
  CLAUDE_HOOK_BINARY,
18
18
  CLAUDE_HOOK_EVENTS,
@@ -24,7 +24,7 @@ import {
24
24
  needsReregistration,
25
25
  registrationSignatures,
26
26
  supportedClaudeEvents
27
- } from "./chunk-ED5TA2FJ.js";
27
+ } from "./chunk-LPYCPFBZ.js";
28
28
  import {
29
29
  CODEX_HOOK_BINARY,
30
30
  addCodexHookTrust,
@@ -44,7 +44,7 @@ import {
44
44
  registrationHolderOf,
45
45
  resolveGlobalBinary,
46
46
  vscodePluginMcp
47
- } from "./chunk-SAF6NNXY.js";
47
+ } from "./chunk-TRLFZKVG.js";
48
48
  import {
49
49
  readJsonSafe,
50
50
  writeFileAtomic,
@@ -4,17 +4,17 @@ import {
4
4
  } from "./chunk-XHKBHWLX.js";
5
5
  import {
6
6
  getMachineId
7
- } from "./chunk-3T52B2OF.js";
7
+ } from "./chunk-NHTAHAIS.js";
8
8
  import {
9
9
  pusharyDir,
10
10
  resolveGlobalBinary
11
- } from "./chunk-SAF6NNXY.js";
11
+ } from "./chunk-TRLFZKVG.js";
12
12
  import {
13
13
  getPackageVersion
14
14
  } from "./chunk-DINDL2CF.js";
15
15
  import {
16
16
  readControlMode
17
- } from "./chunk-TI3ZWXZG.js";
17
+ } from "./chunk-FU2DFEAZ.js";
18
18
  import {
19
19
  readJsonSafe,
20
20
  writeFileAtomic,
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  COMPATIBLE_AGENT_TYPES,
9
9
  isValidApiKey
10
- } from "./chunk-FVKFDTN6.js";
10
+ } from "./chunk-SOUZBGYJ.js";
11
11
 
12
12
  // src/setup/options.ts
13
13
  var AGENT_CHOICES = ["claude_code", "codex", "gemini_cli", "hermes", "cursor", "vscode", "opencode", ...COMPATIBLE_AGENT_TYPES, "custom"];
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HOOK_BUDGETS,
3
3
  OPENCODE_APPROVAL_EVENT
4
- } from "./chunk-FVKFDTN6.js";
4
+ } from "./chunk-SOUZBGYJ.js";
5
5
 
6
6
  // src/opencode-plugin.ts
7
7
  var OPENCODE_PLUGIN_MARKER = "pushary-opencode-plugin w1";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveInstallSourceFor
3
- } from "./chunk-K6I5M2ME.js";
3
+ } from "./chunk-UM5J3J4V.js";
4
4
  import {
5
5
  backupFile,
6
6
  readJsonSafe,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  NOTIFICATION_PUSH_TYPES,
3
3
  POSTTOOLUSE_MIRROR_ONLY_TOOLS
4
- } from "./chunk-WEO5JCB4.js";
4
+ } from "./chunk-YXP3WPAI.js";
5
5
  import {
6
6
  cancelQuestion,
7
7
  isPolicyConfig,
@@ -10,13 +10,13 @@ import {
10
10
  } from "./chunk-LGXUGYUH.js";
11
11
  import {
12
12
  getMachineId
13
- } from "./chunk-3T52B2OF.js";
13
+ } from "./chunk-NHTAHAIS.js";
14
14
  import {
15
15
  withRetry
16
16
  } from "./chunk-EYRGBYZG.js";
17
17
  import {
18
18
  reportedInstallSource
19
- } from "./chunk-K6I5M2ME.js";
19
+ } from "./chunk-UM5J3J4V.js";
20
20
  import {
21
21
  getApiKey,
22
22
  getBaseUrl
@@ -44,7 +44,7 @@ import {
44
44
  resolveAutoResolveOrigin,
45
45
  resolvePolicy,
46
46
  toToolLookup
47
- } from "./chunk-FVKFDTN6.js";
47
+ } from "./chunk-SOUZBGYJ.js";
48
48
 
49
49
  // src/policy.ts
50
50
  import { createHash } from "crypto";
@@ -1368,20 +1368,23 @@ var phoneDrivenEnv = (base) => ({
1368
1368
  import { join as join5 } from "path";
1369
1369
  import { tmpdir as tmpdir4 } from "os";
1370
1370
  import { createHash as createHash4 } from "crypto";
1371
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, statSync as statSync4, writeFileSync as writeFileSync4 } from "fs";
1371
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, statSync as statSync4, writeFileSync as writeFileSync4, rmSync as rmSync2 } from "fs";
1372
1372
  var THROTTLE_DIR = join5(tmpdir4(), "pushary-throttle");
1373
1373
  var markerPath = (key) => join5(THROTTLE_DIR, createHash4("sha256").update(key).digest("hex").slice(0, 16));
1374
- var throttlePass = (key, windowMs) => {
1374
+ var claimThrottle = (key, windowMs) => {
1375
1375
  try {
1376
1376
  const path = markerPath(key);
1377
- if (existsSync4(path) && Date.now() - statSync4(path).mtimeMs < windowMs) return false;
1377
+ if (existsSync4(path) && Date.now() - statSync4(path).mtimeMs < windowMs) return "throttled";
1378
1378
  mkdirSync3(THROTTLE_DIR, { recursive: true });
1379
1379
  writeFileSync4(path, "", "utf-8");
1380
- return true;
1380
+ return "passed";
1381
1381
  } catch {
1382
- return false;
1382
+ return "unavailable";
1383
1383
  }
1384
1384
  };
1385
+ var releaseThrottle = (key) => {
1386
+ rmSync2(markerPath(key), { force: true });
1387
+ };
1385
1388
 
1386
1389
  // src/events.ts
1387
1390
  import { basename as basename3, join as join6 } from "path";
@@ -1688,7 +1691,7 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
1688
1691
  }
1689
1692
  const isMirrorOnly = NON_GATED_MIRROR_TOOLS.has(input.tool_name);
1690
1693
  const decisionSource = isMirrorOnly ? void 0 : deriveDecisionSource(lookup.tool, lookup.input, liveMode, agent.type, input.cwd, input.session_id);
1691
- const beacon = !isMirrorOnly && decisionSource === "policy_auto" && throttlePass(`autodecision:${sessionKey}:${lookup.tool}`, AUTO_DECISION_WINDOW_MS) ? deriveAutoDecisionBeacon(lookup.tool, lookup.input, liveMode, agent.type, input.cwd, input.session_id) : void 0;
1694
+ const beacon = !isMirrorOnly && decisionSource === "policy_auto" && claimThrottle(`autodecision:${sessionKey}:${lookup.tool}`, AUTO_DECISION_WINDOW_MS) === "passed" ? deriveAutoDecisionBeacon(lookup.tool, lookup.input, liveMode, agent.type, input.cwd, input.session_id) : void 0;
1692
1695
  const toolReport = reportEvent({
1693
1696
  event: isError ? "tool_error" : "tool_complete",
1694
1697
  occurredAt,
@@ -1704,7 +1707,7 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
1704
1707
  usage: deriveUsage(input.transcript_path, input.session_id)
1705
1708
  }, { maxAttempts: 1, budgetMs: Math.min(DRAINING_REPORT_BUDGET_MS, Math.max(0, deadline - Date.now())), signal });
1706
1709
  const extraReports = [];
1707
- if (throttlePass(`hookactive:${sessionKey}`, HOOK_ACTIVE_WINDOW_MS)) {
1710
+ if (claimThrottle(`hookactive:${sessionKey}`, HOOK_ACTIVE_WINDOW_MS) === "passed") {
1708
1711
  extraReports.push(
1709
1712
  reportEvent(
1710
1713
  {
@@ -1898,7 +1901,7 @@ var handleNotification = async (input, agent = CLAUDE_CODE_AGENT) => {
1898
1901
  }, { maxAttempts: 1, timeoutMs: 2500, signal }).catch(() => {
1899
1902
  });
1900
1903
  if (!teammateIdle && NOTIFICATION_PUSH_TYPES.has(notifType)) {
1901
- if (!throttlePass(`notify:${sessionKey}:${notifType}`, NOTIFICATION_THROTTLE_MS)) return;
1904
+ if (claimThrottle(`notify:${sessionKey}:${notifType}`, NOTIFICATION_THROTTLE_MS) !== "passed") return;
1902
1905
  let apiKey;
1903
1906
  try {
1904
1907
  apiKey = getApiKey();
@@ -1990,7 +1993,8 @@ export {
1990
1993
  markPendingCommandFailed,
1991
1994
  removePendingCommand,
1992
1995
  repoKeyFor,
1993
- throttlePass,
1996
+ claimThrottle,
1997
+ releaseThrottle,
1994
1998
  readLastUserPrompt,
1995
1999
  CODEX_AGENT,
1996
2000
  codexAllow,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  redactSecrets
3
- } from "./chunk-FVKFDTN6.js";
3
+ } from "./chunk-SOUZBGYJ.js";
4
4
 
5
5
  // src/crypto.ts
6
6
  import nacl from "tweetnacl";
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  CLAUDE_HOOK_EVENTS,
3
3
  supportedClaudeEvents
4
- } from "./chunk-ED5TA2FJ.js";
4
+ } from "./chunk-LPYCPFBZ.js";
5
5
  import {
6
6
  guardBinary,
7
7
  holdBudgetOf,
8
8
  isProtectedByScope,
9
9
  registerHookEntry
10
- } from "./chunk-SAF6NNXY.js";
10
+ } from "./chunk-TRLFZKVG.js";
11
11
  import {
12
12
  HOOK_LOCATOR_BINARY,
13
13
  withHookHoldBudget
14
- } from "./chunk-FVKFDTN6.js";
14
+ } from "./chunk-SOUZBGYJ.js";
15
15
 
16
16
  // src/claude-config.ts
17
17
  import { join } from "path";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  registerTranscript
3
- } from "./chunk-TNS3YLFE.js";
3
+ } from "./chunk-UJBZIKSY.js";
4
4
  import {
5
5
  degradedLine
6
- } from "./chunk-FVKFDTN6.js";
6
+ } from "./chunk-SOUZBGYJ.js";
7
7
 
8
8
  // src/tool-hook-input.ts
9
9
  var OPTIONAL_TEXT_FIELDS = ["hook_event_name", "session_id", "cwd", "transcript_path", "tool_use_id", "permission_mode"];
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isSafeReadOnlyCommand
3
- } from "./chunk-FVKFDTN6.js";
3
+ } from "./chunk-SOUZBGYJ.js";
4
4
 
5
5
  // src/ledger.ts
6
6
  import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync } from "fs";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  NOTIFICATION_MATCHED_TYPES,
3
3
  POSTTOOLUSE_MIRRORED_TOOLS
4
- } from "./chunk-WEO5JCB4.js";
4
+ } from "./chunk-YXP3WPAI.js";
5
5
  import {
6
6
  isProtectedByScope,
7
7
  registerHookEntry
8
- } from "./chunk-SAF6NNXY.js";
8
+ } from "./chunk-TRLFZKVG.js";
9
9
  import {
10
10
  CLAUDE_PRETOOLUSE_MATCHER,
11
11
  HOOK_BUDGETS,
12
12
  HOOK_LOCATOR_BINARY
13
- } from "./chunk-FVKFDTN6.js";
13
+ } from "./chunk-SOUZBGYJ.js";
14
14
 
15
15
  // src/gemini-config.ts
16
16
  var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HOOK_HOLD_BUDGET_ENV,
3
3
  hookHoldBudgetProof
4
- } from "./chunk-FVKFDTN6.js";
4
+ } from "./chunk-SOUZBGYJ.js";
5
5
 
6
6
  // src/hold-budget.ts
7
7
  var takeHookHoldBudget = (args = process.argv.slice(2), env = process.env) => {
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  openCodeConfigDirFrom
3
- } from "./chunk-VYUDGQM7.js";
3
+ } from "./chunk-F4UWL4NY.js";
4
4
  import {
5
5
  codexHomeFrom
6
- } from "./chunk-SAF6NNXY.js";
6
+ } from "./chunk-TRLFZKVG.js";
7
7
  import {
8
8
  HOOK_COMPATIBLE_PROFILES
9
- } from "./chunk-FVKFDTN6.js";
9
+ } from "./chunk-SOUZBGYJ.js";
10
10
 
11
11
  // src/vscode-config.ts
12
12
  import { homedir } from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guardBinary
3
- } from "./chunk-SAF6NNXY.js";
3
+ } from "./chunk-TRLFZKVG.js";
4
4
 
5
5
  // src/bell/install.ts
6
6
  import { join } from "path";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-SAF6NNXY.js";
3
+ } from "./chunk-TRLFZKVG.js";
4
4
  import {
5
5
  writeFileAtomic
6
6
  } from "./chunk-T7E75EKA.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  describeKeyCheck,
3
3
  keyCheckFromResponse
4
- } from "./chunk-QBS6LGEK.js";
4
+ } from "./chunk-NY6XQ6CA.js";
5
5
  import {
6
6
  createIo
7
7
  } from "./chunk-5RUIFDTP.js";
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  isValidApiKey,
15
15
  normalizeKeyScope
16
- } from "./chunk-FVKFDTN6.js";
16
+ } from "./chunk-SOUZBGYJ.js";
17
17
 
18
18
  // src/session.ts
19
19
  var samePusharyAccount = (left, right) => left.kind === "ok" && right.kind === "ok" && left.identity.workspaceId !== "" && left.identity.workspaceId === right.identity.workspaceId && left.identity.siteId === right.identity.siteId;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseVersion
3
- } from "./chunk-ED5TA2FJ.js";
3
+ } from "./chunk-LPYCPFBZ.js";
4
4
 
5
5
  // src/setup/agent-probe.ts
6
6
  import { execSync } from "child_process";
@@ -458,6 +458,9 @@ var degradedPayload = (subsystem, report) => ({
458
458
  });
459
459
  var degradedLine = (subsystem, report) => `${DEGRADED_PREFIX} ${JSON.stringify(degradedPayload(subsystem, report))}`;
460
460
 
461
+ // ../contracts/src/setup-wire.ts
462
+ var PAIR_TTL_SECONDS = 900;
463
+
461
464
  // ../contracts/src/index.ts
462
465
  var KEY_SCOPES = ["full_access", "agent", "connector", "bound"];
463
466
  var normalizeKeyScope = (value) => typeof value === "string" && KEY_SCOPES.includes(value) ? value : null;
@@ -2086,6 +2089,7 @@ export {
2086
2089
  hookWritePath,
2087
2090
  isHookActivationReport,
2088
2091
  hookActivationResult,
2092
+ PAIR_TTL_SECONDS,
2089
2093
  normalizeKeyScope,
2090
2094
  parseAgentQuestion,
2091
2095
  parseAgentQuestions,
@@ -1,17 +1,67 @@
1
1
  import {
2
- canonicalGateInputs
3
- } from "./chunk-LNGYW6G4.js";
2
+ AUTO_DECISION_WINDOW_MS,
3
+ DEFAULT_SESSION,
4
+ canonicalGateInputs,
5
+ claimThrottle,
6
+ deriveToolTarget,
7
+ permissionDeniedAction,
8
+ releaseThrottle,
9
+ reportEvent
10
+ } from "./chunk-G653QPTR.js";
4
11
  import {
5
12
  canonicalJson
6
- } from "./chunk-SAF6NNXY.js";
13
+ } from "./chunk-TRLFZKVG.js";
7
14
  import {
8
15
  writeFileAtomic
9
16
  } from "./chunk-T7E75EKA.js";
10
17
  import {
11
18
  BLOCKED_ACTION_GRANT_TTL_SECONDS,
12
19
  blockedActionIdentity,
13
- shouldDeferToNativeMode
14
- } from "./chunk-FVKFDTN6.js";
20
+ machineDecisionFor,
21
+ shouldDeferToNativeMode,
22
+ wireVerdictFor
23
+ } from "./chunk-SOUZBGYJ.js";
24
+
25
+ // src/machine-decision-audit.ts
26
+ import { basename } from "path";
27
+ var reportMachineDenial = async (input, verdict, agent) => {
28
+ const decision = machineDecisionFor(wireVerdictFor(verdict, 0));
29
+ if (!decision) return;
30
+ const sessionKey = input.session_id || DEFAULT_SESSION;
31
+ const toolTarget = deriveToolTarget(input.tool_name, input.tool_input);
32
+ const throttleKey = `machinedecision:${agent.type}:${sessionKey}:${input.tool_name}:${decision.origin}:${toolTarget ?? ""}`;
33
+ const throttle = claimThrottle(throttleKey, AUTO_DECISION_WINDOW_MS);
34
+ if (throttle === "throttled") return;
35
+ if (throttle === "unavailable") {
36
+ console.error("[Pushary] Could not access the audit throttle; reporting this denial without deduplication.");
37
+ }
38
+ try {
39
+ const response = await reportEvent({
40
+ event: "permission_denied",
41
+ occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
42
+ toolUseId: input.tool_use_id,
43
+ agentType: agent.type,
44
+ agentName: `${agent.label} - ${basename(input.cwd ?? process.cwd())}`,
45
+ action: permissionDeniedAction(input.tool_name),
46
+ sessionId: input.session_id,
47
+ decisionSource: "policy_auto",
48
+ decisionOrigin: decision.origin,
49
+ decisionOutcome: decision.outcome,
50
+ toolName: input.tool_name,
51
+ toolTarget
52
+ }, { maxAttempts: 1, timeoutMs: 800, requireOk: true, skipDrain: true });
53
+ if (response?.ok !== true) throw new Error("Audit delivery was not acknowledged");
54
+ } catch {
55
+ console.error("[Pushary] Could not record the machine denial. The action remains blocked; its audit delivery will be retried on the next matching denial.");
56
+ if (throttle === "passed") {
57
+ try {
58
+ releaseThrottle(throttleKey);
59
+ } catch {
60
+ console.error("[Pushary] Could not reset the failed audit throttle.");
61
+ }
62
+ }
63
+ }
64
+ };
15
65
 
16
66
  // src/native-defer.ts
17
67
  var nativeDeferOptions = () => {
@@ -190,6 +240,7 @@ var forgetBlockedActionHint = (fingerprint) => {
190
240
  };
191
241
 
192
242
  export {
243
+ reportMachineDenial,
193
244
  defersToNativeMode,
194
245
  userScope,
195
246
  codexCallKey,
@@ -15,10 +15,11 @@ import {
15
15
  } from "./chunk-EYRGBYZG.js";
16
16
  import {
17
17
  reportedInstallSource
18
- } from "./chunk-K6I5M2ME.js";
18
+ } from "./chunk-UM5J3J4V.js";
19
19
  import {
20
+ PAIR_TTL_SECONDS,
20
21
  isAnswerSource
21
- } from "./chunk-FVKFDTN6.js";
22
+ } from "./chunk-SOUZBGYJ.js";
22
23
 
23
24
  // src/reach.ts
24
25
  var reachVerdict = (channels) => {
@@ -747,8 +748,13 @@ var printConnectInstructions = async (apiKey) => {
747
748
  return phoneFailure("no_device");
748
749
  };
749
750
  var PAIR_POLL_INTERVAL_MS = 2e3;
750
- var PAIR_TIMEOUT_MS = 9e5;
751
+ var PAIR_STOP_BEFORE_EXPIRY_MS = 1e4;
752
+ var PAIR_TIMEOUT_MS = PAIR_TTL_SECONDS * 1e3 - PAIR_STOP_BEFORE_EXPIRY_MS;
751
753
  var PAIR_HINT_AFTER_MS = 45e3;
754
+ var PAIR_BROWSER_FALLBACK_AFTER_MS = 6e4;
755
+ var BROWSER_CONNECT_COMMAND = "npx @pushary/agent-hooks setup --connect browser";
756
+ var PAIR_BROWSER_FALLBACK_LINE = `Still waiting? Sign in with a browser instead: Ctrl-C, then ${BROWSER_CONNECT_COMMAND}`;
757
+ var SYSTEM_PAIR_CLOCK = { now: () => Date.now(), sleep };
752
758
  var startPairing = async (cliPublicKey) => {
753
759
  try {
754
760
  const res = await fetch(`${apiBase()}/api/mobile/pair/start`, {
@@ -837,7 +843,9 @@ var buildPairLinks = (pairId, publicKeyB64, baseUrl = apiBase(), code = null) =>
837
843
  };
838
844
  };
839
845
  var connectViaAppPairing = async (options = {}) => {
846
+ const clock = options.clock ?? SYSTEM_PAIR_CLOCK;
840
847
  const keypair = generateKeypair();
848
+ const requestedAt = clock.now();
841
849
  const started = await startPairing(keypair.publicKeyB64);
842
850
  if (!started) {
843
851
  console.log(` ${yellow("!")} Couldn't start pairing. Check your connection and try again.`);
@@ -854,12 +862,13 @@ var connectViaAppPairing = async (options = {}) => {
854
862
  console.log(` ${dim("Confirm the app shows fingerprint")} ${cyan(publicKeyFingerprint(keypair.publicKeyB64))}`);
855
863
  console.log(` ${dim("Already have the app and it opened a browser? Use")} ${cyan(deepLink)}`);
856
864
  console.log();
857
- const startedAt = Date.now();
858
- const deadline = startedAt + PAIR_TIMEOUT_MS;
865
+ const startedAt = clock.now();
866
+ const deadline = requestedAt + PAIR_TIMEOUT_MS;
859
867
  let hintShown = false;
868
+ let browserFallbackShown = false;
860
869
  const stop = startSpinner(() => {
861
- const left = Math.max(0, Math.ceil((deadline - Date.now()) / 6e4));
862
- if (Date.now() - startedAt < PAIR_HINT_AFTER_MS) {
870
+ const left = Math.max(0, Math.ceil((deadline - clock.now()) / 6e4));
871
+ if (clock.now() - startedAt < PAIR_HINT_AFTER_MS) {
863
872
  return "Waiting for the app to authorize";
864
873
  }
865
874
  if (!hintShown) {
@@ -880,8 +889,12 @@ var connectViaAppPairing = async (options = {}) => {
880
889
  process.once("SIGINT", onInterrupt);
881
890
  let consecutiveFailures = 0;
882
891
  try {
883
- while (Date.now() < deadline) {
892
+ while (clock.now() < deadline) {
884
893
  if (cancelled) return pairFailed("cancelled");
894
+ if (!browserFallbackShown && clock.now() - startedAt >= PAIR_BROWSER_FALLBACK_AFTER_MS) {
895
+ browserFallbackShown = true;
896
+ writeStatusLine(dim(PAIR_BROWSER_FALLBACK_LINE));
897
+ }
885
898
  const claim = await claimPairing(pairId);
886
899
  if (claim === null) {
887
900
  consecutiveFailures += 1;
@@ -890,7 +903,7 @@ var connectViaAppPairing = async (options = {}) => {
890
903
  await cancelPairing(pairId);
891
904
  return pairFailed("unreachable");
892
905
  }
893
- await sleep(PAIR_POLL_INTERVAL_MS);
906
+ await clock.sleep(PAIR_POLL_INTERVAL_MS);
894
907
  continue;
895
908
  }
896
909
  consecutiveFailures = 0;
@@ -915,7 +928,7 @@ var connectViaAppPairing = async (options = {}) => {
915
928
  stop(yellow("!"), describePairFailure(claim.reason));
916
929
  return pairFailed("rejected");
917
930
  }
918
- await sleep(PAIR_POLL_INTERVAL_MS);
931
+ await clock.sleep(PAIR_POLL_INTERVAL_MS);
919
932
  }
920
933
  stop(yellow("!"), "Timed out waiting for the app");
921
934
  await cancelPairing(pairId);
@@ -940,6 +953,7 @@ export {
940
953
  confirmAppConnection,
941
954
  connectExistingApp,
942
955
  printConnectInstructions,
956
+ BROWSER_CONNECT_COMMAND,
943
957
  pairingEscapeApplies,
944
958
  connectViaAppPairing
945
959
  };
@@ -2,7 +2,7 @@ import {
2
2
  HOOK_BUDGETS,
3
3
  HOOK_LOCATOR_BINARY,
4
4
  withHookHoldBudget
5
- } from "./chunk-FVKFDTN6.js";
5
+ } from "./chunk-SOUZBGYJ.js";
6
6
 
7
7
  // src/npm.ts
8
8
  import { execFileSync, execSync } from "child_process";
@@ -2,10 +2,10 @@ import {
2
2
  resolveBinary,
3
3
  resolveGlobalPackageVersion,
4
4
  resolvePackageVersionFromBinary
5
- } from "./chunk-SAF6NNXY.js";
5
+ } from "./chunk-TRLFZKVG.js";
6
6
  import {
7
7
  MANAGED_PROVIDERS
8
- } from "./chunk-FVKFDTN6.js";
8
+ } from "./chunk-SOUZBGYJ.js";
9
9
 
10
10
  // src/live-capabilities.ts
11
11
  var CLAUDE_BRIDGE_CAPABILITY = "claude-bridge";
@@ -6,16 +6,16 @@ import {
6
6
  } from "./chunk-SGZJ5LYH.js";
7
7
  import {
8
8
  hookOwnerOf
9
- } from "./chunk-KEMEBTCJ.js";
9
+ } from "./chunk-4ZDKSDVW.js";
10
10
  import {
11
11
  ensureDaemonRunning
12
- } from "./chunk-3BPB2HYZ.js";
12
+ } from "./chunk-BZ4GDOJX.js";
13
13
  import {
14
14
  buildTranscriptRecords,
15
15
  decodePublicKey,
16
16
  generateSessionKey,
17
17
  wrapSessionKey
18
- } from "./chunk-CRNAXFQ6.js";
18
+ } from "./chunk-GZ7E6VOB.js";
19
19
  import {
20
20
  fetchTranscriptRecipients,
21
21
  uploadTranscriptRecords
@@ -23,14 +23,14 @@ import {
23
23
  import {
24
24
  transcriptEnvironmentPreference,
25
25
  transcriptsEnabled
26
- } from "./chunk-MN3XOVRK.js";
26
+ } from "./chunk-4BROEAKH.js";
27
27
  import {
28
28
  codexHome,
29
29
  pusharyDir
30
- } from "./chunk-SAF6NNXY.js";
30
+ } from "./chunk-TRLFZKVG.js";
31
31
  import {
32
32
  readTranscriptPreference
33
- } from "./chunk-TI3ZWXZG.js";
33
+ } from "./chunk-FU2DFEAZ.js";
34
34
  import {
35
35
  writeJsonAtomic
36
36
  } from "./chunk-T7E75EKA.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-2UMNXADU.js";
4
4
  import {
5
5
  normalizeInstallSource
6
- } from "./chunk-FVKFDTN6.js";
6
+ } from "./chunk-SOUZBGYJ.js";
7
7
 
8
8
  // src/install-source.ts
9
9
  import { readFileSync } from "fs";