borgmcp 0.5.0 → 0.5.1
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/dist/claude.js +0 -0
- package/dist/index.js +0 -0
- package/dist/log-audit.js +0 -0
- package/dist/regen.js +0 -0
- package/dist/setup.js +0 -0
- package/package.json +2 -1
- package/dist/inbox.d.ts +0 -33
- package/dist/inbox.d.ts.map +0 -1
- package/dist/inbox.js +0 -125
- package/dist/inbox.js.map +0 -1
package/dist/claude.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
File without changes
|
package/dist/log-audit.js
CHANGED
|
File without changes
|
package/dist/regen.js
CHANGED
|
File without changes
|
package/dist/setup.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "borgmcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "Multi-agent coordination for Claude Code — cubes, drones, and a shared activity log.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"borg-log-audit": "dist/log-audit.js"
|
|
13
13
|
},
|
|
14
14
|
"scripts": {
|
|
15
|
+
"prebuild": "rm -rf dist",
|
|
15
16
|
"build": "tsc",
|
|
16
17
|
"dev": "tsc --watch",
|
|
17
18
|
"start": "node dist/index.js",
|
package/dist/inbox.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Real-time drone wakeup via long-poll + inbox file.
|
|
3
|
-
*
|
|
4
|
-
* The MCP client spawns a background poller that long-polls the worker's
|
|
5
|
-
* /api/drone/wait endpoint. When new activity from OTHER drones arrives
|
|
6
|
-
* in the cube, we append a one-line summary per entry to a per-(cube,
|
|
7
|
-
* drone) inbox file (see inboxPathForDrone in cubes.ts). One file per
|
|
8
|
-
* drone session avoids the duplicate-write problem that would happen
|
|
9
|
-
* if multiple drones in the same cube shared a file.
|
|
10
|
-
*
|
|
11
|
-
* Own-drone entries are filtered out — there's no point waking a drone
|
|
12
|
-
* on its own post.
|
|
13
|
-
*
|
|
14
|
-
* The launcher kickoff (see claude.ts) arms a Monitor on the same path
|
|
15
|
-
* so Claude wakes the moment a line is appended — no waiting for the
|
|
16
|
-
* next /loop heartbeat.
|
|
17
|
-
*
|
|
18
|
-
* Dedup by entry id is layered in as defense against any precision /
|
|
19
|
-
* timestamp-cursor edge cases on the server side. Without it, a single
|
|
20
|
-
* sub-millisecond gap between the DB column and our cursor string would
|
|
21
|
-
* have the worker return the same row forever.
|
|
22
|
-
*
|
|
23
|
-
* The poller is fire-and-forget. If it dies, the launcher's fallback
|
|
24
|
-
* heartbeat (ScheduleWakeup, ~30 minutes) still keeps the drone in sync.
|
|
25
|
-
*/
|
|
26
|
-
/**
|
|
27
|
-
* Spawn the background long-poll loop. Idempotent: if no active cube
|
|
28
|
-
* is configured for this project, the loop sleeps and re-checks. The
|
|
29
|
-
* loop runs until process exit. Errors are logged to stderr (so they
|
|
30
|
-
* don't pollute the MCP stdio channel) and the loop continues.
|
|
31
|
-
*/
|
|
32
|
-
export declare function startInboxPoller(): void;
|
|
33
|
-
//# sourceMappingURL=inbox.d.ts.map
|
package/dist/inbox.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAOH;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC"}
|
package/dist/inbox.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Real-time drone wakeup via long-poll + inbox file.
|
|
3
|
-
*
|
|
4
|
-
* The MCP client spawns a background poller that long-polls the worker's
|
|
5
|
-
* /api/drone/wait endpoint. When new activity from OTHER drones arrives
|
|
6
|
-
* in the cube, we append a one-line summary per entry to a per-(cube,
|
|
7
|
-
* drone) inbox file (see inboxPathForDrone in cubes.ts). One file per
|
|
8
|
-
* drone session avoids the duplicate-write problem that would happen
|
|
9
|
-
* if multiple drones in the same cube shared a file.
|
|
10
|
-
*
|
|
11
|
-
* Own-drone entries are filtered out — there's no point waking a drone
|
|
12
|
-
* on its own post.
|
|
13
|
-
*
|
|
14
|
-
* The launcher kickoff (see claude.ts) arms a Monitor on the same path
|
|
15
|
-
* so Claude wakes the moment a line is appended — no waiting for the
|
|
16
|
-
* next /loop heartbeat.
|
|
17
|
-
*
|
|
18
|
-
* Dedup by entry id is layered in as defense against any precision /
|
|
19
|
-
* timestamp-cursor edge cases on the server side. Without it, a single
|
|
20
|
-
* sub-millisecond gap between the DB column and our cursor string would
|
|
21
|
-
* have the worker return the same row forever.
|
|
22
|
-
*
|
|
23
|
-
* The poller is fire-and-forget. If it dies, the launcher's fallback
|
|
24
|
-
* heartbeat (ScheduleWakeup, ~30 minutes) still keeps the drone in sync.
|
|
25
|
-
*/
|
|
26
|
-
import { promises as fs } from 'node:fs';
|
|
27
|
-
import path from 'node:path';
|
|
28
|
-
import { waitForActivity } from './remote-client.js';
|
|
29
|
-
import { getActiveCube, inboxPathForDrone } from './cubes.js';
|
|
30
|
-
/**
|
|
31
|
-
* Spawn the background long-poll loop. Idempotent: if no active cube
|
|
32
|
-
* is configured for this project, the loop sleeps and re-checks. The
|
|
33
|
-
* loop runs until process exit. Errors are logged to stderr (so they
|
|
34
|
-
* don't pollute the MCP stdio channel) and the loop continues.
|
|
35
|
-
*/
|
|
36
|
-
export function startInboxPoller() {
|
|
37
|
-
void runLoop().catch((err) => {
|
|
38
|
-
process.stderr.write(`[borg-mcp inbox poller] fatal: ${err?.message ?? err}\n`);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
async function runLoop() {
|
|
42
|
-
// Initialize lastSeen to "now" so we don't replay history that was
|
|
43
|
-
// already in the regen() snapshot included in the session-start
|
|
44
|
-
// orientation. We only want NEW activity from here forward.
|
|
45
|
-
let lastSeen = new Date().toISOString();
|
|
46
|
-
let currentCubeId = null;
|
|
47
|
-
let ownDroneId = null;
|
|
48
|
-
// Ring buffer of recently-written entry ids — protects against any
|
|
49
|
-
// server-side cursor drift that would otherwise re-emit the same row.
|
|
50
|
-
const recentIds = [];
|
|
51
|
-
const RECENT_CAP = 500;
|
|
52
|
-
while (true) {
|
|
53
|
-
const active = await getActiveCube();
|
|
54
|
-
if (!active) {
|
|
55
|
-
// No active cube — sleep and re-check. The user might assimilate
|
|
56
|
-
// mid-session.
|
|
57
|
-
await sleep(5000);
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
// Reset the cursor and dedup state when the active cube changes so
|
|
61
|
-
// we don't try to pull "since lastSeen" entries from the wrong
|
|
62
|
-
// timeline.
|
|
63
|
-
if (active.cubeId !== currentCubeId) {
|
|
64
|
-
currentCubeId = active.cubeId;
|
|
65
|
-
ownDroneId = active.droneId;
|
|
66
|
-
lastSeen = new Date().toISOString();
|
|
67
|
-
recentIds.length = 0;
|
|
68
|
-
}
|
|
69
|
-
try {
|
|
70
|
-
const { entries, drones, roles } = await waitForActivity(active.sessionToken, active.apiUrl, lastSeen);
|
|
71
|
-
if (entries.length > 0) {
|
|
72
|
-
const seenSet = new Set(recentIds);
|
|
73
|
-
const fresh = entries.filter((e) => {
|
|
74
|
-
if (seenSet.has(e.id))
|
|
75
|
-
return false;
|
|
76
|
-
// Filter out our own posts — we already know what we wrote.
|
|
77
|
-
if (e.drone_id === ownDroneId)
|
|
78
|
-
return false;
|
|
79
|
-
return true;
|
|
80
|
-
});
|
|
81
|
-
if (fresh.length > 0) {
|
|
82
|
-
await appendToInbox(active.cubeId, active.droneId, fresh, drones, roles);
|
|
83
|
-
for (const e of fresh)
|
|
84
|
-
recentIds.push(e.id);
|
|
85
|
-
while (recentIds.length > RECENT_CAP)
|
|
86
|
-
recentIds.shift();
|
|
87
|
-
}
|
|
88
|
-
// Advance the cursor against ALL returned entries (including
|
|
89
|
-
// own / already-seen). Otherwise we'd long-poll forever for
|
|
90
|
-
// entries we've intentionally skipped.
|
|
91
|
-
const newest = entries.reduce((a, b) => new Date(a.created_at) > new Date(b.created_at) ? a : b);
|
|
92
|
-
lastSeen = typeof newest.created_at === 'string'
|
|
93
|
-
? newest.created_at
|
|
94
|
-
: new Date(newest.created_at).toISOString();
|
|
95
|
-
}
|
|
96
|
-
// Whether empty or not, immediately re-poll. The server already
|
|
97
|
-
// held the request for up to ~25s; no client-side sleep needed.
|
|
98
|
-
}
|
|
99
|
-
catch (err) {
|
|
100
|
-
// Network blip, auth refresh, etc — back off briefly so we don't
|
|
101
|
-
// hot-loop on a persistent failure.
|
|
102
|
-
process.stderr.write(`[borg-mcp inbox poller] ${err?.message ?? err}\n`);
|
|
103
|
-
await sleep(5000);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
async function appendToInbox(cubeId, droneId, entries, drones, roles) {
|
|
108
|
-
const droneById = new Map(drones.map((d) => [d.id, d]));
|
|
109
|
-
const roleById = new Map(roles.map((r) => [r.id, r]));
|
|
110
|
-
const lines = entries.map((e) => {
|
|
111
|
-
const d = droneById.get(e.drone_id);
|
|
112
|
-
const r = d ? roleById.get(d.role_id) : null;
|
|
113
|
-
const ts = typeof e.created_at === 'string'
|
|
114
|
-
? new Date(e.created_at).toISOString()
|
|
115
|
-
: new Date(e.created_at).toISOString();
|
|
116
|
-
return `${ts} ${d?.label ?? '?'} (${r?.name ?? '?'}): ${e.message}`;
|
|
117
|
-
});
|
|
118
|
-
const p = inboxPathForDrone(cubeId, droneId);
|
|
119
|
-
await fs.mkdir(path.dirname(p), { recursive: true });
|
|
120
|
-
await fs.appendFile(p, lines.join('\n') + '\n', 'utf-8');
|
|
121
|
-
}
|
|
122
|
-
function sleep(ms) {
|
|
123
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=inbox.js.map
|
package/dist/inbox.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"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"}
|