agent-afk 5.249.2 → 5.249.3
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/dist/cli.mjs +245 -245
- package/dist/index.mjs +111 -111
- package/dist/postinstall.mjs +58 -18
- package/dist/telegram.mjs +130 -130
- package/package.json +1 -1
- package/scripts/postinstall.mjs +58 -18
package/dist/postinstall.mjs
CHANGED
|
@@ -11,9 +11,46 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { execSync, execFileSync } from 'node:child_process';
|
|
14
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
14
|
+
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
15
15
|
import { homedir } from 'node:os';
|
|
16
16
|
import { join } from 'node:path';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
|
|
19
|
+
// ─── Module-scope derived paths ────────────────────────────────────────────
|
|
20
|
+
// Computed once so restartLaunchdServices and the main block share the same
|
|
21
|
+
// decoded, symlink-resolved package root rather than each re-deriving it.
|
|
22
|
+
// fileURLToPath decodes percent-encoded characters (e.g. spaces → %20) that
|
|
23
|
+
// new URL().pathname leaves encoded and that path.join then mis-handles.
|
|
24
|
+
const _pkgRoot = join(fileURLToPath(new URL('.', import.meta.url)), '..');
|
|
25
|
+
|
|
26
|
+
// ─── Exported helpers ───────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Pure function. Returns true when this module is the Node.js entry-point
|
|
30
|
+
* (i.e. run directly, not imported). Accepts the two pieces of identity as
|
|
31
|
+
* parameters so it can be unit-tested with arbitrary values.
|
|
32
|
+
*
|
|
33
|
+
* Comparison uses fileURLToPath (not a raw `file://` string) so that
|
|
34
|
+
* percent-encoded characters in the install path — e.g. `/my%20dir/` — do not
|
|
35
|
+
* cause a false negative. realpathSync resolves symlinks in argv[1] so that
|
|
36
|
+
* globally-installed bins (typically symlinked into /usr/local/bin) compare
|
|
37
|
+
* equal to the real file recorded in import.meta.url.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} metaUrl - import.meta.url of the calling module.
|
|
40
|
+
* @param {string} [argv1] - process.argv[1]; may be absent or non-existent.
|
|
41
|
+
* @returns {boolean}
|
|
42
|
+
*/
|
|
43
|
+
export function isMainModule(metaUrl, argv1) {
|
|
44
|
+
if (!argv1) return false;
|
|
45
|
+
try {
|
|
46
|
+
return fileURLToPath(metaUrl) === realpathSync(argv1);
|
|
47
|
+
} catch {
|
|
48
|
+
// argv[1] does not exist on disk (e.g. a piped script, a test runner
|
|
49
|
+
// that synthesises a path). Fall back to a plain string comparison so
|
|
50
|
+
// the guard never throws at module evaluation time.
|
|
51
|
+
return fileURLToPath(metaUrl) === argv1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
17
54
|
|
|
18
55
|
/**
|
|
19
56
|
* Pure function. Determines whether the npm bin directory is on PATH.
|
|
@@ -49,11 +86,11 @@ export function detectPathGap(prefix, pathEnv) {
|
|
|
49
86
|
* This is a belt-and-suspenders guard: even if npm_config_global were
|
|
50
87
|
* wrong or missing, a .git marker unambiguously rules out a global install.
|
|
51
88
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
89
|
+
* History: Daemon was unconditionally restarted on every postinstall.
|
|
90
|
+
* A cron job that ran `pnpm install` inside a repo worktree triggered this
|
|
91
|
+
* path and restarted the running daemon mid-session, orphaning 438 subagents
|
|
92
|
+
* and leaving the daemon stopped. The guard introduced here ensures restarts
|
|
93
|
+
* occur ONLY for genuine global upgrades. See PR #2195.
|
|
57
94
|
*
|
|
58
95
|
* @param {string} pkgRoot - Absolute path to the package root.
|
|
59
96
|
* @param {object} [env] - Environment variable bag; defaults to process.env.
|
|
@@ -143,12 +180,12 @@ export function isManualBotRunning(pidFilePath, probeFn = process.kill) {
|
|
|
143
180
|
* is swallowed so the install never fails. macOS only — the caller gates on
|
|
144
181
|
* platform; elsewhere ~/Library/LaunchAgents won't exist so nothing restarts.
|
|
145
182
|
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
183
|
+
* Invariant: the daemon is NOT stateless. It may be mid-run on one or more
|
|
184
|
+
* scheduled agent sessions. This function MUST only be called from a global
|
|
185
|
+
* package upgrade path (verified by isGlobalInstall()) — never from a local
|
|
186
|
+
* `pnpm install` inside a source checkout or worktree. The caller in the main
|
|
187
|
+
* block enforces this via isGlobalInstall(); callers in tests must pass stubs
|
|
188
|
+
* for execFn/restartFn so real launchctl is never invoked.
|
|
152
189
|
*
|
|
153
190
|
* Label / path / domain conventions mirror src/service/launchd/paths.ts
|
|
154
191
|
* (labelFor → `com.afk.<name>`, plist under ~/Library/LaunchAgents, guiDomain →
|
|
@@ -186,8 +223,9 @@ export function restartLaunchdServices(opts = {}) {
|
|
|
186
223
|
//
|
|
187
224
|
// __dirname equivalent for ESM: derive from import.meta.url.
|
|
188
225
|
// scripts/postinstall.mjs → dist/cli.mjs (package root / dist/).
|
|
189
|
-
|
|
190
|
-
|
|
226
|
+
// fileURLToPath is used (not .pathname) so percent-encoded characters in the
|
|
227
|
+
// path are decoded correctly — e.g. a space-containing install dir on macOS.
|
|
228
|
+
const pkgRoot = _pkgRoot;
|
|
191
229
|
const cliMjs = join(pkgRoot, 'dist', 'cli.mjs');
|
|
192
230
|
|
|
193
231
|
// Invariant: `afk service restart` is the correct single command — it
|
|
@@ -241,10 +279,14 @@ export function restartLaunchdServices(opts = {}) {
|
|
|
241
279
|
|
|
242
280
|
// ─── Main block ─────────────────────────────────────────────────────────────
|
|
243
281
|
// Guard: only run when executed directly (not when imported by tests).
|
|
282
|
+
// isMainModule() handles percent-encoded paths and symlinked global bins
|
|
283
|
+
// correctly; the raw `file://${process.argv[1]}` comparison it replaces
|
|
284
|
+
// would return false when the install path contains spaces or other chars
|
|
285
|
+
// that import.meta.url encodes as percent-sequences.
|
|
244
286
|
const isMain =
|
|
245
287
|
typeof process !== 'undefined' &&
|
|
246
288
|
typeof process.argv !== 'undefined' &&
|
|
247
|
-
import.meta.url
|
|
289
|
+
isMainModule(import.meta.url, process.argv[1]);
|
|
248
290
|
|
|
249
291
|
if (isMain) {
|
|
250
292
|
// Only meaningful on macOS/Linux where PATH-based installs are common.
|
|
@@ -316,9 +358,7 @@ if (isMain) {
|
|
|
316
358
|
// guard below enforces this; it fails closed toward NOT restarting whenever
|
|
317
359
|
// either detection signal is absent or ambiguous.
|
|
318
360
|
if (process.platform === 'darwin') {
|
|
319
|
-
|
|
320
|
-
const pkgRoot = join(scriptDir, '..');
|
|
321
|
-
if (isGlobalInstall(pkgRoot, process.env, existsSync)) {
|
|
361
|
+
if (isGlobalInstall(_pkgRoot, process.env, existsSync)) {
|
|
322
362
|
try {
|
|
323
363
|
const restarted = restartLaunchdServices({
|
|
324
364
|
labels: ['com.afk.daemon'],
|