@pushary/agent-hooks 0.62.5 → 0.63.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.
- package/CHANGELOG.md +53 -0
- package/dist/bin/pushary-clean.js +32 -22
- package/dist/bin/pushary-connect.js +2 -2
- package/dist/bin/pushary-daemon.js +19 -2
- package/dist/bin/pushary-doctor.js +31 -24
- package/dist/bin/pushary-hook.js +2 -2
- package/dist/bin/pushary-login.js +2 -2
- package/dist/bin/pushary-logout.js +10 -9
- package/dist/bin/pushary-mode.js +2 -2
- package/dist/bin/pushary-setup.js +27 -17
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +37 -6
- package/dist/bin/pushary-suggestions.js +2 -2
- package/dist/bin/pushary-upgrade.js +14 -11
- package/dist/bin/pushary-wait.js +2 -2
- package/dist/bin/pushary.js +1 -1
- package/dist/{chunk-UXXRRXUS.js → chunk-6G2BC4ET.js} +1 -1
- package/dist/{chunk-KVUBLB6K.js → chunk-PPTC2QDB.js} +4 -1
- package/dist/chunk-R22IAMSS.js +86 -0
- package/dist/{chunk-ER657KRJ.js → chunk-RU3CIBXY.js} +31 -1
- package/dist/{chunk-674M3JQF.js → chunk-VYD27DKZ.js} +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.63.0
|
|
4
|
+
|
|
5
|
+
### Machines
|
|
6
|
+
|
|
7
|
+
`pushary daemon` now reports itself to your workspace once a minute, and
|
|
8
|
+
`pushary status --devices` lists what is there:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Machines
|
|
12
|
+
● macbook-pro 0.63.0 just now
|
|
13
|
+
○ build-server 0.62.6 4h ago
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`online` is worked out from the last heartbeat rather than stored, so a laptop
|
|
17
|
+
that closes mid-session reads offline a few minutes later without anything
|
|
18
|
+
having to notice it left.
|
|
19
|
+
|
|
20
|
+
This is what lets a phone start a session on a machine you name, instead of on
|
|
21
|
+
whichever one happens to answer first.
|
|
22
|
+
|
|
23
|
+
Presence is best effort throughout. A heartbeat that fails never stops the daemon
|
|
24
|
+
draining its queue, and `status` still reports your key and channels if the
|
|
25
|
+
machine list cannot be read. Against a server that predates the endpoint,
|
|
26
|
+
`--devices` says so rather than reporting an empty list.
|
|
27
|
+
|
|
28
|
+
**Needs a database migration** (`0066`). Until it is applied, `--devices` reports
|
|
29
|
+
that it could not read the list, and nothing else is affected.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## 0.62.6
|
|
33
|
+
|
|
34
|
+
### `clean` rewrote your project's Cursor config and left your own alone
|
|
35
|
+
|
|
36
|
+
`clean` built the Cursor MCP path without a home directory, so it resolved
|
|
37
|
+
against whatever directory you ran it from. Inside a repo that has a
|
|
38
|
+
`.cursor/mcp.json`, it rewrote that committed file, stripping the Pushary entry
|
|
39
|
+
and reformatting the rest. Meanwhile your real `~/.cursor/mcp.json` was never
|
|
40
|
+
touched, so the API key stayed in it.
|
|
41
|
+
|
|
42
|
+
Check `git status` in any project you ran `clean` from, and check
|
|
43
|
+
`~/.cursor/mcp.json` for a key you thought was gone.
|
|
44
|
+
|
|
45
|
+
### Every file the CLI touches is now named in one place
|
|
46
|
+
|
|
47
|
+
`setup`, `clean`, `doctor`, `logout` and `upgrade` each derived the same paths by
|
|
48
|
+
hand, and they drifted. That drift caused this bug and the `CODEX_HOME` one
|
|
49
|
+
before it. All twenty-three call sites now resolve through one module, and a test
|
|
50
|
+
fails any command that starts spelling a path out again.
|
|
51
|
+
|
|
52
|
+
No behaviour changed anywhere else: setup's output is byte-identical across every
|
|
53
|
+
mode before and after.
|
|
54
|
+
|
|
55
|
+
|
|
3
56
|
## 0.62.5
|
|
4
57
|
|
|
5
58
|
### `clean --dry-run` changed things again
|
|
@@ -10,12 +10,22 @@ import {
|
|
|
10
10
|
removeGeminiSettings
|
|
11
11
|
} from "../chunk-E2U35RLD.js";
|
|
12
12
|
import {
|
|
13
|
+
claudeJson,
|
|
14
|
+
claudeSettings,
|
|
15
|
+
claudeSettingsLocal,
|
|
16
|
+
claudeSkillDir,
|
|
13
17
|
codexAgentsMd,
|
|
14
18
|
codexConfigToml,
|
|
15
19
|
codexHooksJson,
|
|
16
20
|
codexSkillDir,
|
|
21
|
+
cursorPluginDir,
|
|
22
|
+
cursorUserHooks,
|
|
23
|
+
cursorUserMcp,
|
|
24
|
+
geminiMd,
|
|
25
|
+
geminiSettings,
|
|
26
|
+
pusharyDir,
|
|
17
27
|
removeCodexHooks
|
|
18
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-RU3CIBXY.js";
|
|
19
29
|
import {
|
|
20
30
|
removeClaudeAlias
|
|
21
31
|
} from "../chunk-BC3VCZ3E.js";
|
|
@@ -24,8 +34,8 @@ import {
|
|
|
24
34
|
} from "../chunk-MUEW424A.js";
|
|
25
35
|
import {
|
|
26
36
|
exitOnHelpFlag
|
|
27
|
-
} from "../chunk-
|
|
28
|
-
import "../chunk-
|
|
37
|
+
} from "../chunk-VYD27DKZ.js";
|
|
38
|
+
import "../chunk-PPTC2QDB.js";
|
|
29
39
|
import "../chunk-DQAN3JQP.js";
|
|
30
40
|
import "../chunk-KZERVKTD.js";
|
|
31
41
|
|
|
@@ -63,14 +73,14 @@ var green = (s) => `\x1B[32m${s}\x1B[0m`;
|
|
|
63
73
|
var yellow = (s) => `\x1B[33m${s}\x1B[0m`;
|
|
64
74
|
var check = green("\u2713");
|
|
65
75
|
var skip = yellow("\u2013");
|
|
66
|
-
var CLAUDE_SETTINGS =
|
|
67
|
-
var CLAUDE_SETTINGS_LOCAL =
|
|
68
|
-
var CLAUDE_JSON =
|
|
69
|
-
var SKILL_DIR =
|
|
70
|
-
var CURSOR_MCP =
|
|
71
|
-
var CURSOR_PLUGIN_DIR =
|
|
72
|
-
var CURSOR_USER_HOOKS =
|
|
73
|
-
var PUSHARY_DIR =
|
|
76
|
+
var CLAUDE_SETTINGS = claudeSettings();
|
|
77
|
+
var CLAUDE_SETTINGS_LOCAL = claudeSettingsLocal();
|
|
78
|
+
var CLAUDE_JSON = claudeJson();
|
|
79
|
+
var SKILL_DIR = claudeSkillDir();
|
|
80
|
+
var CURSOR_MCP = cursorUserMcp();
|
|
81
|
+
var CURSOR_PLUGIN_DIR = cursorPluginDir();
|
|
82
|
+
var CURSOR_USER_HOOKS = cursorUserHooks();
|
|
83
|
+
var PUSHARY_DIR = pusharyDir();
|
|
74
84
|
var SHELL_FILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"].map((f) => join(homedir(), f));
|
|
75
85
|
var resolveHermesPython = () => {
|
|
76
86
|
try {
|
|
@@ -157,10 +167,10 @@ var main = async () => {
|
|
|
157
167
|
console.log();
|
|
158
168
|
cleanSettingsFile(CLAUDE_SETTINGS, "Claude Code settings");
|
|
159
169
|
cleanSettingsFile(CLAUDE_SETTINGS_LOCAL, "Claude Code settings.local");
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
162
|
-
if (removeClaudeMcpServers(
|
|
163
|
-
writeJson(CLAUDE_JSON,
|
|
170
|
+
const claudeJson2 = readJson(CLAUDE_JSON);
|
|
171
|
+
if (claudeJson2) {
|
|
172
|
+
if (removeClaudeMcpServers(claudeJson2)) {
|
|
173
|
+
writeJson(CLAUDE_JSON, claudeJson2);
|
|
164
174
|
console.log(` ${check} Claude Code MCP servers ${dim("(removed from ~/.claude.json)")}`);
|
|
165
175
|
} else {
|
|
166
176
|
console.log(` ${skip} Claude Code MCP servers ${dim("(no pushary entries)")}`);
|
|
@@ -257,11 +267,11 @@ var main = async () => {
|
|
|
257
267
|
} else {
|
|
258
268
|
console.log(` ${skip} Codex skill directory ${dim("(not found)")}`);
|
|
259
269
|
}
|
|
260
|
-
const geminiSettingsPath =
|
|
261
|
-
const
|
|
262
|
-
if (
|
|
263
|
-
if (removeGeminiSettings(
|
|
264
|
-
writeJson(geminiSettingsPath,
|
|
270
|
+
const geminiSettingsPath = geminiSettings();
|
|
271
|
+
const geminiSettings2 = readJson(geminiSettingsPath);
|
|
272
|
+
if (geminiSettings2) {
|
|
273
|
+
if (removeGeminiSettings(geminiSettings2)) {
|
|
274
|
+
writeJson(geminiSettingsPath, geminiSettings2);
|
|
265
275
|
console.log(` ${check} Gemini CLI settings ${dim(did("cleaned"))}`);
|
|
266
276
|
} else {
|
|
267
277
|
console.log(` ${skip} Gemini CLI settings ${dim("(no pushary entries)")}`);
|
|
@@ -269,8 +279,8 @@ var main = async () => {
|
|
|
269
279
|
} else {
|
|
270
280
|
console.log(` ${skip} Gemini CLI settings ${dim("(not found)")}`);
|
|
271
281
|
}
|
|
272
|
-
const
|
|
273
|
-
if (guardedInstructionBlockRemoval(
|
|
282
|
+
const geminiMd2 = geminiMd();
|
|
283
|
+
if (guardedInstructionBlockRemoval(geminiMd2)) {
|
|
274
284
|
console.log(` ${check} Gemini GEMINI.md ${dim("(removed Pushary block)")}`);
|
|
275
285
|
} else {
|
|
276
286
|
console.log(` ${skip} Gemini GEMINI.md ${dim("(no pushary block)")}`);
|
|
@@ -24,8 +24,8 @@ import {
|
|
|
24
24
|
import "../chunk-BC3VCZ3E.js";
|
|
25
25
|
import {
|
|
26
26
|
exitOnHelpFlag
|
|
27
|
-
} from "../chunk-
|
|
28
|
-
import "../chunk-
|
|
27
|
+
} from "../chunk-VYD27DKZ.js";
|
|
28
|
+
import "../chunk-PPTC2QDB.js";
|
|
29
29
|
import "../chunk-BSZYIAZL.js";
|
|
30
30
|
import "../chunk-SAF6HGAA.js";
|
|
31
31
|
import {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
HEARTBEAT_INTERVAL_MS,
|
|
4
|
+
sendHeartbeat
|
|
5
|
+
} from "../chunk-R22IAMSS.js";
|
|
2
6
|
import {
|
|
3
7
|
spawnClaude
|
|
4
8
|
} from "../chunk-XHKBHWLX.js";
|
|
@@ -7,8 +11,8 @@ import {
|
|
|
7
11
|
} from "../chunk-MUEW424A.js";
|
|
8
12
|
import {
|
|
9
13
|
exitOnHelpFlag
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import "../chunk-
|
|
14
|
+
} from "../chunk-VYD27DKZ.js";
|
|
15
|
+
import "../chunk-PPTC2QDB.js";
|
|
12
16
|
import {
|
|
13
17
|
getMachineId
|
|
14
18
|
} from "../chunk-RN3NOEJF.js";
|
|
@@ -87,6 +91,7 @@ var runSpawnDaemon = async () => {
|
|
|
87
91
|
let fatalCode = null;
|
|
88
92
|
let finish = () => {
|
|
89
93
|
};
|
|
94
|
+
let heartbeat;
|
|
90
95
|
const launch = (req) => {
|
|
91
96
|
spawnTimestamps.push(Date.now());
|
|
92
97
|
const cwd = req.cwd && existsSync(req.cwd) ? req.cwd : process.cwd();
|
|
@@ -166,8 +171,20 @@ var runSpawnDaemon = async () => {
|
|
|
166
171
|
if (stopped) return;
|
|
167
172
|
stopped = true;
|
|
168
173
|
if (timer) clearTimeout(timer);
|
|
174
|
+
if (heartbeat) clearInterval(heartbeat);
|
|
169
175
|
inflight?.abort();
|
|
170
176
|
};
|
|
177
|
+
const beat = async () => {
|
|
178
|
+
if (stopped) return;
|
|
179
|
+
const result = await sendHeartbeat(apiKey, { repoKey: basename(process.cwd()) });
|
|
180
|
+
if (result.kind === "unauthorized" && !stopped) {
|
|
181
|
+
fatalCode = EXIT.UNAUTHENTICATED;
|
|
182
|
+
stderr("[pushary] daemon stopping: this machine's key was rejected. Run `pushary login` to sign in again.\n");
|
|
183
|
+
finish();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
void beat();
|
|
187
|
+
heartbeat = setInterval(() => void beat(), HEARTBEAT_INTERVAL_MS);
|
|
171
188
|
stderr(
|
|
172
189
|
`[pushary] daemon online \u2014 this machine (${machineId}) can now be sent a new session from your phone. Ctrl-C to stop.
|
|
173
190
|
`
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "../chunk-IIENZE2J.js";
|
|
5
5
|
import {
|
|
6
6
|
detectAllAgents
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-6G2BC4ET.js";
|
|
8
8
|
import {
|
|
9
9
|
hasInstructionBlock
|
|
10
10
|
} from "../chunk-N7XJ4L2W.js";
|
|
@@ -14,15 +14,22 @@ import {
|
|
|
14
14
|
missingGeminiHookEvents
|
|
15
15
|
} from "../chunk-E2U35RLD.js";
|
|
16
16
|
import {
|
|
17
|
+
claudeJson,
|
|
18
|
+
claudeSettings,
|
|
19
|
+
claudeSkillDir,
|
|
17
20
|
codexAgentsMd,
|
|
18
21
|
codexConfigToml,
|
|
19
22
|
codexHooksJson,
|
|
20
23
|
codexSkillDir,
|
|
24
|
+
cursorPluginDir,
|
|
25
|
+
cursorUserHooks,
|
|
26
|
+
geminiMd,
|
|
27
|
+
geminiSettings,
|
|
21
28
|
hasCodexHooks,
|
|
22
29
|
missingCodexHookEvents,
|
|
23
30
|
readCodexMcpAuth,
|
|
24
31
|
untrustedCodexHookEvents
|
|
25
|
-
} from "../chunk-
|
|
32
|
+
} from "../chunk-RU3CIBXY.js";
|
|
26
33
|
import {
|
|
27
34
|
describeReach,
|
|
28
35
|
fetchChannels,
|
|
@@ -50,10 +57,10 @@ import {
|
|
|
50
57
|
} from "../chunk-MUEW424A.js";
|
|
51
58
|
import {
|
|
52
59
|
exitOnHelpFlag
|
|
53
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-VYD27DKZ.js";
|
|
54
61
|
import {
|
|
55
62
|
getPackageVersion
|
|
56
|
-
} from "../chunk-
|
|
63
|
+
} from "../chunk-PPTC2QDB.js";
|
|
57
64
|
import {
|
|
58
65
|
readLedgerSummary
|
|
59
66
|
} from "../chunk-WLGEY4UX.js";
|
|
@@ -159,8 +166,8 @@ var { bold, dim, green, yellow, red, cyan } = createIo();
|
|
|
159
166
|
var pass = green("\u2713");
|
|
160
167
|
var fail = red("\u2717");
|
|
161
168
|
var warn = yellow("!");
|
|
162
|
-
var CLAUDE_SETTINGS =
|
|
163
|
-
var SKILL_PATH = join(
|
|
169
|
+
var CLAUDE_SETTINGS = claudeSettings();
|
|
170
|
+
var SKILL_PATH = join(claudeSkillDir(), "SKILL.md");
|
|
164
171
|
var SHELL_FILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"].map((f) => join(homedir2(), f));
|
|
165
172
|
var readJson = (path) => {
|
|
166
173
|
try {
|
|
@@ -277,9 +284,9 @@ var main = async () => {
|
|
|
277
284
|
break;
|
|
278
285
|
}
|
|
279
286
|
}
|
|
280
|
-
const CLAUDE_JSON =
|
|
281
|
-
const
|
|
282
|
-
const mcpServers =
|
|
287
|
+
const CLAUDE_JSON = claudeJson();
|
|
288
|
+
const claudeJson2 = readJson(CLAUDE_JSON);
|
|
289
|
+
const mcpServers = claudeJson2?.mcpServers ?? {};
|
|
283
290
|
const pusharyServer = mcpServers?.pushary;
|
|
284
291
|
check(!!pusharyServer, "Claude Code: MCP server configured");
|
|
285
292
|
if (pusharyServer) {
|
|
@@ -393,10 +400,10 @@ var main = async () => {
|
|
|
393
400
|
const hasCodexInstructions = hasInstructionBlock(codexAgentsMd2);
|
|
394
401
|
check(hasCodexInstructions, "Codex: proactive instructions (AGENTS.md)", hasCodexInstructions ? codexAgentsMd2 : "missing \u2014 re-run setup so Codex asks via push, not the terminal");
|
|
395
402
|
}
|
|
396
|
-
const geminiSettingsPath =
|
|
397
|
-
const
|
|
398
|
-
if (
|
|
399
|
-
const geminiServers =
|
|
403
|
+
const geminiSettingsPath = geminiSettings();
|
|
404
|
+
const geminiSettings2 = readJson(geminiSettingsPath);
|
|
405
|
+
if (geminiSettings2) {
|
|
406
|
+
const geminiServers = geminiSettings2.mcpServers ?? {};
|
|
400
407
|
const geminiPushary = geminiServers.pushary;
|
|
401
408
|
check(!!geminiPushary, "Gemini CLI: MCP server configured");
|
|
402
409
|
if (geminiPushary) {
|
|
@@ -413,11 +420,11 @@ var main = async () => {
|
|
|
413
420
|
}
|
|
414
421
|
}
|
|
415
422
|
}
|
|
416
|
-
const geminiHooksInstalled = hasGeminiHooks(
|
|
423
|
+
const geminiHooksInstalled = hasGeminiHooks(geminiSettings2);
|
|
417
424
|
if (geminiHooksInstalled) {
|
|
418
|
-
const missingEvents = missingGeminiHookEvents(
|
|
425
|
+
const missingEvents = missingGeminiHookEvents(geminiSettings2);
|
|
419
426
|
check(missingEvents.length === 0, "Gemini CLI: native hooks installed", missingEvents.length === 0 ? "all 5 events" : `missing ${missingEvents.join(", ")}, re-run setup`);
|
|
420
|
-
const geminiHooks =
|
|
427
|
+
const geminiHooks = geminiSettings2.hooks;
|
|
421
428
|
const hookCommand = extractHookCommand(geminiHooks?.BeforeTool, GEMINI_HOOK_BINARY) ?? extractHookCommand(geminiHooks?.AfterTool, GEMINI_HOOK_BINARY) ?? extractHookCommand(geminiHooks?.SessionStart, GEMINI_HOOK_BINARY);
|
|
422
429
|
if (hookCommand) {
|
|
423
430
|
const resolves = commandResolves(hookCommand);
|
|
@@ -431,14 +438,14 @@ var main = async () => {
|
|
|
431
438
|
} else {
|
|
432
439
|
check(false, "Gemini CLI: native hooks installed", "no Pushary hooks in ~/.gemini/settings.json \u2014 re-run setup");
|
|
433
440
|
}
|
|
434
|
-
const
|
|
435
|
-
const hasGeminiInstructions = hasInstructionBlock(
|
|
436
|
-
check(hasGeminiInstructions, "Gemini CLI: proactive instructions (GEMINI.md)", hasGeminiInstructions ?
|
|
441
|
+
const geminiMd2 = geminiMd();
|
|
442
|
+
const hasGeminiInstructions = hasInstructionBlock(geminiMd2);
|
|
443
|
+
check(hasGeminiInstructions, "Gemini CLI: proactive instructions (GEMINI.md)", hasGeminiInstructions ? geminiMd2 : "missing \u2014 re-run setup so Gemini asks via push, not the terminal");
|
|
437
444
|
}
|
|
438
|
-
const
|
|
439
|
-
if (existsSync(
|
|
440
|
-
const
|
|
441
|
-
const userHooks = readJson(
|
|
445
|
+
const cursorPluginDir2 = cursorPluginDir();
|
|
446
|
+
if (existsSync(cursorPluginDir2)) {
|
|
447
|
+
const cursorUserHooks2 = cursorUserHooks();
|
|
448
|
+
const userHooks = readJson(cursorUserHooks2);
|
|
442
449
|
const gateEntry = userHooks.hooks?.beforeShellExecution?.find(
|
|
443
450
|
(h) => String(h.command ?? "").includes("pushary-gate")
|
|
444
451
|
);
|
|
@@ -449,7 +456,7 @@ var main = async () => {
|
|
|
449
456
|
const resolves = scriptPath ? existsSync(scriptPath) : false;
|
|
450
457
|
check(resolves, "Cursor: permission gate registered", resolves ? `~/.cursor/hooks.json \u2192 ${scriptPath}` : `gate script not found: ${scriptPath || gateEntry.command} \u2014 re-run setup`);
|
|
451
458
|
}
|
|
452
|
-
const cursorMcp = readJson(join(
|
|
459
|
+
const cursorMcp = readJson(join(cursorPluginDir2, "mcp.json"));
|
|
453
460
|
const cursorServers = cursorMcp?.mcpServers ?? {};
|
|
454
461
|
const cursorAuth = cursorServers.pushary?.headers?.Authorization;
|
|
455
462
|
if (!cursorAuth) {
|
package/dist/bin/pushary-hook.js
CHANGED
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
import "../chunk-CAJZAFVS.js";
|
|
6
6
|
import {
|
|
7
7
|
exitOnHelpFlag
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-VYD27DKZ.js";
|
|
9
|
+
import "../chunk-PPTC2QDB.js";
|
|
10
10
|
import "../chunk-YHG74UFF.js";
|
|
11
11
|
import "../chunk-5ZDYDU2Q.js";
|
|
12
12
|
import "../chunk-WLGEY4UX.js";
|
|
@@ -21,10 +21,10 @@ import {
|
|
|
21
21
|
import "../chunk-BC3VCZ3E.js";
|
|
22
22
|
import {
|
|
23
23
|
exitOnHelpFlag
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-VYD27DKZ.js";
|
|
25
25
|
import {
|
|
26
26
|
getPackageVersion
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-PPTC2QDB.js";
|
|
28
28
|
import "../chunk-SAF6HGAA.js";
|
|
29
29
|
import {
|
|
30
30
|
UsageError
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
claudeJson,
|
|
4
|
+
codexConfigToml,
|
|
5
|
+
cursorUserMcp,
|
|
6
|
+
geminiSettings
|
|
7
|
+
} from "../chunk-RU3CIBXY.js";
|
|
5
8
|
import {
|
|
6
9
|
clearKey,
|
|
7
10
|
readKeySource
|
|
@@ -16,8 +19,8 @@ import {
|
|
|
16
19
|
import "../chunk-BC3VCZ3E.js";
|
|
17
20
|
import {
|
|
18
21
|
exitOnHelpFlag
|
|
19
|
-
} from "../chunk-
|
|
20
|
-
import "../chunk-
|
|
22
|
+
} from "../chunk-VYD27DKZ.js";
|
|
23
|
+
import "../chunk-PPTC2QDB.js";
|
|
21
24
|
import {
|
|
22
25
|
UsageError
|
|
23
26
|
} from "../chunk-7QLSKOSU.js";
|
|
@@ -31,8 +34,6 @@ import {
|
|
|
31
34
|
|
|
32
35
|
// bin/pushary-logout.ts
|
|
33
36
|
import { existsSync } from "fs";
|
|
34
|
-
import { homedir } from "os";
|
|
35
|
-
import { join } from "path";
|
|
36
37
|
exitOnHelpFlag("logout");
|
|
37
38
|
var parseLogoutOptions = (argv) => {
|
|
38
39
|
const flags = parseFlags(argv, { bools: ["json", "revoke", "help", "h"], values: [] });
|
|
@@ -54,10 +55,10 @@ var say = options.json ? (line) => process.stderr.write(`${line}
|
|
|
54
55
|
`) : (line) => process.stdout.write(`${line}
|
|
55
56
|
`);
|
|
56
57
|
var AGENT_CONFIGS = [
|
|
57
|
-
{ label: "Claude Code", path:
|
|
58
|
+
{ label: "Claude Code", path: claudeJson() },
|
|
58
59
|
{ label: "Codex", path: codexConfigToml() },
|
|
59
|
-
{ label: "Gemini CLI", path:
|
|
60
|
-
{ label: "Cursor", path:
|
|
60
|
+
{ label: "Gemini CLI", path: geminiSettings() },
|
|
61
|
+
{ label: "Cursor", path: cursorUserMcp() }
|
|
61
62
|
];
|
|
62
63
|
var revokeRemotely = async (apiKey) => {
|
|
63
64
|
try {
|
package/dist/bin/pushary-mode.js
CHANGED
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
} from "../chunk-GMXKITVA.js";
|
|
12
12
|
import {
|
|
13
13
|
exitOnHelpFlag
|
|
14
|
-
} from "../chunk-
|
|
15
|
-
import "../chunk-
|
|
14
|
+
} from "../chunk-VYD27DKZ.js";
|
|
15
|
+
import "../chunk-PPTC2QDB.js";
|
|
16
16
|
import "../chunk-SAF6HGAA.js";
|
|
17
17
|
import {
|
|
18
18
|
UsageError
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
describeDetection,
|
|
12
12
|
detectAllAgents,
|
|
13
13
|
isDetected
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-6G2BC4ET.js";
|
|
15
15
|
import {
|
|
16
16
|
renderAgentInstructions,
|
|
17
17
|
renderProjectAgentInstructions,
|
|
@@ -26,9 +26,19 @@ import {
|
|
|
26
26
|
addCodexHookTrust,
|
|
27
27
|
addCodexHooks,
|
|
28
28
|
addCodexMcpServer,
|
|
29
|
+
claudeJson,
|
|
30
|
+
claudeSettings,
|
|
31
|
+
claudeSkillDir,
|
|
32
|
+
codexAgentsMd2 as codexAgentsMd,
|
|
29
33
|
codexConfigToml,
|
|
30
|
-
codexHome
|
|
31
|
-
|
|
34
|
+
codexHome,
|
|
35
|
+
codexSkillDir2 as codexSkillDir,
|
|
36
|
+
cursorPluginDir,
|
|
37
|
+
cursorUserHooks,
|
|
38
|
+
geminiMd,
|
|
39
|
+
geminiSettings,
|
|
40
|
+
pusharyConfigFile
|
|
41
|
+
} from "../chunk-RU3CIBXY.js";
|
|
32
42
|
import {
|
|
33
43
|
confirmAppConnection,
|
|
34
44
|
connectDevice,
|
|
@@ -72,7 +82,7 @@ import {
|
|
|
72
82
|
getPackageVersion,
|
|
73
83
|
isNewerVersion,
|
|
74
84
|
renderCommandHelp
|
|
75
|
-
} from "../chunk-
|
|
85
|
+
} from "../chunk-PPTC2QDB.js";
|
|
76
86
|
import {
|
|
77
87
|
reportEvent
|
|
78
88
|
} from "../chunk-5ZDYDU2Q.js";
|
|
@@ -259,17 +269,17 @@ var parseSetupOptions = (input2) => {
|
|
|
259
269
|
};
|
|
260
270
|
|
|
261
271
|
// bin/pushary-setup.ts
|
|
262
|
-
var CLAUDE_SETTINGS =
|
|
263
|
-
var CLAUDE_JSON =
|
|
264
|
-
var CURSOR_PLUGIN_DIR =
|
|
265
|
-
var CURSOR_USER_HOOKS =
|
|
266
|
-
var CLAUDE_SKILL_DIR =
|
|
272
|
+
var CLAUDE_SETTINGS = claudeSettings();
|
|
273
|
+
var CLAUDE_JSON = claudeJson();
|
|
274
|
+
var CURSOR_PLUGIN_DIR = cursorPluginDir();
|
|
275
|
+
var CURSOR_USER_HOOKS = cursorUserHooks();
|
|
276
|
+
var CLAUDE_SKILL_DIR = claudeSkillDir();
|
|
267
277
|
var CODEX_HOME = codexHome();
|
|
268
|
-
var CODEX_SKILL_DIR =
|
|
269
|
-
var CODEX_AGENTS_MD =
|
|
270
|
-
var GEMINI_SETTINGS =
|
|
271
|
-
var GEMINI_MD =
|
|
272
|
-
var PUSHARY_CONFIG_FILE =
|
|
278
|
+
var CODEX_SKILL_DIR = codexSkillDir();
|
|
279
|
+
var CODEX_AGENTS_MD = codexAgentsMd();
|
|
280
|
+
var GEMINI_SETTINGS = geminiSettings();
|
|
281
|
+
var GEMINI_MD = geminiMd();
|
|
282
|
+
var PUSHARY_CONFIG_FILE = pusharyConfigFile();
|
|
273
283
|
var manualSteps = [];
|
|
274
284
|
var noteManual = (step) => {
|
|
275
285
|
manualSteps.push(step);
|
|
@@ -433,10 +443,10 @@ var setupClaudeCode = async (apiKey) => {
|
|
|
433
443
|
${bold("Setting up Claude Code")}
|
|
434
444
|
`);
|
|
435
445
|
await installGlobally2();
|
|
436
|
-
const
|
|
446
|
+
const claudeJson2 = readAgentJson(CLAUDE_JSON);
|
|
437
447
|
const settings = readAgentJson(CLAUDE_SETTINGS);
|
|
438
448
|
await spinner("Adding MCP server (type: http)", async () => {
|
|
439
|
-
addClaudeMcpServer(
|
|
449
|
+
addClaudeMcpServer(claudeJson2, apiKey);
|
|
440
450
|
});
|
|
441
451
|
await spinner("Auto-allowing Pushary tools", async () => {
|
|
442
452
|
addPusharyToolPermissions(settings);
|
|
@@ -445,7 +455,7 @@ var setupClaudeCode = async (apiKey) => {
|
|
|
445
455
|
addPusharyHooks(settings, resolveGlobalBinDir("pushary-hook"));
|
|
446
456
|
});
|
|
447
457
|
await spinner(`Writing ${CLAUDE_JSON}`, async () => {
|
|
448
|
-
writeJsonAtomic(CLAUDE_JSON,
|
|
458
|
+
writeJsonAtomic(CLAUDE_JSON, claudeJson2, 384);
|
|
449
459
|
});
|
|
450
460
|
await spinner(`Writing ${CLAUDE_SETTINGS}`, async () => {
|
|
451
461
|
writeJsonAtomic(CLAUDE_SETTINGS, settings);
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
describeLastSeen,
|
|
4
|
+
listMachines
|
|
5
|
+
} from "../chunk-R22IAMSS.js";
|
|
2
6
|
import {
|
|
3
7
|
describeReach,
|
|
4
8
|
fetchChannels,
|
|
@@ -22,14 +26,15 @@ import {
|
|
|
22
26
|
import "../chunk-BC3VCZ3E.js";
|
|
23
27
|
import {
|
|
24
28
|
exitOnHelpFlag
|
|
25
|
-
} from "../chunk-
|
|
26
|
-
import "../chunk-
|
|
29
|
+
} from "../chunk-VYD27DKZ.js";
|
|
30
|
+
import "../chunk-PPTC2QDB.js";
|
|
27
31
|
import "../chunk-BSZYIAZL.js";
|
|
28
32
|
import "../chunk-SAF6HGAA.js";
|
|
29
33
|
import {
|
|
30
34
|
UsageError
|
|
31
35
|
} from "../chunk-7QLSKOSU.js";
|
|
32
36
|
import "../chunk-DQAN3JQP.js";
|
|
37
|
+
import "../chunk-RN3NOEJF.js";
|
|
33
38
|
import "../chunk-2UMNXADU.js";
|
|
34
39
|
import {
|
|
35
40
|
EXIT
|
|
@@ -57,10 +62,10 @@ var reachLine = (channels) => {
|
|
|
57
62
|
var siteLine = (channels) => {
|
|
58
63
|
const site = channels.site;
|
|
59
64
|
if (site === null || site.otherMembers === 0) return null;
|
|
60
|
-
const
|
|
65
|
+
const devices2 = site.appDevices + site.webActive;
|
|
61
66
|
return {
|
|
62
67
|
label: "Team",
|
|
63
|
-
value: `${
|
|
68
|
+
value: `${devices2} device${devices2 === 1 ? "" : "s"} across ${site.otherMembers + 1} members`,
|
|
64
69
|
ok: null
|
|
65
70
|
};
|
|
66
71
|
};
|
|
@@ -178,8 +183,9 @@ var statusJson = (facts, report) => ({
|
|
|
178
183
|
exitOnHelpFlag("status");
|
|
179
184
|
var { bold, dim, green, red, yellow } = createIo();
|
|
180
185
|
var args = process.argv.slice(2);
|
|
181
|
-
rejectUnknownFlags(args.filter((a) => a !== "status"), ["--json"]);
|
|
186
|
+
rejectUnknownFlags(args.filter((a) => a !== "status"), ["--json", "--devices"]);
|
|
182
187
|
var json = args.includes("--json");
|
|
188
|
+
var devices = args.includes("--devices");
|
|
183
189
|
var main = async () => {
|
|
184
190
|
const source = readKeySource();
|
|
185
191
|
let keyCheck = null;
|
|
@@ -188,10 +194,16 @@ var main = async () => {
|
|
|
188
194
|
keyCheck = await checkApiKey(source.key);
|
|
189
195
|
if (keyCheck.kind === "ok") channels = await fetchChannels(source.key);
|
|
190
196
|
}
|
|
197
|
+
const machines = devices && keyCheck?.kind === "ok" ? await listMachines(source.key) : null;
|
|
191
198
|
const facts = { source, keyCheck, channels };
|
|
192
199
|
const report = buildStatusReport(facts);
|
|
193
200
|
if (json) {
|
|
194
|
-
|
|
201
|
+
const payload = statusJson(facts, report);
|
|
202
|
+
if (machines) {
|
|
203
|
+
payload.machines = machines.kind === "ok" ? machines.machines : [];
|
|
204
|
+
if (machines.kind !== "ok") payload.machinesUnavailable = machines.kind;
|
|
205
|
+
}
|
|
206
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}
|
|
195
207
|
`);
|
|
196
208
|
process.exit(report.exitCode);
|
|
197
209
|
}
|
|
@@ -203,6 +215,25 @@ var main = async () => {
|
|
|
203
215
|
const icon = line.ok === true ? green("\u2713") : line.ok === false ? red("\u2717") : dim("\xB7");
|
|
204
216
|
console.log(` ${icon} ${line.label.padEnd(width)}${line.value}`);
|
|
205
217
|
}
|
|
218
|
+
if (machines) {
|
|
219
|
+
console.log();
|
|
220
|
+
console.log(` ${bold("Machines")}`);
|
|
221
|
+
if (machines.kind === "unsupported") {
|
|
222
|
+
console.log(` ${dim("This server does not report machines yet.")}`);
|
|
223
|
+
} else if (machines.kind === "failed") {
|
|
224
|
+
console.log(` ${dim(`Could not read the machine list (${machines.detail}).`)}`);
|
|
225
|
+
} else if (machines.machines.length === 0) {
|
|
226
|
+
console.log(` ${dim("None registered. Run")} pushary daemon ${dim("to keep a machine reachable.")}`);
|
|
227
|
+
} else {
|
|
228
|
+
const hostWidth = Math.max(...machines.machines.map((m) => m.hostname.length)) + 2;
|
|
229
|
+
for (const machine of machines.machines) {
|
|
230
|
+
const mark = machine.online ? green("\u25CF") : dim("\u25CB");
|
|
231
|
+
console.log(
|
|
232
|
+
` ${mark} ${machine.hostname.padEnd(hostWidth)}${dim(`${machine.cliVersion} ${describeLastSeen(machine.lastSeenAt)}`)}`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
206
237
|
console.log();
|
|
207
238
|
console.log(` ${report.exitCode === 0 ? green(bold(report.headline)) : yellow(bold(report.headline))}`);
|
|
208
239
|
for (const next of report.next) console.log(` ${dim(next)}`);
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
} from "../chunk-GMXKITVA.js";
|
|
8
8
|
import {
|
|
9
9
|
exitOnHelpFlag
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import "../chunk-
|
|
10
|
+
} from "../chunk-VYD27DKZ.js";
|
|
11
|
+
import "../chunk-PPTC2QDB.js";
|
|
12
12
|
import {
|
|
13
13
|
UsageError
|
|
14
14
|
} from "../chunk-7QLSKOSU.js";
|
|
@@ -15,10 +15,13 @@ import {
|
|
|
15
15
|
addCodexHookTrust,
|
|
16
16
|
addCodexHooks,
|
|
17
17
|
addCodexMcpServer,
|
|
18
|
+
claudeJson,
|
|
18
19
|
codexConfigToml,
|
|
19
20
|
codexHooksJson,
|
|
21
|
+
cursorPluginDir,
|
|
22
|
+
geminiSettings,
|
|
20
23
|
hasCodexHooks
|
|
21
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-RU3CIBXY.js";
|
|
22
25
|
import {
|
|
23
26
|
readJsonSafe
|
|
24
27
|
} from "../chunk-6MTNS63X.js";
|
|
@@ -31,10 +34,10 @@ import {
|
|
|
31
34
|
} from "../chunk-MUEW424A.js";
|
|
32
35
|
import {
|
|
33
36
|
exitOnHelpFlag
|
|
34
|
-
} from "../chunk-
|
|
37
|
+
} from "../chunk-VYD27DKZ.js";
|
|
35
38
|
import {
|
|
36
39
|
isNewerVersion
|
|
37
|
-
} from "../chunk-
|
|
40
|
+
} from "../chunk-PPTC2QDB.js";
|
|
38
41
|
import "../chunk-DQAN3JQP.js";
|
|
39
42
|
import {
|
|
40
43
|
getApiKey
|
|
@@ -65,16 +68,16 @@ var writeJson = (filePath, data) => {
|
|
|
65
68
|
writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
66
69
|
};
|
|
67
70
|
var hasPusharyClaudeHooks = (settings) => JSON.stringify(settings.hooks ?? {}).includes("pushary-hook");
|
|
68
|
-
var hasPusharyMcp = (
|
|
71
|
+
var hasPusharyMcp = (claudeJson2) => !!claudeJson2.mcpServers?.pushary;
|
|
69
72
|
var reapplyClaudeSettings = (apiKey, paths = {}) => {
|
|
70
73
|
const settingsPath = paths.settingsPath ?? CLAUDE_SETTINGS;
|
|
71
74
|
const claudeJsonPath = paths.claudeJsonPath ?? CLAUDE_JSON;
|
|
72
75
|
const settings = readJson(settingsPath);
|
|
73
|
-
const
|
|
74
|
-
const configured = settings != null && hasPusharyClaudeHooks(settings) ||
|
|
76
|
+
const claudeJson2 = readJson(claudeJsonPath);
|
|
77
|
+
const configured = settings != null && hasPusharyClaudeHooks(settings) || claudeJson2 != null && hasPusharyMcp(claudeJson2);
|
|
75
78
|
if (!configured) return { reapplied: false, hooks: false, mcp: false };
|
|
76
79
|
const settingsWritable = settings != null;
|
|
77
|
-
const claudeJsonWritable =
|
|
80
|
+
const claudeJsonWritable = claudeJson2 != null;
|
|
78
81
|
let hooks = false;
|
|
79
82
|
let mcp = false;
|
|
80
83
|
try {
|
|
@@ -89,7 +92,7 @@ var reapplyClaudeSettings = (apiKey, paths = {}) => {
|
|
|
89
92
|
if (apiKey) {
|
|
90
93
|
try {
|
|
91
94
|
if (!claudeJsonWritable) throw new Error(".claude.json could not be parsed");
|
|
92
|
-
const cj =
|
|
95
|
+
const cj = claudeJson2;
|
|
93
96
|
addClaudeMcpServer(cj, apiKey);
|
|
94
97
|
writeJson(claudeJsonPath, cj);
|
|
95
98
|
mcp = true;
|
|
@@ -197,7 +200,7 @@ var detectInstallModes = () => {
|
|
|
197
200
|
{
|
|
198
201
|
label: "Cursor plugin",
|
|
199
202
|
upgrade: "updates itself through Cursor",
|
|
200
|
-
present: existsSync2(
|
|
203
|
+
present: existsSync2(cursorPluginDir())
|
|
201
204
|
},
|
|
202
205
|
{
|
|
203
206
|
label: "Codex config",
|
|
@@ -207,12 +210,12 @@ var detectInstallModes = () => {
|
|
|
207
210
|
{
|
|
208
211
|
label: "Claude Code config",
|
|
209
212
|
upgrade: "npx @pushary/agent-hooks@latest setup --agents claude_code",
|
|
210
|
-
present: existsSync2(
|
|
213
|
+
present: existsSync2(claudeJson())
|
|
211
214
|
},
|
|
212
215
|
{
|
|
213
216
|
label: "Gemini config",
|
|
214
217
|
upgrade: "npx @pushary/agent-hooks@latest setup --agents gemini_cli",
|
|
215
|
-
present: existsSync2(
|
|
218
|
+
present: existsSync2(geminiSettings())
|
|
216
219
|
},
|
|
217
220
|
{
|
|
218
221
|
label: "Hermes plugin (pip)",
|
package/dist/bin/pushary-wait.js
CHANGED
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
} from "../chunk-GMXKITVA.js";
|
|
15
15
|
import {
|
|
16
16
|
exitOnHelpFlag
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
17
|
+
} from "../chunk-VYD27DKZ.js";
|
|
18
|
+
import "../chunk-PPTC2QDB.js";
|
|
19
19
|
import "../chunk-SAF6HGAA.js";
|
|
20
20
|
import {
|
|
21
21
|
UsageError
|
package/dist/bin/pushary.js
CHANGED
|
@@ -80,7 +80,10 @@ var COMMAND_OPTIONS = {
|
|
|
80
80
|
["status", "Show the whole ladder"],
|
|
81
81
|
["clear", "Reset the default window"]
|
|
82
82
|
],
|
|
83
|
-
status: [
|
|
83
|
+
status: [
|
|
84
|
+
["--json", "Emit the whole report as one object instead of the screen"],
|
|
85
|
+
["--devices", "Also list the machines registered to this site"]
|
|
86
|
+
],
|
|
84
87
|
logout: [
|
|
85
88
|
["--revoke", "Also kill the key server-side, so it stops working everywhere"],
|
|
86
89
|
["--json", "Emit the result as one object instead of the screen"]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getPackageVersion
|
|
3
|
+
} from "./chunk-PPTC2QDB.js";
|
|
4
|
+
import {
|
|
5
|
+
getMachineId
|
|
6
|
+
} from "./chunk-RN3NOEJF.js";
|
|
7
|
+
import {
|
|
8
|
+
getBaseUrl
|
|
9
|
+
} from "./chunk-2UMNXADU.js";
|
|
10
|
+
|
|
11
|
+
// src/machines.ts
|
|
12
|
+
import { hostname } from "os";
|
|
13
|
+
var MACHINES_PATH = "/api/v1/server/machines";
|
|
14
|
+
var HEARTBEAT_INTERVAL_MS = 6e4;
|
|
15
|
+
var sendHeartbeat = async (apiKey, input = {}, deps = {}) => {
|
|
16
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
17
|
+
const baseUrl = deps.baseUrl ?? getBaseUrl();
|
|
18
|
+
try {
|
|
19
|
+
const res = await fetchImpl(`${baseUrl}${MACHINES_PATH}`, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
22
|
+
body: JSON.stringify({
|
|
23
|
+
machineId: getMachineId(),
|
|
24
|
+
hostname: hostname(),
|
|
25
|
+
cliVersion: getPackageVersion(),
|
|
26
|
+
repoKey: input.repoKey ?? null,
|
|
27
|
+
capabilities: input.capabilities ?? []
|
|
28
|
+
}),
|
|
29
|
+
signal: AbortSignal.timeout(1e4)
|
|
30
|
+
});
|
|
31
|
+
if (res.status === 401 || res.status === 403) return { kind: "unauthorized" };
|
|
32
|
+
if (!res.ok) return { kind: "failed", detail: `HTTP ${res.status}` };
|
|
33
|
+
return { kind: "ok" };
|
|
34
|
+
} catch (err) {
|
|
35
|
+
return { kind: "failed", detail: err instanceof Error ? err.message : "network error" };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var parseMachine = (value) => {
|
|
39
|
+
if (typeof value !== "object" || value === null) return null;
|
|
40
|
+
const raw = value;
|
|
41
|
+
if (typeof raw.machineId !== "string" || typeof raw.hostname !== "string") return null;
|
|
42
|
+
return {
|
|
43
|
+
machineId: raw.machineId,
|
|
44
|
+
hostname: raw.hostname,
|
|
45
|
+
cliVersion: typeof raw.cliVersion === "string" ? raw.cliVersion : "unknown",
|
|
46
|
+
repoKey: typeof raw.repoKey === "string" ? raw.repoKey : null,
|
|
47
|
+
capabilities: Array.isArray(raw.capabilities) ? raw.capabilities.filter((c) => typeof c === "string") : [],
|
|
48
|
+
lastSeenAt: typeof raw.lastSeenAt === "string" ? raw.lastSeenAt : "",
|
|
49
|
+
online: raw.online === true
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
var listMachines = async (apiKey, deps = {}) => {
|
|
53
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
54
|
+
const baseUrl = deps.baseUrl ?? getBaseUrl();
|
|
55
|
+
try {
|
|
56
|
+
const res = await fetchImpl(`${baseUrl}${MACHINES_PATH}`, {
|
|
57
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
58
|
+
signal: AbortSignal.timeout(1e4)
|
|
59
|
+
});
|
|
60
|
+
if (res.status === 404) return { kind: "unsupported" };
|
|
61
|
+
if (!res.ok) return { kind: "failed", detail: `HTTP ${res.status}` };
|
|
62
|
+
const body = await res.json().catch(() => null);
|
|
63
|
+
const list = body && Array.isArray(body.machines) ? body.machines : [];
|
|
64
|
+
return { kind: "ok", machines: list.map(parseMachine).filter((m) => m !== null) };
|
|
65
|
+
} catch (err) {
|
|
66
|
+
return { kind: "failed", detail: err instanceof Error ? err.message : "network error" };
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var describeLastSeen = (iso, now = Date.now()) => {
|
|
70
|
+
const seen = Date.parse(iso);
|
|
71
|
+
if (!Number.isFinite(seen)) return "unknown";
|
|
72
|
+
const seconds = Math.max(0, Math.round((now - seen) / 1e3));
|
|
73
|
+
if (seconds < 60) return "just now";
|
|
74
|
+
const minutes = Math.round(seconds / 60);
|
|
75
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
76
|
+
const hours = Math.round(minutes / 60);
|
|
77
|
+
if (hours < 48) return `${hours}h ago`;
|
|
78
|
+
return `${Math.round(hours / 24)}d ago`;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export {
|
|
82
|
+
HEARTBEAT_INTERVAL_MS,
|
|
83
|
+
sendHeartbeat,
|
|
84
|
+
listMachines,
|
|
85
|
+
describeLastSeen
|
|
86
|
+
};
|
|
@@ -149,6 +149,23 @@ var addCodexHookTrust = (config, hooksJsonPath, command) => {
|
|
|
149
149
|
}
|
|
150
150
|
};
|
|
151
151
|
|
|
152
|
+
// src/setup/paths.ts
|
|
153
|
+
import { homedir as homedir2 } from "os";
|
|
154
|
+
import { join as join2 } from "path";
|
|
155
|
+
var claudeSettings = () => join2(homedir2(), ".claude", "settings.json");
|
|
156
|
+
var claudeJson = () => join2(homedir2(), ".claude.json");
|
|
157
|
+
var claudeSkillDir = () => join2(homedir2(), ".claude", "skills", "pushary");
|
|
158
|
+
var cursorPluginDir = () => join2(homedir2(), ".cursor", "plugins", "local", "pushary");
|
|
159
|
+
var cursorUserHooks = () => join2(homedir2(), ".cursor", "hooks.json");
|
|
160
|
+
var cursorUserMcp = () => join2(homedir2(), ".cursor", "mcp.json");
|
|
161
|
+
var claudeSettingsLocal = () => join2(homedir2(), ".claude", "settings.local.json");
|
|
162
|
+
var pusharyDir = () => join2(homedir2(), ".pushary");
|
|
163
|
+
var codexSkillDir2 = () => join2(codexHome(), "skills", "pushary");
|
|
164
|
+
var codexAgentsMd2 = () => join2(codexHome(), "AGENTS.md");
|
|
165
|
+
var geminiSettings = () => join2(homedir2(), ".gemini", "settings.json");
|
|
166
|
+
var geminiMd = () => join2(homedir2(), ".gemini", "GEMINI.md");
|
|
167
|
+
var pusharyConfigFile = () => join2(homedir2(), ".pushary", "config.json");
|
|
168
|
+
|
|
152
169
|
export {
|
|
153
170
|
CODEX_HOOK_BINARY,
|
|
154
171
|
codexHome,
|
|
@@ -164,5 +181,18 @@ export {
|
|
|
164
181
|
hasCodexHooks,
|
|
165
182
|
missingCodexHookEvents,
|
|
166
183
|
untrustedCodexHookEvents,
|
|
167
|
-
addCodexHookTrust
|
|
184
|
+
addCodexHookTrust,
|
|
185
|
+
claudeSettings,
|
|
186
|
+
claudeJson,
|
|
187
|
+
claudeSkillDir,
|
|
188
|
+
cursorPluginDir,
|
|
189
|
+
cursorUserHooks,
|
|
190
|
+
cursorUserMcp,
|
|
191
|
+
claudeSettingsLocal,
|
|
192
|
+
pusharyDir,
|
|
193
|
+
codexSkillDir2,
|
|
194
|
+
codexAgentsMd2,
|
|
195
|
+
geminiSettings,
|
|
196
|
+
geminiMd,
|
|
197
|
+
pusharyConfigFile
|
|
168
198
|
};
|