borgmcp 1.1.7 → 1.1.9
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/README.md +6 -1
- package/dist/agent-runtime.d.ts +37 -0
- package/dist/agent-runtime.js +1 -0
- package/dist/assimilate-cmd.js +26 -26
- package/dist/claude.js +11 -11
- package/dist/codex-app-wake.d.ts +9 -6
- package/dist/codex-app-wake.js +2 -2
- package/dist/codex-launch.d.ts +1 -1
- package/dist/codex-launch.js +1 -1
- package/dist/codex-remote.js +1 -1
- package/dist/config-utils.d.ts +6 -4
- package/dist/config-utils.js +3 -3
- package/dist/gc-orphan-inboxes.d.ts +8 -3
- package/dist/gc-orphan-inboxes.js +1 -1
- package/dist/health-beat.d.ts +3 -4
- package/dist/health-beat.js +1 -1
- package/dist/inbox-monitor.d.ts +92 -21
- package/dist/inbox-monitor.js +3 -1
- package/dist/index.js +18 -18
- package/dist/regen-format.d.ts +6 -3
- package/dist/regen-format.js +12 -12
- package/dist/regen.js +3 -3
- package/dist/roster-render.d.ts +5 -2
- package/dist/roster-render.js +3 -3
- package/dist/stream-status.d.ts +9 -5
- package/dist/stream-status.js +3 -3
- package/package.json +1 -1
package/dist/regen.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{regen as
|
|
3
|
-
`)}async function
|
|
2
|
+
import{regen as a,listCubes as c}from"./remote-client.js";import{findProjectRoot as u,getActiveCube as h,inboxPathForDrone as l}from"./cubes.js";import{monitorStateRootForWorktree as p}from"./inbox-monitor.js";import{parseHookSource as b,formatLeanOrientation as m,resolveLeanIdentity as g}from"./regen-format.js";import{resolveSessionAgentKind as d}from"./codex-app-wake.js";import{handleVersionFlag as f}from"./version.js";import{gateAllowsActivation as w}from"./launch-gate.js";async function y(){if(process.stdin.isTTY)return"";try{const e=[];for await(const t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}catch{return""}}async function v(){if(f(),!w("borg-regen SessionStart hook"))return;const e=b(await y()),t=await h();if(!t){await _();return}const o=l(t.cubeId,t.droneId),n=p(u()),r=d();let s=null;try{s=await a(t.sessionToken,t.apiUrl)}catch{s=null}const i=g(t,s);process.stdout.write(m({...i,inboxPath:o,monitorStateRoot:n,agentKind:r,source:e})+`
|
|
3
|
+
`)}async function _(){const e=[];e.push("# Borg MCP \u2014 not connected to a cube"),e.push(""),e.push("The borg MCP server is installed in this project but no cube has been joined here yet."),e.push(""),e.push("**Drone instructions:**"),e.push("1. **Tell the user** which cubes exist on their account (see the list below) and ask them which one to join, or whether to create a new cube. This is the first thing you should surface in this session."),e.push("2. **Do not** call `borg_assimilate`, `borg_create-cube`, or any other state-changing borg tool until the user has chosen."),e.push("3. The user may also decline to use borg in this project at all \u2014 that's a valid choice; just stop suggesting it."),e.push("");try{const{cubes:t}=await c();if(t.length>0){e.push("## Cubes on your account");for(const o of t)e.push(`- **${o.name}** (id: ${o.id})`)}else e.push("## Cubes on your account"),e.push("_(none yet \u2014 offer to create one via `borg_create-cube` once the user confirms)_")}catch(t){e.push("## Cubes on your account"),e.push("_(could not list \u2014 "+(t?.message??String(t))+")_")}e.push(""),e.push("## Tools you can call once the user has chosen"),e.push('- Join an existing cube: `borg_assimilate cube_name="<their choice>"`'),e.push('- Create a new cube: `borg_create-cube name="<name>" cube_directive="<markdown>"` (optionally `template="software-dev"`)'),e.push("- See available templates: `borg_list-templates`"),process.stdout.write(e.join(`
|
|
4
4
|
`)+`
|
|
5
|
-
`)}
|
|
5
|
+
`)}v().catch(e=>{const t=e?.message??String(e);process.stderr.write(`borg-regen: ${t}
|
|
6
6
|
`),process.exit(1)});
|
package/dist/roster-render.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface RosterDrone {
|
|
|
24
24
|
/**
|
|
25
25
|
* gh#370 — which AI agent is running this drone. Null for drones that
|
|
26
26
|
* joined before the column existed or via a launcher path that didn't
|
|
27
|
-
* forward the kind.
|
|
27
|
+
* forward the kind. This is the agent CLI, not a model descriptor.
|
|
28
28
|
*/
|
|
29
29
|
agent_kind?: 'claude' | 'codex' | 'opencode' | null;
|
|
30
30
|
regen_count?: number | null;
|
|
@@ -32,7 +32,10 @@ export interface RosterDrone {
|
|
|
32
32
|
wake_path_alert_class?: 'dead' | 'post-blocked' | 'presumed-dead' | 'systemic-post-block' | 'wake-path-deaf' | 'independent' | null;
|
|
33
33
|
/**
|
|
34
34
|
* Model descriptor (e.g., "claude:claude-opus-4-8" or "ollama:qwen3-coder-next:q4_K_M").
|
|
35
|
-
*
|
|
35
|
+
* This is the configured launch setting captured at assimilation, not a live
|
|
36
|
+
* runtime model observation. It may remain after a later CLI relaunch.
|
|
37
|
+
* Null is not enough information to distinguish an inherited default from
|
|
38
|
+
* a legacy/missing report, so renderers must not infer an agent CLI from it.
|
|
36
39
|
*/
|
|
37
40
|
model?: string | null;
|
|
38
41
|
}
|
package/dist/roster-render.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{formatDroneAddressToken as
|
|
2
|
-
`);for(const e of
|
|
3
|
-
`)}export{g as formatRoleAgentLabel,
|
|
1
|
+
import{formatDroneAddressToken as w}from"./drone-address.js";const m={degraded:"unverified",deaf:"unresponsive"};function g(a,o){return`Role: ${a} \xB7 Agent CLI: ${o==="claude"?"Claude Code":o==="codex"?"Codex":o==="opencode"?"OpenCode":"unknown"}`}function v(a){const{cubeName:o,drones:s,roles:k,resolvedSince:t,humanAgo:r}=a,l=new Map;for(const e of k)l.set(e.id,e);const n=[];if(n.push(`# Drones in cube: ${o}`),n.push(""),t&&(n.push(`_Liveness probe since ${t} (${r(t)}). \`awake\` = drone posted to the cube log after that point._`),n.push("")),!s.length)return n.push("_(no drones connected)_"),n.join(`
|
|
2
|
+
`);for(const e of s){const h=l.get(e.role_id)?.name??"unknown",c=g(h,e.agent_kind),d=e.id?` ${w(e.id)}`:"",u=r(e.last_seen),i=e.model?` \xB7 \`Configured model: ${e.model}\``:" \xB7 `Configured model: not reported`",p=e.wake_path&&e.wake_path!=="live"?` \xB7 \`wake-path:${m[e.wake_path]??e.wake_path}\``:"",$=e.wake_path_alert_class&&e.wake_path_alert_class!=="independent"?` \xB7 \`wake-path-class:${e.wake_path_alert_class}\``:"",_=typeof e.regen_count=="number"?` \xB7 \`regen-count:${e.regen_count}\``:"";if(t){const f=e.seen_since===!0?"`awake`":"`stale`";n.push(`- **${e.label}**${d} (${c}) \u2014 last seen ${u} \xB7 ${f}${_}${p}${$}${i}`)}else n.push(`- **${e.label}**${d} (${c}) \u2014 last seen ${u}${_}${p}${$}${i}`)}return n.join(`
|
|
3
|
+
`)}export{g as formatRoleAgentLabel,v as renderRoster};
|
package/dist/stream-status.d.ts
CHANGED
|
@@ -42,13 +42,14 @@ import type { StreamStatus } from './log-stream.js';
|
|
|
42
42
|
* Linux per package.json `os` field; the null branch handles other
|
|
43
43
|
* platforms gracefully).
|
|
44
44
|
*/
|
|
45
|
-
export declare function checkInboxMonitorHealthy(inboxPath: string | null): boolean | null;
|
|
45
|
+
export declare function checkInboxMonitorHealthy(inboxPath: string | null, monitorStateRoot?: string | null): boolean | null;
|
|
46
46
|
/**
|
|
47
|
-
* gh#822:
|
|
48
|
-
*
|
|
49
|
-
*
|
|
47
|
+
* gh#822: are all present holder heartbeat sidecars stale past the threshold?
|
|
48
|
+
* A fresh legacy sidecar wins during migration; absent sidecars (old monitor /
|
|
49
|
+
* just-armed) still fall back to process presence. Only present-and-all-stale
|
|
50
|
+
* state is a wedged-holder signal.
|
|
50
51
|
*/
|
|
51
|
-
export declare function isHeartbeatStale(inboxPath: string): boolean;
|
|
52
|
+
export declare function isHeartbeatStale(inboxPath: string, monitorStateRoot?: string | null): boolean;
|
|
52
53
|
export interface RenderInputs {
|
|
53
54
|
status: StreamStatus;
|
|
54
55
|
/**
|
|
@@ -62,6 +63,8 @@ export interface RenderInputs {
|
|
|
62
63
|
* mode but omit the exact command.
|
|
63
64
|
*/
|
|
64
65
|
inboxPath: string | null;
|
|
66
|
+
/** Explicit worktree-local root for the Monitor command, when known. */
|
|
67
|
+
monitorStateRoot?: string | null;
|
|
65
68
|
/** Drone label for the Monitor description copy. */
|
|
66
69
|
droneLabel: string | null;
|
|
67
70
|
/** Cube name for the Monitor description copy. */
|
|
@@ -108,6 +111,7 @@ export declare function shouldShowWakePathWarning(streamStatus: StreamStatus, in
|
|
|
108
111
|
*/
|
|
109
112
|
export declare function formatWakePathPrefix(inputs: {
|
|
110
113
|
inboxPath: string | null;
|
|
114
|
+
monitorStateRoot?: string | null;
|
|
111
115
|
droneLabel: string | null;
|
|
112
116
|
cubeName: string | null;
|
|
113
117
|
}): string;
|
package/dist/stream-status.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{spawnSync as
|
|
2
|
-
`)}function
|
|
3
|
-
`)}export{
|
|
1
|
+
import{spawnSync as b}from"node:child_process";import{statSync as $}from"node:fs";import{heartbeatPathFor as _,legacyHeartbeatPathFor as k,HEARTBEAT_STALE_MS as y}from"./inbox-monitor.js";import{shellEscape as u}from"./shell-escape.js";function x(n,t){if(!n)return null;try{const o=b("pgrep",["-f",n],{encoding:"utf-8",timeout:2e3});return o.error?null:o.status===0&&o.stdout.trim().length>0?!A(n,t):o.status===1?!1:null}catch{return null}}function A(n,t){const o=[_(n,t)];t&&o.push(k(n));let s=!1;for(const a of new Set(o))try{const c=$(a).mtimeMs;if(s=!0,Date.now()-c<=y)return!1}catch{}return s}function E(n){const{status:t,inboxMonitorHealthy:o,inboxPath:s,monitorStateRoot:a,droneLabel:c,cubeName:p,humanAgo:l}=n,m=t.reconnectAttempts===0&&t.lastWireActivityAt===null&&!t.connected,h=t.ownership?.state==="owned-by-other-process",d=t.ownership?.state==="orphaned-initialization",w=t.ownership?.state==="initializing";let r;d?r="**Stream blocked by an orphaned initialization lock.**":h?r="**Stream owned by another Borg MCP process.**":m?r="**Stream not started.**":t.connected?o===!1?r="**Stream connected (no inbox-Monitor \u2014 wake path broken).**":t.lastContentEventAt===null?r="**Stream connected, awaiting first content event.**":r=`**Stream connected, last content ${l(new Date(t.lastContentEventAt))}.**`:r=`**Stream disconnected (reconnect attempt ${t.reconnectAttempts}).**`;const e=[];if(e.push(r),e.push(""),e.push("# Log-stream status"),e.push(""),d?e.push("- **state**: _(orphaned stream-owner initialization)_"):w?e.push("- **state**: _(stream-owner initialization in progress)_"):h?e.push("- **state**: _(stream owner is another local process)_"):m?e.push("- **state**: _(stream not started)_"):e.push(`- **connected**: ${t.connected}`),e.push(`- **last content event**: ${t.lastContentEventAt?`${t.lastContentEventAt} (${l(new Date(t.lastContentEventAt))})`:"_(none yet)_"}`),e.push(`- **last heartbeat at**: ${t.lastHeartbeatAt?`${t.lastHeartbeatAt} (${l(new Date(t.lastHeartbeatAt))})`:"_(none)_"}`),e.push(`- **last wire activity**: ${t.lastWireActivityAt?`${t.lastWireActivityAt} (${l(new Date(t.lastWireActivityAt))})`:"_(none)_"}`),e.push(`- **last persisted event id**: ${t.lastPersistedEventId??"_(none)_"}`),e.push(`- **reconnect attempts**: ${t.reconnectAttempts}`),e.push(`- **run-loop restarts**: ${t.runLoopRestartCount}`),e.push(`- **stream ownership**: ${t.ownership?.state??"_(unknown)_"}`),t.ownership?.lockPath&&e.push(`- **ownership lock path**: ${t.ownership.lockPath}`),h){const i=t.ownership;e.push(`- **stream owner pid**: ${i.pid??"_(unknown)_"}`),e.push(`- **stream owner cwd**: ${i.cwd??"_(unknown)_"}`),e.push(`- **stream owner heartbeat age**: ${typeof i.ageMs=="number"&&Number.isFinite(i.ageMs)?`${Math.max(0,Math.round(i.ageMs/1e3))}s`:"_(unknown)_"}`)}return t.connected&&o===!1&&(e.push("- **inbox-monitor**: _(no watcher detected \u2014 wake path broken)_"),s&&c&&p&&(e.push(""),e.push("## Real-time wake-up (do this now)"),e.push("No process is tailing this drone's inbox file \u2014 this session won't wake on real-time cube activity, only on its fallback timer, and will miss live coordination from other drones. Arm an inbox Monitor:"),e.push(""),e.push(`> Monitor command: \`${f(s,a)}\` \u2014 persistent, 1h timeout, description "borg inbox for ${c} on cube ${p}".`))),e.join(`
|
|
2
|
+
`)}function C(n,t){return n.connected&&t===!1}function H(n){const{inboxPath:t,monitorStateRoot:o,droneLabel:s,cubeName:a}=n;return!t||!s||!a?"":["## \u26A0 Wake path broken \u2014 arm Monitor NOW","","No process is tailing this drone's inbox file. SSE delivery is healthy (entries reach disk), but Claude Code has no event source to wake on. Until you arm a Monitor, this session only wakes on the /loop fallback heartbeat and will miss live coordination from other drones:","",`> Monitor command: \`${f(t,o)}\` \u2014 persistent, 1h timeout, description "borg inbox for ${s} on cube ${a}".`,"","---",""].join(`
|
|
3
|
+
`)}function f(n,t){return t?`borg-inbox-monitor --state-root ${u(t)} ${u(n)}`:`borg-inbox-monitor ${u(n)}`}export{x as checkInboxMonitorHealthy,H as formatWakePathPrefix,A as isHeartbeatStale,E as renderStreamStatus,C as shouldShowWakePathWarning};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "borgmcp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "Coordinate AI coding agents in shared cubes. Works with Claude Code and Codex. Create projects, assign roles, and share a live activity log.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|