gm-codex 2.0.947 → 2.0.949
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 +94 -26
- package/bin/plugkit.sha256 +6 -6
- package/bin/rtk.sha256 +2 -2
- package/gm.json +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
package/bin/bootstrap.js
CHANGED
|
@@ -88,6 +88,43 @@ function readVersionFile(wrapperDir) {
|
|
|
88
88
|
return fs.readFileSync(p, 'utf8').trim();
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
function readRtkVersion(wrapperDir) {
|
|
92
|
+
const p = path.join(wrapperDir, 'rtk.version');
|
|
93
|
+
if (!fs.existsSync(p)) return null;
|
|
94
|
+
const v = fs.readFileSync(p, 'utf8').trim();
|
|
95
|
+
return v || null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function sha256OfFileSync(filePath) {
|
|
99
|
+
const h = crypto.createHash('sha256');
|
|
100
|
+
const fd = fs.openSync(filePath, 'r');
|
|
101
|
+
try {
|
|
102
|
+
const buf = Buffer.alloc(1024 * 1024);
|
|
103
|
+
for (;;) {
|
|
104
|
+
const n = fs.readSync(fd, buf, 0, buf.length, null);
|
|
105
|
+
if (n <= 0) break;
|
|
106
|
+
h.update(buf.subarray(0, n));
|
|
107
|
+
}
|
|
108
|
+
} finally { try { fs.closeSync(fd); } catch (_) {} }
|
|
109
|
+
return h.digest('hex');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function healIfShaMatches(binPath, expectedSha, sentinelPath, partialPath, kind) {
|
|
113
|
+
if (!fs.existsSync(binPath)) return false;
|
|
114
|
+
if (partialPath) { try { if (fs.existsSync(partialPath)) fs.unlinkSync(partialPath); } catch (_) {} }
|
|
115
|
+
if (!expectedSha) return false;
|
|
116
|
+
let got;
|
|
117
|
+
try { got = sha256OfFileSync(binPath); }
|
|
118
|
+
catch (_) { return false; }
|
|
119
|
+
if (got !== expectedSha) {
|
|
120
|
+
try { fs.unlinkSync(binPath); } catch (_) {}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
try { fs.writeFileSync(sentinelPath, new Date().toISOString()); } catch (_) { return false; }
|
|
124
|
+
obsEvent('bootstrap', 'cache.heal', { path: binPath, kind });
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
91
128
|
function readShaManifest(wrapperDir, manifestName) {
|
|
92
129
|
const p = path.join(wrapperDir, manifestName || 'plugkit.sha256');
|
|
93
130
|
if (!fs.existsSync(p)) return null;
|
|
@@ -248,12 +285,15 @@ function isLockStale(lockPath) {
|
|
|
248
285
|
return false;
|
|
249
286
|
}
|
|
250
287
|
|
|
251
|
-
function pruneOldVersions(root, keepVersion) {
|
|
288
|
+
function pruneOldVersions(root, keepVersion, keepRtkVersion) {
|
|
252
289
|
try {
|
|
253
290
|
const entries = fs.readdirSync(root);
|
|
254
291
|
for (const e of entries) {
|
|
255
|
-
|
|
256
|
-
|
|
292
|
+
const isPlugkit = e.startsWith('v') && !e.startsWith('rtk-');
|
|
293
|
+
const isRtk = e.startsWith('rtk-v');
|
|
294
|
+
if (!isPlugkit && !isRtk) continue;
|
|
295
|
+
if (isPlugkit && e === `v${keepVersion}`) continue;
|
|
296
|
+
if (isRtk && keepRtkVersion && e === `rtk-v${keepRtkVersion}`) continue;
|
|
257
297
|
const dir = path.join(root, e);
|
|
258
298
|
const lock = path.join(dir, '.lock');
|
|
259
299
|
if (fs.existsSync(lock) && !isLockStale(lock)) continue;
|
|
@@ -283,10 +323,19 @@ async function bootstrap(opts) {
|
|
|
283
323
|
|
|
284
324
|
const finalPath = path.join(verDir, binName);
|
|
285
325
|
const okSentinel = path.join(verDir, '.ok');
|
|
326
|
+
const partialPath = `${finalPath}.partial`;
|
|
286
327
|
|
|
287
328
|
if (fs.existsSync(finalPath) && fs.existsSync(okSentinel)) {
|
|
288
329
|
if (!opts.silent) log(`cache hit: ${finalPath}`);
|
|
289
|
-
pruneOldVersions(root, version);
|
|
330
|
+
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
331
|
+
return finalPath;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (healIfShaMatches(finalPath, expectedSha, okSentinel, partialPath, 'plugkit')) {
|
|
335
|
+
if (!opts.silent) log(`cache heal (sha match): ${finalPath}`);
|
|
336
|
+
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
337
|
+
try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent, root); }
|
|
338
|
+
catch (err) { log(`rtk fetch skipped: ${err.message}`); }
|
|
290
339
|
return finalPath;
|
|
291
340
|
}
|
|
292
341
|
|
|
@@ -294,27 +343,33 @@ async function bootstrap(opts) {
|
|
|
294
343
|
acquireLock(lockPath);
|
|
295
344
|
try {
|
|
296
345
|
if (fs.existsSync(finalPath) && fs.existsSync(okSentinel)) {
|
|
297
|
-
pruneOldVersions(root, version);
|
|
346
|
+
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
347
|
+
return finalPath;
|
|
348
|
+
}
|
|
349
|
+
if (healIfShaMatches(finalPath, expectedSha, okSentinel, partialPath, 'plugkit')) {
|
|
350
|
+
log(`cache heal (sha match) under lock: ${finalPath}`);
|
|
351
|
+
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
352
|
+
try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent, root); }
|
|
353
|
+
catch (err) { log(`rtk fetch skipped: ${err.message}`); }
|
|
298
354
|
return finalPath;
|
|
299
355
|
}
|
|
300
356
|
|
|
301
|
-
|
|
302
|
-
if (fs.existsSync(tmpPath)) {
|
|
357
|
+
if (fs.existsSync(partialPath)) {
|
|
303
358
|
try {
|
|
304
|
-
const st = fs.statSync(
|
|
359
|
+
const st = fs.statSync(partialPath);
|
|
305
360
|
if (Date.now() - st.mtimeMs > LOCK_STALE_MS) {
|
|
306
|
-
fs.unlinkSync(
|
|
307
|
-
log(`cleared stale partial: ${
|
|
361
|
+
fs.unlinkSync(partialPath);
|
|
362
|
+
log(`cleared stale partial: ${partialPath}`);
|
|
308
363
|
}
|
|
309
364
|
} catch (_) {}
|
|
310
365
|
}
|
|
311
366
|
const url = `https://github.com/${RELEASE_REPO}/releases/download/v${version}/${binName}`;
|
|
312
|
-
await downloadWithRetry(url,
|
|
367
|
+
await downloadWithRetry(url, partialPath);
|
|
313
368
|
|
|
314
369
|
if (expectedSha) {
|
|
315
|
-
const got = await sha256OfFile(
|
|
370
|
+
const got = await sha256OfFile(partialPath);
|
|
316
371
|
if (got !== expectedSha) {
|
|
317
|
-
try { fs.unlinkSync(
|
|
372
|
+
try { fs.unlinkSync(partialPath); } catch (_) {}
|
|
318
373
|
throw new Error(`sha256 mismatch for ${binName}: expected ${expectedSha}, got ${got}`);
|
|
319
374
|
}
|
|
320
375
|
log('sha256 verified');
|
|
@@ -322,11 +377,11 @@ async function bootstrap(opts) {
|
|
|
322
377
|
log('no sha256 manifest — skipping verify');
|
|
323
378
|
}
|
|
324
379
|
|
|
325
|
-
try { fs.renameSync(
|
|
380
|
+
try { fs.renameSync(partialPath, finalPath); }
|
|
326
381
|
catch (err) {
|
|
327
382
|
if (err.code === 'EEXIST' || err.code === 'EPERM') {
|
|
328
383
|
try { fs.unlinkSync(finalPath); } catch (_) {}
|
|
329
|
-
fs.renameSync(
|
|
384
|
+
fs.renameSync(partialPath, finalPath);
|
|
330
385
|
} else throw err;
|
|
331
386
|
}
|
|
332
387
|
|
|
@@ -337,10 +392,9 @@ async function bootstrap(opts) {
|
|
|
337
392
|
fs.writeFileSync(okSentinel, new Date().toISOString());
|
|
338
393
|
log(`installed ${finalPath}`);
|
|
339
394
|
obsEvent('bootstrap', 'install.done', { path: finalPath, version, kind: 'plugkit' });
|
|
340
|
-
pruneOldVersions(root, version);
|
|
395
|
+
pruneOldVersions(root, version, readRtkVersion(wrapperDir));
|
|
341
396
|
proactiveKillForNewInstall(version);
|
|
342
|
-
|
|
343
|
-
try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent); }
|
|
397
|
+
try { await bootstrapRtk(verDir, version, wrapperDir, opts.silent, root); }
|
|
344
398
|
catch (err) { log(`rtk fetch skipped: ${err.message}`); }
|
|
345
399
|
return finalPath;
|
|
346
400
|
} finally {
|
|
@@ -348,10 +402,19 @@ async function bootstrap(opts) {
|
|
|
348
402
|
}
|
|
349
403
|
}
|
|
350
404
|
|
|
351
|
-
|
|
405
|
+
function rtkCacheDir(root, wrapperDir, plugkitVerDir) {
|
|
406
|
+
const rtkVer = readRtkVersion(wrapperDir);
|
|
407
|
+
if (!rtkVer) return plugkitVerDir;
|
|
408
|
+
const dir = path.join(root, `rtk-v${rtkVer}`);
|
|
409
|
+
ensureDir(dir);
|
|
410
|
+
return dir;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
async function bootstrapRtk(plugkitVerDir, plugkitVersion, wrapperDir, silent, root) {
|
|
352
414
|
const rtkName = rtkBinaryName();
|
|
353
|
-
const
|
|
354
|
-
const
|
|
415
|
+
const cacheDir = rtkCacheDir(root || cacheRoot(), wrapperDir, plugkitVerDir);
|
|
416
|
+
const rtkPath = path.join(cacheDir, rtkName);
|
|
417
|
+
const rtkOk = path.join(cacheDir, '.rtk-ok');
|
|
355
418
|
if (fs.existsSync(rtkPath) && fs.existsSync(rtkOk)) {
|
|
356
419
|
if (!silent) log(`rtk cache hit: ${rtkPath}`);
|
|
357
420
|
return rtkPath;
|
|
@@ -359,7 +422,11 @@ async function bootstrapRtk(verDir, version, wrapperDir, silent) {
|
|
|
359
422
|
const rtkSha = readShaManifest(wrapperDir, 'rtk.sha256');
|
|
360
423
|
const expected = rtkSha ? rtkSha[rtkName] : null;
|
|
361
424
|
const tmp = `${rtkPath}.partial`;
|
|
362
|
-
|
|
425
|
+
if (healIfShaMatches(rtkPath, expected, rtkOk, tmp, 'rtk')) {
|
|
426
|
+
if (!silent) log(`rtk cache heal (sha match): ${rtkPath}`);
|
|
427
|
+
return rtkPath;
|
|
428
|
+
}
|
|
429
|
+
const url = `https://github.com/${RELEASE_REPO}/releases/download/v${plugkitVersion}/${rtkName}`;
|
|
363
430
|
await downloadWithRetry(url, tmp);
|
|
364
431
|
if (expected) {
|
|
365
432
|
const got = await sha256OfFile(tmp);
|
|
@@ -378,7 +445,7 @@ async function bootstrapRtk(verDir, version, wrapperDir, silent) {
|
|
|
378
445
|
if (os.platform() !== 'win32') { try { fs.chmodSync(rtkPath, 0o755); } catch (_) {} }
|
|
379
446
|
fs.writeFileSync(rtkOk, new Date().toISOString());
|
|
380
447
|
log(`installed ${rtkPath}`);
|
|
381
|
-
obsEvent('bootstrap', 'install.done', { path: rtkPath,
|
|
448
|
+
obsEvent('bootstrap', 'install.done', { path: rtkPath, plugkit_version: plugkitVersion, rtk_version: readRtkVersion(wrapperDir) || plugkitVersion, kind: 'rtk' });
|
|
382
449
|
return rtkPath;
|
|
383
450
|
}
|
|
384
451
|
|
|
@@ -390,9 +457,10 @@ function resolveCachedRtk(opts) {
|
|
|
390
457
|
try { const r = cacheRoot(); ensureDir(r); return r; }
|
|
391
458
|
catch (_) { const r = fallbackCacheRoot(); ensureDir(r); return r; }
|
|
392
459
|
})();
|
|
393
|
-
const
|
|
394
|
-
const
|
|
395
|
-
const
|
|
460
|
+
const plugkitVerDir = path.join(root, `v${version}`);
|
|
461
|
+
const cacheDir = rtkCacheDir(root, wrapperDir, plugkitVerDir);
|
|
462
|
+
const rtkPath = path.join(cacheDir, rtkBinaryName());
|
|
463
|
+
const rtkOk = path.join(cacheDir, '.rtk-ok');
|
|
396
464
|
if (fs.existsSync(rtkPath) && fs.existsSync(rtkOk)) return rtkPath;
|
|
397
465
|
return null;
|
|
398
466
|
}
|
package/bin/plugkit.sha256
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
29c07cfbe1536e683a8892a2bfa459a879bd48bf0652adf606dea9a39e4d2fa7 plugkit-win32-x64.exe
|
|
2
|
+
5523ce4c5167cfb01f2dc5a865daf8dfedde321393f8a02743f224cd0b6bf610 plugkit-win32-arm64.exe
|
|
3
|
+
710fdb8a301c7b13b86677bbea64e2a54a092bb91c5fef0c8ec391795ab23202 plugkit-darwin-x64
|
|
4
|
+
082d56484e02458bbc97ba63b89010fd155265e74cb17c7d227ed57dbcef96c3 plugkit-darwin-arm64
|
|
5
|
+
b9d1f97cf048a9ab6345cd68177762a8603cd0f52e79e29c611cacb22adf02f7 plugkit-linux-x64
|
|
6
|
+
6c64c385204b903d661002daf2e6b287082a02e579ce9c5533a24828765e46ab plugkit-linux-arm64
|
package/bin/rtk.sha256
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
67e7f3aa39ab54376f90d040820ae471adc47374b0b9fa2527a09de9be73216b rtk-win32-x64.exe
|
|
2
|
+
7f0ce6ff2ae933fd82c5d309df3e06f2ba12b2a47b495ed54a8eacb096ef5264 rtk-win32-arm64.exe
|
|
3
3
|
1b1e792767ed0e1e6ca0e2f0a8de02e77b06dea2f5ae667278b94baf239fcdc3 rtk-darwin-x64
|
|
4
4
|
9717978d9d6216ea50c94444e00e359479b6315a17bd48c16064b267c8b0b60d rtk-darwin-arm64
|
|
5
5
|
a100d3defac54194144e5723aec57e6f286b42298c67145c8428815246c9ee56 rtk-linux-x64
|
package/gm.json
CHANGED
package/package.json
CHANGED