borgmcp 1.0.15 → 1.0.16
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/auth-recovery.d.ts +4 -3
- package/dist/console-prefix.d.ts +2 -1
- package/dist/remote-client.d.ts +22 -0
- package/dist/remote-client.js +1 -1
- package/dist/setup-action.d.ts +20 -0
- package/dist/setup-action.js +1 -0
- package/dist/setup.js +17 -16
- package/package.json +1 -1
package/dist/auth-recovery.d.ts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* gh#780 companion fix: classify auth-class failures into the RIGHT
|
|
3
3
|
* recovery advice for an in-session agent.
|
|
4
4
|
*
|
|
5
|
-
* Root-cause context: the pre-gh#780 funnel answered every auth failure
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Root-cause context: the pre-gh#780 funnel answered every auth failure by
|
|
6
|
+
* pointing the user at `borg assimilate` (the wrong remedy; gh#794 now also
|
|
7
|
+
* differentiates a dead saved login from never-signed-in, both → `borg setup`).
|
|
8
|
+
* An in-session agent's only reachable assimilate is the borg:assimilate MCP tool, which
|
|
8
9
|
* minted a brand-new drones row — so each auth blip spawned an orphan seat
|
|
9
10
|
* (the gh#780 class). Neither failure mode is fixable by assimilating:
|
|
10
11
|
* assimilate rides the same broken Bearer token.
|
package/dist/console-prefix.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* Drone self-identification prefix for client-emitted console messages.
|
|
3
3
|
*
|
|
4
4
|
* Per gh#25: when a drone session emits a console error (e.g.
|
|
5
|
-
* "Authentication expired. Run: borg
|
|
5
|
+
* "Authentication expired — your saved login has expired. Run: borg setup"),
|
|
6
|
+
* the Queen has no way to
|
|
6
7
|
* tell which drone window the message came from without scanning every
|
|
7
8
|
* open terminal. Window title alone (set by terminal-title.ts) is
|
|
8
9
|
* insufficient — the Queen reads the active terminal's output stream,
|
package/dist/remote-client.d.ts
CHANGED
|
@@ -51,6 +51,28 @@ export declare function retryOn429(initialResponse: Response, doRequest: () => P
|
|
|
51
51
|
* without duplicating the refresh-token plumbing.
|
|
52
52
|
*/
|
|
53
53
|
export declare function getValidToken(): Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* gh#794: the stored session's state, WITHOUT throwing — powers `borg setup`'s
|
|
56
|
+
* short-circuit (SR#3: short-circuit ONLY on `valid`, never past a dead token).
|
|
57
|
+
*/
|
|
58
|
+
export type SessionState = 'valid' | 'dead' | 'transient';
|
|
59
|
+
/**
|
|
60
|
+
* gh#794: classify the stored session into valid | dead | transient.
|
|
61
|
+
*
|
|
62
|
+
* ⚠ EFFECTFUL — NOT a read-only probe. The expired branch ATTEMPTS a refresh,
|
|
63
|
+
* which on success PERSISTS the new id_token (via refreshIdToken → storeIdToken,
|
|
64
|
+
* AES-256-GCM-re-encrypted) and on a dead refresh_token `clearTokens()`s. So a
|
|
65
|
+
* `valid` result may have just refreshed-and-stored the session. `clearTokens`
|
|
66
|
+
* fires ONLY on `dead` (RefreshTokenInvalidError / invalid_grant), NEVER on
|
|
67
|
+
* `transient` — a network blip must not nuke a valid keychain (gh#34 invariant).
|
|
68
|
+
*
|
|
69
|
+
* - cached id_token still valid (outside the config.ts 5-min buffer) → 'valid'
|
|
70
|
+
* - expired/within-buffer + refresh succeeds → 'valid' (refreshed + persisted)
|
|
71
|
+
* - expired + RefreshTokenInvalidError → 'dead' (cleared — re-auth needed)
|
|
72
|
+
* - expired + RefreshTransientError / unknown → 'transient' (keychain intact)
|
|
73
|
+
* - no refresh_token at all → 'dead' (never set up / already cleared)
|
|
74
|
+
*/
|
|
75
|
+
export declare function probeSession(): Promise<SessionState>;
|
|
54
76
|
/**
|
|
55
77
|
* Connect this client as a Drone to a Cube.
|
|
56
78
|
*
|
package/dist/remote-client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getIdToken as
|
|
1
|
+
import{getIdToken as f,getRefreshToken as w,clearTokens as m}from"./config.js";import{refreshIdToken as S,RefreshTokenInvalidError as g,RefreshTransientError as x}from"./auth.js";import{consolePrefix as E}from"./console-prefix.js";import{debugLog as T}from"./debug.js";import{assertUuidShape as $}from"./evict-drone.js";const R=process.env.BORG_API_URL||"https://api.borgmcp.ai",k=3,C=6e4;let l=null;function b(e){return l||(l=S(e).finally(()=>{l=null}),l)}function P(e){if(e==null)return null;const n=e.trim();return/^\d+$/.test(n)?parseInt(n,10)*1e3:null}function I(e,n,t=C,o=()=>Math.random()*500){const s=e??1e3*(n+1);return Math.min(s,t)+o()}function O(e){const n=(t,o)=>`${t}${/[.:!?]$/.test(t)?"":":"} ${o}`;try{const t=JSON.parse(e);if(typeof t?.error=="string")return typeof t.details=="string"?n(t.error,t.details):t.error;if(t?.error&&typeof t.error=="object"){const o=t.error.message,s=t.error.details??t.details;if(typeof o=="string"&&typeof s=="string")return n(o,s);if(typeof o=="string")return o}if(typeof t?.message=="string"&&typeof t?.details=="string")return n(t.message,t.details);if(typeof t?.message=="string")return t.message}catch{}return e}async function A(e,n,t){const o=t.maxRetries??k;let s=e,a=0;for(;s.status===429&&a<o;){const p=I(P(s.headers.get("Retry-After")),a,t.capMs,t.jitter);t.log?.(`rate limited (429); retrying in ${Math.round(p)}ms (attempt ${a+1}/${o})`),await t.sleep(p),a++,s=await n()}return s}function L(e){return new Promise(n=>setTimeout(n,e))}async function G(){let e=await f();if(!e){const n=await w(),t=n!=null;if(n)try{await b(n),e=await f()}catch(o){if(o instanceof g&&await m(),o instanceof x)throw o}if(!e)throw new Error(t?"Authentication expired \u2014 your saved login has expired. Run: borg setup":"Authentication required \u2014 you are not signed in. Run: borg setup")}return e}async function J(){const e=await w();if(!e)return null;try{return await b(e),await f()}catch(n){if(n instanceof g&&await m(),n instanceof x)throw n;return null}}async function q(){if(await f())return"valid";const n=await w();if(!n)return"dead";try{return await b(n),await f()?"valid":"transient"}catch(t){return t instanceof g?(await m(),"dead"):"transient"}}async function r(e,n={}){let t=await G();const{droneSession:o,apiUrl:s,headers:a,...p}=n,_=s??R,y=(p.method??"GET").toUpperCase(),h=async c=>{const u={Authorization:`Bearer ${c}`,...a};o&&(u["X-Drone-Session"]=o),T(`\u2192 ${y} ${e}`);const d=await fetch(`${_}${e}`,{...p,headers:u});return T(`\u2190 ${d.status} ${y} ${e}`),d};let i=await h(t);if(i.status===401){const c=await J();c&&(t=c,i=await h(t))}if(i.status===401)throw new Error("Authentication required. Run: borg setup");if(i.status===429&&(i=await A(i,()=>h(t),{sleep:L,log:c=>console.error(`${E()}${c}`)})),!i.ok){const c=await i.text();T(`\u2717 ${i.status} ${y} ${e}: ${c}`);const u=O(c);if(i.status===429){const d=i.headers.get("Retry-After"),j=d?` (retry after ${d}s)`:"";throw new Error(`HTTP 429: rate limited${j}: ${u}`)}throw new Error(`HTTP ${i.status}: ${u}`)}return i}async function B(e,n,t,o){const s={hostname:t??null};return(o==="claude"||o==="codex")&&(s.agent_kind=o),typeof e=="string"?s.cube_name=e:(e.cube_id&&(s.cube_id=e.cube_id),e.cube_name&&(s.cube_name=e.cube_name),e.role_id&&(s.role_id=e.role_id),e.role_name&&(s.role_name=e.role_name),e.prior_drone_id&&(s.prior_drone_id=e.prior_drone_id)),await(await r("/api/assimilate",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s),apiUrl:n})).json()}async function N(e,n){return await(await r("/api/drone/cube",{method:"GET",droneSession:e,apiUrl:n})).json()}async function F(e,n){return await(await r("/api/drone/role",{method:"GET",droneSession:e,apiUrl:n})).json()}async function X(e,n){return await(await r("/api/drone/whoami",{method:"GET",droneSession:e,apiUrl:n})).json()}async function W(e,n,t){const o=t?`?since=${encodeURIComponent(t)}`:"";return await(await r(`/api/drone/roster${o}`,{method:"GET",droneSession:e,apiUrl:n})).json()}async function z(e,n,t={}){const o=new URLSearchParams;t.since&&o.set("since",t.since),t.limit!==void 0&&o.set("limit",String(t.limit)),t.unreadOnly&&o.set("unread_only","true");const s=o.toString();return await(await r(`/api/drone/log${s?`?${s}`:""}`,{method:"GET",droneSession:e,apiUrl:n})).json()}async function Q(e,n,t){await r(`/api/drone/log/${t}/ack`,{method:"POST",body:JSON.stringify({kind:"ack"}),droneSession:e,apiUrl:n})}async function V(e,n,t={}){const o=new URLSearchParams;t.since&&o.set("since",t.since);const s=o.toString();return await(await r(`/api/drone/regen${s?`?${s}`:""}`,{method:"GET",droneSession:e,apiUrl:n})).json()}async function Y(e,n,t,o){const s=new URLSearchParams({role:t,section:o});return await(await r(`/api/drone/role-rationale?${s.toString()}`,{method:"GET",droneSession:e,apiUrl:n})).json()}async function Z(e,n,t,o={}){const s={message:t,...o.visibility?{visibility:o.visibility}:{},...o.recipientDroneIds?{recipientDroneIds:o.recipientDroneIds}:{},...o.class?{class:o.class}:{},...o.to?{to:o.to}:{}};return await(await r("/api/drone/log",{method:"POST",headers:{"Content-Type":"application/json"},droneSession:e,apiUrl:n,body:JSON.stringify(s)})).json()}async function K(){return await(await r("/api/cubes",{method:"GET"})).json()}async function ee(){return await(await r("/api/templates",{method:"GET"})).json()}async function te(e,n,t){const o={cube_directive:n};e&&(o.name=e),t?.template&&(o.template=t.template),t&&Object.prototype.hasOwnProperty.call(t,"message_taxonomy")&&(o.message_taxonomy=t.message_taxonomy??null);const a=await(await r("/api/cubes",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)})).json();return a.cube?{...a.cube,roles:a.roles??[],drones:a.drones??[]}:a}async function ne(e,n){return await(await r(`/api/cubes/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).json()}async function oe(e,n){return await(await r(`/api/cubes/${e}/taxonomy-patch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).json()}async function se(e){await r(`/api/cubes/${e}`,{method:"DELETE"})}async function re(e,n){return await(await r(`/api/cubes/${e}/roles`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).json()}async function ae(e,n){return await(await r(`/api/roles/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).json()}async function ie(e,n){return await(await r(`/api/roles/${e}/section-patch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)})).json()}async function ce(e){await r(`/api/roles/${e}`,{method:"DELETE"})}async function pe(e,n){return $(e,"drone_id"),await(await r(`/api/drones/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({role_id:n})})).json()}async function ue(e){$(e,"drone_id"),await r(`/api/drones/${e}`,{method:"DELETE"})}async function de(e){const t=await(await r(`/api/cubes/${e}`,{method:"GET"})).json();return t.cube?{...t.cube,roles:t.roles??[],drones:t.drones??[]}:t}async function fe(e,n){return await(await r(`/api/cubes/${e}/apply-template`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template_name:n})})).json()}async function le(){return await(await r("/api/subscription/status",{method:"GET"})).json()}async function ye(e,n="software-dev",t=!1,o){return await(await r(`/api/cubes/${e}/sync-roles`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template_name:n,apply:t,...o?{decisions:o}:{}})})).json()}async function he(){const n=await(await r("/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"}})).json();if(!n.checkout_url)throw new Error("No checkout URL in response");return n.checkout_url}async function we(){const n=await(await r("/api/subscription/portal",{method:"POST",headers:{"Content-Type":"application/json"}})).json();if(!n.portal_url)throw new Error(n.message||"No portal URL in response");return n.portal_url}export{R as API_URL,Q as ackLogEntry,Z as appendLog,fe as applyTemplate,B as assimilate,le as checkSubscriptionStatus,we as createBillingPortalSession,te as createCube,re as createRole,he as createSubscription,se as deleteCube,ce as deleteRole,ue as evictDrone,O as extractHttpErrorMessage,de as getCube,N as getCubeInfo,F as getRoleInfo,W as getRoster,G as getValidToken,K as listCubes,ee as listTemplates,P as parseRetryAfterMs,ie as patchRoleSection,oe as patchTaxonomyClass,q as probeSession,I as rateLimitWaitMs,z as readLog,pe as reassignDrone,V as regen,A as retryOn429,Y as roleRationale,ye as syncRoles,ne as updateCube,ae as updateRole,X as whoami};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* gh#794 (CR 9f302b15): the `borg setup` auth-step decision, extracted as a
|
|
3
|
+
* PURE, side-effect-free mapping so the SR#3 contract is unit-pinned WITHOUT
|
|
4
|
+
* importing setup.ts (which runs `main()` at module load) or mocking the
|
|
5
|
+
* monolithic runSetup. `tsc` proves setup.ts's switch COMPILES; the unit test
|
|
6
|
+
* over this helper proves it MAPS correctly — a future mis-edit (e.g. a
|
|
7
|
+
* 'transient' wrongly skipping → an SR#3 break) fails the mapping test instead
|
|
8
|
+
* of silently passing every probeSession test.
|
|
9
|
+
*
|
|
10
|
+
* - 'valid' → 'skip' (short-circuit OAuth; session is usable)
|
|
11
|
+
* - 'dead' → 'reauth' (full re-auth — NEVER short-circuit past a dead
|
|
12
|
+
* token, the exact failure #794 fixes)
|
|
13
|
+
* - 'transient' → 'retry' (network blip — don't re-auth, don't destroy)
|
|
14
|
+
*
|
|
15
|
+
* Type-only import of SessionState → zero runtime coupling to remote-client.
|
|
16
|
+
*/
|
|
17
|
+
import type { SessionState } from './remote-client.js';
|
|
18
|
+
export type SetupAuthAction = 'skip' | 'reauth' | 'retry';
|
|
19
|
+
export declare function setupActionForSession(state: SessionState): SetupAuthAction;
|
|
20
|
+
//# sourceMappingURL=setup-action.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function t(e){switch(e){case"valid":return"skip";case"transient":return"retry";default:return"reauth"}}export{t as setupActionForSession};
|
package/dist/setup.js
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
\u25FC Borg MCP Setup Wizard \u25FC`));const i=process.argv.includes("--no-browser")||process.argv.includes("--device");let n=null,t=null;try{n=
|
|
2
|
+
import b from"prompts";import e from"chalk";import u from"open";import d from"which";import{authenticateWithGoogle as m}from"./auth.js";import{checkSubscriptionStatus as c,createSubscription as f,probeSession as y}from"./remote-client.js";import{setupActionForSession as w}from"./setup-action.js";import{retrySubscriptionCheck as p}from"./subscription-retry.js";import{addMcpServer as C,addUserPromptSubmitHook as k,addCodexMcpServer as S,addCodexSessionStartHook as x,addCodexUserPromptSubmitHook as v,isMcpServerConfigured as F,isCodexMcpServerConfigured as $,removeSessionStartHook as A}from"./config-utils.js";import{handleVersionFlag as P}from"./version.js";import{initDebugFromArgv as R}from"./debug.js";async function M(){R(process.argv),P(),console.log(e.blue.bold(`
|
|
3
|
+
\u25FC Borg MCP Setup Wizard \u25FC`));const i=process.argv.includes("--no-browser")||process.argv.includes("--device");let n=null,t=null;try{n=d.sync("claude")}catch{}try{t=d.sync("codex")}catch{}if(n&&console.log(e.gray(`Found Claude CLI: ${n}`)),t&&console.log(e.gray(`Found Codex CLI: ${t}`)),(n||t)&&console.log(""),!n&&!t&&(console.error(e.red(`\u25FC No supported agent CLI found
|
|
4
4
|
`)),console.error(e.yellow("Please install Claude Code or Codex first:")),console.error(e.gray(" Claude Code: https://claude.ai/download")),console.error(e.gray(` Codex: https://developers.openai.com/codex
|
|
5
|
-
`)),process.exit(1)),console.log(e.blue("\u25FC Agent CLI Integration")),n)try{
|
|
5
|
+
`)),process.exit(1)),console.log(e.blue("\u25FC Agent CLI Integration")),n)try{F()||C(),A(),k(),console.log(e.green("\u25FC borg configured for Claude Code"))}catch(o){console.error(e.red(`
|
|
6
6
|
\u25FC Failed to configure Claude Code: ${o.message}
|
|
7
|
-
`)),process.exit(1)}if(t)try{
|
|
7
|
+
`)),process.exit(1)}if(t)try{$()||S(),x(),v(),console.log(e.green("\u25FC borg configured for Codex"))}catch(o){console.error(e.red(`
|
|
8
8
|
\u25FC Failed to configure Codex: ${o.message}
|
|
9
|
-
`)),process.exit(1)}
|
|
10
|
-
`));else
|
|
9
|
+
`)),process.exit(1)}console.log(""),console.log(e.blue("\u25FC Google Authentication"));const g=w(await y());if(g==="skip")console.log(e.green(`\u25FC Already signed in
|
|
10
|
+
`));else if(g==="retry")console.error(e.yellow(`
|
|
11
|
+
\u25FC Could not reach Google to verify your session (network issue).`)),console.error(e.yellow("Re-run `borg setup` when your connection is back.\n")),process.exit(1);else try{await m(i?{noBrowser:!0}:void 0)}catch(o){console.error(e.red(`
|
|
11
12
|
\u25FC Authentication failed: ${o.message}
|
|
12
13
|
`)),console.error(e.yellow("Re-run `borg setup` to try again.\n")),process.exit(1)}console.log(e.blue("\u25FC Subscription Check"));let s;try{s=await c()}catch(o){console.error(e.yellow(`
|
|
13
14
|
\u25FC Subscription check failed: ${o.message}`)),console.error(e.gray(`\u25FC Retrying before falling back to the Free tier...
|
|
14
|
-
`)),s={hasAccess:!1}}if(s=await
|
|
15
|
+
`)),s={hasAccess:!1}}if(s=await p(s,{check:c,sleep:o=>new Promise(r=>setTimeout(r,o)),onRetry:(o,r)=>console.log(e.gray(`\u25FC Checking subscription... (attempt ${o}/${r})`))}),s.hasAccess)if(console.log(e.green("\u25FC Active subscription found")),s.expiresAt){const o=new Date(s.expiresAt);console.log(e.gray(` Expires: ${o.toLocaleDateString()}
|
|
15
16
|
`))}else console.log("");else{console.log(e.green("\u25FC You're on the Free tier \u2014 permanent, no card needed: 1 cube + 3 agent sessions + 100 req/hr.")),console.log(e.gray(`\u25FC Start using borgmcp right now. Upgrade any time: $1/month per cube, each cube adds 8 pooled agent sessions + 1000 req/hr.
|
|
16
|
-
`));const{subscribeMethod:o}=await
|
|
17
|
+
`));const{subscribeMethod:o}=await b({type:"select",name:"subscribeMethod",message:"You're ready on the Free tier. Want to do more?",choices:[{title:"\u25FC Continue on the Free tier (recommended)",value:"skip",description:"Start now \u2014 1 cube, 3 agent sessions, 100 req/hr. No payment required."},{title:"\u25FC Upgrade to Cube tier \u2014 $1/month per cube",value:"web",description:"Each cube adds 8 pooled agent sessions + 1000 req/hr. Opens the subscribe page in your browser."},{title:"\u25FC Quick Stripe checkout",value:"stripe",description:"Fast upgrade checkout in the browser"},{title:"\u25FC I already subscribed \u2014 re-check",value:"recheck",description:"Re-check now \u2014 a just-completed subscription can take a moment to activate"}]});switch(o===void 0&&console.log(e.yellow(`
|
|
17
18
|
\u25FC No subscription option selected \u2014 continuing on the Free tier.
|
|
18
19
|
`)),o){case"web":console.log(e.blue(`
|
|
19
|
-
\u25FC Opening: https://borgmcp.ai/subscribe`));try{await
|
|
20
|
-
`)),await
|
|
20
|
+
\u25FC Opening: https://borgmcp.ai/subscribe`));try{await u("https://borgmcp.ai/subscribe"),console.log(e.gray(`\u25FC Waiting for subscription (checking every 5s for 2 min)...
|
|
21
|
+
`)),await h()}catch(r){console.error(e.yellow(`
|
|
21
22
|
\u25FC ${r.message}`)),console.log(e.green(`\u25FC Continuing on the Free tier. Upgrade any time from https://borgmcp.ai/subscribe.
|
|
22
|
-
`))}break;case"stripe":try{const r=await
|
|
23
|
-
\u25FC Opening Stripe: ${r}`)),await
|
|
24
|
-
`)),await
|
|
23
|
+
`))}break;case"stripe":try{const r=await f();console.log(e.blue(`
|
|
24
|
+
\u25FC Opening Stripe: ${r}`)),await u(r),console.log(e.gray(`\u25FC Waiting for subscription...
|
|
25
|
+
`)),await h()}catch(r){console.error(e.red(`
|
|
25
26
|
\u25FC Failed to create checkout: ${r.message}
|
|
26
27
|
`)),console.log(e.green(`\u25FC Continuing on the Free tier. Upgrade any time from https://borgmcp.ai/subscribe.
|
|
27
|
-
`))}break;case"recheck":try{let r;try{r=await c()}catch{r={hasAccess:!1}}r=await
|
|
28
|
+
`))}break;case"recheck":try{let r;try{r=await c()}catch{r={hasAccess:!1}}r=await p(r,{check:c,sleep:a=>new Promise(l=>setTimeout(l,a)),onRetry:(a,l)=>console.log(e.gray(`\u25FC Re-checking subscription... (attempt ${a}/${l})`))}),r.hasAccess?console.log(e.green(`
|
|
28
29
|
\u25FC Subscription found!
|
|
29
30
|
`)):console.log(e.yellow(`
|
|
30
31
|
\u25FC No subscription found \u2014 continuing on the Free tier.
|
|
@@ -36,7 +37,7 @@ import h from"prompts";import e from"chalk";import g from"open";import u from"wh
|
|
|
36
37
|
`));break}}console.log(e.green.bold(`Setup complete!
|
|
37
38
|
`)),console.log(e.yellow(`\u{1F504} Restart Claude Code/Codex (or open a new session) for the changes to take effect.
|
|
38
39
|
`)),console.log(e.gray("\u25FC Next steps:")),console.log(e.gray('1. cd into your project, then run "borg assimilate" to join a cube')),console.log(e.gray(" (this creates/joins the cube and launches your agent)")),console.log(e.gray(`2. Manage cubes and subscription at https://borgmcp.ai/dashboard
|
|
39
|
-
`))}async function
|
|
40
|
-
`));return}}catch{}}throw new Error("Timeout - Run setup again after subscribing")}
|
|
40
|
+
`))}async function h(){for(let n=0;n<24;n++){await new Promise(t=>setTimeout(t,5e3));try{if((await c()).hasAccess){console.log(e.green(`\u25FC Subscription activated!
|
|
41
|
+
`));return}}catch{}}throw new Error("Timeout - Run setup again after subscribing")}M().catch(i=>{console.error(e.red(`
|
|
41
42
|
\u25FC Setup failed: ${i.message}
|
|
42
43
|
`)),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "borgmcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
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",
|