@pushary/agent-hooks 0.42.0 → 0.44.0

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.
@@ -10,9 +10,10 @@ import {
10
10
  fetchModeState,
11
11
  getMachineId,
12
12
  getPolicy,
13
+ reportEvent,
13
14
  resolvePolicy,
14
15
  waitForAnswer
15
- } from "../chunk-ETDXSKR5.js";
16
+ } from "../chunk-VZNP4R5I.js";
16
17
  import "../chunk-DWED7BS3.js";
17
18
  import "../chunk-Z5PL3K7C.js";
18
19
  import {
@@ -104,15 +105,24 @@ var runLocalPassthrough = (binary, args2) => {
104
105
  import { basename } from "path";
105
106
 
106
107
  // src/wrapper/sdkLoader.ts
108
+ import { spawn as spawn2 } from "child_process";
109
+ import { existsSync, mkdirSync, writeFileSync } from "fs";
110
+ import { homedir } from "os";
111
+ import { join as join2 } from "path";
112
+ import { pathToFileURL } from "url";
107
113
  var userMessage = (text) => ({
108
114
  type: "user",
109
115
  message: { role: "user", content: text },
110
116
  parent_tool_use_id: null
111
117
  });
112
- var loadClaudeSdk = async () => {
113
- const specifier = "@anthropic-ai/claude-agent-sdk";
118
+ var SDK_VERSION = "0.3.207";
119
+ var SDK_PACKAGE = "@anthropic-ai/claude-agent-sdk";
120
+ var SDK_SPEC = `${SDK_PACKAGE}@${SDK_VERSION}`;
121
+ var sdkCacheDir = () => process.env.PUSHARY_REMOTE_SDK_DIR?.trim() || join2(homedir(), ".pushary", "remote-sdk");
122
+ var cachedSdkEntry = () => join2(sdkCacheDir(), "node_modules", "@anthropic-ai", "claude-agent-sdk", "sdk.mjs");
123
+ var importSdk = async (specifierOrUrl) => {
114
124
  try {
115
- const mod = await import(specifier);
125
+ const mod = await import(specifierOrUrl);
116
126
  if (typeof mod.query === "function") return mod;
117
127
  if (mod.default && typeof mod.default.query === "function") return mod.default;
118
128
  return null;
@@ -120,6 +130,44 @@ var loadClaudeSdk = async () => {
120
130
  return null;
121
131
  }
122
132
  };
133
+ var loadClaudeSdk = async () => {
134
+ const fromResolution = await importSdk(SDK_PACKAGE);
135
+ if (fromResolution) return fromResolution;
136
+ const entry = cachedSdkEntry();
137
+ if (existsSync(entry)) return importSdk(pathToFileURL(entry).href);
138
+ return null;
139
+ };
140
+ var ensureClaudeSdk = async (log) => {
141
+ const present = await loadClaudeSdk();
142
+ if (present) return present;
143
+ const dir = sdkCacheDir();
144
+ try {
145
+ mkdirSync(dir, { recursive: true });
146
+ const pkgJson = join2(dir, "package.json");
147
+ if (!existsSync(pkgJson)) {
148
+ writeFileSync(pkgJson, `${JSON.stringify({ name: "pushary-remote-sdk", private: true })}
149
+ `);
150
+ }
151
+ } catch {
152
+ return null;
153
+ }
154
+ log?.("[pushary] setting up remote mode (one-time, fetching the Claude Agent SDK)...");
155
+ const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
156
+ const installed = await new Promise((resolve) => {
157
+ const child = spawn2(
158
+ npmCmd,
159
+ ["install", "--no-optional", "--no-audit", "--no-fund", "--loglevel=error", SDK_SPEC],
160
+ { cwd: dir, stdio: "ignore", shell: process.platform === "win32" }
161
+ );
162
+ child.on("error", () => resolve(false));
163
+ child.on("close", (code) => resolve(code === 0));
164
+ });
165
+ if (!installed) {
166
+ log?.(`[pushary] could not auto-install the SDK. Install it manually: npm i -g ${SDK_SPEC}`);
167
+ return null;
168
+ }
169
+ return loadClaudeSdk();
170
+ };
123
171
 
124
172
  // src/wrapper/messageQueue.ts
125
173
  var BoundedInputQueue = class {
@@ -752,7 +800,8 @@ var runRemoteLoop = async (deps) => {
752
800
  permissionMode: deps.permissionMode,
753
801
  canUseTool: deps.canUseTool,
754
802
  env: deps.env,
755
- cwd: deps.cwd
803
+ cwd: deps.cwd,
804
+ pathToClaudeCodeExecutable: deps.pathToClaudeCodeExecutable
756
805
  }
757
806
  });
758
807
  } catch (err) {
@@ -841,6 +890,15 @@ var extractAssistantText = (message) => {
841
890
  }
842
891
  return void 0;
843
892
  };
893
+ var echoLocal = (message) => {
894
+ if (message.type === "assistant") {
895
+ const text = extractAssistantText(message);
896
+ if (text) process.stdout.write(`${text}
897
+ `);
898
+ } else if (message.type === "result") {
899
+ process.stderr.write("[pushary] turn complete \u2014 standing by for phone commands (Ctrl-C to exit)\n");
900
+ }
901
+ };
844
902
  var streamTranscript = (relay, message) => {
845
903
  if (message.type === "assistant") {
846
904
  const text = extractAssistantText(message);
@@ -853,7 +911,7 @@ var streamTranscript = (relay, message) => {
853
911
  );
854
912
  }
855
913
  };
856
- var runRemoteMode = async (_binary, args2) => {
914
+ var runRemoteMode = async (binary, args2) => {
857
915
  let apiKey;
858
916
  try {
859
917
  apiKey = getApiKey();
@@ -863,11 +921,10 @@ var runRemoteMode = async (_binary, args2) => {
863
921
  );
864
922
  return { implemented: false };
865
923
  }
866
- const sdk = await loadClaudeSdk();
924
+ const sdk = await ensureClaudeSdk((message) => process.stderr.write(`${message}
925
+ `));
867
926
  if (!sdk) {
868
- process.stderr.write(
869
- "[pushary] remote mode needs the Claude Agent SDK, which is not installed. Enable it with:\n npm i -g @anthropic-ai/claude-agent-sdk@0.3.207\nRunning the normal passthrough for now.\n"
870
- );
927
+ process.stderr.write("[pushary] remote mode is unavailable; running the normal passthrough.\n");
871
928
  return { implemented: false };
872
929
  }
873
930
  const projectName = basename(process.cwd());
@@ -876,6 +933,21 @@ var runRemoteMode = async (_binary, args2) => {
876
933
  let sessionId;
877
934
  let killed = false;
878
935
  let totalCostUsd = 0;
936
+ const agentName = `Claude Code - ${projectName}`;
937
+ const announcePresence = (event, action) => {
938
+ if (!sessionId) return Promise.resolve();
939
+ return reportEvent(
940
+ { event, agentType: "claude_code", agentName, action, sessionId, machineId },
941
+ { maxAttempts: 2, timeoutMs: 4e3 }
942
+ ).then(() => {
943
+ }).catch(() => {
944
+ });
945
+ };
946
+ const presenceTimer = setInterval(
947
+ () => void announcePresence("stop", "Standing by for phone commands"),
948
+ 5 * 6e4
949
+ );
950
+ presenceTimer.unref?.();
879
951
  const input = new BoundedInputQueue({
880
952
  cap: INPUT_QUEUE_CAP,
881
953
  onDrop: (_dropped, total) => process.stderr.write(`[pushary] input queue full; dropped ${total} stale instruction(s)
@@ -944,25 +1016,38 @@ var runRemoteMode = async (_binary, args2) => {
944
1016
  // recursion guard so a wrapper-spawned claude cannot re-enter the wrapper.
945
1017
  env: { ...process.env, [WRAPPER_ACTIVE_ENV]: "1" },
946
1018
  cwd: process.cwd(),
1019
+ // Run the user's OWN claude, not the SDK's bundled copy, so whatever login
1020
+ // already works for `claude` works here with no extra setup. On Windows a
1021
+ // `.cmd`/`.bat` shim can't be spawned directly by the SDK, so there we let
1022
+ // the SDK use its bundled binary (Windows reads creds from a plain file, so
1023
+ // there is no keychain-ACL mismatch to work around).
1024
+ pathToClaudeCodeExecutable: needsShell(binary) ? void 0 : binary,
947
1025
  onSessionId: (id) => {
948
1026
  sessionId = id;
949
1027
  relay?.reannounce();
1028
+ void announcePresence("session_start", "Remote session ready \u2014 reachable from your phone");
950
1029
  },
951
1030
  onCost: (usd) => {
952
1031
  totalCostUsd = usd;
953
1032
  },
954
- // Stream a bounded live transcript to the phone (relay presence-gates it).
955
- onMessage: relay ? (message) => streamTranscript(relay, message) : void 0,
1033
+ // Always echo the turn to the local terminal; also stream a bounded live
1034
+ // transcript to the phone when the relay is up (it presence-gates it).
1035
+ onMessage: (message) => {
1036
+ echoLocal(message);
1037
+ if (relay) streamTranscript(relay, message);
1038
+ },
956
1039
  log: (message) => process.stderr.write(`${message}
957
1040
  `)
958
1041
  });
959
1042
  return { implemented: true, exitCode: result.exitCode };
960
1043
  } finally {
961
1044
  for (const signal of signals) process.off(signal, onSignal);
1045
+ clearInterval(presenceTimer);
962
1046
  relay?.stop();
963
1047
  poller.stop();
964
1048
  approver.teardown();
965
1049
  input.close();
1050
+ await announcePresence("session_closed", "Remote session ended");
966
1051
  if (totalCostUsd > 0) {
967
1052
  process.stderr.write(`[pushary] remote session cost: $${totalCostUsd.toFixed(4)}
968
1053
  `);
@@ -6,10 +6,19 @@ import {
6
6
  import {
7
7
  CODEX_AGENT,
8
8
  DEFAULT_SESSION,
9
+ askUser,
10
+ cancelQuestion,
9
11
  codexAllow,
10
12
  codexDeny,
11
13
  codexPass,
14
+ deriveActionBody,
15
+ deriveBlocker,
16
+ deriveToolTarget,
12
17
  describeApplyPatch,
18
+ describeToolCall,
19
+ fetchModeState,
20
+ getMachineId,
21
+ getPolicy,
13
22
  handlePostToolUse,
14
23
  handleStop,
15
24
  handleUserPrompt,
@@ -17,24 +26,13 @@ import {
17
26
  preToolUseTimeoutDecision,
18
27
  readLastPrompt,
19
28
  reportEvent,
20
- savePendingQuestion,
21
- toCodexWire,
22
- toPolicyLookup
23
- } from "../chunk-NRCQ5UUR.js";
24
- import {
25
- askUser,
26
- cancelQuestion,
27
- deriveActionBody,
28
- deriveBlocker,
29
- deriveToolTarget,
30
- describeToolCall,
31
- fetchModeState,
32
- getMachineId,
33
- getPolicy,
34
29
  resolvePolicy,
30
+ savePendingQuestion,
35
31
  sendNotification,
32
+ toCodexWire,
33
+ toPolicyLookup,
36
34
  waitForAnswer
37
- } from "../chunk-ETDXSKR5.js";
35
+ } from "../chunk-VZNP4R5I.js";
38
36
  import {
39
37
  isGatingMoment,
40
38
  recordKeylessMoment
@@ -1,12 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- reportEvent
4
- } from "../chunk-NRCQ5UUR.js";
5
2
  import {
6
3
  askUser,
7
4
  getMachineId,
5
+ reportEvent,
8
6
  waitForAnswer
9
- } from "../chunk-ETDXSKR5.js";
7
+ } from "../chunk-VZNP4R5I.js";
10
8
  import "../chunk-DWED7BS3.js";
11
9
  import "../chunk-Z5PL3K7C.js";
12
10
  import {
@@ -5,15 +5,6 @@ import {
5
5
  } from "../chunk-KQYIHZ5E.js";
6
6
  import {
7
7
  DEFAULT_SESSION,
8
- handlePostToolUse,
9
- handleStop,
10
- handleUserPrompt,
11
- readLastPrompt,
12
- readLastUserPrompt,
13
- reportEvent,
14
- savePendingQuestion
15
- } from "../chunk-NRCQ5UUR.js";
16
- import {
17
8
  askUser,
18
9
  cancelQuestion,
19
10
  deriveActionBody,
@@ -23,10 +14,17 @@ import {
23
14
  fetchModeState,
24
15
  getMachineId,
25
16
  getPolicy,
17
+ handlePostToolUse,
18
+ handleStop,
19
+ handleUserPrompt,
20
+ readLastPrompt,
21
+ readLastUserPrompt,
22
+ reportEvent,
26
23
  resolvePolicy,
24
+ savePendingQuestion,
27
25
  sendNotification,
28
26
  waitForAnswer
29
- } from "../chunk-ETDXSKR5.js";
27
+ } from "../chunk-VZNP4R5I.js";
30
28
  import {
31
29
  isGatingMoment,
32
30
  recordKeylessMoment
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePreToolUse
4
- } from "../chunk-V2TSLWTV.js";
4
+ } from "../chunk-E3Q3KYZF.js";
5
5
  import "../chunk-7EW3USQF.js";
6
6
  import "../chunk-KQYIHZ5E.js";
7
- import "../chunk-NRCQ5UUR.js";
8
- import "../chunk-ETDXSKR5.js";
7
+ import "../chunk-VZNP4R5I.js";
9
8
  import "../chunk-R5AJNXZS.js";
10
9
  import "../chunk-DWED7BS3.js";
11
10
  import "../chunk-Z5PL3K7C.js";
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleNotification
4
- } from "../chunk-NRCQ5UUR.js";
5
- import "../chunk-ETDXSKR5.js";
4
+ } from "../chunk-VZNP4R5I.js";
6
5
  import "../chunk-DWED7BS3.js";
7
6
  import "../chunk-Z5PL3K7C.js";
8
7
  import "../chunk-NKXSILEW.js";
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePermissionDenied
4
- } from "../chunk-V2TSLWTV.js";
4
+ } from "../chunk-E3Q3KYZF.js";
5
5
  import "../chunk-7EW3USQF.js";
6
6
  import "../chunk-KQYIHZ5E.js";
7
- import "../chunk-NRCQ5UUR.js";
8
- import "../chunk-ETDXSKR5.js";
7
+ import "../chunk-VZNP4R5I.js";
9
8
  import "../chunk-R5AJNXZS.js";
10
9
  import "../chunk-DWED7BS3.js";
11
10
  import "../chunk-Z5PL3K7C.js";
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePermissionRequest
4
- } from "../chunk-V2TSLWTV.js";
4
+ } from "../chunk-E3Q3KYZF.js";
5
5
  import "../chunk-7EW3USQF.js";
6
6
  import "../chunk-KQYIHZ5E.js";
7
- import "../chunk-NRCQ5UUR.js";
8
- import "../chunk-ETDXSKR5.js";
7
+ import "../chunk-VZNP4R5I.js";
9
8
  import "../chunk-R5AJNXZS.js";
10
9
  import "../chunk-DWED7BS3.js";
11
10
  import "../chunk-Z5PL3K7C.js";
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePostToolUse
4
- } from "../chunk-NRCQ5UUR.js";
5
- import "../chunk-ETDXSKR5.js";
4
+ } from "../chunk-VZNP4R5I.js";
6
5
  import "../chunk-DWED7BS3.js";
7
6
  import "../chunk-Z5PL3K7C.js";
8
7
  import "../chunk-NKXSILEW.js";
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleUserPrompt
4
- } from "../chunk-NRCQ5UUR.js";
5
- import "../chunk-ETDXSKR5.js";
4
+ } from "../chunk-VZNP4R5I.js";
6
5
  import "../chunk-DWED7BS3.js";
7
6
  import "../chunk-Z5PL3K7C.js";
8
7
  import "../chunk-NKXSILEW.js";
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleSessionEnd
4
- } from "../chunk-NRCQ5UUR.js";
5
- import "../chunk-ETDXSKR5.js";
4
+ } from "../chunk-VZNP4R5I.js";
6
5
  import "../chunk-DWED7BS3.js";
7
6
  import "../chunk-Z5PL3K7C.js";
8
7
  import "../chunk-NKXSILEW.js";
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleSessionStart
4
- } from "../chunk-NRCQ5UUR.js";
5
- import "../chunk-ETDXSKR5.js";
4
+ } from "../chunk-VZNP4R5I.js";
6
5
  import "../chunk-DWED7BS3.js";
7
6
  import "../chunk-Z5PL3K7C.js";
8
7
  import "../chunk-NKXSILEW.js";
@@ -24,8 +24,7 @@ import {
24
24
  } from "../chunk-7EW3USQF.js";
25
25
  import {
26
26
  reportEvent
27
- } from "../chunk-NRCQ5UUR.js";
28
- import "../chunk-ETDXSKR5.js";
27
+ } from "../chunk-VZNP4R5I.js";
29
28
  import "../chunk-DWED7BS3.js";
30
29
  import {
31
30
  isValidApiKey
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleStop
4
- } from "../chunk-NRCQ5UUR.js";
5
- import "../chunk-ETDXSKR5.js";
4
+ } from "../chunk-VZNP4R5I.js";
6
5
  import "../chunk-DWED7BS3.js";
7
6
  import "../chunk-Z5PL3K7C.js";
8
7
  import "../chunk-NKXSILEW.js";
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleStopFailure
4
- } from "../chunk-NRCQ5UUR.js";
5
- import "../chunk-ETDXSKR5.js";
4
+ } from "../chunk-VZNP4R5I.js";
6
5
  import "../chunk-DWED7BS3.js";
7
6
  import "../chunk-Z5PL3K7C.js";
8
7
  import "../chunk-NKXSILEW.js";
@@ -48,6 +48,6 @@ Usage:
48
48
  npx @pushary/agent-hooks@latest doctor
49
49
  npx @pushary/agent-hooks@latest mode push_only --for 30m
50
50
  npx @pushary/agent-hooks@latest wait 45
51
- pushary claude --remote -p "start the refactor" # drive from your phone (needs @anthropic-ai/claude-agent-sdk)
51
+ pushary claude --remote -p "start the refactor" # drive from your phone (uses your existing Claude login; sets up on first run)
52
52
  `);
53
53
  }
@@ -7,12 +7,6 @@ import {
7
7
  } from "./chunk-KQYIHZ5E.js";
8
8
  import {
9
9
  DEFAULT_SESSION,
10
- readLastPrompt,
11
- readLastUserPrompt,
12
- savePendingQuestion,
13
- throttlePass
14
- } from "./chunk-NRCQ5UUR.js";
15
- import {
16
10
  askUser,
17
11
  cancelQuestion,
18
12
  deriveAction,
@@ -23,10 +17,14 @@ import {
23
17
  fetchModeState,
24
18
  getMachineId,
25
19
  getPolicy,
20
+ readLastPrompt,
21
+ readLastUserPrompt,
26
22
  resolvePolicy,
23
+ savePendingQuestion,
27
24
  sendNotification,
25
+ throttlePass,
28
26
  waitForAnswer
29
- } from "./chunk-ETDXSKR5.js";
27
+ } from "./chunk-VZNP4R5I.js";
30
28
  import {
31
29
  isGatingMoment,
32
30
  recordKeylessMoment