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 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.0",
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
@@ -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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"}