@pushary/agent-hooks 0.64.2 → 0.64.4

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.64.4
4
+
5
+ ### The shell you ran setup in still exported the key it replaced
6
+
7
+ 0.64.3 stopped a stale export from hiding the working key on disk, and the rc
8
+ file has been rewritten in place since 0.62. Neither reaches the shell you are
9
+ standing in: the export there is still the old key, the environment wins over the
10
+ config file at hook time, and the agent you start in that terminal a minute later
11
+ talks to whichever workspace that key belongs to.
12
+
13
+ `--connect app` mints on every run and is the command onboarding prints, so this
14
+ is the ordinary case rather than an exotic one. Setup now says so under "Still to
15
+ do": open a new terminal, or re-export. No key is printed in that line.
16
+
17
+ ## 0.64.3
18
+
19
+ ### A stale shell export hid the working key on disk
20
+
21
+ `PUSHARY_API_KEY` wins over `~/.pushary/config.json`, which is right and
22
+ unchanged. But the environment used to win on the key's *shape* alone, so a
23
+ well-formed key the server had since revoked shadowed a working one in the config
24
+ file and setup exited "This key was rejected by pushary.com" with a perfectly
25
+ good key sitting on the machine.
26
+
27
+ That is the state any shell left open across a key rotation is in: the export is
28
+ the old key, the file is the new one, and the terminal you happen to be typing in
29
+ decides whether setup works.
30
+
31
+ The environment key is checked with the server before it is chosen now, and a
32
+ rejected one falls through to the stored key rather than ending the run. It costs
33
+ no extra call: the verdict is handed to the verification step that was already
34
+ making it.
35
+
36
+ ### `--connect app` on a machine with no terminal named the wrong problem
37
+
38
+ A headless run that asked to pair said "No API key, and no terminal to sign in
39
+ from" even with a key in the config file, because asking to pair deliberately
40
+ takes the stored key off the table. It now says the flag needs a terminal for the
41
+ QR, and that dropping it uses the key already there.
42
+
3
43
  ## 0.64.2
4
44
 
5
45
  ### A run that gave up reported nothing, and said it stopped at the start
@@ -1180,7 +1180,10 @@ var main = async () => {
1180
1180
  let keyFromPairing = false;
1181
1181
  const storedKey = readConfigFileKey();
1182
1182
  const pairingRequested = connectMode === "app" && options.connectExplicit && !options.skipPhone;
1183
- const storedCheck = !(flagKey && isValidApiKey(flagKey)) && !pairingRequested && !(envKey && isValidApiKey(envKey)) && storedKey !== null && isValidApiKey(storedKey) ? await usableStoredKey(storedKey) : null;
1183
+ const ambientEligible = !(flagKey && isValidApiKey(flagKey)) && !pairingRequested;
1184
+ const envCheck = ambientEligible && envKey && isValidApiKey(envKey) ? await usableStoredKey(envKey) : null;
1185
+ const storedCheck = ambientEligible && envCheck === null && storedKey !== null && isValidApiKey(storedKey) && // login writes both, so without this the same key is probed twice.
1186
+ storedKey !== envKey ? await usableStoredKey(storedKey) : null;
1184
1187
  let storedKeyCheck = null;
1185
1188
  if (flagKey && isValidApiKey(flagKey)) {
1186
1189
  const masked = `${flagKey.slice(0, 8)}...${flagKey.slice(-4)}`;
@@ -1194,13 +1197,14 @@ var main = async () => {
1194
1197
  console.log();
1195
1198
  trimmedKey = storedKey;
1196
1199
  storedKeyCheck = storedCheck;
1197
- } else if (!pairingRequested && envKey && isValidApiKey(envKey)) {
1200
+ } else if (envKey && envCheck !== null) {
1198
1201
  const masked = `${envKey.slice(0, 8)}...${envKey.slice(-4)}`;
1199
1202
  console.log(` ${check} Found API key in environment: ${dim(masked)}`);
1200
1203
  console.log();
1201
1204
  const useExisting = options.nonInteractive ? true : await confirm({ message: "Use this key?", default: true });
1202
1205
  if (useExisting) {
1203
1206
  trimmedKey = envKey;
1207
+ storedKeyCheck = envCheck;
1204
1208
  } else {
1205
1209
  const apiKey = await input({ message: "API key:" });
1206
1210
  trimmedKey = apiKey.trim();
@@ -1231,9 +1235,14 @@ var main = async () => {
1231
1235
  }
1232
1236
  console.log();
1233
1237
  } else if (!canRunBrowserLogin()) {
1234
- console.log(` ${yellow("!")} No API key, and no terminal to sign in from.`);
1235
- console.log(` ${dim("Pass --key <pk_xxx.xxx>, or --key-stdin, or export PUSHARY_API_KEY.")}`);
1236
- console.log(` ${dim("On a machine with a terminal, run")} ${cyan("pushary login")} ${dim("once and re-run this.")}`);
1238
+ if (pairingRequested) {
1239
+ console.log(` ${yellow("!")} ${cyan("--connect app")} needs a terminal to show the pairing QR in.`);
1240
+ console.log(` ${dim("Drop the flag to use the key this machine already has, or pass --key <pk_xxx.xxx>.")}`);
1241
+ } else {
1242
+ console.log(` ${yellow("!")} No API key, and no terminal to sign in from.`);
1243
+ console.log(` ${dim("Pass --key <pk_xxx.xxx>, or --key-stdin, or export PUSHARY_API_KEY.")}`);
1244
+ console.log(` ${dim("On a machine with a terminal, run")} ${cyan("pushary login")} ${dim("once and re-run this.")}`);
1245
+ }
1237
1246
  console.log();
1238
1247
  process.exit(await abortWith("no-key", EXIT.NOT_CONFIGURED));
1239
1248
  } else {
@@ -1287,6 +1296,11 @@ var main = async () => {
1287
1296
  markStep("save-key");
1288
1297
  const rc = await saveApiKey(trimmedKey);
1289
1298
  const context = { rc };
1299
+ if (envKey && envKey !== trimmedKey) {
1300
+ noteManual(
1301
+ `This shell still exports the previous key (${keyPrefix(envKey)}), and it wins over the one just saved. Open a new terminal before starting an agent here, or re-export PUSHARY_API_KEY.`
1302
+ );
1303
+ }
1290
1304
  const failed = [];
1291
1305
  const completed = [];
1292
1306
  const skipped = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushary/agent-hooks",
3
- "version": "0.64.2",
3
+ "version": "0.64.4",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "keywords": [
6
6
  "pushary",