thinkpool-pair 0.7.197 → 0.7.198

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.
Files changed (2) hide show
  1. package/account.mjs +9 -8
  2. package/package.json +1 -1
package/account.mjs CHANGED
@@ -39,25 +39,26 @@ function pidAlive(pid) {
39
39
  try { process.kill(pid, 0); return true } catch (e) { return e.code === 'EPERM' }
40
40
  }
41
41
 
42
- // Returns true if we now hold the lock, false if another LIVE supervisor holds it.
43
- // A stale lock (holder dead / garbage / ours) is taken over. fs errors fail-OPEN
44
- // (return true) — a lock we can't manage must never block the real bridge.
42
+ // Returns true only if we demonstrably hold the lock. A stale lock (holder dead /
43
+ // garbage / ours) is taken over. Filesystem errors fail CLOSED: serving without a
44
+ // lock can start a second bridge, and duplicate bridges can race terminal reconcile
45
+ // and delete room history. A temporarily unmanageable lock is safer than that.
45
46
  export function acquireSingleton(lockPath = LOCK) {
46
- try { fs.mkdirSync(path.dirname(lockPath), { recursive: true }) } catch { /* noop */ }
47
+ try { fs.mkdirSync(path.dirname(lockPath), { recursive: true }) } catch { return false }
47
48
  for (let i = 0; i < 3; i++) {
48
49
  try {
49
50
  const fd = fs.openSync(lockPath, 'wx') // atomic create-exclusive
50
51
  fs.writeSync(fd, String(process.pid)); fs.closeSync(fd)
51
52
  return true
52
53
  } catch (e) {
53
- if (e.code !== 'EEXIST') return true // can't create for another reason → fail open
54
+ if (e.code !== 'EEXIST') return false // cannot prove ownership → refuse to serve
54
55
  let pid = 0
55
- try { pid = parseInt(fs.readFileSync(lockPath, 'utf8').trim(), 10) || 0 } catch { /* unreadable */ }
56
+ try { pid = parseInt(fs.readFileSync(lockPath, 'utf8').trim(), 10) || 0 } catch { return false }
56
57
  if (pidAlive(pid)) return false // a live supervisor owns it → refuse
57
- try { fs.rmSync(lockPath, { force: true }) } catch { return true } // stale → drop + retry
58
+ try { fs.rmSync(lockPath, { force: true }) } catch { return false } // stale but unmanageable
58
59
  }
59
60
  }
60
- return true
61
+ return false
61
62
  }
62
63
 
63
64
  // Release only if WE own it (don't unlink a lock another instance took over).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thinkpool-pair",
3
- "version": "0.7.197",
3
+ "version": "0.7.198",
4
4
  "description": "Share a local coding-agent CLI (Claude Code, Codex, Gemini, Aider, …) into a ThinkPool Code room, live.",
5
5
  "type": "module",
6
6
  "bin": {