@pushary/agent-hooks 0.89.3 → 0.89.5

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 (58) hide show
  1. package/README.md +40 -0
  2. package/dist/bin/pushary-bell-hook.js +3 -3
  3. package/dist/bin/pushary-bell.js +9 -10
  4. package/dist/bin/pushary-claude.js +62 -26
  5. package/dist/bin/pushary-clean.js +25 -7
  6. package/dist/bin/pushary-codex-bridge.js +4 -5
  7. package/dist/bin/pushary-codex-hook.js +8 -7
  8. package/dist/bin/pushary-codex.js +6 -4
  9. package/dist/bin/pushary-connect.js +4 -4
  10. package/dist/bin/pushary-daemon.js +155 -40
  11. package/dist/bin/pushary-disconnect.js +3 -4
  12. package/dist/bin/pushary-doctor.js +77 -39
  13. package/dist/bin/pushary-elicitation-hook.js +4 -2
  14. package/dist/bin/pushary-gemini-bridge.js +3 -4
  15. package/dist/bin/pushary-gemini-hook.js +6 -4
  16. package/dist/bin/pushary-hook.js +9 -7
  17. package/dist/bin/pushary-login.js +4 -4
  18. package/dist/bin/pushary-logout.js +5 -6
  19. package/dist/bin/pushary-mode.js +2 -2
  20. package/dist/bin/pushary-notification-hook.js +6 -4
  21. package/dist/bin/pushary-opencode-hook.js +14 -6
  22. package/dist/bin/pushary-permission-denied-hook.js +7 -5
  23. package/dist/bin/pushary-permission-hook.js +7 -5
  24. package/dist/bin/pushary-post-hook.js +6 -4
  25. package/dist/bin/pushary-prompt-hook.js +6 -4
  26. package/dist/bin/pushary-session-end-hook.js +6 -4
  27. package/dist/bin/pushary-session-start-hook.js +6 -4
  28. package/dist/bin/pushary-setup.js +125 -39
  29. package/dist/bin/pushary-stats.js +2 -2
  30. package/dist/bin/pushary-status.js +7 -6
  31. package/dist/bin/pushary-stop-hook.js +6 -4
  32. package/dist/bin/pushary-stopfailure-hook.js +6 -4
  33. package/dist/bin/pushary-suggestions.js +2 -2
  34. package/dist/bin/pushary-upgrade.js +110 -46
  35. package/dist/bin/pushary-wait.js +2 -2
  36. package/dist/bin/pushary.js +1 -1
  37. package/dist/chunk-2HYPZLYY.js +45 -0
  38. package/dist/{chunk-GOEXZ5QJ.js → chunk-3XTFX4CL.js} +10 -2
  39. package/dist/{chunk-ZYPS2XMT.js → chunk-4ZHQNBDP.js} +1 -1
  40. package/dist/{chunk-HUJAAWNL.js → chunk-GKAKAOKC.js} +10 -3
  41. package/dist/{chunk-LGXTBUT4.js → chunk-KOPUTJQC.js} +1 -0
  42. package/dist/{chunk-LALHWDWL.js → chunk-L3YUHEB6.js} +16 -4
  43. package/dist/{chunk-SQOFGPNX.js → chunk-LURY4WNF.js} +1 -1
  44. package/dist/{chunk-JT6TIBYH.js → chunk-MZBT2LXW.js} +4 -4
  45. package/dist/{chunk-3UBYTSCY.js → chunk-NFI2K2ZQ.js} +15 -7
  46. package/dist/chunk-NKHEHEUM.js +56 -0
  47. package/dist/{chunk-3O2XPYLF.js → chunk-OBI4YMCT.js} +1 -1
  48. package/dist/{chunk-LUCFN47K.js → chunk-QH4AA7QV.js} +1 -1
  49. package/dist/chunk-TRQ46MXR.js +648 -0
  50. package/dist/{chunk-VKVHY5HD.js → chunk-V37ZXMH3.js} +11 -3
  51. package/dist/{chunk-MHBC2XUP.js → chunk-VP7SDXYG.js} +1 -1
  52. package/dist/{chunk-B7JE4XHD.js → chunk-WQGMUIDW.js} +1 -1
  53. package/dist/src/index.js +7 -5
  54. package/package.json +1 -1
  55. package/dist/chunk-GIRT7677.js +0 -11
  56. package/dist/chunk-K42SZKYF.js +0 -343
  57. package/dist/chunk-NRGRUOAR.js +0 -25
  58. package/dist/chunk-RN3NOEJF.js +0 -9
@@ -2,44 +2,45 @@
2
2
  import {
3
3
  HEARTBEAT_INTERVAL_MS,
4
4
  sendHeartbeat
5
- } from "../chunk-MHBC2XUP.js";
5
+ } from "../chunk-VP7SDXYG.js";
6
6
  import {
7
7
  DAEMON_LEASE_RENEW_INTERVAL_MS,
8
8
  acquireDaemonLease,
9
+ ensureDaemonRunning,
10
+ manageDaemonService,
11
+ parseDaemonAction,
9
12
  readDaemonStatus,
10
- requestDaemonHandoff
11
- } from "../chunk-K42SZKYF.js";
13
+ replaceDaemonService,
14
+ requestDaemonHandoff,
15
+ stopDaemonRunning
16
+ } from "../chunk-TRQ46MXR.js";
12
17
  import {
13
- CODEX_BRIDGE_CAPABILITY,
14
- CODEX_RESUME_CAPABILITY,
15
- geminiLiveCapabilities
16
- } from "../chunk-NRGRUOAR.js";
18
+ detectProviderLiveCapabilities,
19
+ hasSpawnProvider
20
+ } from "../chunk-NKHEHEUM.js";
17
21
  import {
18
22
  findLiveProcessBySpawnId,
19
23
  ownsLiveProcess
20
- } from "../chunk-ZYPS2XMT.js";
24
+ } from "../chunk-4ZHQNBDP.js";
21
25
  import {
22
26
  spawnClaude
23
27
  } from "../chunk-XHKBHWLX.js";
24
28
  import {
25
- resolveBinary,
26
- resolveGlobalPackageVersion,
27
- resolvePackageVersionFromBinary
29
+ resolveBinary
28
30
  } from "../chunk-PZA7G4CN.js";
29
- import "../chunk-VKVHY5HD.js";
30
- import "../chunk-GIRT7677.js";
31
31
  import {
32
32
  getMachineId
33
- } from "../chunk-RN3NOEJF.js";
33
+ } from "../chunk-2HYPZLYY.js";
34
+ import "../chunk-V37ZXMH3.js";
34
35
  import {
35
36
  exitOnHelpFlag
36
- } from "../chunk-SQOFGPNX.js";
37
- import "../chunk-GOEXZ5QJ.js";
37
+ } from "../chunk-LURY4WNF.js";
38
+ import "../chunk-3XTFX4CL.js";
38
39
  import "../chunk-DINDL2CF.js";
39
- import "../chunk-6MTNS63X.js";
40
40
  import {
41
41
  EXIT
42
42
  } from "../chunk-KZERVKTD.js";
43
+ import "../chunk-6MTNS63X.js";
43
44
  import {
44
45
  getApiKey,
45
46
  getBaseUrl
@@ -48,7 +49,8 @@ import "../chunk-L4C2JXJS.js";
48
49
 
49
50
  // src/spawn-daemon.ts
50
51
  import { execFileSync, spawn } from "child_process";
51
- import { existsSync } from "fs";
52
+ import { existsSync, statSync } from "fs";
53
+ import { homedir } from "os";
52
54
  import { basename, dirname, join } from "path";
53
55
 
54
56
  // src/stop-requests.ts
@@ -167,10 +169,40 @@ var isAuthFailure = (err) => {
167
169
  if (candidate.name !== "DrainError") return false;
168
170
  return candidate.status === 401 || candidate.status === 403;
169
171
  };
172
+ var normalizeLaunchAgent = (requestedAgent) => {
173
+ if (requestedAgent === void 0 || requestedAgent === "claude") return "claude";
174
+ if (requestedAgent === "codex" || requestedAgent === "gemini") return requestedAgent;
175
+ return null;
176
+ };
177
+ var providerLaunchError = (requestedAgent, binaries) => {
178
+ const agent = normalizeLaunchAgent(requestedAgent);
179
+ if (!agent) return `Unsupported agent provider: ${requestedAgent}`;
180
+ if (binaries[agent]) return null;
181
+ return agent === "claude" ? "Claude Code is not installed on this machine" : `${agent === "codex" ? "Codex" : "Gemini"} CLI is not installed on this machine`;
182
+ };
183
+ var resolveSpawnDirectory = (requested, options = {}) => {
184
+ const fallbackDir = options.fallbackDir ?? process.cwd();
185
+ const value = requested?.trim();
186
+ if (!value) return { ok: true, cwd: fallbackDir };
187
+ const homeDir = options.homeDir ?? homedir();
188
+ const cwd = value === "~" ? homeDir : value.startsWith("~/") || value.startsWith("~\\") ? join(homeDir, value.slice(2)) : value;
189
+ if (!(options.exists ?? existsSync)(cwd)) {
190
+ return { ok: false, message: `Directory does not exist: ${value}` };
191
+ }
192
+ try {
193
+ if (!(options.isDirectory ?? ((path) => statSync(path).isDirectory()))(cwd)) {
194
+ return { ok: false, message: `Not a directory: ${value}` };
195
+ }
196
+ } catch {
197
+ return { ok: false, message: `Not a directory: ${value}` };
198
+ }
199
+ return { ok: true, cwd };
200
+ };
170
201
  var isFlagShapedPrompt = (prompt) => prompt.trimStart().startsWith("-");
171
202
  var buildSpawnLaunch = (req, opts) => {
172
203
  if (isFlagShapedPrompt(req.prompt)) return null;
173
- const agent = req.agent === "codex" || req.agent === "gemini" ? req.agent : "claude";
204
+ const agent = normalizeLaunchAgent(req.agent);
205
+ if (!agent) return null;
174
206
  const model = typeof req.model === "string" && req.model.length > 0 ? ["--model", req.model] : [];
175
207
  if (agent === "claude") {
176
208
  const claudeArgs = ["claude", "--remote", ...model, "-p", req.prompt];
@@ -209,11 +241,7 @@ var runSpawnDaemon = async () => {
209
241
  const machineId = getMachineId();
210
242
  const baseUrl = getBaseUrl();
211
243
  const pusharyBin = resolveBinary("pushary") ?? "pushary";
212
- const codexBin = resolveBinary("codex");
213
- const geminiBin = resolveBinary("gemini");
214
- const geminiCapabilities = geminiBin ? geminiLiveCapabilities(
215
- resolvePackageVersionFromBinary(geminiBin, "@google/gemini-cli") ?? resolveGlobalPackageVersion("@google/gemini-cli")
216
- ) : [];
244
+ const providerCapabilities = detectProviderLiveCapabilities();
217
245
  const siblingEntry = process.argv[1] ? join(dirname(process.argv[1]), "pushary.js") : "";
218
246
  const codexBridgeEntry = process.argv[1] ? join(dirname(process.argv[1]), "pushary-codex-bridge.js") : "pushary-codex-bridge";
219
247
  const geminiBridgeEntry = process.argv[1] ? join(dirname(process.argv[1]), "pushary-gemini-bridge.js") : "pushary-gemini-bridge";
@@ -261,8 +289,19 @@ var runSpawnDaemon = async () => {
261
289
  if (launchedProcesses.size >= MAX_TRACKED_PROCESSES) {
262
290
  return Promise.reject(new Error("This daemon is already tracking 100 active sessions"));
263
291
  }
292
+ const directory = resolveSpawnDirectory(req.cwd);
293
+ if (!directory.ok) return Promise.reject(new Error(directory.message));
294
+ const agent = normalizeLaunchAgent(req.agent);
295
+ if (!agent) return Promise.reject(new Error(`Unsupported agent provider: ${req.agent}`));
296
+ const providerBin = resolveBinary(agent);
297
+ const unavailable = providerLaunchError(req.agent, {
298
+ claude: agent === "claude" ? providerBin ?? null : null,
299
+ codex: agent === "codex" ? providerBin ?? null : null,
300
+ gemini: agent === "gemini" ? providerBin ?? null : null
301
+ });
302
+ if (unavailable) return Promise.reject(new Error(unavailable));
264
303
  spawnTimestamps.push(Date.now());
265
- const cwd = req.cwd && existsSync(req.cwd) ? req.cwd : process.cwd();
304
+ const cwd = directory.cwd;
266
305
  const env = {
267
306
  ...process.env,
268
307
  PUSHARY_SPAWN_ID: req.id,
@@ -274,10 +313,10 @@ var runSpawnDaemon = async () => {
274
313
  PUSHARY_BRIDGE_RESUME_SESSION_ID: req.resumeSessionId || void 0
275
314
  } : {},
276
315
  ...req.agent === "codex" ? {
277
- PUSHARY_CODEX_COMMAND: codexBin ?? "codex"
316
+ PUSHARY_CODEX_COMMAND: providerBin ?? "codex"
278
317
  } : {},
279
318
  ...req.agent === "gemini" ? {
280
- PUSHARY_GEMINI_COMMAND: geminiBin ?? "gemini"
319
+ PUSHARY_GEMINI_COMMAND: providerBin ?? "gemini"
281
320
  } : {}
282
321
  };
283
322
  const plan = buildSpawnLaunch(req, {
@@ -501,11 +540,10 @@ var runSpawnDaemon = async () => {
501
540
  const result = await sendHeartbeat(apiKey, {
502
541
  repoKey: basename(process.cwd()),
503
542
  capabilities: [
504
- "spawn",
543
+ ...hasSpawnProvider(providerCapabilities) ? ["spawn"] : [],
505
544
  STOP_CAPABILITY,
506
545
  STOP_ACK_CAPABILITY,
507
- ...codexBin ? [CODEX_BRIDGE_CAPABILITY, CODEX_RESUME_CAPABILITY] : [],
508
- ...geminiCapabilities
546
+ ...providerCapabilities
509
547
  ]
510
548
  });
511
549
  if (result.kind === "ok") daemonLease.recordSuccessfulHeartbeat();
@@ -521,10 +559,9 @@ var runSpawnDaemon = async () => {
521
559
  versionWatch = setInterval(() => {
522
560
  if (daemonLease.shouldYield()) finish();
523
561
  }, VERSION_CHECK_INTERVAL_MS);
524
- stderr(
525
- `[pushary] daemon online \u2014 this machine (${machineId}) can now be sent a new session from your phone. Ctrl-C to stop.
526
- `
527
- );
562
+ stderr(hasSpawnProvider(providerCapabilities) ? `[pushary] daemon online \u2014 this machine (${machineId}) can now be sent a new session from your phone. Ctrl-C to stop.
563
+ ` : `[pushary] daemon online \u2014 no supported Claude, Codex, or Gemini CLI was found, so phone-start is unavailable. Ctrl-C to stop.
564
+ `);
528
565
  timer = setTimeout(tick, FAST_POLL_MS);
529
566
  const signals = daemonSignals();
530
567
  await new Promise((resolve) => {
@@ -541,10 +578,88 @@ var runSpawnDaemon = async () => {
541
578
 
542
579
  // bin/pushary-daemon.ts
543
580
  exitOnHelpFlag("daemon");
544
- runSpawnDaemon().then((code) => process.exit(code)).catch((err) => {
545
- process.stderr.write(
546
- `[pushary] daemon error: ${err instanceof Error ? err.message : String(err)}
547
- `
548
- );
549
- process.exit(1);
581
+ var serviceFailure = (result) => result.kind === "ok" ? null : result.detail;
582
+ var applyService = (action) => serviceFailure(manageDaemonService(action));
583
+ var waitForManagedDaemon = async () => {
584
+ const result = await ensureDaemonRunning({ spawnDaemon: () => {
585
+ } });
586
+ return "detail" in result ? result.detail : null;
587
+ };
588
+ var main = async () => {
589
+ const action = parseDaemonAction(process.argv.slice(2));
590
+ if (!action) {
591
+ process.stderr.write("Unknown daemon action. Use install, start, stop, restart, status, uninstall, or foreground.\n");
592
+ return EXIT.USAGE;
593
+ }
594
+ if (action === "foreground") return await runSpawnDaemon();
595
+ if (action === "status") {
596
+ const status = readDaemonStatus();
597
+ process.stdout.write(`Pushary daemon: ${status.kind}${status.pid ? ` (pid ${status.pid})` : ""}
598
+ `);
599
+ return status.kind === "running" ? EXIT.OK : EXIT.UNREACHABLE;
600
+ }
601
+ if (action === "install") {
602
+ const installed = await replaceDaemonService();
603
+ if (installed.kind !== "ok") {
604
+ process.stderr.write(`[pushary] daemon service install failed: ${installed.detail}
605
+ `);
606
+ return EXIT.FAILED;
607
+ }
608
+ const unhealthy = await waitForManagedDaemon();
609
+ if (unhealthy) {
610
+ process.stderr.write(`[pushary] daemon service installed but unavailable: ${unhealthy}
611
+ `);
612
+ return EXIT.UNREACHABLE;
613
+ }
614
+ process.stdout.write("[pushary] daemon service installed and online\n");
615
+ return EXIT.OK;
616
+ }
617
+ if (action === "start") {
618
+ const failed2 = applyService("start");
619
+ if (failed2) {
620
+ process.stderr.write(`[pushary] daemon service could not start: ${failed2}
621
+ `);
622
+ return EXIT.FAILED;
623
+ }
624
+ const unhealthy = await waitForManagedDaemon();
625
+ if (unhealthy) {
626
+ process.stderr.write(`[pushary] daemon service did not become healthy: ${unhealthy}
627
+ `);
628
+ return EXIT.UNREACHABLE;
629
+ }
630
+ process.stdout.write("[pushary] daemon service online\n");
631
+ return EXIT.OK;
632
+ }
633
+ const serviceAction = action === "uninstall" ? "uninstall" : "stop";
634
+ const failed = applyService(serviceAction);
635
+ const stopped = await stopDaemonRunning();
636
+ if (failed || stopped.kind === "unavailable") {
637
+ const detail = [failed, stopped.kind === "unavailable" ? stopped.detail : null].filter(Boolean).join("; ");
638
+ process.stderr.write(`[pushary] daemon could not stop: ${detail}
639
+ `);
640
+ return EXIT.FAILED;
641
+ }
642
+ if (action === "restart") {
643
+ const startFailed = applyService("start");
644
+ if (startFailed) {
645
+ process.stderr.write(`[pushary] daemon service could not restart: ${startFailed}
646
+ `);
647
+ return EXIT.FAILED;
648
+ }
649
+ const unhealthy = await waitForManagedDaemon();
650
+ if (unhealthy) {
651
+ process.stderr.write(`[pushary] daemon service did not become healthy: ${unhealthy}
652
+ `);
653
+ return EXIT.UNREACHABLE;
654
+ }
655
+ process.stdout.write("[pushary] daemon service restarted\n");
656
+ return EXIT.OK;
657
+ }
658
+ process.stdout.write(action === "uninstall" ? "[pushary] daemon service removed\n" : "[pushary] daemon stopped\n");
659
+ return EXIT.OK;
660
+ };
661
+ main().then((code) => process.exit(code)).catch((err) => {
662
+ process.stderr.write(`[pushary] daemon error: ${err instanceof Error ? err.message : String(err)}
663
+ `);
664
+ process.exit(EXIT.FAILED);
550
665
  });
@@ -29,12 +29,11 @@ import {
29
29
  geminiSettings,
30
30
  removeCodexHooks,
31
31
  removeCodexSettings
32
- } from "../chunk-VKVHY5HD.js";
33
- import "../chunk-GIRT7677.js";
32
+ } from "../chunk-V37ZXMH3.js";
34
33
  import {
35
34
  exitOnHelpFlag
36
- } from "../chunk-SQOFGPNX.js";
37
- import "../chunk-GOEXZ5QJ.js";
35
+ } from "../chunk-LURY4WNF.js";
36
+ import "../chunk-3XTFX4CL.js";
38
37
  import "../chunk-DINDL2CF.js";
39
38
  import "../chunk-KZERVKTD.js";
40
39
  import "../chunk-L4C2JXJS.js";
@@ -7,10 +7,7 @@ import {
7
7
  codexWired,
8
8
  geminiWired,
9
9
  pusharyHookExecutable
10
- } from "../chunk-3O2XPYLF.js";
11
- import {
12
- readDaemonStatus
13
- } from "../chunk-K42SZKYF.js";
10
+ } from "../chunk-OBI4YMCT.js";
14
11
  import {
15
12
  agentProbes,
16
13
  detectAgent,
@@ -19,7 +16,7 @@ import {
19
16
  isDetected,
20
17
  isPluginRegistered,
21
18
  vscodeSettingsTargets
22
- } from "../chunk-LUCFN47K.js";
19
+ } from "../chunk-QH4AA7QV.js";
23
20
  import {
24
21
  OPENCODE_PLUGIN_PLACEHOLDER,
25
22
  openCodePluginDir,
@@ -33,10 +30,27 @@ import {
33
30
  } from "../chunk-7TS2G4QG.js";
34
31
  import "../chunk-ATBKJNWS.js";
35
32
  import "../chunk-AIGDBRIJ.js";
33
+ import {
34
+ daemonServiceManagerAvailable,
35
+ hasDaemonServiceDefinition,
36
+ readDaemonStatus
37
+ } from "../chunk-TRQ46MXR.js";
38
+ import {
39
+ detectProviderLiveCapabilities,
40
+ hasSpawnProvider,
41
+ resolveControlPolicy
42
+ } from "../chunk-NKHEHEUM.js";
36
43
  import "../chunk-XHKBHWLX.js";
37
44
  import {
38
45
  execNpm
39
46
  } from "../chunk-PZA7G4CN.js";
47
+ import {
48
+ readLedgerSummary
49
+ } from "../chunk-VZKXBFUA.js";
50
+ import "../chunk-KOPUTJQC.js";
51
+ import {
52
+ getMachineId
53
+ } from "../chunk-2HYPZLYY.js";
40
54
  import {
41
55
  claudeJson,
42
56
  claudeSettings,
@@ -56,15 +70,7 @@ import {
56
70
  readCodexMcpAuth,
57
71
  untrustedCodexHookEvents,
58
72
  vscodePluginDir
59
- } from "../chunk-VKVHY5HD.js";
60
- import {
61
- readLedgerSummary
62
- } from "../chunk-VZKXBFUA.js";
63
- import "../chunk-GIRT7677.js";
64
- import "../chunk-LGXTBUT4.js";
65
- import {
66
- getMachineId
67
- } from "../chunk-RN3NOEJF.js";
73
+ } from "../chunk-V37ZXMH3.js";
68
74
  import {
69
75
  describeReach,
70
76
  describeRoundTrip,
@@ -82,20 +88,20 @@ import {
82
88
  } from "../chunk-5RUIFDTP.js";
83
89
  import {
84
90
  keyPrefix,
91
+ readControlMode,
85
92
  readKeySource
86
- } from "../chunk-LALHWDWL.js";
93
+ } from "../chunk-L3YUHEB6.js";
87
94
  import {
88
95
  parseFlags
89
96
  } from "../chunk-GMXKITVA.js";
90
97
  import {
91
98
  exitOnHelpFlag
92
- } from "../chunk-SQOFGPNX.js";
93
- import "../chunk-GOEXZ5QJ.js";
99
+ } from "../chunk-LURY4WNF.js";
100
+ import "../chunk-3XTFX4CL.js";
94
101
  import "../chunk-BC3VCZ3E.js";
95
102
  import {
96
103
  getPackageVersion
97
104
  } from "../chunk-DINDL2CF.js";
98
- import "../chunk-6MTNS63X.js";
99
105
  import {
100
106
  callMcpTool,
101
107
  sendMcpRequest
@@ -108,6 +114,7 @@ import {
108
114
  import {
109
115
  EXIT
110
116
  } from "../chunk-KZERVKTD.js";
117
+ import "../chunk-6MTNS63X.js";
111
118
  import {
112
119
  getBaseUrl
113
120
  } from "../chunk-2UMNXADU.js";
@@ -177,6 +184,17 @@ var resolveDoctorExit = ({ keyExit, failures }) => {
177
184
  return EXIT.PROBLEMS_FOUND;
178
185
  };
179
186
 
187
+ // src/setup/agent-exec.ts
188
+ var firstToken = (command) => {
189
+ const trimmed = command.trim();
190
+ const quote = trimmed[0];
191
+ if (quote === '"' || quote === "'") {
192
+ const close = trimmed.indexOf(quote, 1);
193
+ if (close > 0) return trimmed.slice(1, close);
194
+ }
195
+ return trimmed.split(/\s+/)[0] ?? "";
196
+ };
197
+
180
198
  // bin/pushary-doctor.ts
181
199
  exitOnHelpFlag("doctor");
182
200
  var parseDoctorOptions = (argv) => {
@@ -221,7 +239,8 @@ var readJson = (path) => {
221
239
  }
222
240
  };
223
241
  var commandResolves = (command) => {
224
- const target = pusharyHookExecutable(command) ?? command;
242
+ const target = pusharyHookExecutable(command) ?? firstToken(command);
243
+ if (!target) return false;
225
244
  if (target.includes("/") || target.includes("\\")) return existsSync(target);
226
245
  try {
227
246
  const whichCmd = process.platform === "win32" ? "where" : "which";
@@ -343,23 +362,6 @@ var main = async () => {
343
362
  break;
344
363
  }
345
364
  }
346
- const daemon = readDaemonStatus();
347
- const daemonOk = daemon.kind === "running";
348
- const daemonFailure = daemonOk ? null : `local state is ${daemon.kind}`;
349
- const daemonDetail = daemonFailure ? `${daemonFailure}; run \`pushary daemon\` in a terminal to inspect it` : null;
350
- check(
351
- daemonOk,
352
- "Remote-control daemon",
353
- [
354
- daemonDetail,
355
- daemon.kind,
356
- `pid ${daemon.pid ?? "none"}`,
357
- `daemon ${daemon.daemonVersion ?? "none"}`,
358
- `installed ${daemon.installedVersion}`,
359
- `machine ${daemon.machineId ?? "none"}`,
360
- `heartbeat ${daemon.lastSuccessfulHeartbeatAt ?? "none yet"}`
361
- ].filter((value) => value !== null).join(" \xB7 ")
362
- );
363
365
  const CLAUDE_JSON = claudeJson();
364
366
  const claudeInPlay = claudeWired({
365
367
  claudeJson: readJson(CLAUDE_JSON),
@@ -427,11 +429,12 @@ var main = async () => {
427
429
  codexParsed = parseTOML(codexConfig);
428
430
  } catch {
429
431
  }
430
- if (codexWired({
432
+ const codexInPlay = codexWired({
431
433
  config: codexParsed,
432
434
  hooks: codexHooksConfig,
433
435
  skillExists: existsSync(join(codexSkillDir(), "SKILL.md"))
434
- })) {
436
+ });
437
+ if (codexInPlay) {
435
438
  checking("Codex");
436
439
  const codexMcp = codexParsed.mcp_servers?.pushary;
437
440
  const codexTransport = !!codexMcp && (typeof codexMcp.url === "string" || typeof codexMcp.command === "string");
@@ -506,7 +509,8 @@ var main = async () => {
506
509
  }
507
510
  const geminiSettingsPath = geminiSettings();
508
511
  const geminiSettings2 = readJson(geminiSettingsPath);
509
- if (geminiSettings2 && geminiWired({ settings: geminiSettings2 })) {
512
+ const geminiInPlay = geminiSettings2 !== null && geminiWired({ settings: geminiSettings2 });
513
+ if (geminiInPlay) {
510
514
  checking("Gemini CLI");
511
515
  const geminiServers = geminiSettings2.mcpServers ?? {};
512
516
  const geminiPushary = geminiServers.pushary;
@@ -549,6 +553,40 @@ var main = async () => {
549
553
  } else {
550
554
  skipped("Gemini CLI", installed("gemini_cli") ? "installed, but Pushary is not set up for it" : "not installed");
551
555
  }
556
+ const configuredManagedProviders = [
557
+ ...claudeInPlay ? ["claude"] : [],
558
+ ...codexInPlay ? ["codex"] : [],
559
+ ...geminiInPlay ? ["gemini"] : []
560
+ ];
561
+ const controlSupported = hasSpawnProvider(detectProviderLiveCapabilities(configuredManagedProviders));
562
+ const controlMode = readControlMode();
563
+ const daemon = readDaemonStatus();
564
+ const serviceDefined = hasDaemonServiceDefinition();
565
+ const managerAvailable = daemonServiceManagerAvailable();
566
+ const controlPolicy = resolveControlPolicy({
567
+ mode: controlMode,
568
+ providerAvailable: controlSupported,
569
+ managerAvailable,
570
+ servicePresent: serviceDefined || daemon.kind !== "absent"
571
+ });
572
+ const controlRequired = controlPolicy === "enabled";
573
+ const controlUnsupported = controlMode === "on" && controlPolicy !== "enabled";
574
+ const daemonOk = controlUnsupported ? false : controlPolicy === "disabled" ? daemon.kind === "absent" && !serviceDefined : controlPolicy === "enabled" ? daemon.kind === "running" : controlPolicy === "legacy" ? false : daemon.kind === "absent" && !serviceDefined;
575
+ const daemonFailure = daemonOk ? null : controlUnsupported ? "control is required but no usable provider/service-manager pair is available" : controlPolicy === "disabled" ? `control is disabled but ${serviceDefined ? "the service definition remains" : `local state is ${daemon.kind}`}` : controlPolicy === "legacy" ? "a legacy service exists without a usable provider/service-manager pair" : `local state is ${daemon.kind}`;
576
+ const daemonDetail = daemonFailure ? controlUnsupported ? `${daemonFailure}; re-run setup with \`--control off\`, or restore both requirements` : controlPolicy === "disabled" ? `${daemonFailure}; re-run setup with \`--control off\`` : controlPolicy === "legacy" ? `${daemonFailure}; run setup with \`--control off\`, or restore both requirements` : `${daemonFailure}; run \`pushary daemon install\` to install or repair the background service` : controlPolicy === "disabled" ? "disabled by setup" : controlPolicy === "preserve-absent" ? "legacy absence preserved" : !controlRequired && daemon.kind === "absent" ? "managed control is unsupported on this provider or operating-system session" : null;
577
+ check(
578
+ daemonOk,
579
+ "Remote-control daemon",
580
+ [
581
+ daemonDetail,
582
+ daemon.kind,
583
+ `pid ${daemon.pid ?? "none"}`,
584
+ `daemon ${daemon.daemonVersion ?? "none"}`,
585
+ `installed ${daemon.installedVersion}`,
586
+ `machine ${daemon.machineId ?? "none"}`,
587
+ `heartbeat ${daemon.lastSuccessfulHeartbeatAt ?? "none yet"}`
588
+ ].filter((value) => value !== null).join(" \xB7 ")
589
+ );
552
590
  const cursorPluginDir2 = cursorPluginDir();
553
591
  if (existsSync(cursorPluginDir2)) {
554
592
  checking("Cursor");
@@ -11,14 +11,16 @@ import {
11
11
  cancelQuestion,
12
12
  pollForAnswer,
13
13
  savePendingQuestion
14
- } from "../chunk-HUJAAWNL.js";
14
+ } from "../chunk-GKAKAOKC.js";
15
15
  import {
16
16
  getMachineId
17
- } from "../chunk-RN3NOEJF.js";
17
+ } from "../chunk-2HYPZLYY.js";
18
+ import "../chunk-V37ZXMH3.js";
18
19
  import "../chunk-BSZYIAZL.js";
19
20
  import "../chunk-SAF6HGAA.js";
20
21
  import "../chunk-7QLSKOSU.js";
21
22
  import "../chunk-KZERVKTD.js";
23
+ import "../chunk-6MTNS63X.js";
22
24
  import {
23
25
  getApiKey
24
26
  } from "../chunk-2UMNXADU.js";
@@ -10,18 +10,17 @@ import "../chunk-PMHTCDEO.js";
10
10
  import {
11
11
  startProcessOwnership,
12
12
  withSpawnProcessOwnership
13
- } from "../chunk-ZYPS2XMT.js";
13
+ } from "../chunk-4ZHQNBDP.js";
14
14
  import {
15
15
  spawnClaude
16
16
  } from "../chunk-XHKBHWLX.js";
17
17
  import {
18
18
  resolveBinary
19
19
  } from "../chunk-PZA7G4CN.js";
20
- import "../chunk-VKVHY5HD.js";
21
- import "../chunk-GIRT7677.js";
22
20
  import {
23
21
  getMachineId
24
- } from "../chunk-RN3NOEJF.js";
22
+ } from "../chunk-2HYPZLYY.js";
23
+ import "../chunk-V37ZXMH3.js";
25
24
  import "../chunk-6MTNS63X.js";
26
25
  import {
27
26
  getApiKey,
@@ -21,7 +21,7 @@ import {
21
21
  readLastUserPrompt,
22
22
  repoKeyFor,
23
23
  reportEvent
24
- } from "../chunk-3UBYTSCY.js";
24
+ } from "../chunk-NFI2K2ZQ.js";
25
25
  import {
26
26
  DEFAULT_SESSION,
27
27
  askUser,
@@ -29,22 +29,24 @@ import {
29
29
  savePendingQuestion,
30
30
  sendNotification,
31
31
  waitForAnswer
32
- } from "../chunk-HUJAAWNL.js";
32
+ } from "../chunk-GKAKAOKC.js";
33
33
  import {
34
34
  deriveActionBody,
35
35
  deriveBlocker,
36
36
  deriveToolTarget,
37
37
  describeToolCall,
38
38
  scopePathFor
39
- } from "../chunk-LGXTBUT4.js";
39
+ } from "../chunk-KOPUTJQC.js";
40
40
  import {
41
41
  getMachineId
42
- } from "../chunk-RN3NOEJF.js";
42
+ } from "../chunk-2HYPZLYY.js";
43
+ import "../chunk-V37ZXMH3.js";
43
44
  import "../chunk-BSZYIAZL.js";
44
45
  import "../chunk-SAF6HGAA.js";
45
46
  import "../chunk-OFRNZWC4.js";
46
47
  import "../chunk-7QLSKOSU.js";
47
48
  import "../chunk-KZERVKTD.js";
49
+ import "../chunk-6MTNS63X.js";
48
50
  import {
49
51
  getApiKey
50
52
  } from "../chunk-2UMNXADU.js";
@@ -1,27 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePreToolUse
4
- } from "../chunk-JT6TIBYH.js";
4
+ } from "../chunk-MZBT2LXW.js";
5
5
  import "../chunk-ATBKJNWS.js";
6
6
  import "../chunk-VZKXBFUA.js";
7
7
  import {
8
8
  readHookInput
9
9
  } from "../chunk-6CUUA7HO.js";
10
10
  import "../chunk-YHG74UFF.js";
11
- import "../chunk-3UBYTSCY.js";
12
- import "../chunk-HUJAAWNL.js";
13
- import "../chunk-LGXTBUT4.js";
14
- import "../chunk-RN3NOEJF.js";
11
+ import "../chunk-NFI2K2ZQ.js";
12
+ import "../chunk-GKAKAOKC.js";
13
+ import "../chunk-KOPUTJQC.js";
14
+ import "../chunk-2HYPZLYY.js";
15
+ import "../chunk-V37ZXMH3.js";
15
16
  import {
16
17
  exitOnHelpFlag
17
- } from "../chunk-SQOFGPNX.js";
18
- import "../chunk-GOEXZ5QJ.js";
18
+ } from "../chunk-LURY4WNF.js";
19
+ import "../chunk-3XTFX4CL.js";
19
20
  import "../chunk-DINDL2CF.js";
20
21
  import "../chunk-BSZYIAZL.js";
21
22
  import "../chunk-SAF6HGAA.js";
22
23
  import "../chunk-OFRNZWC4.js";
23
24
  import "../chunk-7QLSKOSU.js";
24
25
  import "../chunk-KZERVKTD.js";
26
+ import "../chunk-6MTNS63X.js";
25
27
  import "../chunk-2UMNXADU.js";
26
28
  import "../chunk-L4C2JXJS.js";
27
29
 
@@ -13,19 +13,18 @@ import {
13
13
  import {
14
14
  readKeySource,
15
15
  writeKey
16
- } from "../chunk-LALHWDWL.js";
16
+ } from "../chunk-L3YUHEB6.js";
17
17
  import {
18
18
  parseFlags
19
19
  } from "../chunk-GMXKITVA.js";
20
20
  import {
21
21
  exitOnHelpFlag
22
- } from "../chunk-SQOFGPNX.js";
23
- import "../chunk-GOEXZ5QJ.js";
22
+ } from "../chunk-LURY4WNF.js";
23
+ import "../chunk-3XTFX4CL.js";
24
24
  import "../chunk-BC3VCZ3E.js";
25
25
  import {
26
26
  getPackageVersion
27
27
  } from "../chunk-DINDL2CF.js";
28
- import "../chunk-6MTNS63X.js";
29
28
  import "../chunk-SAF6HGAA.js";
30
29
  import "../chunk-OFRNZWC4.js";
31
30
  import {
@@ -34,6 +33,7 @@ import {
34
33
  import {
35
34
  EXIT
36
35
  } from "../chunk-KZERVKTD.js";
36
+ import "../chunk-6MTNS63X.js";
37
37
  import "../chunk-2UMNXADU.js";
38
38
  import {
39
39
  isValidApiKey