gm-plugkit 2.0.1718 → 2.0.1720

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-plugkit",
3
- "version": "2.0.1718",
3
+ "version": "2.0.1720",
4
4
  "description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -608,7 +608,12 @@ function stampBrowserLastUse(cwd, claudeSessionId) {
608
608
  function atomicWriteRaw(filePath, data) {
609
609
  const tmp = filePath + '.tmp.' + process.pid + '.' + Date.now() + '.' + Math.random().toString(36).slice(2, 8);
610
610
  fs.writeFileSync(tmp, data);
611
- fs.renameSync(tmp, filePath);
611
+ try {
612
+ fs.renameSync(tmp, filePath);
613
+ } catch (err) {
614
+ try { fs.unlinkSync(tmp); } catch (_) {}
615
+ throw err;
616
+ }
612
617
  }
613
618
 
614
619
  function atomicWriteJson(filePath, obj) {
@@ -1198,7 +1203,7 @@ function chromeLogHasSandboxDenied(chromeLogPath) {
1198
1203
  }
1199
1204
  }
1200
1205
 
1201
- function spawnChromiumOnce(browserBin, profileDir, port, headless, noSandbox) {
1206
+ function spawnChromiumOnce(browserBin, profileDir, port, headless, noSandbox, cwd) {
1202
1207
  const args = [
1203
1208
  '--user-data-dir=' + profileDir,
1204
1209
  '--remote-debugging-port=' + port,
@@ -1214,7 +1219,7 @@ function spawnChromiumOnce(browserBin, profileDir, port, headless, noSandbox) {
1214
1219
  if (headless) {
1215
1220
  args.push('--headless=new');
1216
1221
  } else {
1217
- args.push('about:blank');
1222
+ args.push(resolveBrowserStartUrl(cwd));
1218
1223
  }
1219
1224
  const chromeLogPath = path.join(profileDir, '.chrome-launch.log');
1220
1225
  let logFd;
@@ -1230,6 +1235,17 @@ function spawnChromiumOnce(browserBin, profileDir, port, headless, noSandbox) {
1230
1235
  return { pid: child.pid, chromeLogPath };
1231
1236
  }
1232
1237
 
1238
+ function resolveBrowserStartUrl(cwd) {
1239
+ if (process.env.GM_BROWSER_START_URL) return process.env.GM_BROWSER_START_URL;
1240
+ try {
1241
+ const root = cwd || process.env.CLAUDE_PROJECT_DIR || process.cwd();
1242
+ const cfgPath = path.join(root, '.gm', 'browser-target-url');
1243
+ const url = fs.readFileSync(cfgPath, 'utf-8').trim();
1244
+ if (url) return url;
1245
+ } catch (_) {}
1246
+ return 'about:blank';
1247
+ }
1248
+
1233
1249
  function waitForCdpReady(port, deadlineMs) {
1234
1250
  const start = Date.now();
1235
1251
  const deadline = start + deadlineMs;
@@ -1241,7 +1257,7 @@ function waitForCdpReady(port, deadlineMs) {
1241
1257
  return null;
1242
1258
  }
1243
1259
 
1244
- function startManagedBrowser(pw, profileDir) {
1260
+ function startManagedBrowser(pw, profileDir, cwd) {
1245
1261
  const rawHeadlessEnv = process.env.GM_BROWSER_HEADLESS;
1246
1262
  const headless = rawHeadlessEnv === '1';
1247
1263
  const unexpectedHeadlessEnv = rawHeadlessEnv !== undefined && rawHeadlessEnv !== '1';
@@ -1273,7 +1289,7 @@ function startManagedBrowser(pw, profileDir) {
1273
1289
  }
1274
1290
  const port = findFreePortSync();
1275
1291
  let noSandbox = process.env.GM_BROWSER_NO_SANDBOX === '1';
1276
- let { pid, chromeLogPath } = spawnChromiumOnce(browserBin, profileDir, port, headless, noSandbox);
1292
+ let { pid, chromeLogPath } = spawnChromiumOnce(browserBin, profileDir, port, headless, noSandbox, cwd);
1277
1293
  logEvent('plugkit', 'browser.chromium-launched', { pid, port, profileDir, headless, noSandbox, binary: browserBin, chromeLogPath });
1278
1294
  let ready = waitForCdpReady(port, 30000);
1279
1295
  if (!ready) {
@@ -1288,7 +1304,7 @@ function startManagedBrowser(pw, profileDir) {
1288
1304
  purgeProfileLockFiles(profileDir);
1289
1305
  noSandbox = true;
1290
1306
  const port2 = findFreePortSync();
1291
- ({ pid, chromeLogPath } = spawnChromiumOnce(browserBin, profileDir, port2, headless, noSandbox));
1307
+ ({ pid, chromeLogPath } = spawnChromiumOnce(browserBin, profileDir, port2, headless, noSandbox, cwd));
1292
1308
  logEvent('plugkit', 'browser.chromium-launched', { pid, port: port2, profileDir, headless, noSandbox, binary: browserBin, chromeLogPath, retry: true });
1293
1309
  ready = waitForCdpReady(port2, 30000);
1294
1310
  if (!ready) {
@@ -1485,7 +1501,7 @@ function getOrCreateBrowserSession(cwd, claudeSessionId, pw) {
1485
1501
  logEvent('plugkit', 'browser.reused-existing-chromium', { pid: browserPid, port, profileDir });
1486
1502
  } else {
1487
1503
  logEvent('plugkit', 'browser.start', { profileDir });
1488
- ({ pid: browserPid, port, wsEndpoint } = startManagedBrowser(pw, profileDir));
1504
+ ({ pid: browserPid, port, wsEndpoint } = startManagedBrowser(pw, profileDir, cwd));
1489
1505
  freshLaunch = true;
1490
1506
  }
1491
1507
  markLaunching(browserPid);
@@ -2913,6 +2929,22 @@ async function runSpoolWatcher(instance, spoolDir) {
2913
2929
  }
2914
2930
  writeBootActive();
2915
2931
 
2932
+ function sweepStaleAtomicTmpFiles(dir, maxAgeMs) {
2933
+ try {
2934
+ const entries = fs.readdirSync(dir);
2935
+ const now = Date.now();
2936
+ for (const name of entries) {
2937
+ if (!/\.tmp(\.|$)/.test(name)) continue;
2938
+ const full = path.join(dir, name);
2939
+ try {
2940
+ const st = fs.statSync(full);
2941
+ if (now - st.mtimeMs > maxAgeMs) fs.unlinkSync(full);
2942
+ } catch (_) {}
2943
+ }
2944
+ } catch (_) {}
2945
+ }
2946
+ sweepStaleAtomicTmpFiles(GM_TOOLS_ROOT, 10 * 60 * 1000);
2947
+
2916
2948
  const PEER_REGISTRY_PATH = path.join(GM_TOOLS_ROOT, 'peer-registry.json');
2917
2949
  function registerSelfAsPeer() {
2918
2950
  try {
@@ -3942,12 +3974,15 @@ async function runSpoolWatcher(instance, spoolDir) {
3942
3974
  return null;
3943
3975
  }
3944
3976
  function writeSharedUpdateCache(latest, status) {
3977
+ let tmp = null;
3945
3978
  try {
3946
3979
  fs.mkdirSync(path.dirname(UPDATE_CHECK_SHARED_CACHE), { recursive: true });
3947
- const tmp = UPDATE_CHECK_SHARED_CACHE + '.tmp.' + process.pid;
3980
+ tmp = UPDATE_CHECK_SHARED_CACHE + '.tmp.' + process.pid;
3948
3981
  fs.writeFileSync(tmp, JSON.stringify({ ts: Date.now(), latest, status, by_pid: process.pid }));
3949
3982
  fs.renameSync(tmp, UPDATE_CHECK_SHARED_CACHE);
3950
- } catch (_) {}
3983
+ } catch (_) {
3984
+ if (tmp) { try { fs.unlinkSync(tmp); } catch (_) {} }
3985
+ }
3951
3986
  }
3952
3987
  const UPDATE_CHECK_ERROR_MARKER = path.join(GM_TOOLS_ROOT, '.update-check-error.json');
3953
3988
  let _lastKnownUpdateError = null;
@@ -3962,11 +3997,13 @@ async function runSpoolWatcher(instance, spoolDir) {
3962
3997
  return null;
3963
3998
  }
3964
3999
  function writeSharedUpdateErrorKey(key) {
4000
+ const tmp = UPDATE_CHECK_ERROR_MARKER + '.tmp.' + process.pid;
3965
4001
  try {
3966
- const tmp = UPDATE_CHECK_ERROR_MARKER + '.tmp';
3967
4002
  fs.writeFileSync(tmp, JSON.stringify({ ts: Date.now(), key, by_pid: process.pid }));
3968
4003
  fs.renameSync(tmp, UPDATE_CHECK_ERROR_MARKER);
3969
- } catch (_) {}
4004
+ } catch (_) {
4005
+ try { fs.unlinkSync(tmp); } catch (_) {}
4006
+ }
3970
4007
  }
3971
4008
  function clearSharedUpdateErrorKey() {
3972
4009
  try { fs.unlinkSync(UPDATE_CHECK_ERROR_MARKER); } catch (_) {}