@essentialai/cogent-bridge 3.23.3 → 3.23.4
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/CHANGELOG.md +51 -4
- package/dist/services/auto-relay.d.ts +14 -0
- package/dist/services/auto-relay.d.ts.map +1 -1
- package/dist/services/auto-relay.js +94 -0
- package/dist/services/auto-relay.js.map +1 -1
- package/dist/services/session-wake-lock.d.ts +26 -0
- package/dist/services/session-wake-lock.d.ts.map +1 -0
- package/dist/services/session-wake-lock.js +198 -0
- package/dist/services/session-wake-lock.js.map +1 -0
- package/dist/services/wake-lock.d.ts +30 -0
- package/dist/services/wake-lock.d.ts.map +1 -0
- package/dist/services/wake-lock.js +257 -0
- package/dist/services/wake-lock.js.map +1 -0
- package/dist/services/wake-ownership.d.ts +48 -0
- package/dist/services/wake-ownership.d.ts.map +1 -0
- package/dist/services/wake-ownership.js +193 -0
- package/dist/services/wake-ownership.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WAKE OWNERSHIP — a superseded bridge process stops waking, by itself, with nobody running pkill.
|
|
3
|
+
*
|
|
4
|
+
* ── WHY (operator, 2026-09-05) ───────────────────────────────────────────────────────────
|
|
5
|
+
* "killed, but my users dont do that - so think how to have self healing mechanism"
|
|
6
|
+
*
|
|
7
|
+
* ── WHAT IS ACTUALLY ON A REAL MACHINE (measured here, 2026-09-05) ───────────────────────
|
|
8
|
+
* 37 live cogent-bridge processes, and NOT ONE of them is an orphan — every parent is alive:
|
|
9
|
+
*
|
|
10
|
+
* codex app-server (1 daemon, up 3.5 days) ......... 7 bridges, all at a stale 3.22.0
|
|
11
|
+
* claude --resume <one interactive session> ........ 2 bridges (plugin AND an npx @latest)
|
|
12
|
+
* 5 other interactive `claude --resume` sessions ... 1 each
|
|
13
|
+
*
|
|
14
|
+
* That kills the obvious fix. "Exit when stdin hits EOF" heals nothing here, because no bridge has
|
|
15
|
+
* lost its parent. They are not orphaned, they are REDUNDANT: a long-lived daemon spawns a bridge
|
|
16
|
+
* per MCP session and never reaps them, and one agent session can have cogent registered twice.
|
|
17
|
+
* A plugin update does not stop any of them, so old versions keep serving for days.
|
|
18
|
+
*
|
|
19
|
+
* ── THE SIGNAL: SAME peerId, NOT same cwd ────────────────────────────────────────────────
|
|
20
|
+
* Superseding on cwd alone would break a legitimate setup — two agents working one checkout (say
|
|
21
|
+
* `marvin-coder` and `marvin-mobile`) are two DIFFERENT peers and both must keep waking. What is
|
|
22
|
+
* never legitimate is the same peerId served by two bridges in one checkout: that is the ghost,
|
|
23
|
+
* and it is exactly what was measured on the real user (`marvin-coder` live on the FREE relay at
|
|
24
|
+
* v3.20.0 and on the TEAM relay at v3.23.1, same cwd, same thread).
|
|
25
|
+
*
|
|
26
|
+
* So ownership is keyed on (cwd, peerId). The wake LOCK (wake-lock.ts) stays keyed on cwd alone,
|
|
27
|
+
* because worktree corruption does not care which peer caused it. Two invariants, two keys:
|
|
28
|
+
* ownership → only ONE process does this peer's work (kills duplicate work)
|
|
29
|
+
* lock → only ONE turn runs in this checkout (kills concurrent corruption)
|
|
30
|
+
*
|
|
31
|
+
* ── NEWEST WINS, BY PROCESS START, SO IT CANNOT OSCILLATE ────────────────────────────────
|
|
32
|
+
* The owner is the live bridge with the latest PROCESS START time. Start time is fixed for the
|
|
33
|
+
* life of a process, so a superseded bridge can never win the title back — if ownership were keyed
|
|
34
|
+
* on registration time instead, a stood-down bridge that re-registered would steal it back and the
|
|
35
|
+
* two would ping-pong forever.
|
|
36
|
+
*
|
|
37
|
+
* ── ONE FILE PER PID, SO THERE IS NO WRITE RACE ──────────────────────────────────────────
|
|
38
|
+
* Each process writes ONLY its own `<pid>.json`; nobody rewrites a shared document, so concurrent
|
|
39
|
+
* registration cannot corrupt or lose an entry. Reading is a readdir plus a liveness check, and
|
|
40
|
+
* dead entries are pruned opportunistically by whoever notices them.
|
|
41
|
+
*
|
|
42
|
+
* ── FAILS OPEN ───────────────────────────────────────────────────────────────────────────
|
|
43
|
+
* Any unreadable/unwritable state resolves to "you are the owner, go ahead and wake". A
|
|
44
|
+
* self-healing mechanism that can silence a healthy agent is a worse bug than the one it heals —
|
|
45
|
+
* that is the 3.21.5 lesson, where a fix took auto-wake down for every default-config macOS user.
|
|
46
|
+
*/
|
|
47
|
+
import crypto from "node:crypto";
|
|
48
|
+
import fs from "node:fs";
|
|
49
|
+
import os from "node:os";
|
|
50
|
+
import path from "node:path";
|
|
51
|
+
import { logger } from "../logger.js";
|
|
52
|
+
/**
|
|
53
|
+
* When this process started. Captured at module load — as close to process start as we can get
|
|
54
|
+
* from inside — and never recomputed, which is what makes ownership stable and non-oscillating.
|
|
55
|
+
*/
|
|
56
|
+
const PROCESS_STARTED_AT = Date.now() - Math.floor(process.uptime() * 1000);
|
|
57
|
+
/** MUST match wake-lock / wake-claim / credential-store — one cwd, one key, everywhere. */
|
|
58
|
+
function hashCwd(cwd) {
|
|
59
|
+
return crypto.createHash("sha256").update(path.resolve(cwd)).digest("hex").slice(0, 16);
|
|
60
|
+
}
|
|
61
|
+
const safe = (s) => String(s).replace(/[^A-Za-z0-9._-]/g, "_");
|
|
62
|
+
/** `~/.cogent/bridges/<sha256(cwd)[..16]>.<peerId>/` — one directory per identity. */
|
|
63
|
+
export function bridgeDirFor(cwd, peerId) {
|
|
64
|
+
return path.join(os.homedir(), ".cogent", "bridges", `${hashCwd(cwd)}.${safe(peerId)}`);
|
|
65
|
+
}
|
|
66
|
+
/** Is that pid a live process? Unknown/odd values count as DEAD so their entries get pruned. */
|
|
67
|
+
function pidAlive(pid) {
|
|
68
|
+
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
|
|
69
|
+
return false;
|
|
70
|
+
if (pid === process.pid)
|
|
71
|
+
return true;
|
|
72
|
+
try {
|
|
73
|
+
process.kill(pid, 0); // signal 0 = existence check only
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
// EPERM means it EXISTS but belongs to another user — alive for our purposes.
|
|
78
|
+
return err?.code === "EPERM";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Announce this process as a bridge serving `peerId` in `cwd`.
|
|
83
|
+
*
|
|
84
|
+
* Called once the peer is actually registered, so a bridge that never registered never competes
|
|
85
|
+
* for ownership. Best-effort: a failure here leaves us un-announced, which can only make us LOSE
|
|
86
|
+
* ownership to someone else, never wrongly take it.
|
|
87
|
+
*/
|
|
88
|
+
export function announceBridge(cwd, peerId, version, endpoint) {
|
|
89
|
+
const dir = bridgeDirFor(cwd, peerId);
|
|
90
|
+
try {
|
|
91
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
92
|
+
const entry = {
|
|
93
|
+
pid: process.pid,
|
|
94
|
+
startedAt: PROCESS_STARTED_AT,
|
|
95
|
+
version,
|
|
96
|
+
peerId,
|
|
97
|
+
endpoint,
|
|
98
|
+
cwd: path.resolve(cwd),
|
|
99
|
+
};
|
|
100
|
+
fs.writeFileSync(path.join(dir, `${process.pid}.json`), JSON.stringify(entry));
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
logger.debug(`wake-ownership: could not announce this bridge (${err.message})`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** Remove this process's announcement. Called on graceful shutdown; a crash is handled by pruning. */
|
|
107
|
+
export function withdrawBridge(cwd, peerId) {
|
|
108
|
+
try {
|
|
109
|
+
fs.unlinkSync(path.join(bridgeDirFor(cwd, peerId), `${process.pid}.json`));
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
/* already gone, or never announced */
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Every LIVE bridge announced for this identity, newest process first.
|
|
117
|
+
*
|
|
118
|
+
* Prunes entries whose process is gone, so a machine that has been through a dozen plugin updates
|
|
119
|
+
* does not accumulate junk here forever.
|
|
120
|
+
*/
|
|
121
|
+
export function listLiveBridges(cwd, peerId) {
|
|
122
|
+
const dir = bridgeDirFor(cwd, peerId);
|
|
123
|
+
let names;
|
|
124
|
+
try {
|
|
125
|
+
names = fs.readdirSync(dir);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return []; // no directory = nobody announced = no competition
|
|
129
|
+
}
|
|
130
|
+
const live = [];
|
|
131
|
+
for (const name of names) {
|
|
132
|
+
if (!name.endsWith(".json"))
|
|
133
|
+
continue;
|
|
134
|
+
const p = path.join(dir, name);
|
|
135
|
+
let entry = null;
|
|
136
|
+
try {
|
|
137
|
+
entry = JSON.parse(fs.readFileSync(p, "utf-8"));
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
entry = null;
|
|
141
|
+
}
|
|
142
|
+
if (!entry || !pidAlive(entry.pid) || typeof entry.startedAt !== "number") {
|
|
143
|
+
try {
|
|
144
|
+
fs.unlinkSync(p); // prune: the process is gone or the record is unusable
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
/* raced with another pruner */
|
|
148
|
+
}
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
live.push(entry);
|
|
152
|
+
}
|
|
153
|
+
// Newest process first; pid breaks a same-millisecond tie deterministically so every process
|
|
154
|
+
// computes the SAME owner. A non-deterministic tie-break would let two bridges each believe
|
|
155
|
+
// they own it — the exact condition this exists to prevent.
|
|
156
|
+
live.sort((a, b) => b.startedAt - a.startedAt || b.pid - a.pid);
|
|
157
|
+
return live;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Should THIS process wake for `peerId` in `cwd`?
|
|
161
|
+
*
|
|
162
|
+
* No when a strictly newer live bridge serves the same identity — that bridge is the one the user
|
|
163
|
+
* most recently started, and we are the leftover.
|
|
164
|
+
*/
|
|
165
|
+
export function checkWakeOwnership(cwd, peerId) {
|
|
166
|
+
let live;
|
|
167
|
+
try {
|
|
168
|
+
live = listLiveBridges(cwd, peerId);
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
logger.warn(`wake-ownership: could not read bridge registry (${err.message}) — assuming ownership`);
|
|
172
|
+
return { isOwner: true, liveCount: 1 };
|
|
173
|
+
}
|
|
174
|
+
// Nobody announced (including us — announcement is best-effort): assume ownership. Standing
|
|
175
|
+
// down on missing evidence would mute a healthy, solitary agent.
|
|
176
|
+
if (live.length === 0)
|
|
177
|
+
return { isOwner: true, liveCount: 0 };
|
|
178
|
+
const owner = live[0];
|
|
179
|
+
if (owner.pid === process.pid)
|
|
180
|
+
return { isOwner: true, liveCount: live.length };
|
|
181
|
+
// We are announced but are not newest -> superseded.
|
|
182
|
+
if (live.some((e) => e.pid === process.pid)) {
|
|
183
|
+
return {
|
|
184
|
+
isOwner: false,
|
|
185
|
+
owner: { pid: owner.pid, version: owner.version, endpoint: owner.endpoint },
|
|
186
|
+
liveCount: live.length,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
// Others are announced but we are not (our own announce failed). Do NOT stand down on the
|
|
190
|
+
// strength of a record we could not write: fail open.
|
|
191
|
+
return { isOwner: true, liveCount: live.length + 1 };
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=wake-ownership.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wake-ownership.js","sourceRoot":"","sources":["../../src/services/wake-ownership.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@essentialai/cogent-bridge",
|
|
3
|
-
"version": "3.23.
|
|
3
|
+
"version": "3.23.4",
|
|
4
4
|
"description": "Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.eaisdevelopment/cogent",
|
|
4
4
|
"title": "Cogent Bridge from Essential AI Solutions (essentialai.uk)",
|
|
5
5
|
"description": "MCP bridge for inter-session communication between Claude Code instances",
|
|
6
|
-
"version": "3.23.
|
|
6
|
+
"version": "3.23.4",
|
|
7
7
|
"repository": {
|
|
8
8
|
"url": "https://github.com/eaisdevelopment/cogent",
|
|
9
9
|
"source": "github"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "@essentialai/cogent-bridge",
|
|
15
|
-
"version": "3.23.
|
|
15
|
+
"version": "3.23.4",
|
|
16
16
|
"runtimeHint": "npx",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|