autodev-cli 1.4.192 → 1.4.194
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/out/cli.js +4 -0
- package/out/cli.js.map +1 -1
- package/out/commands/grokKeepalive.d.ts +10 -0
- package/out/commands/grokKeepalive.js +27 -0
- package/out/commands/grokKeepalive.js.map +1 -0
- package/out/commands/leaderStop.d.ts +10 -0
- package/out/commands/leaderStop.js +63 -0
- package/out/commands/leaderStop.js.map +1 -0
- package/out/messageBuilder.js +5 -3
- package/out/messageBuilder.js.map +1 -1
- package/out/profileBuilder.js +1 -0
- package/out/profileBuilder.js.map +1 -1
- package/out/providers/acp/AcpSession.d.ts +30 -0
- package/out/providers/acp/AcpSession.js +86 -1
- package/out/providers/acp/AcpSession.js.map +1 -1
- package/out/providers/grok/GrokAcpSession.d.ts +14 -1
- package/out/providers/grok/GrokAcpSession.js +29 -2
- package/out/providers/grok/GrokAcpSession.js.map +1 -1
- package/out/providers/grok/keepalive.d.ts +15 -0
- package/out/providers/grok/keepalive.js +141 -0
- package/out/providers/grok/keepalive.js.map +1 -0
- package/out/providers/grok/keepaliveMain.d.ts +1 -0
- package/out/providers/grok/keepaliveMain.js +22 -0
- package/out/providers/grok/keepaliveMain.js.map +1 -0
- package/out/providers/grok/leader.d.ts +66 -0
- package/out/providers/grok/leader.js +390 -0
- package/out/providers/grok/leader.js.map +1 -0
- package/out/providers/grok/tui.js +130 -29
- package/out/providers/grok/tui.js.map +1 -1
- package/out/providers/opencode/sdk.d.ts +11 -0
- package/out/providers/opencode/sdk.js +110 -10
- package/out/providers/opencode/sdk.js.map +1 -1
- package/out/taskLoop.d.ts +64 -0
- package/out/taskLoop.js +270 -9
- package/out/taskLoop.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// grok LEADER daemon — "always open, reconnect-never-reload" (Layer B, 1.4.193).
|
|
4
|
+
//
|
|
5
|
+
// GOAL: the grok backend OUTLIVES loop/app restarts so a restarted loop
|
|
6
|
+
// RECONNECTS to the live in-memory session with NO `session/load` replay (the
|
|
7
|
+
// office-feed spam Layer A only quieted). GATED behind env AUTODEV_GROK_LEADER,
|
|
8
|
+
// DEFAULT OFF — when off, the existing non-leader ACP path (1.4.188/1.4.191) is
|
|
9
|
+
// used UNCHANGED.
|
|
10
|
+
//
|
|
11
|
+
// ARCHITECTURE (verified live on grok 1.0.41; see memory `grok-leader-always-open`
|
|
12
|
+
// + the 1.4.193 re-spike):
|
|
13
|
+
// • A per-agent grok LEADER daemon (`grok agent --always-approve leader
|
|
14
|
+
// --no-exit-on-disconnect --relay-on-demand --no-auto-update --leader-socket
|
|
15
|
+
// <per-agent .sock>`) is a shared backend that survives client disconnects.
|
|
16
|
+
// • CRITICAL grok-1.0.41 fact: the leader EVICTS a session's in-memory context
|
|
17
|
+
// when its LAST client disconnects (the session persists on disk, but a fresh
|
|
18
|
+
// client then gets "unknown session id" and must `session/load` = the replay).
|
|
19
|
+
// So a bare leader is NOT enough for attach-without-load across a loop restart.
|
|
20
|
+
// • Fix: a detached KEEPALIVE client holds the session warm in the leader's
|
|
21
|
+
// memory forever. Loop clients then attach as a SECOND concurrent client and
|
|
22
|
+
// `session/prompt {sessionId}` DIRECTLY — context intact, NO session/load —
|
|
23
|
+
// across any number of loop-process restarts (proven: codeword recalled,
|
|
24
|
+
// zero session/load).
|
|
25
|
+
// • The ONE `session/load` (cold recovery from disk) happens inside the
|
|
26
|
+
// keepalive at cold start when it is seeded with the persisted id; every
|
|
27
|
+
// subsequent loop restart is a warm attach. No live keepalive ⇒ degrade to
|
|
28
|
+
// Layer A (session/load), never data-loss.
|
|
29
|
+
//
|
|
30
|
+
// REAP BY PID (critical): `grok leader list/kill` CANNOT see a per-socket
|
|
31
|
+
// `--relay-on-demand` leader (verified: list→[], "No leader candidates found").
|
|
32
|
+
// So we track the leader + keepalive PIDs in `.autodev/leader.json` and reap the
|
|
33
|
+
// pid-trees ourselves. `autodev leader-stop <root>` (hidden) is what the app calls
|
|
34
|
+
// on office stop/remove/quit. The loop's own SIGINT/exit reaper kills ONLY the
|
|
35
|
+
// thin client (leader/keepalive are DETACHED, so they survive a loop restart).
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
38
|
+
if (k2 === undefined) k2 = k;
|
|
39
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
40
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
41
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
42
|
+
}
|
|
43
|
+
Object.defineProperty(o, k2, desc);
|
|
44
|
+
}) : (function(o, m, k, k2) {
|
|
45
|
+
if (k2 === undefined) k2 = k;
|
|
46
|
+
o[k2] = m[k];
|
|
47
|
+
}));
|
|
48
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
49
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
50
|
+
}) : function(o, v) {
|
|
51
|
+
o["default"] = v;
|
|
52
|
+
});
|
|
53
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
54
|
+
var ownKeys = function(o) {
|
|
55
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
56
|
+
var ar = [];
|
|
57
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
58
|
+
return ar;
|
|
59
|
+
};
|
|
60
|
+
return ownKeys(o);
|
|
61
|
+
};
|
|
62
|
+
return function (mod) {
|
|
63
|
+
if (mod && mod.__esModule) return mod;
|
|
64
|
+
var result = {};
|
|
65
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
66
|
+
__setModuleDefault(result, mod);
|
|
67
|
+
return result;
|
|
68
|
+
};
|
|
69
|
+
})();
|
|
70
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
71
|
+
exports.runKeepalive = void 0;
|
|
72
|
+
exports.leaderModeEnabled = leaderModeEnabled;
|
|
73
|
+
exports.leaderSocketPath = leaderSocketPath;
|
|
74
|
+
exports.leaderJsonPath = leaderJsonPath;
|
|
75
|
+
exports.leaderSidPath = leaderSidPath;
|
|
76
|
+
exports.readLeaderInfo = readLeaderInfo;
|
|
77
|
+
exports.writeLeaderInfo = writeLeaderInfo;
|
|
78
|
+
exports.removeLeaderInfo = removeLeaderInfo;
|
|
79
|
+
exports.isPidAlive = isPidAlive;
|
|
80
|
+
exports.decideLeaderAction = decideLeaderAction;
|
|
81
|
+
exports.leaderHealthy = leaderHealthy;
|
|
82
|
+
exports.keepaliveEntryPath = keepaliveEntryPath;
|
|
83
|
+
exports.ensureLeader = ensureLeader;
|
|
84
|
+
exports.stopLeader = stopLeader;
|
|
85
|
+
const fs = __importStar(require("fs"));
|
|
86
|
+
const os = __importStar(require("os"));
|
|
87
|
+
const path = __importStar(require("path"));
|
|
88
|
+
const crypto = __importStar(require("crypto"));
|
|
89
|
+
const child_process = __importStar(require("child_process"));
|
|
90
|
+
const killProcessTree_1 = require("../../core/killProcessTree");
|
|
91
|
+
const sessionState_1 = require("../../sessionState");
|
|
92
|
+
// Re-export the keepalive runner + its options so existing importers keep working.
|
|
93
|
+
var keepalive_1 = require("./keepalive");
|
|
94
|
+
Object.defineProperty(exports, "runKeepalive", { enumerable: true, get: function () { return keepalive_1.runKeepalive; } });
|
|
95
|
+
/** Env gate — leader mode is OPT-IN and DEFAULT OFF. Pure (env injectable). */
|
|
96
|
+
function leaderModeEnabled(env = process.env) {
|
|
97
|
+
const raw = String(env['AUTODEV_GROK_LEADER'] ?? '').toLowerCase().trim();
|
|
98
|
+
return raw === '1' || raw === 'true' || raw === 'on' || raw === 'yes';
|
|
99
|
+
}
|
|
100
|
+
/** Per-agent AF_UNIX socket. Prefer `.autodev/grok-leader.sock`; fall back to a
|
|
101
|
+
* hashed path under tmp when the workspace path would blow the ~108-byte sun_path
|
|
102
|
+
* limit (a deterministic function of the root either way). */
|
|
103
|
+
function leaderSocketPath(root) {
|
|
104
|
+
const inAutodev = path.join(root, '.autodev', 'grok-leader.sock');
|
|
105
|
+
if (Buffer.byteLength(inAutodev) <= 100) {
|
|
106
|
+
return inAutodev;
|
|
107
|
+
}
|
|
108
|
+
const h = crypto.createHash('sha1').update(path.resolve(root)).digest('hex').slice(0, 16);
|
|
109
|
+
return path.join(os.tmpdir(), `autodev-grok-${h}.sock`);
|
|
110
|
+
}
|
|
111
|
+
function leaderJsonPath(root) { return path.join(root, '.autodev', 'leader.json'); }
|
|
112
|
+
function leaderSidPath(root) { return path.join(root, '.autodev', 'grok-leader.sid'); }
|
|
113
|
+
function readLeaderInfo(root) {
|
|
114
|
+
try {
|
|
115
|
+
const raw = fs.readFileSync(leaderJsonPath(root), 'utf8');
|
|
116
|
+
const info = JSON.parse(raw);
|
|
117
|
+
if (info && typeof info.pid === 'number' && typeof info.socket === 'string') {
|
|
118
|
+
return info;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch { /* absent / malformed */ }
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
function writeLeaderInfo(root, info) {
|
|
125
|
+
try {
|
|
126
|
+
(0, sessionState_1.autodevDir)(root);
|
|
127
|
+
fs.writeFileSync(leaderJsonPath(root), JSON.stringify(info, null, 2), 'utf8');
|
|
128
|
+
}
|
|
129
|
+
catch { /* best effort */ }
|
|
130
|
+
}
|
|
131
|
+
function removeLeaderInfo(root) {
|
|
132
|
+
try {
|
|
133
|
+
fs.unlinkSync(leaderJsonPath(root));
|
|
134
|
+
}
|
|
135
|
+
catch { /* already gone */ }
|
|
136
|
+
}
|
|
137
|
+
/** `process.kill(pid, 0)` liveness probe — true iff the pid exists (and is ours
|
|
138
|
+
* or EPERM, which still means alive). */
|
|
139
|
+
function isPidAlive(pid) {
|
|
140
|
+
if (!pid || !Number.isInteger(pid) || pid <= 1) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
process.kill(pid, 0);
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
return err?.code === 'EPERM';
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* PURE orphan-sweep decision. Given the persisted info and the observed liveness
|
|
153
|
+
* of its pieces, decide whether to reuse a still-live leader ('adopt'), reap a
|
|
154
|
+
* stale/dead one ('reap-stale'), or spawn fresh ('spawn'). Unit-tested.
|
|
155
|
+
*/
|
|
156
|
+
function decideLeaderAction(info, alive) {
|
|
157
|
+
if (!info) {
|
|
158
|
+
return 'spawn';
|
|
159
|
+
}
|
|
160
|
+
const keepaliveOk = info.keepalivePid ? alive.keepalive : true;
|
|
161
|
+
if (alive.leader && keepaliveOk && alive.socket) {
|
|
162
|
+
return 'adopt';
|
|
163
|
+
}
|
|
164
|
+
return 'reap-stale';
|
|
165
|
+
}
|
|
166
|
+
/** Is the persisted leader fully healthy right now (adoptable)? */
|
|
167
|
+
function leaderHealthy(info) {
|
|
168
|
+
if (!info) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
const alive = { leader: isPidAlive(info.pid), keepalive: isPidAlive(info.keepalivePid), socket: (() => { try {
|
|
172
|
+
return fs.existsSync(info.socket);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return false;
|
|
176
|
+
} })() };
|
|
177
|
+
return decideLeaderAction(info, alive) === 'adopt';
|
|
178
|
+
}
|
|
179
|
+
function readSidFile(sidFile) {
|
|
180
|
+
try {
|
|
181
|
+
const s = fs.readFileSync(sidFile, 'utf8').trim();
|
|
182
|
+
return s || null;
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function waitUntil(pred, ms, stepMs = 100) {
|
|
189
|
+
const end = Date.now() + ms;
|
|
190
|
+
while (Date.now() < end) {
|
|
191
|
+
if (pred()) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
await new Promise((r) => setTimeout(r, stepMs));
|
|
195
|
+
}
|
|
196
|
+
return pred();
|
|
197
|
+
}
|
|
198
|
+
function openLogFd(file) {
|
|
199
|
+
try {
|
|
200
|
+
return fs.openSync(file, 'a');
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return 'ignore';
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/** Resolve the minimal keepalive entry (out/providers/grok/keepaliveMain.js) so a
|
|
207
|
+
* detached keepalive loads with NO commander/CLI graph. Overridable for odd
|
|
208
|
+
* packagings via AUTODEV_KEEPALIVE_ENTRY. */
|
|
209
|
+
function keepaliveEntryPath() {
|
|
210
|
+
const override = process.env['AUTODEV_KEEPALIVE_ENTRY'];
|
|
211
|
+
if (override && fs.existsSync(override)) {
|
|
212
|
+
return override;
|
|
213
|
+
}
|
|
214
|
+
return path.join(__dirname, 'keepaliveMain.js');
|
|
215
|
+
}
|
|
216
|
+
/** Reap the leader + keepalive pid-trees named in `info` (best-effort). */
|
|
217
|
+
function reapLeaderProcs(info) {
|
|
218
|
+
if (info.keepalivePid) {
|
|
219
|
+
try {
|
|
220
|
+
(0, killProcessTree_1.killProcessTree)(info.keepalivePid);
|
|
221
|
+
}
|
|
222
|
+
catch { /* ignore */ }
|
|
223
|
+
}
|
|
224
|
+
if (info.pid) {
|
|
225
|
+
try {
|
|
226
|
+
(0, killProcessTree_1.killProcessTree)(info.pid);
|
|
227
|
+
}
|
|
228
|
+
catch { /* ignore */ }
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* ORPHAN-SWEEP + ensure a live leader+keepalive for this root. Adopts a still-live
|
|
233
|
+
* one (no second leader), reaps a stale/dead one, else spawns both DETACHED so they
|
|
234
|
+
* survive the loop process exiting. Returns the LeaderInfo (with the warm session
|
|
235
|
+
* id) or null when the backend could not be established (caller falls back to the
|
|
236
|
+
* non-leader ACP path). Never throws.
|
|
237
|
+
*/
|
|
238
|
+
async function ensureLeader(opts) {
|
|
239
|
+
const { root, bin, providerId, model, log } = opts;
|
|
240
|
+
const existing = readLeaderInfo(root);
|
|
241
|
+
if (existing && leaderHealthy(existing)) {
|
|
242
|
+
log(`grok leader: adopting live backend (leader=${existing.pid} keepalive=${existing.keepalivePid ?? '?'} sid=${(existing.sessionId ?? '').slice(0, 8)}…)`);
|
|
243
|
+
return existing;
|
|
244
|
+
}
|
|
245
|
+
if (existing) {
|
|
246
|
+
log(`grok leader: reaping stale backend (leader=${existing.pid} keepalive=${existing.keepalivePid ?? '?'})`);
|
|
247
|
+
reapLeaderProcs(existing);
|
|
248
|
+
removeLeaderInfo(existing.root ?? root);
|
|
249
|
+
}
|
|
250
|
+
const socket = leaderSocketPath(root);
|
|
251
|
+
try {
|
|
252
|
+
fs.unlinkSync(socket);
|
|
253
|
+
}
|
|
254
|
+
catch { /* no stale socket */ }
|
|
255
|
+
(0, sessionState_1.autodevDir)(root);
|
|
256
|
+
// 1) Spawn the LEADER daemon, detached.
|
|
257
|
+
const leaderArgs = ['agent', '--always-approve', 'leader', '--no-exit-on-disconnect', '--relay-on-demand', '--no-auto-update', '--leader-socket', socket];
|
|
258
|
+
const leaderErrFd = openLogFd(path.join(root, '.autodev', 'grok-leader.err'));
|
|
259
|
+
let leaderChild;
|
|
260
|
+
try {
|
|
261
|
+
leaderChild = child_process.spawn(bin, leaderArgs, {
|
|
262
|
+
cwd: root, detached: true,
|
|
263
|
+
stdio: ['ignore', 'ignore', leaderErrFd],
|
|
264
|
+
env: { ...process.env, TERM: process.env['TERM'] || 'xterm-256color' },
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
log(`grok leader: spawn failed (${err?.message ?? err})`);
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
leaderChild.unref();
|
|
272
|
+
const leaderPid = leaderChild.pid;
|
|
273
|
+
if (!leaderPid) {
|
|
274
|
+
log('grok leader: no pid after spawn');
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
const sockOk = await waitUntil(() => { try {
|
|
278
|
+
return fs.existsSync(socket);
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
return false;
|
|
282
|
+
} }, 15_000);
|
|
283
|
+
if (!sockOk) {
|
|
284
|
+
log('grok leader: socket never appeared — reaping');
|
|
285
|
+
try {
|
|
286
|
+
(0, killProcessTree_1.killProcessTree)(leaderPid);
|
|
287
|
+
}
|
|
288
|
+
catch { /* ignore */ }
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
// 2) Spawn the KEEPALIVE client, detached — it holds the session warm. Seed it
|
|
292
|
+
// with the persisted id so a cold start does its ONE session/load here.
|
|
293
|
+
const sidFile = leaderSidPath(root);
|
|
294
|
+
try {
|
|
295
|
+
fs.unlinkSync(sidFile);
|
|
296
|
+
}
|
|
297
|
+
catch { /* ignore */ }
|
|
298
|
+
const seed = (0, sessionState_1.getSessionId)(root, providerId) || undefined;
|
|
299
|
+
const kaArgs = [keepaliveEntryPath(), '--socket', socket, '--cwd', root, '--sid-file', sidFile, '--bin', bin];
|
|
300
|
+
if (seed) {
|
|
301
|
+
kaArgs.push('--seed', seed);
|
|
302
|
+
}
|
|
303
|
+
let kaChild;
|
|
304
|
+
try {
|
|
305
|
+
kaChild = child_process.spawn(process.execPath, kaArgs, {
|
|
306
|
+
cwd: root, detached: true, stdio: 'ignore',
|
|
307
|
+
// ELECTRON_RUN_AS_NODE so an Electron-bundled CLI runs the keepalive as pure
|
|
308
|
+
// node (no window) — the inverse of the app's ELECTRON_RUN_AS_NODE trap.
|
|
309
|
+
env: { ...process.env, ELECTRON_RUN_AS_NODE: '1', TERM: process.env['TERM'] || 'xterm-256color' },
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
log(`grok leader: keepalive spawn failed (${err?.message ?? err})`);
|
|
314
|
+
try {
|
|
315
|
+
(0, killProcessTree_1.killProcessTree)(leaderPid);
|
|
316
|
+
}
|
|
317
|
+
catch { /* ignore */ }
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
kaChild.unref();
|
|
321
|
+
const keepalivePid = kaChild.pid;
|
|
322
|
+
const gotSid = await waitUntil(() => readSidFile(sidFile) !== null, 25_000);
|
|
323
|
+
const sessionId = readSidFile(sidFile) || undefined;
|
|
324
|
+
if (!keepalivePid || !gotSid || !sessionId) {
|
|
325
|
+
log('grok leader: keepalive failed to establish a session — reaping');
|
|
326
|
+
if (keepalivePid) {
|
|
327
|
+
try {
|
|
328
|
+
(0, killProcessTree_1.killProcessTree)(keepalivePid);
|
|
329
|
+
}
|
|
330
|
+
catch { /* ignore */ }
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
(0, killProcessTree_1.killProcessTree)(leaderPid);
|
|
334
|
+
}
|
|
335
|
+
catch { /* ignore */ }
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
const info = { pid: leaderPid, socket, startedAt: new Date().toISOString(), keepalivePid, sessionId, root };
|
|
339
|
+
writeLeaderInfo(root, info);
|
|
340
|
+
try {
|
|
341
|
+
(0, sessionState_1.saveSessionId)(root, providerId, sessionId);
|
|
342
|
+
}
|
|
343
|
+
catch { /* ignore */ }
|
|
344
|
+
log(`grok leader: backend up (leader=${leaderPid} keepalive=${keepalivePid} sid=${sessionId.slice(0, 8)}…)`);
|
|
345
|
+
return info;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* `autodev leader-stop <root>` — kill the leader + keepalive pid-trees named in
|
|
349
|
+
* `.autodev/leader.json` and clean up the socket / sid / json. This is what the
|
|
350
|
+
* app calls on office stop / remove / quit. Best-effort; returns whether anything
|
|
351
|
+
* was reaped.
|
|
352
|
+
*/
|
|
353
|
+
function stopLeader(root, log) {
|
|
354
|
+
const info = readLeaderInfo(root);
|
|
355
|
+
let killed = false;
|
|
356
|
+
if (info) {
|
|
357
|
+
if (info.keepalivePid && isPidAlive(info.keepalivePid)) {
|
|
358
|
+
try {
|
|
359
|
+
(0, killProcessTree_1.killProcessTree)(info.keepalivePid);
|
|
360
|
+
killed = true;
|
|
361
|
+
}
|
|
362
|
+
catch { /* ignore */ }
|
|
363
|
+
}
|
|
364
|
+
if (info.pid && isPidAlive(info.pid)) {
|
|
365
|
+
try {
|
|
366
|
+
(0, killProcessTree_1.killProcessTree)(info.pid);
|
|
367
|
+
killed = true;
|
|
368
|
+
}
|
|
369
|
+
catch { /* ignore */ }
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
if (info.socket) {
|
|
373
|
+
fs.unlinkSync(info.socket);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
catch { /* ignore */ }
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
fs.unlinkSync(leaderSocketPath(root));
|
|
380
|
+
}
|
|
381
|
+
catch { /* ignore */ }
|
|
382
|
+
try {
|
|
383
|
+
fs.unlinkSync(leaderSidPath(root));
|
|
384
|
+
}
|
|
385
|
+
catch { /* ignore */ }
|
|
386
|
+
removeLeaderInfo(root);
|
|
387
|
+
log(killed ? `leader-stop: reaped grok leader backend for ${root}` : `leader-stop: no live grok leader for ${root}`);
|
|
388
|
+
return killed;
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=leader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leader.js","sourceRoot":"","sources":["../../../src/providers/grok/leader.ts"],"names":[],"mappings":";AAAA,8EAA8E;AAC9E,iFAAiF;AACjF,EAAE;AACF,wEAAwE;AACxE,8EAA8E;AAC9E,gFAAgF;AAChF,gFAAgF;AAChF,kBAAkB;AAClB,EAAE;AACF,mFAAmF;AACnF,2BAA2B;AAC3B,0EAA0E;AAC1E,iFAAiF;AACjF,gFAAgF;AAChF,iFAAiF;AACjF,kFAAkF;AAClF,mFAAmF;AACnF,oFAAoF;AACpF,8EAA8E;AAC9E,iFAAiF;AACjF,gFAAgF;AAChF,6EAA6E;AAC7E,0BAA0B;AAC1B,0EAA0E;AAC1E,6EAA6E;AAC7E,+EAA+E;AAC/E,+CAA+C;AAC/C,EAAE;AACF,0EAA0E;AAC1E,gFAAgF;AAChF,iFAAiF;AACjF,mFAAmF;AACnF,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4B9E,8CAGC;AAKD,4CAKC;AAED,wCAA2G;AAC3G,sCAA8G;AAE9G,wCAOC;AAED,0CAEC;AAED,4CAEC;AAID,gCAGC;AAOD,gDAQC;AAGD,sCAIC;AAmBD,gDAIC;AAuBD,oCAkEC;AAQD,gCAaC;AA7ND,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAC7B,+CAAiC;AACjC,6DAA+C;AAC/C,gEAA6D;AAC7D,qDAA6E;AAG7E,mFAAmF;AACnF,yCAA2C;AAAlC,yGAAA,YAAY,OAAA;AAerB,+EAA+E;AAC/E,SAAgB,iBAAiB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACpE,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC1E,OAAO,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,CAAC;AACxE,CAAC;AAED;;+DAE+D;AAC/D,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAClE,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC;QAAC,OAAO,SAAS,CAAC;IAAC,CAAC;IAC9D,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,SAAgB,cAAc,CAAC,IAAY,IAAY,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;AAC3G,SAAgB,aAAa,CAAC,IAAY,IAAY,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAE9G,SAAgB,cAAc,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;QAC3C,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;IAC/F,CAAC;IAAC,MAAM,CAAC,CAAC,wBAAwB,CAAC,CAAC;IACpC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,eAAe,CAAC,IAAY,EAAE,IAAgB;IAC5D,IAAI,CAAC;QAAC,IAAA,yBAAU,EAAC,IAAI,CAAC,CAAC;QAAC,EAAE,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;AACtI,CAAC;AAED,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,IAAI,CAAC;QAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;AAC3E,CAAC;AAED;0CAC0C;AAC1C,SAAgB,UAAU,CAAC,GAAuB;IAChD,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;IACjE,IAAI,CAAC;QAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAQ,GAA6B,EAAE,IAAI,KAAK,OAAO,CAAC;IAAC,CAAC;AACrH,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB,CAChC,IAAuB,EACvB,KAA+D;IAE/D,IAAI,CAAC,IAAI,EAAE,CAAC;QAAC,OAAO,OAAO,CAAC;IAAC,CAAC;IAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,IAAI,KAAK,CAAC,MAAM,IAAI,WAAW,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QAAC,OAAO,OAAO,CAAC;IAAC,CAAC;IACpE,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,mEAAmE;AACnE,SAAgB,aAAa,CAAC,IAAuB;IACnD,IAAI,CAAC,IAAI,EAAE,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YAAC,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACnL,OAAO,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC;AACrD,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,IAAI,CAAC;QAAC,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AACrG,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,IAAmB,EAAE,EAAU,EAAE,MAAM,GAAG,GAAG;IACpE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAC5B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;QAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,CAAC;IAC1G,OAAO,IAAI,EAAE,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,CAAC;QAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,QAAQ,CAAC;IAAC,CAAC;AACnE,CAAC;AAED;;8CAE8C;AAC9C,SAAgB,kBAAkB;IAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACxD,IAAI,QAAQ,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAAC,OAAO,QAAQ,CAAC;IAAC,CAAC;IAC7D,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAClD,CAAC;AAED,2EAA2E;AAC3E,SAAS,eAAe,CAAC,IAAgB;IACvC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QAAC,IAAI,CAAC;YAAC,IAAA,iCAAe,EAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAAC,CAAC;IAC7F,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QAAC,IAAI,CAAC;YAAC,IAAA,iCAAe,EAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAAC,CAAC;AAC7E,CAAC;AAUD;;;;;;GAMG;AACI,KAAK,UAAU,YAAY,CAAC,IAAsB;IACvD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACnD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,QAAQ,IAAI,aAAa,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxC,GAAG,CAAC,8CAA8C,QAAQ,CAAC,GAAG,cAAc,QAAQ,CAAC,YAAY,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC5J,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,GAAG,CAAC,8CAA8C,QAAQ,CAAC,GAAG,cAAc,QAAQ,CAAC,YAAY,IAAI,GAAG,GAAG,CAAC,CAAC;QAC7G,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC1B,gBAAgB,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC;QAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC;IAC9D,IAAA,yBAAU,EAAC,IAAI,CAAC,CAAC;IAEjB,wCAAwC;IACxC,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAC1J,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC9E,IAAI,WAAuC,CAAC;IAC5C,IAAI,CAAC;QACH,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,UAAU,EAAE;YACjD,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI;YACzB,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC;YACxC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,gBAAgB,EAAE;SACvE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,GAAG,CAAC,8BAA+B,GAAa,EAAE,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACpG,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC;IAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACxE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,KAAK,CAAC;IAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAChH,IAAI,CAAC,MAAM,EAAE,CAAC;QAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAAC,IAAI,CAAC;YAAC,IAAA,iCAAe,EAAC,SAAS,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IAE7I,+EAA+E;IAC/E,2EAA2E;IAC3E,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC;QAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,IAAA,2BAAY,EAAC,IAAI,EAAE,UAAU,CAAC,IAAI,SAAS,CAAC;IACzD,MAAM,MAAM,GAAG,CAAC,kBAAkB,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC9G,IAAI,IAAI,EAAE,CAAC;QAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAAC,CAAC;IAC1C,IAAI,OAAmC,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE;YACtD,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ;YAC1C,6EAA6E;YAC7E,yEAAyE;YACzE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,oBAAoB,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,gBAAgB,EAAE;SAClG,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,GAAG,CAAC,wCAAyC,GAAa,EAAE,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC;QAAC,IAAI,CAAC;YAAC,IAAA,iCAAe,EAAC,SAAS,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACzK,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;IACpD,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3C,GAAG,CAAC,gEAAgE,CAAC,CAAC;QACtE,IAAI,YAAY,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,IAAA,iCAAe,EAAC,YAAY,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAAC,CAAC;QACnF,IAAI,CAAC;YAAC,IAAA,iCAAe,EAAC,SAAS,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAAe,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACxH,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC;QAAC,IAAA,4BAAa,EAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAC1E,GAAG,CAAC,mCAAmC,SAAS,cAAc,YAAY,QAAQ,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7G,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,IAAY,EAAE,GAA0B;IACjE,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,IAAI,CAAC,YAAY,IAAI,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,IAAA,iCAAe,EAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAAC,MAAM,GAAG,IAAI,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAAC,CAAC;QAC7I,IAAI,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,IAAA,iCAAe,EAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAAC,MAAM,GAAG,IAAI,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QAAC,CAAC;QAClH,IAAI,CAAC;YAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,CAAC;QAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACrE,IAAI,CAAC;QAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAClE,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,+CAA+C,IAAI,EAAE,CAAC,CAAC,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;IACrH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -111,6 +111,8 @@ const grokEvents_1 = require("../../core/grokEvents");
|
|
|
111
111
|
const sessions_1 = require("./sessions");
|
|
112
112
|
const redactSecrets_1 = require("../../core/redactSecrets");
|
|
113
113
|
const GrokAcpSession_1 = require("./GrokAcpSession");
|
|
114
|
+
const AcpSession_1 = require("../acp/AcpSession");
|
|
115
|
+
const leader_1 = require("./leader");
|
|
114
116
|
// ---------------------------------------------------------------------------
|
|
115
117
|
// Constants
|
|
116
118
|
// ---------------------------------------------------------------------------
|
|
@@ -2378,20 +2380,10 @@ function sendGrokCliPrompt(root, promptFilePath, resolvedSessionId, stdoutFile,
|
|
|
2378
2380
|
// ---------------------------------------------------------------------------
|
|
2379
2381
|
// PERSISTENT-PROCESS (ACP) path — one long-lived `grok agent stdio` per root.
|
|
2380
2382
|
// ---------------------------------------------------------------------------
|
|
2381
|
-
/**
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
return sess;
|
|
2386
|
-
}
|
|
2387
|
-
// Resume-on-(re)start: seed the id to session/load from the persisted id, else
|
|
2388
|
-
// the newest grok session on disk for this cwd (works whether that session was
|
|
2389
|
-
// created by a prior ACP run or the legacy headless `--continue`).
|
|
2390
|
-
// Layer A.2: PREFER the persisted id (session-state.json) over the disk-latest
|
|
2391
|
-
// fallback — disk-latest can resume the WRONG session (a stray/newer dir). Use
|
|
2392
|
-
// disk-latest ONLY when there is no persisted id.
|
|
2393
|
-
const seedId = (0, sessionState_1.getSessionId)(root, providerId) || resolvedSessionId || (0, sessions_1.getGrokLatestSessionId)(root) || undefined;
|
|
2394
|
-
const hooks = {
|
|
2383
|
+
/** Redaction-aware AcpHostHooks that append to this root's hook feed. Shared by
|
|
2384
|
+
* the non-leader and leader ACP paths so hook emission stays in one place. */
|
|
2385
|
+
function makeAcpHooks(root, log) {
|
|
2386
|
+
return {
|
|
2395
2387
|
emitHook: (name, extra) => {
|
|
2396
2388
|
if (name === 'Notification' && typeof extra['message'] === 'string') {
|
|
2397
2389
|
const msg = (0, redactSecrets_1.redactSecrets)(String(extra['message'])).slice(0, 1200);
|
|
@@ -2406,10 +2398,88 @@ function getOrCreateAcpSession(root, providerId, model, log, resolvedSessionId)
|
|
|
2406
2398
|
},
|
|
2407
2399
|
log,
|
|
2408
2400
|
};
|
|
2409
|
-
|
|
2401
|
+
}
|
|
2402
|
+
/** Get (or lazily create) the NON-LEADER persistent ACP session for a root. */
|
|
2403
|
+
function getOrCreateAcpSession(root, providerId, model, log, resolvedSessionId) {
|
|
2404
|
+
let sess = _acpSessions.get(root);
|
|
2405
|
+
if (sess) {
|
|
2406
|
+
return sess;
|
|
2407
|
+
}
|
|
2408
|
+
// Resume-on-(re)start: seed the id to session/load from the persisted id, else
|
|
2409
|
+
// the newest grok session on disk for this cwd (works whether that session was
|
|
2410
|
+
// created by a prior ACP run or the legacy headless `--continue`).
|
|
2411
|
+
// Layer A.2: PREFER the persisted id (session-state.json) over the disk-latest
|
|
2412
|
+
// fallback — disk-latest can resume the WRONG session (a stray/newer dir). Use
|
|
2413
|
+
// disk-latest ONLY when there is no persisted id.
|
|
2414
|
+
const seedId = (0, sessionState_1.getSessionId)(root, providerId) || resolvedSessionId || (0, sessions_1.getGrokLatestSessionId)(root) || undefined;
|
|
2415
|
+
sess = new GrokAcpSession_1.GrokAcpSession({ root, model, bin: GROK_BIN, hooks: makeAcpHooks(root, log), initialSessionId: seedId });
|
|
2410
2416
|
_acpSessions.set(root, sess);
|
|
2411
2417
|
return sess;
|
|
2412
2418
|
}
|
|
2419
|
+
/**
|
|
2420
|
+
* LEADER-AWARE ensure (Layer B, 1.4.193). When AUTODEV_GROK_LEADER is ON, ensure a
|
|
2421
|
+
* per-agent leader + keepalive backend (orphan-sweeping/adopting/spawning as
|
|
2422
|
+
* needed) and return a LEADER-CLIENT ACP session that ATTACHES to the warm session
|
|
2423
|
+
* WITHOUT session/load. When the flag is OFF — or the leader backend can't be
|
|
2424
|
+
* established — this returns the existing non-leader session UNCHANGED. Async
|
|
2425
|
+
* because ensuring the leader spawns detached processes on a cold start.
|
|
2426
|
+
*/
|
|
2427
|
+
async function ensureAcpSession(root, providerId, model, log, resolvedSessionId) {
|
|
2428
|
+
if ((0, leader_1.leaderModeEnabled)()) {
|
|
2429
|
+
const cached = _acpSessions.get(root);
|
|
2430
|
+
if (cached && cached.isAlive()) {
|
|
2431
|
+
return cached;
|
|
2432
|
+
}
|
|
2433
|
+
if (cached) {
|
|
2434
|
+
try {
|
|
2435
|
+
cached.close();
|
|
2436
|
+
}
|
|
2437
|
+
catch { /* ignore */ }
|
|
2438
|
+
_acpSessions.delete(root);
|
|
2439
|
+
}
|
|
2440
|
+
const info = await (0, leader_1.ensureLeader)({ root, bin: GROK_BIN, providerId, model, log });
|
|
2441
|
+
if (info) {
|
|
2442
|
+
const sess = new GrokAcpSession_1.GrokAcpSession({
|
|
2443
|
+
root, model, bin: GROK_BIN, hooks: makeAcpHooks(root, log),
|
|
2444
|
+
initialSessionId: info.sessionId, leaderSocket: info.socket, attachWithoutLoad: true,
|
|
2445
|
+
});
|
|
2446
|
+
_acpSessions.set(root, sess);
|
|
2447
|
+
return sess;
|
|
2448
|
+
}
|
|
2449
|
+
log('grok leader: backend unavailable — falling back to the non-leader ACP path');
|
|
2450
|
+
}
|
|
2451
|
+
return getOrCreateAcpSession(root, providerId, model, log, resolvedSessionId);
|
|
2452
|
+
}
|
|
2453
|
+
/**
|
|
2454
|
+
* Leader POISON-ESCAPE: the attached session id was rejected by the leader
|
|
2455
|
+
* ("unknown session id" — the keepalive died / a wrong id). Reap the leader
|
|
2456
|
+
* backend, clear the persisted id, drop the thin client — the caller then
|
|
2457
|
+
* re-ensures a FRESH leader with session/new.
|
|
2458
|
+
*/
|
|
2459
|
+
function recoverLeaderPoison(root, providerId, log) {
|
|
2460
|
+
try {
|
|
2461
|
+
(0, leader_1.stopLeader)(root, log);
|
|
2462
|
+
}
|
|
2463
|
+
catch { /* ignore */ }
|
|
2464
|
+
try {
|
|
2465
|
+
(0, sessionState_1.clearSessionId)(root, providerId);
|
|
2466
|
+
}
|
|
2467
|
+
catch { /* ignore */ }
|
|
2468
|
+
const s = _acpSessions.get(root);
|
|
2469
|
+
if (s) {
|
|
2470
|
+
if (s.pid) {
|
|
2471
|
+
try {
|
|
2472
|
+
(0, killProcessTree_1.killProcessTree)(s.pid);
|
|
2473
|
+
}
|
|
2474
|
+
catch { /* ignore */ }
|
|
2475
|
+
}
|
|
2476
|
+
try {
|
|
2477
|
+
s.close();
|
|
2478
|
+
}
|
|
2479
|
+
catch { /* ignore */ }
|
|
2480
|
+
_acpSessions.delete(root);
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2413
2483
|
/**
|
|
2414
2484
|
* Fire-and-forget: run ONE turn through the persistent ACP session. Streams
|
|
2415
2485
|
* assistant text to stdoutFile and writes the exit code to exitFile exactly once
|
|
@@ -2443,7 +2513,6 @@ function sendGrokAcpPrompt(root, promptFilePath, resolvedSessionId, stdoutFile,
|
|
|
2443
2513
|
catch { /* ignore */ }
|
|
2444
2514
|
return;
|
|
2445
2515
|
}
|
|
2446
|
-
const sess = getOrCreateAcpSession(root, providerId, model, log, resolvedSessionId);
|
|
2447
2516
|
_busyRoots.add(root);
|
|
2448
2517
|
if (showOutput) {
|
|
2449
2518
|
try {
|
|
@@ -2456,23 +2525,29 @@ function sendGrokAcpPrompt(root, promptFilePath, resolvedSessionId, stdoutFile,
|
|
|
2456
2525
|
}
|
|
2457
2526
|
catch { /* ignore */ } };
|
|
2458
2527
|
void (async () => {
|
|
2528
|
+
let sess;
|
|
2459
2529
|
try {
|
|
2530
|
+
sess = await ensureAcpSession(root, providerId, model, log, resolvedSessionId);
|
|
2460
2531
|
await sess.ensureReady();
|
|
2461
2532
|
}
|
|
2462
2533
|
catch (err) {
|
|
2463
|
-
const
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2534
|
+
const cur = _acpSessions.get(root);
|
|
2535
|
+
const stderr = cur?.stderrSnapshot ?? '';
|
|
2536
|
+
const startupErr = `${err?.message ?? err} ${stderr}`;
|
|
2537
|
+
log(`Grok ACP: startup failed (${err?.message ?? err}); stderr="${stderr.slice(0, 200)}" — falling back to headless one-shot`);
|
|
2538
|
+
if (cur) {
|
|
2539
|
+
try {
|
|
2540
|
+
cur.close();
|
|
2541
|
+
}
|
|
2542
|
+
catch { /* ignore */ }
|
|
2467
2543
|
}
|
|
2468
|
-
catch { /* ignore */ }
|
|
2469
2544
|
_acpSessions.delete(root);
|
|
2470
2545
|
_busyRoots.delete(root);
|
|
2471
2546
|
// AUTH failure at ACP startup (grok not signed in): the headless fallback
|
|
2472
2547
|
// would just re-hit the same logged-out gate, so short-circuit to
|
|
2473
2548
|
// reauth_required (non-retryable) instead of falling through.
|
|
2474
2549
|
if ((0, authClassify_1.isGrokAuthFailure)(startupErr)) {
|
|
2475
|
-
_emitGrokReauthHook(root, stdoutFile, log, 'ACP startup (not signed in)', providerId,
|
|
2550
|
+
_emitGrokReauthHook(root, stdoutFile, log, 'ACP startup (not signed in)', providerId, stderr.slice(0, 160));
|
|
2476
2551
|
try {
|
|
2477
2552
|
fs.writeFileSync(exitFile, '1\n', 'utf8');
|
|
2478
2553
|
}
|
|
@@ -2491,12 +2566,34 @@ function sendGrokAcpPrompt(root, promptFilePath, resolvedSessionId, stdoutFile,
|
|
|
2491
2566
|
}
|
|
2492
2567
|
catch { /* ignore */ }
|
|
2493
2568
|
}
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2569
|
+
const runTurnSafe = async (s) => {
|
|
2570
|
+
try {
|
|
2571
|
+
return await s.runTurn(promptText, sink);
|
|
2572
|
+
}
|
|
2573
|
+
catch (err) {
|
|
2574
|
+
return { clean: false, stopReason: 'exception', error: err?.message ?? String(err) };
|
|
2575
|
+
}
|
|
2576
|
+
};
|
|
2577
|
+
let res = await runTurnSafe(sess);
|
|
2578
|
+
// Leader POISON-ESCAPE: the warm session was rejected (keepalive died / stale
|
|
2579
|
+
// id). Reap the leader + session/new on a FRESH leader, then retry ONCE.
|
|
2580
|
+
if ((0, leader_1.leaderModeEnabled)() && sess.attachMode && !res.clean && AcpSession_1.AcpSession.isUnknownSessionError(res.error)) {
|
|
2581
|
+
log('Grok leader: attach rejected (poison) — reaping leader, starting a fresh session, retrying once');
|
|
2582
|
+
recoverLeaderPoison(root, providerId, log);
|
|
2583
|
+
try {
|
|
2584
|
+
sess = await ensureAcpSession(root, providerId, model, log, undefined);
|
|
2585
|
+
await sess.ensureReady();
|
|
2586
|
+
if (sess.sessionId) {
|
|
2587
|
+
try {
|
|
2588
|
+
(0, sessionState_1.saveSessionId)(root, providerId, sess.sessionId);
|
|
2589
|
+
}
|
|
2590
|
+
catch { /* ignore */ }
|
|
2591
|
+
}
|
|
2592
|
+
res = await runTurnSafe(sess);
|
|
2593
|
+
}
|
|
2594
|
+
catch (err) {
|
|
2595
|
+
res = { clean: false, stopReason: 'poison-recover-failed', error: err?.message ?? String(err) };
|
|
2596
|
+
}
|
|
2500
2597
|
}
|
|
2501
2598
|
if (!res.clean && res.error) {
|
|
2502
2599
|
try {
|
|
@@ -2572,7 +2669,7 @@ async function ensureGrokAcpSteer(root, providerId, model, text, log) {
|
|
|
2572
2669
|
if (!grokAcpEnabled()) {
|
|
2573
2670
|
return null;
|
|
2574
2671
|
}
|
|
2575
|
-
const sess =
|
|
2672
|
+
const sess = await ensureAcpSession(root, providerId, model, log, undefined);
|
|
2576
2673
|
try {
|
|
2577
2674
|
await sess.ensureReady();
|
|
2578
2675
|
}
|
|
@@ -2835,6 +2932,10 @@ function closeGrokTuiSession(root, _log) {
|
|
|
2835
2932
|
if (acp) {
|
|
2836
2933
|
// Reap grok's whole worker subtree (grok forks a per-turn worker child), then
|
|
2837
2934
|
// close — SIGKILL of just the parent would orphan the worker to init.
|
|
2935
|
+
// LEADER-AWARE (Layer B): acp.pid here is the THIN CLIENT. The leader + keepalive
|
|
2936
|
+
// are DETACHED (their own process groups, not in the client's tree), so this
|
|
2937
|
+
// reaps ONLY the client — the leader survives the loop restart, exactly as
|
|
2938
|
+
// intended. The app reaps the leader itself via `autodev leader-stop <root>`.
|
|
2838
2939
|
if (acp.pid) {
|
|
2839
2940
|
try {
|
|
2840
2941
|
(0, killProcessTree_1.killProcessTree)(acp.pid);
|