@pushary/agent-hooks 0.89.8 → 0.89.10

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 (67) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/bin/pushary-bell-hook.js +4 -4
  3. package/dist/bin/pushary-bell.js +7 -7
  4. package/dist/bin/pushary-claude.js +64 -33
  5. package/dist/bin/pushary-clean.js +53 -46
  6. package/dist/bin/pushary-codex-bridge.js +8 -8
  7. package/dist/bin/pushary-codex-hook.js +12 -8
  8. package/dist/bin/pushary-codex.js +7 -7
  9. package/dist/bin/pushary-connect.js +6 -6
  10. package/dist/bin/pushary-daemon.js +57 -22
  11. package/dist/bin/pushary-disconnect.js +34 -9
  12. package/dist/bin/pushary-doctor.js +43 -22
  13. package/dist/bin/pushary-elicitation-hook.js +4 -4
  14. package/dist/bin/pushary-gemini-bridge.js +7 -7
  15. package/dist/bin/pushary-gemini-hook.js +8 -8
  16. package/dist/bin/pushary-hook.js +11 -10
  17. package/dist/bin/pushary-login.js +4 -4
  18. package/dist/bin/pushary-logout.js +4 -4
  19. package/dist/bin/pushary-mode.js +3 -3
  20. package/dist/bin/pushary-notification-hook.js +7 -7
  21. package/dist/bin/pushary-opencode-hook.js +8 -8
  22. package/dist/bin/pushary-permission-denied-hook.js +11 -10
  23. package/dist/bin/pushary-permission-hook.js +11 -10
  24. package/dist/bin/pushary-post-hook.js +7 -7
  25. package/dist/bin/pushary-prompt-hook.js +7 -7
  26. package/dist/bin/pushary-session-end-hook.js +7 -7
  27. package/dist/bin/pushary-session-start-hook.js +7 -7
  28. package/dist/bin/pushary-setup.js +66 -55
  29. package/dist/bin/pushary-stats.js +2 -2
  30. package/dist/bin/pushary-status.js +8 -8
  31. package/dist/bin/pushary-stop-hook.js +7 -7
  32. package/dist/bin/pushary-stopfailure-hook.js +7 -7
  33. package/dist/bin/pushary-upgrade.js +25 -17
  34. package/dist/bin/pushary-wait.js +3 -3
  35. package/dist/{chunk-SS72Z7FV.js → chunk-253WC6O5.js} +1 -1
  36. package/dist/{chunk-T3LRWZKI.js → chunk-2LPEZYMC.js} +1 -1
  37. package/dist/{chunk-O5B7EK5U.js → chunk-34GN3IPX.js} +1 -1
  38. package/dist/{chunk-V6N4Q223.js → chunk-3CUDMTL4.js} +1 -1
  39. package/dist/{chunk-VZKXBFUA.js → chunk-3HFK3UXM.js} +1 -1
  40. package/dist/{chunk-R2AGKCXL.js → chunk-3SQYKLBW.js} +52 -22
  41. package/dist/{chunk-ATBKJNWS.js → chunk-6EKQZA6R.js} +5 -1
  42. package/dist/{chunk-NKHEHEUM.js → chunk-6XUABEX2.js} +1 -1
  43. package/dist/{chunk-I5L6SK5V.js → chunk-BLODMQKJ.js} +1 -1
  44. package/dist/{chunk-DKDDLF5P.js → chunk-DKWM5T3P.js} +1 -1
  45. package/dist/{chunk-BAE45YLP.js → chunk-FZ73G2RO.js} +3 -3
  46. package/dist/{chunk-EJT2ER6G.js → chunk-GSSFSVAQ.js} +15 -21
  47. package/dist/{chunk-4XZCDSNG.js → chunk-GTZLL7F4.js} +5 -5
  48. package/dist/{chunk-PMHTCDEO.js → chunk-IUN6VOKV.js} +1 -1
  49. package/dist/{chunk-OFRNZWC4.js → chunk-IUWRVTQK.js} +1 -1
  50. package/dist/{chunk-J2JZJZKB.js → chunk-KVE5RCQL.js} +1 -1
  51. package/dist/{chunk-A4O5ROZK.js → chunk-MZGWKIUZ.js} +2 -2
  52. package/dist/chunk-NCVIWGVA.js +18 -0
  53. package/dist/{chunk-C623LWJR.js → chunk-OLAGKKSR.js} +1 -1
  54. package/dist/{chunk-EA3E74P2.js → chunk-PZRWFWSR.js} +6 -6
  55. package/dist/{chunk-VA7VUNRD.js → chunk-Q223OM5J.js} +58 -8
  56. package/dist/{chunk-GMI5QZLG.js → chunk-QA72MKIT.js} +5 -1
  57. package/dist/{chunk-AIGDBRIJ.js → chunk-SYUIXXQW.js} +1 -1
  58. package/dist/{chunk-TF247BET.js → chunk-TEZ2FZD6.js} +1 -1
  59. package/dist/{chunk-KOPUTJQC.js → chunk-TG3T3M4K.js} +1 -1
  60. package/dist/{chunk-FX5QSMPY.js → chunk-TRVIRETT.js} +1 -1
  61. package/dist/{chunk-ZL7HEF2T.js → chunk-TY5HVMXT.js} +32 -1
  62. package/dist/chunk-UDBJHQMG.js +240 -0
  63. package/dist/{chunk-GKAKAOKC.js → chunk-UXHMWF4H.js} +64 -11
  64. package/dist/{chunk-PZA7G4CN.js → chunk-X4ZUUFKV.js} +1 -0
  65. package/dist/{chunk-L4C2JXJS.js → chunk-X6RXX2NF.js} +5 -0
  66. package/dist/src/index.js +11 -10
  67. package/package.json +1 -1
@@ -4,19 +4,19 @@ import {
4
4
  } from "../chunk-6CUUA7HO.js";
5
5
  import {
6
6
  handleStop
7
- } from "../chunk-4XZCDSNG.js";
8
- import "../chunk-GKAKAOKC.js";
9
- import "../chunk-KOPUTJQC.js";
10
- import "../chunk-DKDDLF5P.js";
11
- import "../chunk-GMI5QZLG.js";
7
+ } from "../chunk-GTZLL7F4.js";
8
+ import "../chunk-UXHMWF4H.js";
9
+ import "../chunk-TG3T3M4K.js";
10
+ import "../chunk-DKWM5T3P.js";
11
+ import "../chunk-QA72MKIT.js";
12
12
  import "../chunk-BSZYIAZL.js";
13
13
  import "../chunk-SAF6HGAA.js";
14
- import "../chunk-OFRNZWC4.js";
14
+ import "../chunk-IUWRVTQK.js";
15
15
  import "../chunk-7QLSKOSU.js";
16
16
  import "../chunk-KZERVKTD.js";
17
17
  import "../chunk-XX2V4QS5.js";
18
18
  import "../chunk-2UMNXADU.js";
19
- import "../chunk-L4C2JXJS.js";
19
+ import "../chunk-X6RXX2NF.js";
20
20
 
21
21
  // bin/pushary-stop-hook.ts
22
22
  var main = async () => {
@@ -4,19 +4,19 @@ import {
4
4
  } from "../chunk-6CUUA7HO.js";
5
5
  import {
6
6
  handleStopFailure
7
- } from "../chunk-4XZCDSNG.js";
8
- import "../chunk-GKAKAOKC.js";
9
- import "../chunk-KOPUTJQC.js";
10
- import "../chunk-DKDDLF5P.js";
11
- import "../chunk-GMI5QZLG.js";
7
+ } from "../chunk-GTZLL7F4.js";
8
+ import "../chunk-UXHMWF4H.js";
9
+ import "../chunk-TG3T3M4K.js";
10
+ import "../chunk-DKWM5T3P.js";
11
+ import "../chunk-QA72MKIT.js";
12
12
  import "../chunk-BSZYIAZL.js";
13
13
  import "../chunk-SAF6HGAA.js";
14
- import "../chunk-OFRNZWC4.js";
14
+ import "../chunk-IUWRVTQK.js";
15
15
  import "../chunk-7QLSKOSU.js";
16
16
  import "../chunk-KZERVKTD.js";
17
17
  import "../chunk-XX2V4QS5.js";
18
18
  import "../chunk-2UMNXADU.js";
19
- import "../chunk-L4C2JXJS.js";
19
+ import "../chunk-X6RXX2NF.js";
20
20
 
21
21
  // bin/pushary-stopfailure-hook.ts
22
22
  var main = async () => {
@@ -1,26 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  reapplyAllAgents
4
- } from "../chunk-EA3E74P2.js";
5
- import "../chunk-J2JZJZKB.js";
6
- import "../chunk-BAE45YLP.js";
7
- import "../chunk-VA7VUNRD.js";
8
- import "../chunk-ATBKJNWS.js";
9
- import "../chunk-AIGDBRIJ.js";
4
+ } from "../chunk-PZRWFWSR.js";
5
+ import "../chunk-KVE5RCQL.js";
6
+ import "../chunk-FZ73G2RO.js";
10
7
  import {
8
+ waitForMachineReadiness
9
+ } from "../chunk-TY5HVMXT.js";
10
+ import "../chunk-Q223OM5J.js";
11
+ import "../chunk-6EKQZA6R.js";
12
+ import "../chunk-SYUIXXQW.js";
13
+ import {
14
+ daemonHasRemoteProof,
11
15
  daemonServiceManagerAvailable,
12
16
  disableDaemonService,
13
17
  ensureDaemonRunning,
14
18
  hasDaemonServiceDefinition,
15
19
  readDaemonStatus,
16
20
  replaceDaemonService,
17
- stopDaemonService
18
- } from "../chunk-R2AGKCXL.js";
21
+ stopDaemonService,
22
+ waitForDaemonRemoteProof
23
+ } from "../chunk-3SQYKLBW.js";
19
24
  import {
20
25
  detectProviderLiveCapabilities,
21
26
  hasSpawnProvider,
22
27
  resolveControlPolicy
23
- } from "../chunk-NKHEHEUM.js";
28
+ } from "../chunk-6XUABEX2.js";
24
29
  import {
25
30
  needsShell
26
31
  } from "../chunk-XHKBHWLX.js";
@@ -28,18 +33,18 @@ import {
28
33
  execNpm,
29
34
  npmErrorMessage,
30
35
  resolveGlobalBinary
31
- } from "../chunk-PZA7G4CN.js";
32
- import "../chunk-DKDDLF5P.js";
36
+ } from "../chunk-X4ZUUFKV.js";
37
+ import "../chunk-DKWM5T3P.js";
33
38
  import {
34
39
  claudeJson,
35
40
  codexConfigToml,
36
41
  cursorPluginDir,
37
42
  geminiSettings,
38
43
  vscodePluginDir
39
- } from "../chunk-GMI5QZLG.js";
44
+ } from "../chunk-QA72MKIT.js";
40
45
  import {
41
46
  readControlMode
42
- } from "../chunk-V6N4Q223.js";
47
+ } from "../chunk-3CUDMTL4.js";
43
48
  import {
44
49
  exitOnHelpFlag
45
50
  } from "../chunk-LURY4WNF.js";
@@ -48,13 +53,13 @@ import "../chunk-BC3VCZ3E.js";
48
53
  import {
49
54
  isNewerVersion
50
55
  } from "../chunk-DINDL2CF.js";
51
- import "../chunk-OFRNZWC4.js";
56
+ import "../chunk-IUWRVTQK.js";
52
57
  import "../chunk-KZERVKTD.js";
53
58
  import "../chunk-XX2V4QS5.js";
54
59
  import {
55
60
  getApiKey
56
61
  } from "../chunk-2UMNXADU.js";
57
- import "../chunk-L4C2JXJS.js";
62
+ import "../chunk-X6RXX2NF.js";
58
63
 
59
64
  // bin/pushary-upgrade.ts
60
65
  import { existsSync } from "fs";
@@ -129,9 +134,10 @@ var finishUpgrade = async () => {
129
134
  const controlMode = readControlMode();
130
135
  const daemonStatus = readDaemonStatus();
131
136
  const serviceWasPresent = daemonStatus.kind !== "absent" || hasDaemonServiceDefinition();
137
+ const controlCapabilities = detectProviderLiveCapabilities(configuredControlProviders);
132
138
  const controlPolicy = resolveControlPolicy({
133
139
  mode: controlMode,
134
- providerAvailable: hasSpawnProvider(detectProviderLiveCapabilities(configuredControlProviders)),
140
+ providerAvailable: hasSpawnProvider(controlCapabilities),
135
141
  managerAvailable: daemonServiceManagerAvailable(),
136
142
  servicePresent: serviceWasPresent
137
143
  });
@@ -150,7 +156,9 @@ var finishUpgrade = async () => {
150
156
  const service = await replaceDaemonService();
151
157
  const daemon = service.kind === "ok" ? await ensureDaemonRunning({ spawnDaemon: () => {
152
158
  } }) : null;
153
- daemonReady = service.kind === "ok" && (daemon?.kind === "running" || daemon?.kind === "started");
159
+ const localProof = daemon?.kind === "running" || daemon?.kind === "started" ? await waitForDaemonRemoteProof() : null;
160
+ const serverProof = localProof && daemonHasRemoteProof(localProof) ? await waitForMachineReadiness(apiKey, ["spawn", ...controlCapabilities]) : null;
161
+ daemonReady = service.kind === "ok" && localProof !== null && daemonHasRemoteProof(localProof) && (serverProof?.kind === "ready" || serverProof?.kind === "unsupported");
154
162
  }
155
163
  } else if (controlMode === "on" && controlPolicy === "unsupported") {
156
164
  daemonReady = false;
@@ -4,8 +4,8 @@ import {
4
4
  } from "../chunk-IIENZE2J.js";
5
5
  import {
6
6
  exitOnFailedResponse
7
- } from "../chunk-SS72Z7FV.js";
8
- import "../chunk-I5L6SK5V.js";
7
+ } from "../chunk-253WC6O5.js";
8
+ import "../chunk-BLODMQKJ.js";
9
9
  import {
10
10
  createIo
11
11
  } from "../chunk-5RUIFDTP.js";
@@ -28,7 +28,7 @@ import {
28
28
  getApiKey,
29
29
  getBaseUrl
30
30
  } from "../chunk-2UMNXADU.js";
31
- import "../chunk-L4C2JXJS.js";
31
+ import "../chunk-X6RXX2NF.js";
32
32
 
33
33
  // bin/pushary-wait.ts
34
34
  exitOnHelpFlag("wait");
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  describeKeyCheck,
3
3
  keyCheckFromResponse
4
- } from "./chunk-I5L6SK5V.js";
4
+ } from "./chunk-BLODMQKJ.js";
5
5
  import {
6
6
  createIo
7
7
  } from "./chunk-5RUIFDTP.js";
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-BSZYIAZL.js";
12
12
  import {
13
13
  reportedInstallSource
14
- } from "./chunk-OFRNZWC4.js";
14
+ } from "./chunk-IUWRVTQK.js";
15
15
 
16
16
  // src/reach.ts
17
17
  var reachVerdict = (channels) => {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HOOK_BUDGETS,
3
3
  OPENCODE_APPROVAL_EVENT
4
- } from "./chunk-L4C2JXJS.js";
4
+ } from "./chunk-X6RXX2NF.js";
5
5
 
6
6
  // src/opencode-plugin.ts
7
7
  var OPENCODE_PLUGIN_MARKER = "pushary-opencode-plugin w1";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-BC3VCZ3E.js";
4
4
  import {
5
5
  resolveInstallSourceFor
6
- } from "./chunk-OFRNZWC4.js";
6
+ } from "./chunk-IUWRVTQK.js";
7
7
  import {
8
8
  backupFile,
9
9
  readJsonSafe,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isSafeReadOnlyCommand
3
- } from "./chunk-L4C2JXJS.js";
3
+ } from "./chunk-X6RXX2NF.js";
4
4
 
5
5
  // src/ledger.ts
6
6
  import { appendFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync } from "fs";
@@ -4,13 +4,13 @@ import {
4
4
  } from "./chunk-XHKBHWLX.js";
5
5
  import {
6
6
  resolveGlobalBinary
7
- } from "./chunk-PZA7G4CN.js";
7
+ } from "./chunk-X4ZUUFKV.js";
8
8
  import {
9
9
  getMachineId
10
- } from "./chunk-DKDDLF5P.js";
10
+ } from "./chunk-DKWM5T3P.js";
11
11
  import {
12
12
  pusharyDir
13
- } from "./chunk-GMI5QZLG.js";
13
+ } from "./chunk-QA72MKIT.js";
14
14
  import {
15
15
  getPackageVersion
16
16
  } from "./chunk-DINDL2CF.js";
@@ -31,6 +31,14 @@ import { createHash, randomUUID } from "crypto";
31
31
  import { homedir } from "os";
32
32
  import { execFileSync } from "child_process";
33
33
  var daemonNeedsHandoff = (status) => status.kind === "version-mismatch" || status.kind === "configuration-mismatch" || status.kind === "unresponsive" && status.processAlive === true;
34
+ var DAEMON_REMOTE_PROOF_MAX_AGE_MS = 18e4;
35
+ var DAEMON_REMOTE_PROOF_CLOCK_SKEW_MS = 3e4;
36
+ var remoteProofIsFresh = (timestamp, now) => {
37
+ if (timestamp === null) return false;
38
+ const age = now - Date.parse(timestamp);
39
+ return Number.isFinite(age) && age >= -DAEMON_REMOTE_PROOF_CLOCK_SKEW_MS && age < DAEMON_REMOTE_PROOF_MAX_AGE_MS;
40
+ };
41
+ var daemonHasRemoteProof = (status, now = Date.now()) => status.kind === "running" && remoteProofIsFresh(status.lastSuccessfulHeartbeatAt, now) && remoteProofIsFresh(status.lastSuccessfulControlAt, now);
34
42
  var runDaemonServiceCommand = (command, args) => execFileSync(command, [...args], {
35
43
  encoding: "utf-8",
36
44
  stdio: ["ignore", "pipe", "ignore"],
@@ -241,7 +249,7 @@ WantedBy=default.target
241
249
  "-NoProfile",
242
250
  "-NonInteractive",
243
251
  "-Command",
244
- "$task = @(Get-ScheduledTask -ErrorAction Stop) | Where-Object { $_.TaskName -eq 'Pushary Daemon' -and $_.TaskPath -eq '\\' } | Select-Object -First 1; if ($null -eq $task) { exit 3 }; if ($task.State -eq 'Disabled') { exit 4 }"
252
+ "$task = @(Get-ScheduledTask -ErrorAction Stop) | Where-Object { $_.TaskName -eq 'Pushary Daemon' -and $_.TaskPath -eq '\\' } | Select-Object -First 1; if ($null -eq $task) { exit 3 }; if ($null -eq $task.Settings -or $null -eq $task.Settings.Enabled) { exit 5 }; if (-not $task.Settings.Enabled) { exit 4 }"
245
253
  ],
246
254
  negativeExitCodes: [3, 4]
247
255
  },
@@ -313,16 +321,10 @@ var applyDaemonService = (action, definition, options = {}) => {
313
321
  const steps = action === "uninstall" ? [...definition.stop, ...definition.uninstall] : definition[action];
314
322
  runDaemonServiceSteps(steps, run);
315
323
  if (action === "uninstall") {
316
- let registered = true;
317
- try {
318
- run(definition.registrationProbe.command, definition.registrationProbe.args);
319
- } catch (err) {
320
- if (!isExpectedProbeFailure(definition.registrationProbe, err)) {
321
- throw new Error(`Could not verify native background service is absent: ${commandFailureOutput(err) || String(err)}`);
322
- }
323
- registered = false;
324
- }
325
- if (registered) throw new Error("Native background service remains registered");
324
+ const state = probeDaemonServiceState(definition, run);
325
+ if (state.kind !== "ok") throw new Error(`Could not verify native background service is absent: ${state.detail}`);
326
+ if (state.registered) throw new Error("Native background service remains registered");
327
+ if (state.running) throw new Error("Native background service remains active");
326
328
  safeUnlink(definition.definitionPath);
327
329
  const reload = definition.reloadAfterUninstall;
328
330
  if (reload) run(reload.command, reload.args);
@@ -412,7 +414,7 @@ var currentConfigurationId = () => {
412
414
  var parseDaemonState = (value) => {
413
415
  if (typeof value !== "object" || value === null) return null;
414
416
  const state = value;
415
- if (!isString(state.instanceId) || !Number.isInteger(state.pid) || state.pid <= 0 || !isString(state.version) || !(state.configurationId === void 0 || state.configurationId === null || isString(state.configurationId)) || !isString(state.machineId) || !isTimestamp(state.startedAt) || !isTimestamp(state.updatedAt) || !(state.lastSuccessfulHeartbeatAt === null || isTimestamp(state.lastSuccessfulHeartbeatAt))) return null;
417
+ if (!isString(state.instanceId) || !Number.isInteger(state.pid) || state.pid <= 0 || !isString(state.version) || !(state.configurationId === void 0 || state.configurationId === null || isString(state.configurationId)) || !isString(state.machineId) || !isTimestamp(state.startedAt) || !isTimestamp(state.updatedAt) || !(state.lastSuccessfulHeartbeatAt === null || isTimestamp(state.lastSuccessfulHeartbeatAt)) || !(state.lastSuccessfulControlAt === void 0 || state.lastSuccessfulControlAt === null || isTimestamp(state.lastSuccessfulControlAt))) return null;
416
418
  return {
417
419
  instanceId: state.instanceId,
418
420
  pid: state.pid,
@@ -421,7 +423,8 @@ var parseDaemonState = (value) => {
421
423
  machineId: state.machineId,
422
424
  startedAt: state.startedAt,
423
425
  updatedAt: state.updatedAt,
424
- lastSuccessfulHeartbeatAt: state.lastSuccessfulHeartbeatAt
426
+ lastSuccessfulHeartbeatAt: state.lastSuccessfulHeartbeatAt,
427
+ lastSuccessfulControlAt: state.lastSuccessfulControlAt ?? null
425
428
  };
426
429
  };
427
430
  var parseLockOwner = (value) => {
@@ -443,7 +446,8 @@ var readDaemonStatus = (options = {}) => {
443
446
  daemonVersion: null,
444
447
  startedAt: null,
445
448
  updatedAt: null,
446
- lastSuccessfulHeartbeatAt: null
449
+ lastSuccessfulHeartbeatAt: null,
450
+ lastSuccessfulControlAt: null
447
451
  };
448
452
  }
449
453
  const value = state.kind === "ok" ? parseDaemonState(state.value) : null;
@@ -460,7 +464,8 @@ var readDaemonStatus = (options = {}) => {
460
464
  daemonVersion: value.version,
461
465
  startedAt: value.startedAt,
462
466
  updatedAt: value.updatedAt,
463
- lastSuccessfulHeartbeatAt: value.lastSuccessfulHeartbeatAt
467
+ lastSuccessfulHeartbeatAt: value.lastSuccessfulHeartbeatAt,
468
+ lastSuccessfulControlAt: value.lastSuccessfulControlAt
464
469
  };
465
470
  }
466
471
  return {
@@ -472,7 +477,8 @@ var readDaemonStatus = (options = {}) => {
472
477
  daemonVersion: null,
473
478
  startedAt: null,
474
479
  updatedAt: null,
475
- lastSuccessfulHeartbeatAt: null
480
+ lastSuccessfulHeartbeatAt: null,
481
+ lastSuccessfulControlAt: null
476
482
  };
477
483
  };
478
484
  var safeUnlink = (path) => {
@@ -540,7 +546,8 @@ var acquireDaemonLease = (options = {}) => {
540
546
  machineId,
541
547
  startedAt,
542
548
  updatedAt: startedAt,
543
- lastSuccessfulHeartbeatAt: null
549
+ lastSuccessfulHeartbeatAt: null,
550
+ lastSuccessfulControlAt: null
544
551
  };
545
552
  try {
546
553
  writeJsonAtomic(statePath(dir), state, 384);
@@ -576,6 +583,14 @@ var acquireDaemonLease = (options = {}) => {
576
583
  lastSuccessfulHeartbeatAt: timestamp
577
584
  });
578
585
  },
586
+ recordSuccessfulControl: (at = now()) => {
587
+ const timestamp = new Date(at).toISOString();
588
+ updateState({
589
+ ...currentState,
590
+ updatedAt: timestamp,
591
+ lastSuccessfulControlAt: timestamp
592
+ });
593
+ },
579
594
  shouldYield: () => {
580
595
  if (!isOwner()) return true;
581
596
  const target = readJsonSafe(targetPath(dir));
@@ -645,7 +660,8 @@ var deactivateDaemonService = async (action, options) => {
645
660
  const platform = options.platform ?? process.platform;
646
661
  const supported = ["darwin", "linux", "win32"].includes(platform);
647
662
  const managerAvailable = supported && daemonServiceManagerAvailable(options);
648
- const service = supported && !managerAvailable ? { kind: "failed", detail: "Native background-service manager is unavailable" } : managerAvailable ? manageDaemonService(action, options) : { kind: "ok" };
663
+ const absenceMustBeProven = options.requireAbsenceProof || hasDaemonServiceDefinition(options);
664
+ const service = supported && !managerAvailable && absenceMustBeProven ? { kind: "failed", detail: "Native background-service manager is unavailable" } : managerAvailable ? manageDaemonService(action, options) : { kind: "ok" };
649
665
  const stopped = await stopDaemonRunning(options);
650
666
  const failures = [
651
667
  service.kind === "ok" ? null : service.detail,
@@ -956,8 +972,21 @@ var ensureDaemonRunning = async (options = {}) => {
956
972
  }
957
973
  return { kind: "unavailable", status, detail: `daemon did not become healthy (${status.kind})` };
958
974
  };
975
+ var waitForDaemonRemoteProof = async (options = {}) => {
976
+ const sleep = options.sleep ?? wait;
977
+ const pollIntervalMs = options.pollIntervalMs ?? 250;
978
+ const attempts = Math.max(1, Math.ceil((options.waitTimeoutMs ?? 5e3) / pollIntervalMs));
979
+ let status = readDaemonStatus(options);
980
+ for (let attempt = 0; attempt < attempts; attempt++) {
981
+ status = readDaemonStatus(options);
982
+ if (daemonHasRemoteProof(status)) return status;
983
+ if (attempt + 1 < attempts) await sleep(pollIntervalMs);
984
+ }
985
+ return status;
986
+ };
959
987
 
960
988
  export {
989
+ daemonHasRemoteProof,
961
990
  daemonServiceManagerAvailable,
962
991
  DAEMON_LEASE_RENEW_INTERVAL_MS,
963
992
  parseDaemonAction,
@@ -970,5 +999,6 @@ export {
970
999
  stopDaemonService,
971
1000
  disableDaemonService,
972
1001
  replaceDaemonService,
973
- ensureDaemonRunning
1002
+ ensureDaemonRunning,
1003
+ waitForDaemonRemoteProof
974
1004
  };
@@ -1,3 +1,7 @@
1
+ import {
2
+ ASKED_IN_EVERY_MODE_TOOLS
3
+ } from "./chunk-X6RXX2NF.js";
4
+
1
5
  // src/claude-tools.ts
2
6
  var PRETOOLUSE_GATED_TOOLS = [
3
7
  "Bash",
@@ -8,7 +12,7 @@ var PRETOOLUSE_GATED_TOOLS = [
8
12
  "PowerShell",
9
13
  "Monitor"
10
14
  ];
11
- var PRETOOLUSE_PHONE_ANSWERED_TOOLS = ["AskUserQuestion", "ExitPlanMode"];
15
+ var PRETOOLUSE_PHONE_ANSWERED_TOOLS = ASKED_IN_EVERY_MODE_TOOLS;
12
16
  var POSTTOOLUSE_MIRRORED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, "TodoWrite"];
13
17
  var PRETOOLUSE_HANDLED_TOOLS = /* @__PURE__ */ new Set([...PRETOOLUSE_GATED_TOOLS, ...PRETOOLUSE_PHONE_ANSWERED_TOOLS]);
14
18
 
@@ -2,7 +2,7 @@ import {
2
2
  resolveBinary,
3
3
  resolveGlobalPackageVersion,
4
4
  resolvePackageVersionFromBinary
5
- } from "./chunk-PZA7G4CN.js";
5
+ } from "./chunk-X4ZUUFKV.js";
6
6
 
7
7
  // src/live-capabilities.ts
8
8
  var CLAUDE_BRIDGE_CAPABILITY = "claude-bridge";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-2UMNXADU.js";
13
13
  import {
14
14
  isValidApiKey
15
- } from "./chunk-L4C2JXJS.js";
15
+ } from "./chunk-X6RXX2NF.js";
16
16
 
17
17
  // src/session.ts
18
18
  var IDENTITY_PATH = "/api/v1/server/identity";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-GMI5QZLG.js";
3
+ } from "./chunk-QA72MKIT.js";
4
4
  import {
5
5
  writeFileAtomic
6
6
  } from "./chunk-XX2V4QS5.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  hasGeminiHooks
3
- } from "./chunk-VA7VUNRD.js";
3
+ } from "./chunk-Q223OM5J.js";
4
4
  import {
5
5
  hasCodexHooks
6
- } from "./chunk-GMI5QZLG.js";
6
+ } from "./chunk-QA72MKIT.js";
7
7
  import {
8
8
  HOOK_LOCATOR_BINARY
9
- } from "./chunk-L4C2JXJS.js";
9
+ } from "./chunk-X6RXX2NF.js";
10
10
 
11
11
  // src/diagnostics/wiring.ts
12
12
  var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -1,11 +1,14 @@
1
1
  import {
2
2
  PRETOOLUSE_HANDLED_TOOLS,
3
3
  PRETOOLUSE_PHONE_ANSWERED_TOOLS
4
- } from "./chunk-ATBKJNWS.js";
4
+ } from "./chunk-6EKQZA6R.js";
5
+ import {
6
+ defersToNativeMode
7
+ } from "./chunk-NCVIWGVA.js";
5
8
  import {
6
9
  isGatingMoment,
7
10
  recordKeylessMoment
8
- } from "./chunk-VZKXBFUA.js";
11
+ } from "./chunk-3HFK3UXM.js";
9
12
  import {
10
13
  denyReasonFrom,
11
14
  isDeferAnswer
@@ -17,7 +20,7 @@ import {
17
20
  readLastUserPrompt,
18
21
  repoKeyFor,
19
22
  throttlePass
20
- } from "./chunk-4XZCDSNG.js";
23
+ } from "./chunk-GTZLL7F4.js";
21
24
  import {
22
25
  DEFAULT_SESSION,
23
26
  askUser,
@@ -25,7 +28,7 @@ import {
25
28
  pollForAnswer,
26
29
  savePendingQuestion,
27
30
  sendNotification
28
- } from "./chunk-GKAKAOKC.js";
31
+ } from "./chunk-UXHMWF4H.js";
29
32
  import {
30
33
  deriveAction,
31
34
  deriveActionBody,
@@ -33,10 +36,10 @@ import {
33
36
  deriveToolTarget,
34
37
  describeToolCall,
35
38
  scopePathFor
36
- } from "./chunk-KOPUTJQC.js";
39
+ } from "./chunk-TG3T3M4K.js";
37
40
  import {
38
41
  getMachineId
39
- } from "./chunk-DKDDLF5P.js";
42
+ } from "./chunk-DKWM5T3P.js";
40
43
  import {
41
44
  getApiKey,
42
45
  getBaseUrl
@@ -50,9 +53,8 @@ import {
50
53
  hookWaitDeadline,
51
54
  parseAgentQuestionAnswers,
52
55
  parseAgentQuestions,
53
- resolveGate,
54
- shouldDeferToNativeMode
55
- } from "./chunk-L4C2JXJS.js";
56
+ resolveGate
57
+ } from "./chunk-X6RXX2NF.js";
56
58
 
57
59
  // src/decision-episode.ts
58
60
  var EPISODE_PATH = "/api/agent/decision-episode";
@@ -302,15 +304,7 @@ var keylessNoticeOnce = (sessionId) => {
302
304
  } catch {
303
305
  }
304
306
  };
305
- var nativeDeferOptions = () => {
306
- const respect = process.env.PUSHARY_RESPECT_PERMISSION_MODE;
307
- const bypass = process.env.PUSHARY_DEFER_BYPASS;
308
- return {
309
- respectPermissionMode: !(respect === "0" || respect === "false"),
310
- deferBypass: bypass === "1" || bypass === "true"
311
- };
312
- };
313
- var shouldDeferToNativeMode2 = (permissionMode, toolName) => shouldDeferToNativeMode(permissionMode, toolName, nativeDeferOptions());
307
+ var shouldDeferToNativeMode = defersToNativeMode;
314
308
  var handedToTerminal = (result) => result.suppressed === true || result.noDevices === true || result.status === "terminal";
315
309
  var withLabels = (question) => ({
316
310
  ...question,
@@ -487,14 +481,14 @@ var handlePreToolUse = async (input) => {
487
481
  const policy = await getPolicy(apiKey, modeState.policyVersion, "claude_code", true, input.session_id);
488
482
  const verdict = resolveGate(claudeGateInput(modeState, policy, input));
489
483
  if (verdict.kind === "kill") return deny(verdict.reason);
484
+ if (verdict.kind === "deny") return deny(verdict.reason);
490
485
  if (input.tool_name === "AskUserQuestion") {
491
486
  return handleAskUserQuestion(apiKey, input);
492
487
  }
493
- if (verdict.kind === "deny") return deny(verdict.reason);
494
488
  if (input.tool_name === "ExitPlanMode") {
495
489
  return handleExitPlanMode(apiKey, input);
496
490
  }
497
- if (shouldDeferToNativeMode2(input.permission_mode, input.tool_name)) {
491
+ if (shouldDeferToNativeMode(input.permission_mode, input.tool_name)) {
498
492
  return void 0;
499
493
  }
500
494
  switch (verdict.kind) {
@@ -525,7 +519,7 @@ var toPermissionRequestOutput = (hookOutput) => {
525
519
  };
526
520
  var handlePermissionRequest = async (input) => {
527
521
  if (PRETOOLUSE_HANDLED_TOOLS.has(input.tool_name)) {
528
- const reclaimDeferredExec = !PRETOOLUSE_PHONE_ANSWERED_TOOLS.includes(input.tool_name) && shouldDeferToNativeMode2(input.permission_mode, input.tool_name);
522
+ const reclaimDeferredExec = !PRETOOLUSE_PHONE_ANSWERED_TOOLS.includes(input.tool_name) && shouldDeferToNativeMode(input.permission_mode, input.tool_name);
529
523
  if (!reclaimDeferredExec) return void 0;
530
524
  }
531
525
  if (input.tool_name.startsWith("mcp__pushary__")) return void 0;
@@ -12,7 +12,7 @@ import {
12
12
  savePendingCommand,
13
13
  sendNotification,
14
14
  waitForAnswer
15
- } from "./chunk-GKAKAOKC.js";
15
+ } from "./chunk-UXHMWF4H.js";
16
16
  import {
17
17
  AGENT_IDENTITIES,
18
18
  deriveReceiptMeta,
@@ -26,16 +26,16 @@ import {
26
26
  summarizeStop,
27
27
  taskTitleFrom,
28
28
  toolResultErrorText
29
- } from "./chunk-KOPUTJQC.js";
29
+ } from "./chunk-TG3T3M4K.js";
30
30
  import {
31
31
  getMachineId
32
- } from "./chunk-DKDDLF5P.js";
32
+ } from "./chunk-DKWM5T3P.js";
33
33
  import {
34
34
  withRetry
35
35
  } from "./chunk-BSZYIAZL.js";
36
36
  import {
37
37
  reportedInstallSource
38
- } from "./chunk-OFRNZWC4.js";
38
+ } from "./chunk-IUWRVTQK.js";
39
39
  import {
40
40
  getApiKey,
41
41
  getBaseUrl
@@ -51,7 +51,7 @@ import {
51
51
  pendingCommandEvents,
52
52
  resolveAutoResolveOrigin,
53
53
  resolvePolicy
54
- } from "./chunk-L4C2JXJS.js";
54
+ } from "./chunk-X6RXX2NF.js";
55
55
 
56
56
  // src/policy.ts
57
57
  import { createHash } from "crypto";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-2UMNXADU.js";
4
4
  import {
5
5
  redactSecrets
6
- } from "./chunk-L4C2JXJS.js";
6
+ } from "./chunk-X6RXX2NF.js";
7
7
 
8
8
  // src/crypto.ts
9
9
  import nacl from "tweetnacl";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-2UMNXADU.js";
4
4
  import {
5
5
  normalizeInstallSource
6
- } from "./chunk-L4C2JXJS.js";
6
+ } from "./chunk-X6RXX2NF.js";
7
7
 
8
8
  // src/install-source.ts
9
9
  import { readFileSync } from "fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  parseVersion
3
- } from "./chunk-VA7VUNRD.js";
3
+ } from "./chunk-Q223OM5J.js";
4
4
 
5
5
  // src/setup/agent-probe.ts
6
6
  import { execSync } from "child_process";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  openCodeConfigDirFrom
3
- } from "./chunk-O5B7EK5U.js";
3
+ } from "./chunk-34GN3IPX.js";
4
4
  import {
5
5
  codexHomeFrom
6
- } from "./chunk-GMI5QZLG.js";
6
+ } from "./chunk-QA72MKIT.js";
7
7
 
8
8
  // src/vscode-config.ts
9
9
  import { homedir } from "os";
@@ -0,0 +1,18 @@
1
+ import {
2
+ shouldDeferToNativeMode
3
+ } from "./chunk-X6RXX2NF.js";
4
+
5
+ // src/native-defer.ts
6
+ var nativeDeferOptions = () => {
7
+ const respect = process.env.PUSHARY_RESPECT_PERMISSION_MODE;
8
+ const bypass = process.env.PUSHARY_DEFER_BYPASS;
9
+ return {
10
+ respectPermissionMode: !(respect === "0" || respect === "false"),
11
+ deferBypass: bypass === "1" || bypass === "true"
12
+ };
13
+ };
14
+ var defersToNativeMode = (permissionMode, toolName) => shouldDeferToNativeMode(permissionMode, toolName, nativeDeferOptions());
15
+
16
+ export {
17
+ defersToNativeMode
18
+ };