borgmcp 1.0.13 → 1.0.14
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 +5 -5
- package/dist/get-started.d.ts +20 -0
- package/dist/get-started.js +2 -0
- package/dist/token-store.js +1 -1
- package/package.json +1 -1
package/dist/claude.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{spawn as
|
|
3
|
-
`)})();if((process.argv[2]==="--help"||process.argv[2]==="-h")&&(process.stdout.write(
|
|
2
|
+
import{spawn as S}from"child_process";import{randomUUID as y}from"node:crypto";import{basename as A}from"node:path";import{createInterface as P}from"node:readline/promises";import s from"chalk";import{findProjectRoot as T,getActiveCube as I,inboxPathForDrone as E,setCodexWakeTarget as R}from"./cubes.js";import{handleVersionFlag as D,getPackageVersion as g}from"./version.js";import{isHelpFlag as O,setupHelpText as F,topLevelHelpText as N}from"./cli-help.js";import{runSpawn as H}from"./spawn.js";import{parseSyncArgs as M,runSync as B}from"./sync.js";import{parseAssimilateArgs as G}from"./parse-assimilate-args.js";import{runAssimilate as L}from"./assimilate-cmd.js";import{buildDefaultAssimilateDeps as _}from"./assimilate-deps.js";import{setTerminalTitle as W}from"./terminal-title.js";import{initConsolePrefix as U,consolePrefix as r}from"./console-prefix.js";import{initDebugFromArgv as V}from"./debug.js";import{fetchLatestBorgmcpVersion as j,compareVersionsForStaleness as K}from"./stale-version-check.js";import{defaultCliChoiceDeps as Y,detectCliAvailability as v,installedCliNames as q,parseCliFlag as z,resolveCliChoice as X}from"./cli-platform.js";import{getRefreshToken as J,getIdToken as Q}from"./config.js";import{composeGetStarted as Z,shouldShowGetStarted as ee}from"./get-started.js";import{prepareCodexRemoteLaunch as re,withCodexCwdArg as oe,defaultCodexRemoteDeps as se}from"./codex-remote.js";import{findLoadedCodexThread as te}from"./codex-app-server.js";import{buildAgentKickoffPrompt as ie,recordCodexWakeTarget as ae,socketPathFromRemoteArgs as k}from"./codex-launch.js";import{codexBorgSessionConfigArgs as ne}from"./launch-gate.js";import{addCodexMcpServer as ce,addCodexSessionStartHook as le,addCodexUserPromptSubmitHook as de,addMcpServer as pe,addProjectSessionStartHook as me,addUserPromptSubmitHook as fe,isCodexMcpServerConfigured as ue,isMcpServerConfigured as ge,removeSessionStartHook as he}from"./config-utils.js";async function we(){V(process.argv),D(),await U();const n=(async()=>{if(!process.stderr.isTTY)return;const e=g(),a=await j();if(!a)return;const p=K(e,a);p.stale&&p.message&&process.stderr.write(`${r()}${p.message}
|
|
3
|
+
`)})();if((process.argv[2]==="--help"||process.argv[2]==="-h")&&(process.stdout.write(N(g())),process.exit(0)),process.argv[2]==="setup"){O(process.argv[3])&&(process.stdout.write(F(g())),process.exit(0)),await import("./setup.js");return}if(process.argv[2]==="assimilate"){const e=G(process.argv.slice(3));e.ok||(process.stderr.write(s.red(`${r()}\u25FC borg assimilate: ${e.error}
|
|
4
4
|
`)),process.exit(1));const a=_(),p=await L({role:e.role,flags:e.flags},a);process.exit(p)}if(process.argv[2]==="spawn"){const e=await H();process.exit(e)}if(process.argv[2]==="sync"){const e=M(process.argv.slice(3));e.ok||(process.stderr.write(s.red(`${r()}\u25FC borg sync: ${e.error}
|
|
5
|
-
`)),process.exit(1));const a=await
|
|
6
|
-
`)),process.exit(1));const
|
|
5
|
+
`)),process.exit(1));const a=await B({},e.options);process.exit(a)}if(ee(await J()!==null,await Q()!==null)){const e=q(v()).length>0;process.stdout.write(Z(e)),process.exit(0)}const t=z(process.argv.slice(2));t.error&&(process.stderr.write(s.red(`${r()}\u25FC ${t.error}
|
|
6
|
+
`)),process.exit(1));const $=async e=>{const a=P({input:process.stdin,output:process.stdout});try{return await a.question(e)}finally{a.close()}},o=await X(t.cli,Y($,()=>process.stdin.isTTY===!0));xe();const c=t.rest,i=await I();W(i?{label:i.droneLabel,cubeName:i.name}:null,A(process.cwd()));const b=i&&o==="claude"?`If you haven't yet, arm a persistent Monitor running the command \`borg-inbox-monitor ${E(i.cubeId,i.droneId)}\` so each event's task-notification title summarizes the new cube log entry (drone label, role, and first ~80 chars of the message body) \u2014 letting you triage events without reading the full body. `:"";await Promise.race([n,new Promise(e=>setTimeout(e,2e3))]);const h=o==="codex"?`borg-wake-${y()}`:null;let m,w=[],f={...process.env,BORG_SESSION:"1"},l=null,d=null;if(o==="codex"&&!c.includes("--remote")){console.error(`${r()}${s.gray("\u25FC Starting Codex remote-wake app-server\u2026")}`);const e=await re(se());e.warning?(console.error(`${r()}${s.yellow(`warning: ${e.warning}`)}`),m="\u26A0 Codex wake-path capability check failed: remote-control is unavailable for this session. Run borg:regen manually whenever you return, and expect only fallback wakeups until relaunch."):m="Codex wake-path capability check passed: remote-control socket established for this session.",w=e.args,f={...process.env,...e.env,BORG_SESSION:"1"},l=k(e.args),d=e.server?.cleanup??null}else o==="codex"&&c.includes("--remote")&&(m="Codex wake-path capability check: using caller-provided --remote socket; if no wake arrives, run borg:regen manually when returning to the session.",l=k(c),l&&(f={...process.env,BORG_CODEX_REMOTE_WAKE:"1",BORG_SESSION:"1"}));const x=ie({cli:o,codexWakeNonce:h,monitorClause:b,codexWakePathClause:m});let u=[...c,x];o==="codex"&&(u=[...ne(),...w,...oe(u,process.cwd())]),console.error(`${r()}${s.blue(`\u25FC Launching ${o==="claude"?"Claude Code":"Codex"}\u2026`)}`);const C=S(o,u,{stdio:"inherit",shell:!1,env:f});o==="codex"&&i&&l&&ae({deps:{setCodexWakeTarget:R,findLoadedCodexThread:te},cubeId:i.cubeId,droneId:i.droneId,socketPath:l,passthroughArgs:c,previewNeedle:h??x.slice(0,120),cwd:process.cwd(),launchedAtSeconds:Math.floor(Date.now()/1e3)}),C.on("error",e=>{if(d)try{d()}catch{}e.code==="ENOENT"?(console.error(`${r()}${s.red(`
|
|
7
7
|
\u25FC Failed to launch ${o}`)}`),console.error(`${r()}${s.gray(`Make sure ${o} is installed.
|
|
8
8
|
`)}`)):console.error(`${r()}${s.red(`
|
|
9
9
|
\u25FC Failed to launch ${o}: ${e.message}
|
|
10
|
-
`)}`),process.exit(1)}),
|
|
10
|
+
`)}`),process.exit(1)}),C.on("exit",e=>{if(d)try{d()}catch{}process.exit(e??0)})}function xe(){const n=v();if(n.claude)try{ge()||pe(),me(T(process.cwd())),he(),fe()}catch(t){console.error(`${r()}${s.yellow(`warning: Claude Code integration check failed: ${t?.message??t}`)}`)}if(n.codex)try{ue()||ce(),le(),de()}catch(t){console.error(`${r()}${s.yellow(`warning: Codex integration check failed: ${t?.message??t}`)}`)}}we().catch(n=>{console.error(`${r()}${s.red(`
|
|
11
11
|
\u25FC Error: ${n.message}
|
|
12
12
|
`)}`),process.exit(1)});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fresh-vs-configured rule. "Configured" = the user has completed `borg setup`,
|
|
3
|
+
* signalled by the PRESENCE of a stored credential. Inputs are existence
|
|
4
|
+
* booleans only — the caller null-checks the token accessors and never decodes,
|
|
5
|
+
* logs, or prints the token value (SR gh#817 constraint).
|
|
6
|
+
*
|
|
7
|
+
* Refresh-token presence is the durable signal: it survives id_token expiry, so
|
|
8
|
+
* a configured user whose id_token has lapsed is NOT mistaken for fresh (which
|
|
9
|
+
* would wrongly suppress their normal launch). The id_token presence is the
|
|
10
|
+
* fallback for the rare case where Google returned no refresh_token and the
|
|
11
|
+
* id_token is still valid.
|
|
12
|
+
*/
|
|
13
|
+
export declare function shouldShowGetStarted(hasRefreshToken: boolean, hasIdToken: boolean): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The user-visible get-started text. Carries ZERO auth material (no tokens, no
|
|
16
|
+
* PII) — it is pure onboarding guidance. When no agent CLI is detected, lead
|
|
17
|
+
* with the install-an-agent-CLI step (mirrors the B1 banner intent).
|
|
18
|
+
*/
|
|
19
|
+
export declare function composeGetStarted(hasAgentCli: boolean): string;
|
|
20
|
+
//# sourceMappingURL=get-started.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function n(o,e){return!o&&!e}function r(o){const e=["","Welcome to Borg MCP \u2014 multi-agent coordination for your AI coding agent.","","You're not set up yet. To get started:",""];let t=1;return o||(e.push(` ${t}. Install an agent CLI first:`," Claude Code: https://claude.ai/download"," Codex: https://developers.openai.com/codex"),t++),e.push(` ${t}. borg setup${" ".repeat(Math.max(1,8))}\u2014 sign in with Google`),t++,e.push(` ${t}. cd into your project, then: borg assimilate \u2014 join/create a cube`,"","Then `borg` launches your agent in that cube. Run `borg --help` for more.",""),e.join(`
|
|
2
|
+
`)}export{r as composeGetStarted,n as shouldShowGetStarted};
|
package/dist/token-store.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import w from"path";import d from"crypto";import{AsyncEntry as h}from"@napi-rs/keyring";import{decryptString as k,encryptString as g}from"./token-crypto.js";const S="borg-mcp",E=t=>new h(S,t);function K(t=E){return{name:"keychain",async get(e){return await t(e).getPassword()??null},async set(e,o){await t(e).setPassword(o)},async delete(e){try{await t(e).deletePassword()}catch(o){const a=String(o?.message??"");if(/no entry|not found|no matching/i.test(a))return;throw o}}}}const O=25,_=2e3,F=1e4;function x(t){return new Promise(e=>setTimeout(e,t))}function v(){return`${process.pid}.${d.randomBytes(6).toString("hex")}`}function T(t){const{filePath:e,key:o,fs:a}=t,y=t.sleep??x,s=t.now??Date.now,p=t.uniqueSuffix??v,c=`${e}.lock`;async function l(){let r;try{r=await a.readFile(e)}catch{return{}}try{const n=k(r.trim(),o),i=JSON.parse(n);return i&&typeof i=="object"?i:{}}catch{return{}}}async function u(r){await a.mkdir(w.dirname(e),448);const n=`${e}.${p()}.tmp`;await a.writeFile(n,g(JSON.stringify(r),o),384);try{await a.rename(n,e)}catch(i){try{await a.removeFile(n)}catch{}throw i}}async function f(r){await a.mkdir(w.dirname(c),448);const n=s()+_;let i=!1;for(;!i&&(i=await a.createExclusive(c,`${process.pid}@${s()}`),!i);){const m=await a.fileAgeMs(c);if(m!==null&&m>F){await a.removeFile(c);continue}if(s()>=n){await a.removeFile(c),i=await a.createExclusive(c,`${process.pid}@${s()}`);break}await y(O)}try{return await r()}finally{i&&await a.removeFile(c)}}return{name:"encrypted-file",async get(r){const n=await l();return Object.prototype.hasOwnProperty.call(n,r)?n[r]:null},set(r,n){return f(async()=>{const i=await l();i[r]=n,await u(i)})},delete(r){return f(async()=>{const n=await l();Object.prototype.hasOwnProperty.call(n,r)&&(delete n[r],await u(n))})}}}async function b(t){return t.forced==="keychain"?t.makeKeychain():t.forced==="file"?t.makeFile():await t.keyringAvailable()?t.makeKeychain():t.makeFile()}async function L(t){const e=t.env.BORG_TOKEN?.trim();if(e)return e;const o=t.env.BORG_TOKEN_FILE?.trim();return o?(await t.readFile(o)).trim():null}export{T as makeEncryptedFileBackend,K as makeKeychainBackend,L as readCallerManagedIdToken,b as selectTokenBackend};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "borgmcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
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",
|