pushary 1.9.8 → 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 (103) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/bin/pushary-bell-hook.js +22 -23
  3. package/dist/bin/pushary-bell.js +13 -13
  4. package/dist/bin/pushary-claude.js +26 -27
  5. package/dist/bin/pushary-clean.js +48 -51
  6. package/dist/bin/pushary-codex-bridge.js +20 -20
  7. package/dist/bin/pushary-codex-hook.js +34 -35
  8. package/dist/bin/pushary-codex.js +13 -13
  9. package/dist/bin/pushary-connect.js +39 -16
  10. package/dist/bin/pushary-cowork.js +5 -5
  11. package/dist/bin/pushary-daemon.js +35 -37
  12. package/dist/bin/pushary-disconnect.js +29 -32
  13. package/dist/bin/pushary-doctor.js +83 -72
  14. package/dist/bin/pushary-elicitation-hook.js +25 -26
  15. package/dist/bin/pushary-gemini-bridge.js +13 -13
  16. package/dist/bin/pushary-gemini-hook.js +29 -30
  17. package/dist/bin/pushary-hook.js +36 -37
  18. package/dist/bin/pushary-login.js +12 -12
  19. package/dist/bin/pushary-logout.js +10 -10
  20. package/dist/bin/pushary-mcp.js +9 -9
  21. package/dist/bin/pushary-mode.js +12 -12
  22. package/dist/bin/pushary-notification-hook.js +29 -30
  23. package/dist/bin/pushary-opencode-hook.js +28 -29
  24. package/dist/bin/pushary-permission-denied-hook.js +30 -31
  25. package/dist/bin/pushary-permission-hook.js +33 -34
  26. package/dist/bin/pushary-post-hook.js +30 -31
  27. package/dist/bin/pushary-prompt-hook.js +29 -30
  28. package/dist/bin/pushary-session-end-hook.js +29 -30
  29. package/dist/bin/pushary-session-start-hook.js +33 -35
  30. package/dist/bin/pushary-setup.js +132 -114
  31. package/dist/bin/pushary-stats.js +5 -5
  32. package/dist/bin/pushary-status.js +48 -18
  33. package/dist/bin/pushary-stop-hook.js +29 -30
  34. package/dist/bin/pushary-stopfailure-hook.js +29 -30
  35. package/dist/bin/pushary-suggestions.js +12 -12
  36. package/dist/bin/pushary-transcript-register.js +18 -19
  37. package/dist/bin/pushary-transcripts.js +7 -7
  38. package/dist/bin/pushary-upgrade.js +38 -44
  39. package/dist/bin/pushary-wait.js +12 -12
  40. package/dist/bin/pushary.js +6 -6
  41. package/dist/{chunk-CLOSJ4ES.js → chunk-462EQA6K.js} +1 -1
  42. package/dist/{chunk-7DVNSQWF.js → chunk-5DCDQ5VW.js} +1 -1
  43. package/dist/{chunk-TCQ43LSG.js → chunk-5N5L6DNN.js} +3 -3
  44. package/dist/{chunk-I5IJRMNV.js → chunk-5RGA636G.js} +21 -9
  45. package/dist/{chunk-MKTJEXZ3.js → chunk-6AYSKVLL.js} +3 -3
  46. package/dist/{chunk-MXHTGVFZ.js → chunk-6EBGOHDJ.js} +16 -20
  47. package/dist/{chunk-ZN3C6GBG.js → chunk-6W5M3MSE.js} +4 -4
  48. package/dist/{chunk-2A53H4S6.js → chunk-AI7RMFVV.js} +22 -21
  49. package/dist/{chunk-ZBK6E2OR.js → chunk-APP43AW7.js} +1 -1
  50. package/dist/{chunk-V5HPPF3E.js → chunk-AZOKPWVI.js} +1 -1
  51. package/dist/{chunk-IHO3YQAN.js → chunk-B5NMSP3V.js} +2 -2
  52. package/dist/{chunk-FQ2GORVG.js → chunk-BNSKVIAW.js} +2 -2
  53. package/dist/{chunk-2QGYMY7A.js → chunk-BYLKCZ2G.js} +142 -4
  54. package/dist/{chunk-MFF3ONG5.js → chunk-BZLHTMT6.js} +76 -8
  55. package/dist/{chunk-DPGSLWOS.js → chunk-COQ64C4F.js} +10 -10
  56. package/dist/{chunk-IAD2RT4L.js → chunk-DCCSULXK.js} +4 -4
  57. package/dist/{chunk-6TE27XZR.js → chunk-DP3WX7FW.js} +2 -2
  58. package/dist/chunk-E5HOHIUV.js +52 -0
  59. package/dist/{chunk-GU3EJCVV.js → chunk-EA5NWDK7.js} +4 -0
  60. package/dist/{chunk-BXET3ALR.js → chunk-EIAEUG7G.js} +2 -2
  61. package/dist/{chunk-I6MJXLMY.js → chunk-F7R3SZ4Q.js} +2 -2
  62. package/dist/{chunk-IHFDPV7C.js → chunk-G7RIDXAT.js} +1 -1
  63. package/dist/{chunk-HRULIYDU.js → chunk-H5T27W7M.js} +2 -2
  64. package/dist/{chunk-BEJRK4DF.js → chunk-HBWYMRR5.js} +4 -4
  65. package/dist/{chunk-ZSTSEBG7.js → chunk-IIVZZMSO.js} +1 -1
  66. package/dist/{chunk-5QUPKDI5.js → chunk-IRHABAQT.js} +1 -1
  67. package/dist/{chunk-7PT35RY2.js → chunk-K545B734.js} +2 -2
  68. package/dist/{chunk-DUZVXBBU.js → chunk-KOWFRUIT.js} +1 -1
  69. package/dist/{chunk-KRCR2CRQ.js → chunk-KQFTBQ66.js} +11 -11
  70. package/dist/{chunk-TCWKTUAE.js → chunk-LENBKYRB.js} +2 -2
  71. package/dist/{chunk-3I6IVOZV.js → chunk-M3STIAGU.js} +3 -3
  72. package/dist/{chunk-CD47ZFFZ.js → chunk-MD4SVNT6.js} +1 -1
  73. package/dist/{chunk-WG3K4TCH.js → chunk-MLGIVVSG.js} +1 -1
  74. package/dist/{chunk-MGRFDGWU.js → chunk-NGKUXZID.js} +2 -2
  75. package/dist/{chunk-KF3UZLYI.js → chunk-NUVGDBZC.js} +1 -1
  76. package/dist/{chunk-NWDG3MSW.js → chunk-OAYWO5NP.js} +1 -1
  77. package/dist/{chunk-2WXF3QJR.js → chunk-Q6C6ILUS.js} +2 -2
  78. package/dist/{chunk-2QTO5YIT.js → chunk-QIOIO7VN.js} +6 -6
  79. package/dist/{chunk-LWOO567I.js → chunk-QRXPWW3M.js} +3 -3
  80. package/dist/{chunk-B64KHETR.js → chunk-QTIUJZRX.js} +3 -3
  81. package/dist/{chunk-WWOHTTVP.js → chunk-R5RIVOPL.js} +2 -2
  82. package/dist/{chunk-N4QSPI3B.js → chunk-REU2VQPH.js} +2 -2
  83. package/dist/{chunk-WS4H76EP.js → chunk-RQ32ADJP.js} +2 -2
  84. package/dist/{chunk-LKLVTG3V.js → chunk-SZ4Q6ZVS.js} +5 -5
  85. package/dist/{chunk-QOLITCIP.js → chunk-T6ZN4TEF.js} +1 -1
  86. package/dist/{chunk-CKV3UPMU.js → chunk-TO3PS646.js} +2 -2
  87. package/dist/{chunk-KFF7G225.js → chunk-UAP5DS6P.js} +3 -3
  88. package/dist/{chunk-KHNFLYJO.js → chunk-UF6RBP5V.js} +4 -4
  89. package/dist/{chunk-DKMD6AWR.js → chunk-UPIZSCYD.js} +4 -4
  90. package/dist/{chunk-ZW3XZLJC.js → chunk-VHPFNLRS.js} +5 -5
  91. package/dist/{chunk-M6BZZFVQ.js → chunk-VIIHC42X.js} +1 -1
  92. package/dist/{chunk-2VZAALEJ.js → chunk-WRPYCIV2.js} +8 -8
  93. package/dist/{chunk-ZBHUHJG6.js → chunk-Z23ZBYDW.js} +6 -4
  94. package/dist/{chunk-DL7XWKYV.js → chunk-ZGADIZDS.js} +2 -2
  95. package/dist/{global-upgrade-I56HNM23.js → global-upgrade-H272QOGD.js} +6 -6
  96. package/dist/{paths-AGY43CXS.js → paths-HMVOTFUN.js} +2 -2
  97. package/dist/{reapply-IA5XUKWW.js → reapply-Q5NHDTVU.js} +22 -24
  98. package/dist/src/index.js +19 -19
  99. package/dist/{upgrade-lock-B34TAUKV.js → upgrade-lock-L3GHFIRW.js} +3 -3
  100. package/package.json +1 -1
  101. package/dist/chunk-3Z3A37WD.js +0 -77
  102. package/dist/chunk-OP7IHC2I.js +0 -24
  103. package/dist/chunk-YIG2R3BJ.js +0 -145
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getBaseUrl
3
- } from "./chunk-5QUPKDI5.js";
3
+ } from "./chunk-IRHABAQT.js";
4
4
 
5
5
  // src/transcript-api.ts
6
6
  var fetchTranscriptRecipients = async (apiKey, baseUrl = getBaseUrl()) => {
@@ -2,7 +2,7 @@ import {
2
2
  DISCONNECT_AGENT_IDS,
3
3
  SETUP_AGENT_CHOICES,
4
4
  isApprovalMode
5
- } from "./chunk-I5IJRMNV.js";
5
+ } from "./chunk-5RGA636G.js";
6
6
 
7
7
  // src/cli/mode-request.ts
8
8
  var parseDuration = (value) => {
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  readExistingMachineId
3
- } from "./chunk-DUZVXBBU.js";
3
+ } from "./chunk-KOWFRUIT.js";
4
4
  import {
5
5
  NetworkError
6
6
  } from "./chunk-7QLSKOSU.js";
7
7
  import {
8
8
  getBaseUrl
9
- } from "./chunk-5QUPKDI5.js";
9
+ } from "./chunk-IRHABAQT.js";
10
10
  import {
11
11
  clientContextHeaders,
12
12
  getPackageVersion
13
- } from "./chunk-I5IJRMNV.js";
13
+ } from "./chunk-5RGA636G.js";
14
14
 
15
15
  // src/cli/net.ts
16
16
  import { createRequire } from "module";
@@ -2186,7 +2186,9 @@ function agentQuestionStrategy(source, event, toolName) {
2186
2186
  if (source !== null && event === "PreToolUse" && UPDATED_INPUT_QUESTION_SOURCES.has(source)) return AGENT_QUESTION_STRATEGY.updatedInput;
2187
2187
  return AGENT_QUESTION_STRATEGY.native;
2188
2188
  }
2189
- var ASKED_IN_EVERY_MODE_TOOLS = [AGENT_QUESTION_TOOL, "ExitPlanMode"];
2189
+ var questionHandedToTheTerminal = (toolName, modeState) => toolName === AGENT_QUESTION_TOOL && modeState.askHandoff === true;
2190
+ var EXIT_PLAN_MODE_TOOL = "ExitPlanMode";
2191
+ var ASKED_IN_EVERY_MODE_TOOLS = [AGENT_QUESTION_TOOL, EXIT_PLAN_MODE_TOOL];
2190
2192
  var ASKED_IN_EVERY_MODE = new Set(ASKED_IN_EVERY_MODE_TOOLS);
2191
2193
  var isAskedInEveryMode = (toolName) => ASKED_IN_EVERY_MODE.has(toolName);
2192
2194
  var NATIVE_BLOCK_EVENTS = /* @__PURE__ */ new Set(["PermissionDenied"]);
@@ -2267,6 +2269,12 @@ var resolveGate = (input) => {
2267
2269
  };
2268
2270
  var editAsksAtTheAgentsPrompt = (input, verdict) => verdict.kind === "gate" && !verdict.scopeReason && (input.modeState.mode ?? input.config.modeOverride ?? null) === null && !aChosenRuleGoverns(input) && verdict.policy.mode === "push_first" && ACCEPT_EDITS_DEFER_TOOLS.has(input.toolName);
2269
2271
  var claudePromptsBeforeAnEdit = (permissionMode) => permissionMode === "default";
2272
+ var runsTheClaudeHook = (source) => source === null || source === "claude" || hookCompatibleProfileBySource(source) !== void 0;
2273
+ var agentPromptsBeforeAnEdit = ({ source, event, permissionMode }) => {
2274
+ if (source === "codex") return event === "PermissionRequest";
2275
+ return event === "PreToolUse" && runsTheClaudeHook(source) && claudePromptsBeforeAnEdit(permissionMode);
2276
+ };
2277
+ var editGoesToTheAgentsPrompt = (call, input, verdict) => agentPromptsBeforeAnEdit(call) && editAsksAtTheAgentsPrompt(input, verdict);
2270
2278
  var MAX_AGENT_PERMISSION_RULES_PER_KIND = 256;
2271
2279
  var MAX_AGENT_PERMISSION_RULE_LENGTH = 512;
2272
2280
  var isAgentPermissionRule = (value) => typeof value === "string" && value.length > 0 && value.length <= MAX_AGENT_PERMISSION_RULE_LENGTH;
@@ -2437,6 +2445,7 @@ var claudePermissionRequestOutput = (decision, reason, updatedInput) => ({
2437
2445
  decision: decision === "allow" ? { behavior: "allow", ...updatedInput ? { updatedInput } : {} } : { behavior: "deny", ...reason ? { message: reason } : {} }
2438
2446
  }
2439
2447
  });
2448
+ var DENIED_FROM_PUSHARY_REASON = "Denied from Pushary";
2440
2449
  var gateOutputFor = (source, event, decision, reason) => {
2441
2450
  let output;
2442
2451
  if (source === "claude" || source === "vscode") {
@@ -2452,7 +2461,7 @@ var gateOutputFor = (source, event, decision, reason) => {
2452
2461
  output = {
2453
2462
  hookSpecificOutput: {
2454
2463
  hookEventName: "PermissionRequest",
2455
- decision: decision === "allow" ? { behavior: "allow" } : { behavior: "deny", message: reason ?? "Denied from Pushary" }
2464
+ decision: decision === "allow" ? { behavior: "allow" } : { behavior: "deny", message: reason ?? DENIED_FROM_PUSHARY_REASON }
2456
2465
  }
2457
2466
  };
2458
2467
  } else if (event === "PreToolUse" && decision === "deny") {
@@ -2460,19 +2469,19 @@ var gateOutputFor = (source, event, decision, reason) => {
2460
2469
  hookSpecificOutput: {
2461
2470
  hookEventName: "PreToolUse",
2462
2471
  permissionDecision: "deny",
2463
- permissionDecisionReason: reason ?? "Denied from Pushary"
2472
+ permissionDecisionReason: reason ?? DENIED_FROM_PUSHARY_REASON
2464
2473
  }
2465
2474
  };
2466
2475
  }
2467
2476
  } else if (source === "gemini" && event === "BeforeTool" && decision !== "ask") {
2468
- output = decision === "allow" ? { decision: "allow" } : { decision: "deny", reason: reason ?? "Denied from Pushary" };
2477
+ output = decision === "allow" ? { decision: "allow" } : { decision: "deny", reason: reason ?? DENIED_FROM_PUSHARY_REASON };
2469
2478
  } else if (source === "opencode" && event === OPENCODE_APPROVAL_EVENT) {
2470
- output = decision === "deny" ? { status: "deny", reason: reason ?? "Denied from Pushary" } : { status: decision };
2479
+ output = decision === "deny" ? { status: "deny", reason: reason ?? DENIED_FROM_PUSHARY_REASON } : { status: decision };
2471
2480
  } else if (source === "cursor" && CURSOR_GATE_EVENTS.includes(event)) {
2472
2481
  output = decision === "allow" ? { permission: "allow" } : decision === "ask" && event !== "preToolUse" ? { permission: "ask" } : {
2473
2482
  permission: "deny",
2474
2483
  user_message: "Command denied via Pushary.",
2475
- agent_message: reason ?? "Denied from Pushary"
2484
+ agent_message: reason ?? DENIED_FROM_PUSHARY_REASON
2476
2485
  };
2477
2486
  } else {
2478
2487
  const profile = hookCompatibleProfileBySource(source);
@@ -2500,7 +2509,9 @@ var renderElicitationOutput = (event, action, content) => ELICITATION_EVENTS.inc
2500
2509
  var UNVERIFIABLE_APPROVAL_REASON = "Pushary could not create a verifiable approval. Retry the action.";
2501
2510
  var DECISION_STOP_REASON = "Approval was cancelled or became unavailable. Retry only after resolving it.";
2502
2511
  var WITHDRAWN_APPROVAL_REASON = "The phone question was withdrawn. Approve in the current client.";
2512
+ var PLAN_DECLINED_REASON = "Plan declined from the phone. Ask what to change before coding.";
2503
2513
  var claudeStoppedPreToolUseOutput = (reason) => stoppedOutput(claudePreToolUseOutput("deny", reason), reason);
2514
+ var claudeStoppedPermissionRequestOutput = (reason) => stoppedOutput(claudePermissionRequestOutput("deny", reason), reason);
2504
2515
  var ELICITATION_ANSWERABLE_MODE = "form";
2505
2516
  var ELICITATION_MIN_OPTIONS = 2;
2506
2517
  var ELICITATION_MAX_MULTI_QUESTIONS = 4;
@@ -2866,6 +2877,7 @@ export {
2866
2877
  shouldDeferToNativeMode,
2867
2878
  AGENT_QUESTION_STRATEGY,
2868
2879
  agentQuestionStrategy,
2880
+ questionHandedToTheTerminal,
2869
2881
  CODEX_RESCUE_TOOL_NAME,
2870
2882
  isBlockedActionRequest,
2871
2883
  BLOCKED_ACTION_GRANT_TTL_SECONDS,
@@ -2874,8 +2886,7 @@ export {
2874
2886
  isPermissionRequestOwnedByPreToolUse,
2875
2887
  CLAUDE_PRETOOLUSE_MATCHER,
2876
2888
  resolveGate,
2877
- editAsksAtTheAgentsPrompt,
2878
- claudePromptsBeforeAnEdit,
2889
+ editGoesToTheAgentsPrompt,
2879
2890
  claudePermissionRulesFromSettings,
2880
2891
  claudeConsultsItsAllowlist,
2881
2892
  agentRulesAllowEveryInput,
@@ -2888,7 +2899,6 @@ export {
2888
2899
  machineDecisionFor,
2889
2900
  claudePermissionDeniedOutput,
2890
2901
  codexStopRescueOutput,
2891
- stoppedOutput,
2892
2902
  claudePreToolUseOutput,
2893
2903
  PENDING_COMMAND_PREFIX,
2894
2904
  pendingCommandEvents,
@@ -2898,7 +2908,9 @@ export {
2898
2908
  UNVERIFIABLE_APPROVAL_REASON,
2899
2909
  DECISION_STOP_REASON,
2900
2910
  WITHDRAWN_APPROVAL_REASON,
2911
+ PLAN_DECLINED_REASON,
2901
2912
  claudeStoppedPreToolUseOutput,
2913
+ claudeStoppedPermissionRequestOutput,
2902
2914
  ELICITATION_ANSWERABLE_MODE,
2903
2915
  readElicitationFields,
2904
2916
  planElicitationAsk,
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  keyCheckFromResponse
3
- } from "./chunk-LWOO567I.js";
3
+ } from "./chunk-QRXPWW3M.js";
4
4
  import {
5
5
  installNetworkDefaults
6
- } from "./chunk-TCQ43LSG.js";
6
+ } from "./chunk-5N5L6DNN.js";
7
7
  import {
8
8
  getBaseUrl
9
- } from "./chunk-5QUPKDI5.js";
9
+ } from "./chunk-IRHABAQT.js";
10
10
 
11
11
  // src/retry.ts
12
12
  var isRetryable = (err) => {
@@ -1,36 +1,31 @@
1
- import {
2
- agentHookOwner,
3
- macAppBridgeAvailable,
4
- openCodePluginOwner
5
- } from "./chunk-3Z3A37WD.js";
6
1
  import {
7
2
  ensureCodexTrustsPusharyHooks
8
- } from "./chunk-MGRFDGWU.js";
3
+ } from "./chunk-NGKUXZID.js";
4
+ import {
5
+ detectClaudeVersion
6
+ } from "./chunk-RIVNNBEK.js";
9
7
  import {
10
8
  OPENCODE_HOOK_BINARY,
9
+ agentHookOwner,
11
10
  installOpenCodePlugin,
11
+ macAppBridgeAvailable,
12
12
  openCodeHookArgv,
13
13
  openCodePluginDir,
14
14
  openCodeWired
15
- } from "./chunk-MFF3ONG5.js";
15
+ } from "./chunk-BZLHTMT6.js";
16
16
  import {
17
17
  addClaudeMcpServer,
18
18
  addPusharyHooks,
19
19
  addPusharyToolPermissions
20
- } from "./chunk-KHNFLYJO.js";
21
- import {
22
- detectClaudeVersion
23
- } from "./chunk-RIVNNBEK.js";
24
- import {
25
- planHooks
26
- } from "./chunk-YIG2R3BJ.js";
20
+ } from "./chunk-UF6RBP5V.js";
27
21
  import {
28
22
  claudeUnprovenHolds,
29
23
  claudeWired,
30
24
  codexUnprovenHolds,
31
25
  codexWired,
32
- geminiWired
33
- } from "./chunk-2QGYMY7A.js";
26
+ geminiWired,
27
+ planHooks
28
+ } from "./chunk-BYLKCZ2G.js";
34
29
  import {
35
30
  CLAUDE_HOOK_BINARY,
36
31
  CLAUDE_HOOK_EVENTS,
@@ -41,7 +36,7 @@ import {
41
36
  needsReregistration,
42
37
  registrationSignatures,
43
38
  supportedClaudeEvents
44
- } from "./chunk-3I6IVOZV.js";
39
+ } from "./chunk-M3STIAGU.js";
45
40
  import {
46
41
  formatVersion
47
42
  } from "./chunk-6ICPEJY5.js";
@@ -64,7 +59,7 @@ import {
64
59
  registrationHolderOf,
65
60
  resolveGlobalBinary,
66
61
  vscodePluginMcp
67
- } from "./chunk-ZBHUHJG6.js";
62
+ } from "./chunk-Z23ZBYDW.js";
68
63
  import {
69
64
  readJsonSafe,
70
65
  writeFileAtomic,
@@ -335,9 +330,10 @@ var SETUP_CHOICE_BY_REAPPLY_ID = {
335
330
  codex: "codex",
336
331
  gemini: "gemini_cli",
337
332
  cursor: "cursor",
338
- vscode: "vscode"
333
+ vscode: "vscode",
334
+ opencode: "opencode"
339
335
  };
340
- var reapplyHookOwner = (id, appAvailable) => id === "opencode" ? openCodePluginOwner(appAvailable) : agentHookOwner(SETUP_CHOICE_BY_REAPPLY_ID[id], appAvailable);
336
+ var reapplyHookOwner = (id, appAvailable) => agentHookOwner(SETUP_CHOICE_BY_REAPPLY_ID[id], appAvailable);
341
337
  var reapplyHolder = (id, appAvailable) => planHooks({ owner: reapplyHookOwner(id, appAvailable), takeOverHooks: false, nonInteractive: true }) === "keep" ? "app" : "cli";
342
338
  var KEPT_FOR_APP = { configured: true, reapplied: false, hooks: false, mcp: false };
343
339
  var FAILED_REAPPLY = { configured: false, reapplied: false, hooks: false, mcp: false, failed: true };
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  MCP_BRIDGE_BINARY
3
- } from "./chunk-HRULIYDU.js";
3
+ } from "./chunk-H5T27W7M.js";
4
4
  import {
5
5
  KEY_FILE_MODE
6
- } from "./chunk-N4QSPI3B.js";
6
+ } from "./chunk-REU2VQPH.js";
7
7
  import {
8
8
  NpmMissingError
9
- } from "./chunk-ZBHUHJG6.js";
9
+ } from "./chunk-Z23ZBYDW.js";
10
10
  import {
11
11
  readJsonSafe,
12
12
  writeFileAtomic,
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-T7E75EKA.js";
15
15
  import {
16
16
  NPX_LATEST_COMMAND
17
- } from "./chunk-7DVNSQWF.js";
17
+ } from "./chunk-5DCDQ5VW.js";
18
18
 
19
19
  // src/instruction-file.ts
20
20
  import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
@@ -1,21 +1,21 @@
1
- import {
2
- activeHookSource,
3
- activeIdentity
4
- } from "./chunk-KHNFLYJO.js";
5
1
  import {
6
2
  defersToNativeMode,
7
3
  reportMachineDenial
8
- } from "./chunk-IHO3YQAN.js";
4
+ } from "./chunk-B5NMSP3V.js";
9
5
  import {
10
6
  isGatingMoment,
11
7
  recordKeylessMoment
12
- } from "./chunk-ZSTSEBG7.js";
8
+ } from "./chunk-IIVZZMSO.js";
13
9
  import {
14
10
  announceSubscriptionRequired,
15
11
  denyReasonFrom,
16
12
  isDeferAnswer,
17
13
  oncePerSession
18
14
  } from "./chunk-5OP5MQI7.js";
15
+ import {
16
+ activeHookSource,
17
+ activeIdentity
18
+ } from "./chunk-UF6RBP5V.js";
19
19
  import {
20
20
  UNNAMED_ACTION,
21
21
  approvalAwaitingRetry,
@@ -39,7 +39,7 @@ import {
39
39
  reportEvent,
40
40
  scopePathFor,
41
41
  settleQuestionsForToolUse
42
- } from "./chunk-KRCR2CRQ.js";
42
+ } from "./chunk-KQFTBQ66.js";
43
43
  import {
44
44
  DEFAULT_SESSION
45
45
  } from "./chunk-N6IOSZOE.js";
@@ -53,25 +53,26 @@ import {
53
53
  requestGate,
54
54
  sendNotification,
55
55
  waitForQuestion
56
- } from "./chunk-2VZAALEJ.js";
56
+ } from "./chunk-WRPYCIV2.js";
57
57
  import {
58
58
  SubscriptionRequiredError
59
- } from "./chunk-MKTJEXZ3.js";
59
+ } from "./chunk-6AYSKVLL.js";
60
60
  import {
61
61
  getMachineId
62
- } from "./chunk-DUZVXBBU.js";
62
+ } from "./chunk-KOWFRUIT.js";
63
63
  import {
64
64
  getApiKey,
65
65
  getBaseUrl
66
- } from "./chunk-5QUPKDI5.js";
66
+ } from "./chunk-IRHABAQT.js";
67
67
  import {
68
68
  NPX_LATEST_COMMAND
69
- } from "./chunk-7DVNSQWF.js";
69
+ } from "./chunk-5DCDQ5VW.js";
70
70
  import {
71
71
  AGENT_QUESTION_STRATEGY,
72
72
  DECISION_STOP_REASON,
73
73
  GATE_BLOCK_REASON_MAX_LENGTH,
74
74
  GATE_WIRE,
75
+ PLAN_DECLINED_REASON,
75
76
  UNVERIFIABLE_APPROVAL_REASON,
76
77
  WITHDRAWN_APPROVAL_REASON,
77
78
  agentQuestionStrategy,
@@ -83,9 +84,9 @@ import {
83
84
  claudePermissionRequestOutput,
84
85
  claudePermissionRulesFromSettings,
85
86
  claudePreToolUseOutput,
86
- claudePromptsBeforeAnEdit,
87
+ claudeStoppedPermissionRequestOutput,
87
88
  claudeStoppedPreToolUseOutput,
88
- editAsksAtTheAgentsPrompt,
89
+ editGoesToTheAgentsPrompt,
89
90
  effectiveWaitSeconds,
90
91
  hookHoldWindowMs,
91
92
  hookWaitClamped,
@@ -96,9 +97,9 @@ import {
96
97
  isPusharyOwnTool,
97
98
  parseAgentQuestionAnswers,
98
99
  parseAgentQuestions,
99
- resolveGate,
100
- stoppedOutput
101
- } from "./chunk-I5IJRMNV.js";
100
+ questionHandedToTheTerminal,
101
+ resolveGate
102
+ } from "./chunk-5RGA636G.js";
102
103
 
103
104
  // src/claude-permission-rules.ts
104
105
  import { readFileSync, statSync } from "fs";
@@ -450,7 +451,7 @@ var askQuestionByQuestion = async (apiKey, input, parsed, projectName, deadline)
450
451
  return answers;
451
452
  };
452
453
  var handleAskUserQuestion = async (apiKey, input, modeState) => {
453
- if (modeState.askHandoff) return void 0;
454
+ if (questionHandedToTheTerminal(input.tool_name, modeState)) return void 0;
454
455
  const parsed = parseQuestions(input.tool_input ?? {});
455
456
  if (!parsed) return void 0;
456
457
  const projectName = basename(input.cwd ?? process.cwd());
@@ -496,7 +497,7 @@ var handleExitPlanMode = async (apiKey, input) => {
496
497
  return void 0;
497
498
  }
498
499
  if (value === PLAN_APPROVE) return allow();
499
- return deny("Plan declined from the phone. Ask what to change before coding.");
500
+ return deny(PLAN_DECLINED_REASON);
500
501
  };
501
502
  var handleKeyless = (input) => {
502
503
  try {
@@ -617,7 +618,7 @@ var handlePreToolUse = async (input, canonical) => {
617
618
  return void 0;
618
619
  }
619
620
  if (claudeAllowlistOwnsCall(gateInput, verdict, input.permission_mode, claudePermissionRulesFor(input))) return void 0;
620
- if (claudePromptsBeforeAnEdit(input.permission_mode) && editAsksAtTheAgentsPrompt(gateInput, verdict)) return handleTerminalOnly();
621
+ if (editGoesToTheAgentsPrompt({ source: ACTIVE_SOURCE, event: "PreToolUse", permissionMode: input.permission_mode }, gateInput, verdict)) return handleTerminalOnly();
621
622
  switch (verdict.kind) {
622
623
  case "allow":
623
624
  return allow();
@@ -637,7 +638,7 @@ var handlePreToolUse = async (input, canonical) => {
637
638
  };
638
639
  var permReqAllow = (updatedInput) => claudePermissionRequestOutput("allow", void 0, updatedInput);
639
640
  var permReqDeny = (message) => claudePermissionRequestOutput("deny", message);
640
- var permReqHalted = (reason) => stoppedOutput(permReqDeny(reason), reason);
641
+ var permReqHalted = (reason) => claudeStoppedPermissionRequestOutput(reason);
641
642
  var toPermissionRequestOutput = (hookOutput) => {
642
643
  if (!hookOutput) return void 0;
643
644
  const d = hookOutput.hookSpecificOutput;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  redactSecretsFromContent
3
- } from "./chunk-I5IJRMNV.js";
3
+ } from "./chunk-5RGA636G.js";
4
4
 
5
5
  // src/crypto.ts
6
6
  import nacl from "tweetnacl";
@@ -2,7 +2,7 @@ import {
2
2
  autoUpdateLock,
3
3
  installPackageGlobally,
4
4
  npmErrorMessage
5
- } from "./chunk-ZBHUHJG6.js";
5
+ } from "./chunk-Z23ZBYDW.js";
6
6
  import {
7
7
  writeJsonAtomic
8
8
  } from "./chunk-T7E75EKA.js";
@@ -5,7 +5,7 @@ import {
5
5
  permissionDeniedAction,
6
6
  releaseThrottle,
7
7
  reportEvent
8
- } from "./chunk-KRCR2CRQ.js";
8
+ } from "./chunk-KQFTBQ66.js";
9
9
  import {
10
10
  DEFAULT_SESSION
11
11
  } from "./chunk-N6IOSZOE.js";
@@ -13,7 +13,7 @@ import {
13
13
  machineDecisionFor,
14
14
  shouldDeferToNativeMode,
15
15
  wireVerdictFor
16
- } from "./chunk-I5IJRMNV.js";
16
+ } from "./chunk-5RGA636G.js";
17
17
 
18
18
  // src/machine-decision-audit.ts
19
19
  import { basename } from "path";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  configFilePath
3
- } from "./chunk-5QUPKDI5.js";
3
+ } from "./chunk-IRHABAQT.js";
4
4
  import {
5
5
  normalizeInstallSource
6
- } from "./chunk-I5IJRMNV.js";
6
+ } from "./chunk-5RGA636G.js";
7
7
 
8
8
  // src/install-source.ts
9
9
  import { readFileSync } from "fs";
@@ -2,17 +2,23 @@ import {
2
2
  CLAUDE_HOOK_EVENTS,
3
3
  GEMINI_HOOK_EVENTS,
4
4
  hasGeminiHooks
5
- } from "./chunk-3I6IVOZV.js";
5
+ } from "./chunk-M3STIAGU.js";
6
+ import {
7
+ AGENT_CHOICES
8
+ } from "./chunk-ZGADIZDS.js";
9
+ import {
10
+ BELL_HOOK_BINARY
11
+ } from "./chunk-MLGIVVSG.js";
6
12
  import {
7
13
  CODEX_HOOK_EVENTS,
8
14
  hasCodexHooks,
9
15
  holdBudgetOf
10
- } from "./chunk-ZBHUHJG6.js";
16
+ } from "./chunk-Z23ZBYDW.js";
11
17
  import {
12
18
  CURSOR_GATE_EVENTS,
13
19
  HOOK_LOCATOR_BINARY,
14
20
  hookCommandHoldBudget
15
- } from "./chunk-I5IJRMNV.js";
21
+ } from "./chunk-5RGA636G.js";
16
22
 
17
23
  // src/diagnostics/bridge.ts
18
24
  import { execFileSync } from "child_process";
@@ -206,6 +212,126 @@ var describeHoldTimeout = (holder) => {
206
212
  var describeOtherHolder = (holder) => `another hook also registered on ${holder.event}: ${holderExecutable(holder.command)} (${describeHoldTimeout(holder)})`;
207
213
  var describeHoldSentence = (agentLabel) => `${agentLabel} waits for every hook on an event, so the terminal cannot move until that one returns, however fast your phone answered.`;
208
214
 
215
+ // src/setup/hook-ownership.ts
216
+ var commandsIn = (value) => {
217
+ if (Array.isArray(value)) return value.flatMap(commandsIn);
218
+ if (!value || typeof value !== "object") return [];
219
+ return Object.entries(value).flatMap(([key, item]) => key === "command" && typeof item === "string" ? [item] : commandsIn(item));
220
+ };
221
+ var isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
222
+ var hasPaidPusharyCommand = (value) => commandsIn(value).some((command) => {
223
+ const executable = pusharyHookExecutable(command);
224
+ const name = executable?.split(/[/\\]/).pop()?.replace(/\.(cmd|exe|mjs)$/i, "");
225
+ return executable !== null && !isBridgeLocator(executable) && name !== BELL_HOOK_BINARY;
226
+ });
227
+ var hasAppCommand = (value) => commandsIn(value).some((command) => {
228
+ const executable = pusharyHookExecutable(command);
229
+ return executable !== null && isBridgeLocator(executable);
230
+ });
231
+ var mcpBearerKey = (document, containerKey, headersKey) => {
232
+ const servers = isRecord(document?.[containerKey]) ? document[containerKey] : null;
233
+ const pushary = isRecord(servers?.pushary) ? servers.pushary : null;
234
+ const headers = isRecord(pushary?.[headersKey]) ? pushary[headersKey] : null;
235
+ const authorization = headers?.Authorization;
236
+ const match = typeof authorization === "string" ? authorization.trim().match(/^Bearer\s+(\S+)$/) : null;
237
+ return match?.[1] ?? null;
238
+ };
239
+ var captureMcpServer = (document, containerKey) => {
240
+ const container = document[containerKey];
241
+ const servers = isRecord(container) ? container : null;
242
+ if (!servers && Object.hasOwn(document, containerKey)) {
243
+ return { present: false, containerValue: structuredClone(container) };
244
+ }
245
+ return servers && Object.hasOwn(servers, "pushary") ? { present: true, value: structuredClone(servers.pushary) } : { present: false };
246
+ };
247
+ var restoreMcpServer = (document, containerKey, snapshot) => {
248
+ const before = JSON.stringify(document);
249
+ const existing = isRecord(document[containerKey]) ? document[containerKey] : null;
250
+ if (snapshot.present) {
251
+ const servers = existing ?? {};
252
+ servers.pushary = structuredClone(snapshot.value);
253
+ document[containerKey] = servers;
254
+ } else if (Object.hasOwn(snapshot, "containerValue")) {
255
+ document[containerKey] = structuredClone(snapshot.containerValue);
256
+ } else if (existing && Object.hasOwn(existing, "pushary")) {
257
+ delete existing.pushary;
258
+ if (Object.keys(existing).length === 0) delete document[containerKey];
259
+ }
260
+ return JSON.stringify(document) !== before;
261
+ };
262
+ var captureHookTakeover = (agent, document) => {
263
+ const hooks = isRecord(document?.hooks) ? document.hooks : null;
264
+ if (!hooks) return null;
265
+ const captured = {};
266
+ for (const [event, entries] of Object.entries(hooks)) {
267
+ if (!Array.isArray(entries)) continue;
268
+ const appEntries = entries.flatMap((value, index) => isRecord(value) && hasAppCommand(value) ? [{ index, value: structuredClone(value) }] : []);
269
+ if (appEntries.length > 0) captured[event] = appEntries;
270
+ }
271
+ return Object.keys(captured).length > 0 ? { version: 1, agent, hooks: captured } : null;
272
+ };
273
+ var isHookTakeoverReceipt = (value) => {
274
+ if (!isRecord(value) || value.version !== 1 || typeof value.agent !== "string" || !AGENT_CHOICES.includes(value.agent) || !isRecord(value.hooks)) return false;
275
+ const expectsMcp = ["claude_code", "codex", "gemini_cli", "vscode"].includes(value.agent);
276
+ if (value.mcpServer !== void 0 !== expectsMcp) return false;
277
+ if (value.codexTrust !== void 0 !== (value.agent === "codex")) return false;
278
+ if (value.codexTrust !== void 0 && !isRecord(value.codexTrust)) return false;
279
+ if (value.mcpServer !== void 0 && (!isRecord(value.mcpServer) || typeof value.mcpServer.present !== "boolean" || value.mcpServer.present && !Object.hasOwn(value.mcpServer, "value"))) return false;
280
+ return Object.values(value.hooks).every((entries) => Array.isArray(entries) && entries.length > 0 && entries.every((item) => isRecord(item) && Number.isInteger(item.index) && item.index >= 0 && isRecord(item.value)));
281
+ };
282
+ var restoreHookTakeover = (document, receipt) => {
283
+ const before = JSON.stringify(document);
284
+ const appOwnsNow = hookOwnerOf(document) === "app";
285
+ const hooks = isRecord(document.hooks) ? document.hooks : {};
286
+ for (const [event, value] of Object.entries(hooks)) {
287
+ if (!Array.isArray(value)) continue;
288
+ const kept = value.filter((entry) => !hasPaidPusharyCommand(entry));
289
+ if (kept.length === 0) delete hooks[event];
290
+ else hooks[event] = kept;
291
+ }
292
+ if (!appOwnsNow) {
293
+ for (const [event, snapshots] of Object.entries(receipt.hooks)) {
294
+ const entries = Array.isArray(hooks[event]) ? [...hooks[event]] : [];
295
+ for (const snapshot of snapshots) {
296
+ entries.splice(Math.min(snapshot.index, entries.length), 0, structuredClone(snapshot.value));
297
+ }
298
+ hooks[event] = entries;
299
+ }
300
+ }
301
+ document.hooks = hooks;
302
+ return JSON.stringify(document) !== before;
303
+ };
304
+ var hookOwnerOf = (document, appAvailable = true, hooksKeyPath = ["hooks"]) => {
305
+ const hooks = hooksKeyPath.reduce(
306
+ (node, key) => node && typeof node === "object" ? node[key] : void 0,
307
+ document
308
+ );
309
+ return hookOwnerOfCommands(commandsIn(hooks), appAvailable);
310
+ };
311
+ var hookOwnerOfCommands = (commands, appAvailable = true) => {
312
+ const executables = commands.map(pusharyHookExecutable).filter((executable) => executable !== null);
313
+ if (appAvailable && executables.some(isBridgeLocator)) return "app";
314
+ if (executables.some((executable) => !isBridgeLocator(executable))) return "cli";
315
+ return "none";
316
+ };
317
+ var planHooks = (context) => {
318
+ if (context.owner !== "app") return "install";
319
+ if (context.takeOverHooks) return "install";
320
+ return "keep";
321
+ };
322
+ var describeAppOwnership = (agentName) => `The Pushary Mac app owns ${agentName}'s hooks.`;
323
+ var KEEP_HINT = "Kept with the app's account. Pass --take-over-hooks to have the CLI own them instead.";
324
+ var OWNER_LABELS = {
325
+ app: "the Pushary Mac app",
326
+ cli: "the CLI"
327
+ };
328
+ var describeHookOwnership = (entries, names) => {
329
+ const owned = entries.filter((entry) => entry.owner !== "none");
330
+ if (owned.length === 0) return null;
331
+ const parts = owned.map((entry) => `${names[entry.agent]} by ${OWNER_LABELS[entry.owner]}${entry.kept ? " (kept)" : ""}`);
332
+ return `Hooks: ${parts.join(", ")}.`;
333
+ };
334
+
209
335
  export {
210
336
  resolveBridgeStub,
211
337
  describeBridgeResolution,
@@ -225,5 +351,17 @@ export {
225
351
  codexUnprovenHolds,
226
352
  holdsLong,
227
353
  describeOtherHolder,
228
- describeHoldSentence
354
+ describeHoldSentence,
355
+ mcpBearerKey,
356
+ captureMcpServer,
357
+ restoreMcpServer,
358
+ captureHookTakeover,
359
+ isHookTakeoverReceipt,
360
+ restoreHookTakeover,
361
+ hookOwnerOf,
362
+ hookOwnerOfCommands,
363
+ planHooks,
364
+ describeAppOwnership,
365
+ KEEP_HINT,
366
+ describeHookOwnership
229
367
  };