gm-codex 2.0.951 → 2.0.952
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/.codex-plugin/plugin.json +1 -1
- package/bin/bootstrap.js +83 -12
- package/gm.json +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
package/bin/bootstrap.js
CHANGED
|
@@ -328,12 +328,14 @@ async function bootstrap(opts) {
|
|
|
328
328
|
if (fs.existsSync(finalPath) && fs.existsSync(okSentinel)) {
|
|
329
329
|
if (!opts.silent) log(`cache hit: ${finalPath}`);
|
|
330
330
|
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
331
|
+
proactiveKillForNewInstall(version, finalPath);
|
|
331
332
|
return finalPath;
|
|
332
333
|
}
|
|
333
334
|
|
|
334
335
|
if (healIfShaMatches(finalPath, expectedSha, okSentinel, partialPath, 'plugkit')) {
|
|
335
336
|
if (!opts.silent) log(`cache heal (sha match): ${finalPath}`);
|
|
336
337
|
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
338
|
+
proactiveKillForNewInstall(version, finalPath);
|
|
337
339
|
try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent, root); }
|
|
338
340
|
catch (err) { log(`rtk fetch skipped: ${err.message}`); }
|
|
339
341
|
return finalPath;
|
|
@@ -344,11 +346,13 @@ async function bootstrap(opts) {
|
|
|
344
346
|
try {
|
|
345
347
|
if (fs.existsSync(finalPath) && fs.existsSync(okSentinel)) {
|
|
346
348
|
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
349
|
+
proactiveKillForNewInstall(version, finalPath);
|
|
347
350
|
return finalPath;
|
|
348
351
|
}
|
|
349
352
|
if (healIfShaMatches(finalPath, expectedSha, okSentinel, partialPath, 'plugkit')) {
|
|
350
353
|
log(`cache heal (sha match) under lock: ${finalPath}`);
|
|
351
354
|
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
355
|
+
proactiveKillForNewInstall(version, finalPath);
|
|
352
356
|
try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent, root); }
|
|
353
357
|
catch (err) { log(`rtk fetch skipped: ${err.message}`); }
|
|
354
358
|
return finalPath;
|
|
@@ -393,7 +397,7 @@ async function bootstrap(opts) {
|
|
|
393
397
|
log(`installed ${finalPath}`);
|
|
394
398
|
obsEvent('bootstrap', 'install.done', { path: finalPath, version, kind: 'plugkit' });
|
|
395
399
|
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
396
|
-
proactiveKillForNewInstall(version);
|
|
400
|
+
proactiveKillForNewInstall(version, finalPath);
|
|
397
401
|
try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent, root); }
|
|
398
402
|
catch (err) { log(`rtk fetch skipped: ${err.message}`); }
|
|
399
403
|
return finalPath;
|
|
@@ -539,6 +543,60 @@ function killRunningDaemons(reason) {
|
|
|
539
543
|
return killedPids;
|
|
540
544
|
}
|
|
541
545
|
|
|
546
|
+
function listRunningPlugkitImagePaths() {
|
|
547
|
+
const out = [];
|
|
548
|
+
try {
|
|
549
|
+
const { spawnSync } = require('child_process');
|
|
550
|
+
if (os.platform() === 'win32') {
|
|
551
|
+
const r = spawnSync('tasklist', ['/FI', 'IMAGENAME eq plugkit*', '/FO', 'CSV', '/NH'], { windowsHide: true, encoding: 'utf8' });
|
|
552
|
+
const text = (r && r.stdout) || '';
|
|
553
|
+
const seen = new Set();
|
|
554
|
+
for (const line of text.split(/\r?\n/)) {
|
|
555
|
+
const m = line.match(/^"([^"]+)","(\d+)"/);
|
|
556
|
+
if (!m) continue;
|
|
557
|
+
const pid = parseInt(m[2], 10);
|
|
558
|
+
if (!Number.isFinite(pid) || seen.has(pid)) continue;
|
|
559
|
+
seen.add(pid);
|
|
560
|
+
let imagePath = '';
|
|
561
|
+
try {
|
|
562
|
+
const p = spawnSync('powershell', ['-NoProfile', '-NonInteractive', '-Command', `(Get-Process -Id ${pid} -ErrorAction SilentlyContinue).Path`], { windowsHide: true, encoding: 'utf8' });
|
|
563
|
+
imagePath = ((p && p.stdout) || '').trim();
|
|
564
|
+
} catch (_) {}
|
|
565
|
+
out.push({ pid, path: imagePath });
|
|
566
|
+
}
|
|
567
|
+
} else if (os.platform() === 'linux') {
|
|
568
|
+
let entries = [];
|
|
569
|
+
try { entries = fs.readdirSync('/proc'); } catch (_) {}
|
|
570
|
+
for (const e of entries) {
|
|
571
|
+
if (!/^\d+$/.test(e)) continue;
|
|
572
|
+
const pid = parseInt(e, 10);
|
|
573
|
+
let comm = '';
|
|
574
|
+
try { comm = fs.readFileSync(`/proc/${pid}/comm`, 'utf8').trim(); } catch (_) { continue; }
|
|
575
|
+
if (!/^plugkit/i.test(comm)) continue;
|
|
576
|
+
let imagePath = '';
|
|
577
|
+
try { imagePath = fs.readlinkSync(`/proc/${pid}/exe`); } catch (_) {}
|
|
578
|
+
out.push({ pid, path: imagePath });
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
const r = spawnSync('ps', ['-axo', 'pid=,comm='], { encoding: 'utf8' });
|
|
582
|
+
const text = (r && r.stdout) || '';
|
|
583
|
+
for (const line of text.split(/\r?\n/)) {
|
|
584
|
+
const m = line.match(/^\s*(\d+)\s+(.+?)\s*$/);
|
|
585
|
+
if (!m) continue;
|
|
586
|
+
if (!/plugkit/i.test(m[2])) continue;
|
|
587
|
+
const pid = parseInt(m[1], 10);
|
|
588
|
+
let imagePath = '';
|
|
589
|
+
try {
|
|
590
|
+
const p = spawnSync('ps', ['-p', String(pid), '-o', 'command='], { encoding: 'utf8' });
|
|
591
|
+
imagePath = ((p && p.stdout) || '').trim().split(/\s+/)[0] || '';
|
|
592
|
+
} catch (_) {}
|
|
593
|
+
out.push({ pid, path: imagePath });
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
} catch (_) {}
|
|
597
|
+
return out;
|
|
598
|
+
}
|
|
599
|
+
|
|
542
600
|
function killSpoolWatcherInCwd(reason) {
|
|
543
601
|
try {
|
|
544
602
|
const pidPath = path.join(process.cwd(), '.gm', 'exec-spool', '.watcher.pid');
|
|
@@ -554,19 +612,27 @@ function killSpoolWatcherInCwd(reason) {
|
|
|
554
612
|
return null;
|
|
555
613
|
}
|
|
556
614
|
|
|
557
|
-
function proactiveKillForNewInstall(installedVersion) {
|
|
615
|
+
function proactiveKillForNewInstall(installedVersion, finalPath) {
|
|
558
616
|
try {
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if (
|
|
567
|
-
if (
|
|
568
|
-
|
|
617
|
+
const reason = `install:v${installedVersion}`;
|
|
618
|
+
const target = finalPath ? path.resolve(finalPath).toLowerCase() : null;
|
|
619
|
+
const cacheRootNorm = (() => {
|
|
620
|
+
try { return path.resolve(cacheRoot()).toLowerCase(); } catch (_) { return null; }
|
|
621
|
+
})();
|
|
622
|
+
const procs = listRunningPlugkitImagePaths();
|
|
623
|
+
for (const { pid, path: imagePath } of procs) {
|
|
624
|
+
if (!Number.isFinite(pid) || pid === process.pid) continue;
|
|
625
|
+
if (!imagePath) continue;
|
|
626
|
+
const norm = path.resolve(imagePath).toLowerCase();
|
|
627
|
+
if (target && norm === target) continue;
|
|
628
|
+
if (!cacheRootNorm || !norm.startsWith(cacheRootNorm + path.sep.toLowerCase())) continue;
|
|
629
|
+
if (killPid(pid)) {
|
|
630
|
+
try { process.stderr.write(`[bootstrap] killed stale daemon pid=${pid} path=${imagePath} (current install: v${installedVersion})\n`); } catch (_) {}
|
|
631
|
+
obsEvent('bootstrap', 'daemon.killed', { pid, oldPath: imagePath, installedVersion, mechanism: 'process-path' });
|
|
632
|
+
}
|
|
569
633
|
}
|
|
634
|
+
killRunningDaemons(reason);
|
|
635
|
+
killSpoolWatcherInCwd(reason);
|
|
570
636
|
writeDaemonVersion(installedVersion);
|
|
571
637
|
} catch (_) {}
|
|
572
638
|
}
|
|
@@ -576,6 +642,11 @@ function proactiveKillForNewInstall(installedVersion) {
|
|
|
576
642
|
function killStaleDaemonIfVersionChanged(wrapperDir) {
|
|
577
643
|
let currentVersion;
|
|
578
644
|
try { currentVersion = readVersionFile(wrapperDir); } catch (_) { return; }
|
|
645
|
+
const cached = resolveCachedBinary({ wrapperDir, version: currentVersion });
|
|
646
|
+
if (cached) {
|
|
647
|
+
proactiveKillForNewInstall(currentVersion, cached);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
579
650
|
const recorded = readDaemonVersion();
|
|
580
651
|
if (recorded === currentVersion) return;
|
|
581
652
|
if (recorded) killRunningDaemons(`version_change:${recorded}->${currentVersion}`);
|
package/gm.json
CHANGED
package/package.json
CHANGED