autodev-cli 1.4.74 → 1.4.75

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.
@@ -39,6 +39,7 @@ const path = __importStar(require("path"));
39
39
  const logger_1 = require("../logger");
40
40
  const sdk_1 = require("../sdk");
41
41
  const version_1 = require("../version");
42
+ const presenceGuard_1 = require("../presenceGuard");
42
43
  const PROVIDERS = ['claude-cli', 'claude-tui', 'copilot-cli', 'copilot-sdk', 'opencode-cli', 'opencode-sdk', 'grok-cli', 'grok-tui'];
43
44
  function startCommand(program) {
44
45
  program
@@ -48,9 +49,28 @@ function startCommand(program) {
48
49
  .option('--todo <file>', 'Path to TODO.md (relative to workspace)', 'TODO.md')
49
50
  .option('--once', 'Run until the TODO drains, then exit (default: poll forever)')
50
51
  .option('--session-name <name>', 'Display name for this session (opencode --title, copilot --name, shown in pixel-office)')
52
+ .option('--force', 'Start even if another loop already owns this workspace (bypass the duplicate-loop guard)')
51
53
  .action(async (workspacePath, opts) => {
52
54
  const cwd = workspacePath ? path.resolve(workspacePath) : process.cwd();
53
55
  const todoFile = path.resolve(cwd, opts.todo);
56
+ // ── Duplicate-loop guard ───────────────────────────────────────────────
57
+ // The running `autodev start` loop drops .autodev/ws-presence.lock
58
+ // ({pid, slug, ts}) once its WS connects and refreshes ts every heartbeat.
59
+ // If a DIFFERENT, still-alive loop already holds a FRESH lock for this
60
+ // workspace, a second loop would open a competing WS that (last-wins on the
61
+ // server's slug index) evicts the first every ~5s — a WebSocket flap. Bail
62
+ // out cleanly instead. --force bypasses (intentional takeover/restart). At
63
+ // boot we haven't written our own lock yet, so the guard only ever sees the
64
+ // OTHER loop's lock — never our own — and never kills a lone re-connecting
65
+ // loop.
66
+ if (!opts.force) {
67
+ const ownerPid = (0, presenceGuard_1.foreignLoopOwner)((0, presenceGuard_1.readPresenceLock)(cwd));
68
+ if (ownerPid !== null) {
69
+ logger_1.log.warn(`⚠ Another autodev loop (pid ${ownerPid}) already owns this workspace — exiting to avoid a duplicate connection.`);
70
+ logger_1.log.gray(' Run `autodev start --force` to take over anyway.');
71
+ process.exit(0);
72
+ }
73
+ }
54
74
  // Parent-death watchdog: when a manager spawns this loop and sets
55
75
  // AUTODEV_EXIT_WITH_PARENT=1 (the desktop app does), exit if that parent
56
76
  // process disappears — so closing, crashing, or force-quitting the app never
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export interface PresenceLock {
2
+ pid?: number;
3
+ slug?: string;
4
+ ts?: number;
5
+ }
6
+ /** Path to the loop's live-presence lock for a workspace. */
7
+ export declare function presenceLockPath(cwd: string): string;
8
+ /** Read + parse the presence lock; null on absent / unreadable / bad JSON. */
9
+ export declare function readPresenceLock(cwd: string): PresenceLock | null;
10
+ export interface ForeignOwnerOpts {
11
+ now?: number;
12
+ selfPid?: number;
13
+ freshMs?: number;
14
+ isAlive?: (pid: number, selfPid: number) => boolean;
15
+ }
16
+ /**
17
+ * Given a parsed ws-presence.lock, return the pid of a DIFFERENT, still-alive
18
+ * loop that currently owns this workspace's live presence — or null when the
19
+ * caller should proceed (no lock, our own pid, a dead pid, or a stale ts).
20
+ * Freshness defaults to 90s (the loop refreshes ts every ~25s heartbeat, so this
21
+ * tolerates a few missed beats while still ignoring a crashed loop's stale lock).
22
+ */
23
+ export declare function foreignLoopOwner(lock: PresenceLock | null | undefined, opts?: ForeignOwnerOpts): number | null;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.presenceLockPath = presenceLockPath;
37
+ exports.readPresenceLock = readPresenceLock;
38
+ exports.foreignLoopOwner = foreignLoopOwner;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ /** Path to the loop's live-presence lock for a workspace. */
42
+ function presenceLockPath(cwd) {
43
+ return path.join(cwd, '.autodev', 'ws-presence.lock');
44
+ }
45
+ /** Read + parse the presence lock; null on absent / unreadable / bad JSON. */
46
+ function readPresenceLock(cwd) {
47
+ try {
48
+ return JSON.parse(fs.readFileSync(presenceLockPath(cwd), 'utf8'));
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ /** True if pid is a live process OTHER than self. process.kill(pid,0) throwing
55
+ * ESRCH ⇒ dead; EPERM ⇒ exists but owned by another user (still alive). */
56
+ function defaultPidAlive(pid, selfPid) {
57
+ if (!pid || pid === selfPid) {
58
+ return false;
59
+ }
60
+ try {
61
+ process.kill(pid, 0);
62
+ return true;
63
+ }
64
+ catch (e) {
65
+ return e.code === 'EPERM';
66
+ }
67
+ }
68
+ /**
69
+ * Given a parsed ws-presence.lock, return the pid of a DIFFERENT, still-alive
70
+ * loop that currently owns this workspace's live presence — or null when the
71
+ * caller should proceed (no lock, our own pid, a dead pid, or a stale ts).
72
+ * Freshness defaults to 90s (the loop refreshes ts every ~25s heartbeat, so this
73
+ * tolerates a few missed beats while still ignoring a crashed loop's stale lock).
74
+ */
75
+ function foreignLoopOwner(lock, opts = {}) {
76
+ if (!lock) {
77
+ return null;
78
+ }
79
+ const now = opts.now ?? Date.now();
80
+ const selfPid = opts.selfPid ?? process.pid;
81
+ const freshMs = opts.freshMs ?? 90_000;
82
+ const alive = opts.isAlive ?? defaultPidAlive;
83
+ const pid = typeof lock.pid === 'number' ? lock.pid : 0;
84
+ const ts = typeof lock.ts === 'number' ? lock.ts : 0;
85
+ if (pid <= 0 || pid === selfPid) {
86
+ return null;
87
+ } // no/own pid → not a foreign owner
88
+ if (now - ts >= freshMs) {
89
+ return null;
90
+ } // stale lock → crashed/gone owner
91
+ if (!alive(pid, selfPid)) {
92
+ return null;
93
+ } // dead pid → free to take over
94
+ return pid;
95
+ }
96
+ //# sourceMappingURL=presenceGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presenceGuard.js","sourceRoot":"","sources":["../src/presenceGuard.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,4CAEC;AAGD,4CAIC;AAwBD,4CAYC;AA7DD,uCAAyB;AACzB,2CAA6B;AAc7B,6DAA6D;AAC7D,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;AACxD,CAAC;AAED,8EAA8E;AAC9E,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAiB,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC1B,CAAC;AAED;4EAC4E;AAC5E,SAAS,eAAe,CAAC,GAAW,EAAE,OAAe;IACnD,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;IAC9C,IAAI,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC;QAAC,OAAQ,CAA2B,CAAC,IAAI,KAAK,OAAO,CAAC;IAAC,CAAC;AACrE,CAAC;AASD;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,IAAqC,EAAE,OAAyB,EAAE;IACjG,IAAI,CAAC,IAAI,EAAE,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,IAAI,eAAe,CAAC;IAC9C,MAAM,GAAG,GAAG,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,MAAM,EAAE,GAAG,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC,CAAC,mCAAmC;IACrF,IAAI,GAAG,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC,CAAS,kCAAkC;IACpF,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC,CAAQ,+BAA+B;IACjF,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autodev-cli",
3
- "version": "1.4.74",
3
+ "version": "1.4.75",
4
4
  "description": "AutoAIDev CLI — autonomous AI task loop with VS Code / Cursor launcher",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -29,7 +29,7 @@
29
29
  "dev": "tsc -p ./ --watch",
30
30
  "prepublishOnly": "npm run build",
31
31
  "start": "node bin/autodev.js",
32
- "test": "node test/smoke.mjs && node test/liveNarration.smoke.mjs && node test/liveNarration.edge.smoke.mjs && node test/normalizer.parity.smoke.mjs && node test/providerConfig.smoke.mjs && node test/mcpOnlyOperator.smoke.mjs && node test/opencodeEventFilter.smoke.mjs && node test/copilotMcpIsolation.smoke.mjs && node test/grokSpawnError.smoke.mjs && node test/initTemplate.smoke.mjs && node test/settingsAliases.smoke.mjs && node test/setupWritesOfficeMcp.smoke.mjs && node test/claudePermissions.smoke.mjs"
32
+ "test": "node test/smoke.mjs && node test/liveNarration.smoke.mjs && node test/liveNarration.edge.smoke.mjs && node test/normalizer.parity.smoke.mjs && node test/providerConfig.smoke.mjs && node test/mcpOnlyOperator.smoke.mjs && node test/opencodeEventFilter.smoke.mjs && node test/copilotMcpIsolation.smoke.mjs && node test/grokSpawnError.smoke.mjs && node test/initTemplate.smoke.mjs && node test/settingsAliases.smoke.mjs && node test/setupWritesOfficeMcp.smoke.mjs && node test/claudePermissions.smoke.mjs && node test/presenceGuard.smoke.mjs"
33
33
  },
34
34
  "dependencies": {
35
35
  "commander": "^12.1.0",