@pushary/agent-hooks 0.61.0 → 0.62.1
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 +76 -0
- package/dist/bin/pushary-claude.js +4 -4
- package/dist/bin/pushary-clean.js +82 -35
- package/dist/bin/pushary-codex-hook.js +4 -4
- package/dist/bin/pushary-codex.js +3 -3
- package/dist/bin/pushary-connect.js +7 -6
- package/dist/bin/pushary-daemon.js +37 -5
- package/dist/bin/pushary-doctor.js +114 -34
- package/dist/bin/pushary-gemini-hook.js +4 -4
- package/dist/bin/pushary-hook.js +5 -5
- package/dist/bin/pushary-login.js +5 -4
- package/dist/bin/pushary-logout.js +52 -9
- package/dist/bin/pushary-mode.js +4 -4
- package/dist/bin/pushary-notification-hook.js +2 -2
- package/dist/bin/pushary-permission-denied-hook.js +3 -3
- package/dist/bin/pushary-permission-hook.js +3 -3
- package/dist/bin/pushary-post-hook.js +2 -2
- package/dist/bin/pushary-prompt-hook.js +2 -2
- package/dist/bin/pushary-session-end-hook.js +2 -2
- package/dist/bin/pushary-session-start-hook.js +2 -2
- package/dist/bin/pushary-setup.js +97 -155
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +6 -5
- package/dist/bin/pushary-stop-hook.js +2 -2
- package/dist/bin/pushary-stopfailure-hook.js +2 -2
- package/dist/bin/pushary-suggestions.js +2 -2
- package/dist/bin/pushary-upgrade.js +189 -18
- package/dist/bin/pushary-wait.js +4 -4
- package/dist/bin/pushary.js +1 -1
- package/dist/{chunk-GX64YGU3.js → chunk-3O27ZSRE.js} +25 -0
- package/dist/{chunk-HI4AGGE6.js → chunk-5SO3CEGJ.js} +4 -4
- package/dist/chunk-6MTNS63X.js +55 -0
- package/dist/{chunk-B26DNXCA.js → chunk-COC6NPWG.js} +13 -59
- package/dist/chunk-E2U35RLD.js +108 -0
- package/dist/chunk-ER657KRJ.js +168 -0
- package/dist/{chunk-HUJQSP4F.js → chunk-IIZZYUWK.js} +1 -1
- package/dist/chunk-N7XJ4L2W.js +79 -0
- package/dist/{chunk-R6C4USIV.js → chunk-ONVEYEVR.js} +2 -2
- package/dist/{chunk-SML23YOT.js → chunk-SP7OZXCQ.js} +10 -2
- package/dist/chunk-UXXRRXUS.js +93 -0
- package/dist/{chunk-UKNAAVEE.js → chunk-YJ7YZRVV.js} +1 -1
- package/dist/src/index.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-S4TFBJ5O.js +0 -339
- package/dist/{chunk-VFBYRR2N.js → chunk-HIIBSYFJ.js} +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.62.1
|
|
4
|
+
|
|
5
|
+
### `pushary clean --dry-run` was not a dry run
|
|
6
|
+
|
|
7
|
+
In 0.62.0 the flag ran four real operations while printing "would":
|
|
8
|
+
|
|
9
|
+
- uninstalled the global `@pushary/agent-hooks` package
|
|
10
|
+
- rewrote your shell profile to remove the `claude` alias
|
|
11
|
+
- stripped the Pushary block from `~/.codex/AGENTS.md`
|
|
12
|
+
- stripped it from `~/.gemini/GEMINI.md`
|
|
13
|
+
|
|
14
|
+
If you ran `pushary clean --dry-run` on 0.62.0 and the CLI then seemed to
|
|
15
|
+
disappear, that is why. Reinstall with `npm i -g @pushary/agent-hooks`, and check
|
|
16
|
+
your shell profile and those two files against version control if you keep them
|
|
17
|
+
there.
|
|
18
|
+
|
|
19
|
+
### `pushary upgrade` could destroy `~/.claude.json`
|
|
20
|
+
|
|
21
|
+
`upgrade` treated an unparseable config as an empty one and wrote it back, so a
|
|
22
|
+
truncated `~/.claude.json` was replaced with nothing but the Pushary MCP entry,
|
|
23
|
+
losing every project, MCP server and permission rule in it. A half-written
|
|
24
|
+
`~/.claude.json` is what an interrupted write leaves behind, so this needed only
|
|
25
|
+
one earlier crash to line up.
|
|
26
|
+
|
|
27
|
+
A config that cannot be parsed is now left untouched, and the other agent files
|
|
28
|
+
are still refreshed around it.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## 0.62.0
|
|
32
|
+
|
|
33
|
+
### `pushary clean` could leave your API key on disk
|
|
34
|
+
|
|
35
|
+
If `CODEX_HOME` was set, `clean` looked for Codex's `config.toml` in `~/.codex`
|
|
36
|
+
and never found the real one. It printed `Codex config (not found)`, exited `0`,
|
|
37
|
+
and left the key in the file. A user who ran `clean` to remove their key was told
|
|
38
|
+
it had worked.
|
|
39
|
+
|
|
40
|
+
The same fault ran through the rest of the Codex path. With `CODEX_HOME` set:
|
|
41
|
+
|
|
42
|
+
- `setup` wrote the MCP server, the trust hashes and the notify entry to
|
|
43
|
+
`~/.codex/config.toml` while writing `hooks.json`, `AGENTS.md` and the skill to
|
|
44
|
+
the real `CODEX_HOME`, splitting the install across two directories
|
|
45
|
+
- `setup --dry-run` named the relocated path, so the preview and the real run
|
|
46
|
+
disagreed about where the key would land
|
|
47
|
+
- `doctor` read the relocated config and reported the key missing
|
|
48
|
+
- `logout` treated an exported-but-empty `CODEX_HOME` as a path relative to the
|
|
49
|
+
current directory
|
|
50
|
+
|
|
51
|
+
If you use `CODEX_HOME`, run `pushary clean --dry-run` to see what is still
|
|
52
|
+
there, and check `$CODEX_HOME/config.toml` for a key you thought was gone.
|
|
53
|
+
|
|
54
|
+
### New
|
|
55
|
+
|
|
56
|
+
- `pushary clean --dry-run` lists everything it would remove and changes nothing
|
|
57
|
+
- `pushary doctor --bundle` writes a redacted diagnostics file for a support
|
|
58
|
+
thread. Keys, your home directory and the machine name are stripped.
|
|
59
|
+
- `pushary logout --revoke` kills the key server-side as well as locally, so it
|
|
60
|
+
stops working everywhere rather than only on this machine
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
|
|
64
|
+
- `pushary upgrade` now refreshes Codex, Gemini CLI and Cursor, not only Claude
|
|
65
|
+
Code, and names the agents it actually touched. It matters most for Codex,
|
|
66
|
+
whose hooks are trusted by hash: a refreshed hook command without a refreshed
|
|
67
|
+
trust entry is a hook Codex silently declines to run.
|
|
68
|
+
- `pushary upgrade` with no global install now names the install modes it can
|
|
69
|
+
see and the command that updates each, instead of one generic line and exit 0
|
|
70
|
+
- `pushary daemon` stops on a rejected key or a closed plan and exits `4`
|
|
71
|
+
(`UNAUTHENTICATED`). It used to treat that like a network blip, back off to a
|
|
72
|
+
two-minute poll and sit there under an `online` banner, so a revoked key left a
|
|
73
|
+
daemon that looked healthy and would never launch anything again.
|
|
74
|
+
- Ctrl-C during app pairing now cancels the pairing on the server, so a QR still
|
|
75
|
+
on your screen stops being claimable immediately instead of staying live for
|
|
76
|
+
the rest of its five minutes
|
|
77
|
+
- `setup` prints the command surface when it finishes
|
|
78
|
+
|
|
3
79
|
## 0.61.0
|
|
4
80
|
|
|
5
81
|
The largest release since the CLI shipped. Setup no longer asks you to paste an
|
|
@@ -17,14 +17,14 @@ import {
|
|
|
17
17
|
reportEvent,
|
|
18
18
|
resolvePolicy,
|
|
19
19
|
waitForAnswer
|
|
20
|
-
} from "../chunk-
|
|
21
|
-
import {
|
|
22
|
-
getMachineId
|
|
23
|
-
} from "../chunk-RN3NOEJF.js";
|
|
20
|
+
} from "../chunk-HIIBSYFJ.js";
|
|
24
21
|
import "../chunk-HNTKTK5B.js";
|
|
25
22
|
import {
|
|
26
23
|
redactSecrets
|
|
27
24
|
} from "../chunk-DQAN3JQP.js";
|
|
25
|
+
import {
|
|
26
|
+
getMachineId
|
|
27
|
+
} from "../chunk-RN3NOEJF.js";
|
|
28
28
|
import {
|
|
29
29
|
getApiKey,
|
|
30
30
|
getBaseUrl
|
|
@@ -4,10 +4,18 @@ import {
|
|
|
4
4
|
removePusharySettings
|
|
5
5
|
} from "../chunk-CAJZAFVS.js";
|
|
6
6
|
import {
|
|
7
|
-
removeCodexHooks,
|
|
8
|
-
removeGeminiSettings,
|
|
9
7
|
removeInstructionBlock
|
|
10
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-N7XJ4L2W.js";
|
|
9
|
+
import {
|
|
10
|
+
removeGeminiSettings
|
|
11
|
+
} from "../chunk-E2U35RLD.js";
|
|
12
|
+
import {
|
|
13
|
+
codexAgentsMd,
|
|
14
|
+
codexConfigToml,
|
|
15
|
+
codexHooksJson,
|
|
16
|
+
codexSkillDir,
|
|
17
|
+
removeCodexHooks
|
|
18
|
+
} from "../chunk-ER657KRJ.js";
|
|
11
19
|
import {
|
|
12
20
|
removeClaudeAlias
|
|
13
21
|
} from "../chunk-BC3VCZ3E.js";
|
|
@@ -16,8 +24,8 @@ import {
|
|
|
16
24
|
} from "../chunk-MUEW424A.js";
|
|
17
25
|
import {
|
|
18
26
|
exitOnHelpFlag
|
|
19
|
-
} from "../chunk-
|
|
20
|
-
import "../chunk-
|
|
27
|
+
} from "../chunk-IIZZYUWK.js";
|
|
28
|
+
import "../chunk-SP7OZXCQ.js";
|
|
21
29
|
import "../chunk-DQAN3JQP.js";
|
|
22
30
|
|
|
23
31
|
// bin/pushary-clean.ts
|
|
@@ -66,8 +74,38 @@ var readJson = (path) => {
|
|
|
66
74
|
return null;
|
|
67
75
|
}
|
|
68
76
|
};
|
|
77
|
+
var dryRun = false;
|
|
78
|
+
var did = (past) => dryRun ? `(would ${past === "cleaned" ? "clean" : past === "removed" ? "remove" : past === "uninstalled" ? "uninstall" : past})` : `(${past})`;
|
|
79
|
+
var wouldNote = (action, path) => {
|
|
80
|
+
console.log(` ${dim("would")} ${action} ${path}`);
|
|
81
|
+
};
|
|
82
|
+
var guardedWrite = (path, contents) => {
|
|
83
|
+
if (dryRun) return wouldNote("rewrite", path);
|
|
84
|
+
writeFileSync(path, contents, "utf-8");
|
|
85
|
+
};
|
|
86
|
+
var guardedRemove = (path, options = {}) => {
|
|
87
|
+
if (dryRun) return wouldNote("remove ", path);
|
|
88
|
+
rmSync(path, { recursive: true, force: options.force });
|
|
89
|
+
};
|
|
90
|
+
var guardedExec = (command, options, describe) => {
|
|
91
|
+
if (dryRun) return wouldNote("run ", describe);
|
|
92
|
+
execSync(command, options);
|
|
93
|
+
};
|
|
94
|
+
var guardedInstructionBlockRemoval = (path) => {
|
|
95
|
+
if (!dryRun) return removeInstructionBlock(path);
|
|
96
|
+
if (!existsSync(path)) return false;
|
|
97
|
+
const hasBlock = readFileSync(path, "utf-8").includes("pushary");
|
|
98
|
+
if (hasBlock) wouldNote("rewrite", path);
|
|
99
|
+
return hasBlock;
|
|
100
|
+
};
|
|
101
|
+
var guardedAliasRemoval = () => {
|
|
102
|
+
if (!dryRun) return removeClaudeAlias();
|
|
103
|
+
const shells = [".zshrc", ".bashrc", ".bash_profile", ".profile"].map((name) => join(homedir(), name)).filter((path) => existsSync(path) && readFileSync(path, "utf-8").includes("pushary claude"));
|
|
104
|
+
for (const path of shells) wouldNote("rewrite", path);
|
|
105
|
+
return shells;
|
|
106
|
+
};
|
|
69
107
|
var writeJson = (path, data) => {
|
|
70
|
-
|
|
108
|
+
guardedWrite(path, JSON.stringify(data, null, 2) + "\n");
|
|
71
109
|
};
|
|
72
110
|
var cleanSettingsFile = (path, label) => {
|
|
73
111
|
const data = readJson(path);
|
|
@@ -78,7 +116,7 @@ var cleanSettingsFile = (path, label) => {
|
|
|
78
116
|
const changed = removePusharySettings(data);
|
|
79
117
|
if (changed) {
|
|
80
118
|
writeJson(path, data);
|
|
81
|
-
console.log(` ${check} ${label} ${dim("
|
|
119
|
+
console.log(` ${check} ${label} ${dim(did("cleaned"))}`);
|
|
82
120
|
} else {
|
|
83
121
|
console.log(` ${skip} ${label} ${dim("(no pushary entries)")}`);
|
|
84
122
|
}
|
|
@@ -88,7 +126,12 @@ var main = async () => {
|
|
|
88
126
|
console.log(` ${bold("Pushary Clean")}`);
|
|
89
127
|
console.log(` ${dim("Removes all Pushary configuration")}`);
|
|
90
128
|
console.log();
|
|
91
|
-
|
|
129
|
+
dryRun = process.argv.includes("--dry-run");
|
|
130
|
+
if (dryRun) {
|
|
131
|
+
console.log(` ${bold("Dry run")} ${dim("- nothing will be changed")}`);
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
const assumeYes = dryRun || process.argv.includes("--yes") || process.argv.includes("-y");
|
|
92
135
|
if (!assumeYes && !process.stdin.isTTY) {
|
|
93
136
|
console.log(` ${yellow("!")} Non-interactive shell. Re-run with --yes to confirm removal.`);
|
|
94
137
|
process.exit(1);
|
|
@@ -118,7 +161,7 @@ var main = async () => {
|
|
|
118
161
|
if (mcpServers?.pushary) {
|
|
119
162
|
delete mcpServers.pushary;
|
|
120
163
|
writeJson(CURSOR_MCP, cursorData);
|
|
121
|
-
console.log(` ${check} Cursor MCP config ${dim("
|
|
164
|
+
console.log(` ${check} Cursor MCP config ${dim(did("cleaned"))}`);
|
|
122
165
|
} else {
|
|
123
166
|
console.log(` ${skip} Cursor MCP config ${dim("(no pushary entries)")}`);
|
|
124
167
|
}
|
|
@@ -126,7 +169,7 @@ var main = async () => {
|
|
|
126
169
|
console.log(` ${skip} Cursor MCP config ${dim("(not found)")}`);
|
|
127
170
|
}
|
|
128
171
|
if (existsSync(CURSOR_PLUGIN_DIR)) {
|
|
129
|
-
|
|
172
|
+
guardedRemove(CURSOR_PLUGIN_DIR);
|
|
130
173
|
console.log(` ${check} Cursor plugin ${dim("(removed from ~/.cursor/plugins/local)")}`);
|
|
131
174
|
} else {
|
|
132
175
|
console.log(` ${skip} Cursor plugin ${dim("(not installed)")}`);
|
|
@@ -149,12 +192,12 @@ var main = async () => {
|
|
|
149
192
|
console.log(` ${skip} Cursor gate ${dim("(no hooks.json)")}`);
|
|
150
193
|
}
|
|
151
194
|
if (existsSync(SKILL_DIR)) {
|
|
152
|
-
|
|
153
|
-
console.log(` ${check} Skill directory ${dim("
|
|
195
|
+
guardedRemove(SKILL_DIR);
|
|
196
|
+
console.log(` ${check} Skill directory ${dim(did("removed"))}`);
|
|
154
197
|
} else {
|
|
155
198
|
console.log(` ${skip} Skill directory ${dim("(not found)")}`);
|
|
156
199
|
}
|
|
157
|
-
const codexConfig =
|
|
200
|
+
const codexConfig = codexConfigToml();
|
|
158
201
|
try {
|
|
159
202
|
const config = readFileSync(codexConfig, "utf-8");
|
|
160
203
|
const hadPushary = config.includes("pushary");
|
|
@@ -168,19 +211,19 @@ var main = async () => {
|
|
|
168
211
|
parsed.notify = parsed.notify.filter((n) => typeof n !== "string" || !n.includes("pushary-codex"));
|
|
169
212
|
if (parsed.notify.length === 0) delete parsed.notify;
|
|
170
213
|
}
|
|
171
|
-
|
|
172
|
-
console.log(` ${check} Codex config ${dim("
|
|
214
|
+
guardedWrite(codexConfig, stringifyTOML(parsed));
|
|
215
|
+
console.log(` ${check} Codex config ${dim(did("cleaned"))}`);
|
|
173
216
|
} else {
|
|
174
217
|
console.log(` ${skip} Codex config ${dim("(no pushary entries)")}`);
|
|
175
218
|
}
|
|
176
219
|
} catch {
|
|
177
220
|
console.log(` ${skip} Codex config ${dim("(not found)")}`);
|
|
178
221
|
}
|
|
179
|
-
const
|
|
180
|
-
const codexHooksData = readJson(
|
|
222
|
+
const codexHooksJson2 = codexHooksJson();
|
|
223
|
+
const codexHooksData = readJson(codexHooksJson2);
|
|
181
224
|
if (codexHooksData) {
|
|
182
225
|
if (removeCodexHooks(codexHooksData)) {
|
|
183
|
-
writeJson(
|
|
226
|
+
writeJson(codexHooksJson2, codexHooksData);
|
|
184
227
|
console.log(` ${check} Codex hooks ${dim("(removed from ~/.codex/hooks.json)")}`);
|
|
185
228
|
} else {
|
|
186
229
|
console.log(` ${skip} Codex hooks ${dim("(no pushary entries)")}`);
|
|
@@ -188,16 +231,16 @@ var main = async () => {
|
|
|
188
231
|
} else {
|
|
189
232
|
console.log(` ${skip} Codex hooks ${dim("(not found)")}`);
|
|
190
233
|
}
|
|
191
|
-
const
|
|
192
|
-
if (
|
|
234
|
+
const codexAgentsMd2 = codexAgentsMd();
|
|
235
|
+
if (guardedInstructionBlockRemoval(codexAgentsMd2)) {
|
|
193
236
|
console.log(` ${check} Codex AGENTS.md ${dim("(removed Pushary block)")}`);
|
|
194
237
|
} else {
|
|
195
238
|
console.log(` ${skip} Codex AGENTS.md ${dim("(no pushary block)")}`);
|
|
196
239
|
}
|
|
197
|
-
const
|
|
198
|
-
if (existsSync(
|
|
199
|
-
|
|
200
|
-
console.log(` ${check} Codex skill directory ${dim("
|
|
240
|
+
const codexSkillDir2 = codexSkillDir();
|
|
241
|
+
if (existsSync(codexSkillDir2)) {
|
|
242
|
+
guardedRemove(codexSkillDir2);
|
|
243
|
+
console.log(` ${check} Codex skill directory ${dim(did("removed"))}`);
|
|
201
244
|
} else {
|
|
202
245
|
console.log(` ${skip} Codex skill directory ${dim("(not found)")}`);
|
|
203
246
|
}
|
|
@@ -206,7 +249,7 @@ var main = async () => {
|
|
|
206
249
|
if (geminiSettings) {
|
|
207
250
|
if (removeGeminiSettings(geminiSettings)) {
|
|
208
251
|
writeJson(geminiSettingsPath, geminiSettings);
|
|
209
|
-
console.log(` ${check} Gemini CLI settings ${dim("
|
|
252
|
+
console.log(` ${check} Gemini CLI settings ${dim(did("cleaned"))}`);
|
|
210
253
|
} else {
|
|
211
254
|
console.log(` ${skip} Gemini CLI settings ${dim("(no pushary entries)")}`);
|
|
212
255
|
}
|
|
@@ -214,7 +257,7 @@ var main = async () => {
|
|
|
214
257
|
console.log(` ${skip} Gemini CLI settings ${dim("(not found)")}`);
|
|
215
258
|
}
|
|
216
259
|
const geminiMd = join(homedir(), ".gemini", "GEMINI.md");
|
|
217
|
-
if (
|
|
260
|
+
if (guardedInstructionBlockRemoval(geminiMd)) {
|
|
218
261
|
console.log(` ${check} Gemini GEMINI.md ${dim("(removed Pushary block)")}`);
|
|
219
262
|
} else {
|
|
220
263
|
console.log(` ${skip} Gemini GEMINI.md ${dim("(no pushary block)")}`);
|
|
@@ -223,13 +266,13 @@ var main = async () => {
|
|
|
223
266
|
if (hermesPython) {
|
|
224
267
|
const snippet = 'from hermes_cli.config import load_config, save_config; c = load_config(); p = c.get("plugins") if isinstance(c.get("plugins"), dict) else {}; e = p.get("enabled") if isinstance(p.get("enabled"), list) else []; p["enabled"] = [x for x in e if x != "pushary"]; c["plugins"] = p; a = c.get("agent") if isinstance(c.get("agent"), dict) else {}; d = a.get("disabled_toolsets") if isinstance(a.get("disabled_toolsets"), list) else []; a["disabled_toolsets"] = [x for x in d if x != "clarify"]; c["agent"] = a; save_config(c)';
|
|
225
268
|
try {
|
|
226
|
-
|
|
269
|
+
guardedExec(`"${hermesPython}" -c '${snippet}'`, { stdio: "pipe", timeout: 15e3 }, "hermes plugin config update");
|
|
227
270
|
console.log(` ${check} Hermes config ${dim("(plugin disabled, clarify toolset restored)")}`);
|
|
228
271
|
} catch {
|
|
229
272
|
console.log(` ${skip} Hermes config ${dim("(could not update config.yaml)")}`);
|
|
230
273
|
}
|
|
231
274
|
try {
|
|
232
|
-
|
|
275
|
+
guardedExec(`"${hermesPython}" -m pip uninstall -y hermes-plugin-pushary`, { stdio: "pipe", timeout: 6e4 }, "pip uninstall hermes-plugin-pushary");
|
|
233
276
|
console.log(` ${check} Hermes plugin ${dim("(pip uninstalled)")}`);
|
|
234
277
|
} catch {
|
|
235
278
|
console.log(` ${skip} Hermes plugin ${dim("(not installed)")}`);
|
|
@@ -247,8 +290,8 @@ var main = async () => {
|
|
|
247
290
|
const cleaned = lines.filter((l) => !isOurExport(l)).join("\n");
|
|
248
291
|
if (cleaned !== content) {
|
|
249
292
|
const backup = `${shellFile}.pushary-backup-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`;
|
|
250
|
-
copyFileSync(shellFile, backup);
|
|
251
|
-
|
|
293
|
+
if (!dryRun) copyFileSync(shellFile, backup);
|
|
294
|
+
guardedWrite(shellFile, cleaned);
|
|
252
295
|
console.log(` ${check} ${shellFile.split("/").pop()} ${dim(`(removed the export, backup at ${backup})`)}`);
|
|
253
296
|
}
|
|
254
297
|
for (const line of declined) {
|
|
@@ -258,14 +301,14 @@ var main = async () => {
|
|
|
258
301
|
} catch {
|
|
259
302
|
}
|
|
260
303
|
}
|
|
261
|
-
const aliasRemovedFrom =
|
|
304
|
+
const aliasRemovedFrom = guardedAliasRemoval();
|
|
262
305
|
if (aliasRemovedFrom.length > 0) {
|
|
263
306
|
console.log(` ${check} claude alias ${dim(`(removed from ${aliasRemovedFrom.map((p) => p.split("/").pop()).join(", ")})`)}`);
|
|
264
307
|
} else {
|
|
265
308
|
console.log(` ${skip} claude alias ${dim("(not set)")}`);
|
|
266
309
|
}
|
|
267
310
|
if (existsSync(PUSHARY_DIR)) {
|
|
268
|
-
|
|
311
|
+
guardedRemove(PUSHARY_DIR);
|
|
269
312
|
console.log(` ${check} Local state ${dim("(~/.pushary removed: stored API key, ledger)")}`);
|
|
270
313
|
} else {
|
|
271
314
|
console.log(` ${skip} Local state ${dim("(~/.pushary not found)")}`);
|
|
@@ -275,7 +318,7 @@ var main = async () => {
|
|
|
275
318
|
for (const f of readdirSync(tmpdir())) {
|
|
276
319
|
if (!f.startsWith("pushary-")) continue;
|
|
277
320
|
try {
|
|
278
|
-
|
|
321
|
+
guardedRemove(join(tmpdir(), f), { force: true });
|
|
279
322
|
swept++;
|
|
280
323
|
} catch {
|
|
281
324
|
}
|
|
@@ -284,8 +327,12 @@ var main = async () => {
|
|
|
284
327
|
} catch {
|
|
285
328
|
}
|
|
286
329
|
try {
|
|
287
|
-
|
|
288
|
-
|
|
330
|
+
if (dryRun) {
|
|
331
|
+
wouldNote("run ", "npm uninstall -g @pushary/agent-hooks");
|
|
332
|
+
} else {
|
|
333
|
+
execNpm("uninstall -g --no-workspaces @pushary/agent-hooks", { stdio: "ignore", timeout: 3e4 });
|
|
334
|
+
}
|
|
335
|
+
console.log(` ${check} Global package ${dim(did("uninstalled"))}`);
|
|
289
336
|
} catch {
|
|
290
337
|
console.log(` ${skip} Global package ${dim("(not installed)")}`);
|
|
291
338
|
}
|
|
@@ -31,10 +31,7 @@ import {
|
|
|
31
31
|
toCodexWire,
|
|
32
32
|
toPolicyLookup,
|
|
33
33
|
waitForAnswer
|
|
34
|
-
} from "../chunk-
|
|
35
|
-
import {
|
|
36
|
-
getMachineId
|
|
37
|
-
} from "../chunk-RN3NOEJF.js";
|
|
34
|
+
} from "../chunk-HIIBSYFJ.js";
|
|
38
35
|
import {
|
|
39
36
|
isGatingMoment,
|
|
40
37
|
recordKeylessMoment
|
|
@@ -46,6 +43,9 @@ import {
|
|
|
46
43
|
hookWaitClamped,
|
|
47
44
|
hookWaitDeadline
|
|
48
45
|
} from "../chunk-DQAN3JQP.js";
|
|
46
|
+
import {
|
|
47
|
+
getMachineId
|
|
48
|
+
} from "../chunk-RN3NOEJF.js";
|
|
49
49
|
import {
|
|
50
50
|
getApiKey
|
|
51
51
|
} from "../chunk-2UMNXADU.js";
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
askUser,
|
|
4
4
|
reportEvent,
|
|
5
5
|
waitForAnswer
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-HIIBSYFJ.js";
|
|
7
|
+
import "../chunk-HNTKTK5B.js";
|
|
8
|
+
import "../chunk-DQAN3JQP.js";
|
|
7
9
|
import {
|
|
8
10
|
getMachineId
|
|
9
11
|
} from "../chunk-RN3NOEJF.js";
|
|
10
|
-
import "../chunk-HNTKTK5B.js";
|
|
11
|
-
import "../chunk-DQAN3JQP.js";
|
|
12
12
|
import {
|
|
13
13
|
getApiKey
|
|
14
14
|
} from "../chunk-2UMNXADU.js";
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
printKeyCheck
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-ONVEYEVR.js";
|
|
5
5
|
import {
|
|
6
6
|
confirmAppConnection,
|
|
7
7
|
connectDevice,
|
|
8
8
|
printConnectInstructions
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-3O27ZSRE.js";
|
|
10
10
|
import "../chunk-3EGEA4KH.js";
|
|
11
11
|
import {
|
|
12
12
|
parseFlags
|
|
13
13
|
} from "../chunk-N4DA4CJB.js";
|
|
14
14
|
import {
|
|
15
15
|
readKeySource
|
|
16
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-COC6NPWG.js";
|
|
17
|
+
import "../chunk-6MTNS63X.js";
|
|
17
18
|
import {
|
|
18
19
|
checkApiKey
|
|
19
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-YJ7YZRVV.js";
|
|
20
21
|
import {
|
|
21
22
|
createIo
|
|
22
23
|
} from "../chunk-TX7KBKT7.js";
|
|
@@ -26,10 +27,10 @@ import {
|
|
|
26
27
|
import "../chunk-BC3VCZ3E.js";
|
|
27
28
|
import {
|
|
28
29
|
exitOnHelpFlag
|
|
29
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-IIZZYUWK.js";
|
|
30
31
|
import {
|
|
31
32
|
EXIT
|
|
32
|
-
} from "../chunk-
|
|
33
|
+
} from "../chunk-SP7OZXCQ.js";
|
|
33
34
|
import "../chunk-HNTKTK5B.js";
|
|
34
35
|
import "../chunk-DQAN3JQP.js";
|
|
35
36
|
import "../chunk-2UMNXADU.js";
|
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
} from "../chunk-MUEW424A.js";
|
|
8
8
|
import {
|
|
9
9
|
exitOnHelpFlag
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import
|
|
10
|
+
} from "../chunk-IIZZYUWK.js";
|
|
11
|
+
import {
|
|
12
|
+
EXIT
|
|
13
|
+
} from "../chunk-SP7OZXCQ.js";
|
|
12
14
|
import {
|
|
13
15
|
getMachineId
|
|
14
16
|
} from "../chunk-RN3NOEJF.js";
|
|
@@ -30,6 +32,19 @@ var MAX_ERROR_STREAK = 6;
|
|
|
30
32
|
var REQUEST_TIMEOUT_MS = 1e4;
|
|
31
33
|
var MAX_SPAWNS_PER_WINDOW = 5;
|
|
32
34
|
var SPAWN_WINDOW_MS = 6e4;
|
|
35
|
+
var DrainError = class extends Error {
|
|
36
|
+
constructor(status) {
|
|
37
|
+
super(`drain ${status}`);
|
|
38
|
+
this.status = status;
|
|
39
|
+
this.name = "DrainError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var isAuthFailure = (err) => {
|
|
43
|
+
if (typeof err !== "object" || err === null) return false;
|
|
44
|
+
const candidate = err;
|
|
45
|
+
if (candidate.name !== "DrainError") return false;
|
|
46
|
+
return candidate.status === 401 || candidate.status === 403;
|
|
47
|
+
};
|
|
33
48
|
var NATIVE_AGENT_BINARIES = { codex: "codex", gemini: "gemini" };
|
|
34
49
|
var buildSpawnLaunch = (req, opts) => {
|
|
35
50
|
const agent = req.agent === "codex" || req.agent === "gemini" ? req.agent : "claude";
|
|
@@ -68,6 +83,9 @@ var runSpawnDaemon = async () => {
|
|
|
68
83
|
const spawnTimestamps = [];
|
|
69
84
|
let timer;
|
|
70
85
|
let inflight;
|
|
86
|
+
let fatalCode = null;
|
|
87
|
+
let finish = () => {
|
|
88
|
+
};
|
|
71
89
|
const launch = (req) => {
|
|
72
90
|
spawnTimestamps.push(Date.now());
|
|
73
91
|
const cwd = req.cwd && existsSync(req.cwd) ? req.cwd : process.cwd();
|
|
@@ -98,7 +116,7 @@ var runSpawnDaemon = async () => {
|
|
|
98
116
|
body: JSON.stringify({ machineId }),
|
|
99
117
|
signal
|
|
100
118
|
});
|
|
101
|
-
if (!res.ok) throw new
|
|
119
|
+
if (!res.ok) throw new DrainError(res.status);
|
|
102
120
|
const data = await res.json();
|
|
103
121
|
const spawn2 = data.spawn;
|
|
104
122
|
return spawn2 && typeof spawn2.prompt === "string" && typeof spawn2.id === "string" ? spawn2 : null;
|
|
@@ -126,7 +144,16 @@ var runSpawnDaemon = async () => {
|
|
|
126
144
|
} else {
|
|
127
145
|
idleTicks++;
|
|
128
146
|
}
|
|
129
|
-
} catch {
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (isAuthFailure(err)) {
|
|
149
|
+
const status = err.status;
|
|
150
|
+
fatalCode = EXIT.UNAUTHENTICATED;
|
|
151
|
+
stderr(
|
|
152
|
+
status === 401 ? "[pushary] daemon stopping: this machine's key was rejected. Run `pushary login` to sign in again.\n" : "[pushary] daemon stopping: this workspace has no active plan, so the queue is closed. Pick one at pushary.com/dashboard/settings?tab=billing\n"
|
|
153
|
+
);
|
|
154
|
+
finish();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
130
157
|
errorStreak = Math.min(errorStreak + 1, MAX_ERROR_STREAK);
|
|
131
158
|
} finally {
|
|
132
159
|
clearTimeout(timeout);
|
|
@@ -152,8 +179,13 @@ var runSpawnDaemon = async () => {
|
|
|
152
179
|
resolve();
|
|
153
180
|
};
|
|
154
181
|
for (const signal of signals) process.on(signal, onSignal);
|
|
182
|
+
finish = () => {
|
|
183
|
+
teardown();
|
|
184
|
+
for (const signal of signals) process.off(signal, onSignal);
|
|
185
|
+
resolve();
|
|
186
|
+
};
|
|
155
187
|
});
|
|
156
|
-
return 0;
|
|
188
|
+
return fatalCode ?? 0;
|
|
157
189
|
};
|
|
158
190
|
|
|
159
191
|
// bin/pushary-daemon.ts
|