bridge-agent 0.6.0 → 0.6.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/bridge-mcp.cjs +0 -9
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/bridge-mcp.cjs
CHANGED
|
@@ -22463,15 +22463,6 @@ async function applyPersona(ctx, params) {
|
|
|
22463
22463
|
|
|
22464
22464
|
// ../mcp-server/src/tools/plan.ts
|
|
22465
22465
|
function registerPlanTools(server, ctx) {
|
|
22466
|
-
server.tool(
|
|
22467
|
-
"bridge_get_project",
|
|
22468
|
-
"Get project metadata: name, cwd (working directory), machineId, and current plan.",
|
|
22469
|
-
{},
|
|
22470
|
-
async () => {
|
|
22471
|
-
const project = await getProject(ctx);
|
|
22472
|
-
return { content: [{ type: "text", text: JSON.stringify(project) }] };
|
|
22473
|
-
}
|
|
22474
|
-
);
|
|
22475
22466
|
server.tool(
|
|
22476
22467
|
"bridge_get_execution_status",
|
|
22477
22468
|
"Get the execution run history and status for this project. Returns recent runs with todo completion counts.",
|
package/dist/index.js
CHANGED
|
@@ -432,4 +432,4 @@ ${a} </dict>
|
|
|
432
432
|
</plist>
|
|
433
433
|
`;try{return(0,T.writeFileSync)(t,f,"utf-8"),!0}catch(h){return console.warn("[bridge] launchd.plist.write.failed",{error:String(h)}),!1}}function bc(){let r=xe(),e=L.default.join(jt,r);try{return(0,he.execSync)(`launchctl kickstart -kp gui/$(id -u)/${r} 2>/dev/null; launchctl unload "${e}" 2>/dev/null; launchctl load "${e}"`,{stdio:"pipe"}),{ok:!0,permissionDenied:!1}}catch(t){let n=String(t);return{ok:!1,permissionDenied:n.includes("Permission denied")||n.includes("not allowed")||n.includes("bootstrap")}}}function wc(r){let{out:e,err:t}=Pt();try{let n=(0,he.spawn)(r,["start"],{detached:!0,stdio:"ignore",env:{...process.env,PATH:oi(),BRIDGE_DAEMON:"1"}});n.unref(),setTimeout(()=>{n.pid&&process.kill(n.pid,0)?(console.log("[bridge] daemon.pid",{pid:n.pid}),console.log("[bridge] background.ok",{log:e})):console.error("[bridge] background.failed \u2014 check: tail -f",{log:t})},2e3)}catch(n){console.error("[bridge] background.spawn.failed",{error:String(n)})}}function Sc(){let r=parseInt(process.env.HEALTH_PORT??"3101",10),e=Date.now()+6e3,t=()=>{if(Date.now()>e){console.error("[bridge] health.verify.timeout \u2014 daemon may have crashed immediately");return}try{let s=require("node:http").get(`http://127.0.0.1:${r}/health`,i=>{i.statusCode===200?console.log("[bridge] health.verify.ok"):setTimeout(t,500)});s.on("error",()=>{setTimeout(t,500)}),s.setTimeout(1e3,()=>{s.destroy(),setTimeout(t,500)})}catch{setTimeout(t,500)}};setTimeout(t,1e3)}function vc(){ii();let r=new dt;ni(r),r.startLivenessCheck(6e4);let e=parseInt(process.env.HEALTH_PORT??"3101",10),t=(0,si.createServer)((n,s)=>{let i=ri(),o=JSON.stringify({status:"ok",connected:i,uptime:process.uptime()});s.writeHead(i?200:503,{"Content-Type":"application/json"}),s.end(o)});t.listen(e,"127.0.0.1",()=>{console.log(`[bridge] health. listening on 127.0.0.1:${e}`)}),t.on("error",n=>{console.error("[bridge] health.error",{error:n.message})})}function ai(){let r=process.env.BRIDGE_DAEMON==="1"||process.argv.includes("--daemon");if(!r&&!process.env.BRIDGE_PROFILE){let a=process.argv[1]??"";(a.includes("packages/daemon/dist")||a.includes("packages/daemon/src"))&&(console.warn("[bridge] WARNING: running monorepo daemon without --profile \u2014 will use prod config (~/.jerico/settings.json)."),console.warn("[bridge] If this is unintentional, stop and rerun with: node packages/daemon/dist/index.js --profile dev start"))}if(console.log("[bridge] Starting bridge-agent daemon..."),r){vc();return}_c()||(console.warn("[bridge] start.aborted.already.running"),process.exit(1));let e=mc(),t=yc(e),{ok:n,permissionDenied:s}=t?bc():{ok:!1,permissionDenied:!1},i=L.default.join(jt,xe()),{out:o,err:c}=Pt();if(n){console.log("[bridge] launchd.ok \u2014 managed, auto-restart enabled"),console.log("[bridge] logs: tail -f",{out:o,err:c}),Sc(),process.exit(0);return}s&&(console.warn("[bridge] launchd.permission.denied"),console.warn("[bridge] \u2192 Auto-start on login requires:"),console.warn(`[bridge] sudo launchctl bootstrap gui/$(id -u) "${i}"`),console.warn(`[bridge] Falling back to background process...
|
|
434
434
|
`)),wc(e),process.exit(0)}var ci=_(require("https")),li=_(require("http"));Oe();var kc="https://lcars.jerico.appnova.io";function Ec(r){return(r??"").trim()}async function di(r,e=!1,t){let n=!(r&&r.trim()),s=n?kc:r.trim();console.log("[bridge] Starting auth flow..."),console.log(`[bridge] Server: ${s}${n?" (default)":""}`),console.log("[bridge] Open this URL to generate a daemon token:"),console.log(` ${s}/connect`);let i=Ec(t);i&&console.log("[bridge] Using token from --token"),e&&(i?console.log("[bridge] --no-browser ignored because --token is provided."):(console.log("[bridge] --no-browser: exiting after printing URL."),process.exit(0)));let o=i;o||(console.log(),console.log("[bridge] After authenticating, paste your token here:"),o=await Ic()),o||(console.error("[bridge] No token provided. Exiting."),process.exit(1)),await xc(s,o)||(console.error("[bridge] Token validation failed. Please try again."),process.exit(1));let l=s.replace(/^https?:\/\//,d=>d.startsWith("https")?"wss://":"ws://").replace(/\/?$/,"/ws/daemon");de({server:l,token:o,name:process.env.HOSTNAME??"My Machine"}),console.log("[bridge] Auth successful! Config saved to ~/.bridge/config.json"),console.log("[bridge] Run: bridge-agent start"),process.exit(0)}async function Ic(){return new Promise(r=>{process.stdout.write("Token: ");let e="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",t=>{e+=t,e.includes(`
|
|
435
|
-
`)&&(process.stdin.pause(),r(e.trim()))}),process.stdin.resume()})}async function xc(r,e){return new Promise(t=>{let n=new URL("/api/tokens/validate",r),s=n.protocol==="https:",i=s?ci.default:li.default,o={hostname:n.hostname,port:n.port||(s?443:80),path:n.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}},c=i.request(o,a=>{t(a.statusCode===200)});c.on("error",()=>t(!1)),c.end()})}var ui=_(require("https")),pi=_(require("http")),$r=_(require("fs")),Br=_(require("path")),hi=require("node:crypto");Oe();function Oc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function fi(r,e,t){let n=le(),s=(0,hi.createHash)("sha256").update(n.token).digest("hex"),i=Oc(n.server),o=Br.default.resolve(t);Br.default.isAbsolute(o)||(console.error("[bridge] link-project: path must be absolute"),process.exit(1)),$r.default.existsSync(o)||(console.error("[bridge] link-project: path does not exist:",o),process.exit(1)),$r.default.statSync(o).isDirectory()||(console.error("[bridge] link-project: path must be a directory:",o),process.exit(1));let a=new URL(`/api/workspaces/${r}/projects/${e}/machine-paths`,i),l=a.protocol==="https:",d=l?ui.default:pi.default;n.projectPaths={...n.projectPaths??{},[e]:o},de(n),console.log("[cli] link-project.local_json_written",{projectId:e,path:o});let u=JSON.stringify({daemonId:s,localPath:o,machineFingerprint:Mr()}),f=await new Promise((h,g)=>{let p=d.request({hostname:a.hostname,port:a.port||(l?443:80),path:a.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"Content-Length":Buffer.byteLength(u)}},m=>{let I="";m.on("data",v=>{I+=v}),m.on("end",()=>{if(m.statusCode===200)h(200);else{try{let v=JSON.parse(I);console.error("[bridge] link-project failed:",v.error??`HTTP ${m.statusCode}`)}catch{console.error("[bridge] link-project failed:",`HTTP ${m.statusCode}`)}h(m.statusCode??0)}})});p.on("error",m=>{g(m)}),p.write(u),p.end()});f===200?(console.log("[cli] link-project.server_success",{projectId:e}),console.log("[cli] link-project.success (dual-write)"),console.log(` workspace: ${r}`),console.log(` project: ${e}`),console.log(` daemon: ${s.slice(0,16)}\u2026`),console.log(` path: ${o}`),console.log("[cli] Next spawn for this project will use the linked path."),process.exit(0)):(console.warn("[cli] link-project.server_fail",{projectId:e,statusCode:f}),console.log("[cli] Local override still active \u2014 path will work on this machine"),process.exit(0))}Oe();function Cc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function gi(){let r=le(),e=Cc(r.server),t=await fetch(`${e}/api/admin/cleanup-orphans`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:"{}"});t.ok||(console.error(`[cli] cleanup-orphans: HTTP ${t.status}`),process.exit(1));let{deleted:n}=await t.json();console.log(`[cli] cleanup-orphans: deleted ${n} orphaned path ${n===1?"entry":"entries"}`),process.exit(0)}var Ur=require("node:child_process"),nt=require("node:fs"),Wr=_(require("path"));Ve();var mi=require("node:os"),Pc=Wr.default.join((0,mi.homedir)(),"Library","LaunchAgents");function _i(){let r=xe(),e=r.replace(".plist",""),t=Wr.default.join(Pc,r);try{(0,Ur.execSync)(`launchctl bootout gui/$(id -u)/${e}`,{stdio:"pipe"}),console.log("[bridge] launchd.stopped \u2014 daemon unloaded")}catch{try{(0,nt.existsSync)(t)?((0,Ur.execSync)(`launchctl unload "${t}"`,{stdio:"pipe"}),console.log("[bridge] launchd.unloaded \u2014 daemon stopped")):console.warn("[bridge] launchd.stop.failed \u2014 plist not found, daemon may not be running via launchd")}catch{console.warn("[bridge] launchd.stop.failed \u2014 daemon may not be running via launchd"),console.warn(`[bridge] Manual: launchctl bootout gui/$(id -u)/${e}`)}}let n=qe();if((0,nt.existsSync)(n))try{(0,nt.unlinkSync)(n),console.log("[bridge] lock.cleaned")}catch{}}var te=new rn;te.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.6.
|
|
435
|
+
`)&&(process.stdin.pause(),r(e.trim()))}),process.stdin.resume()})}async function xc(r,e){return new Promise(t=>{let n=new URL("/api/tokens/validate",r),s=n.protocol==="https:",i=s?ci.default:li.default,o={hostname:n.hostname,port:n.port||(s?443:80),path:n.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`}},c=i.request(o,a=>{t(a.statusCode===200)});c.on("error",()=>t(!1)),c.end()})}var ui=_(require("https")),pi=_(require("http")),$r=_(require("fs")),Br=_(require("path")),hi=require("node:crypto");Oe();function Oc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function fi(r,e,t){let n=le(),s=(0,hi.createHash)("sha256").update(n.token).digest("hex"),i=Oc(n.server),o=Br.default.resolve(t);Br.default.isAbsolute(o)||(console.error("[bridge] link-project: path must be absolute"),process.exit(1)),$r.default.existsSync(o)||(console.error("[bridge] link-project: path does not exist:",o),process.exit(1)),$r.default.statSync(o).isDirectory()||(console.error("[bridge] link-project: path must be a directory:",o),process.exit(1));let a=new URL(`/api/workspaces/${r}/projects/${e}/machine-paths`,i),l=a.protocol==="https:",d=l?ui.default:pi.default;n.projectPaths={...n.projectPaths??{},[e]:o},de(n),console.log("[cli] link-project.local_json_written",{projectId:e,path:o});let u=JSON.stringify({daemonId:s,localPath:o,machineFingerprint:Mr()}),f=await new Promise((h,g)=>{let p=d.request({hostname:a.hostname,port:a.port||(l?443:80),path:a.pathname,method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.token}`,"Content-Length":Buffer.byteLength(u)}},m=>{let I="";m.on("data",v=>{I+=v}),m.on("end",()=>{if(m.statusCode===200)h(200);else{try{let v=JSON.parse(I);console.error("[bridge] link-project failed:",v.error??`HTTP ${m.statusCode}`)}catch{console.error("[bridge] link-project failed:",`HTTP ${m.statusCode}`)}h(m.statusCode??0)}})});p.on("error",m=>{g(m)}),p.write(u),p.end()});f===200?(console.log("[cli] link-project.server_success",{projectId:e}),console.log("[cli] link-project.success (dual-write)"),console.log(` workspace: ${r}`),console.log(` project: ${e}`),console.log(` daemon: ${s.slice(0,16)}\u2026`),console.log(` path: ${o}`),console.log("[cli] Next spawn for this project will use the linked path."),process.exit(0)):(console.warn("[cli] link-project.server_fail",{projectId:e,statusCode:f}),console.log("[cli] Local override still active \u2014 path will work on this machine"),process.exit(0))}Oe();function Cc(r){return r.replace(/^wss?:/,e=>e==="wss:"?"https:":"http:").replace(/\/ws(\/.*)?$/,"")}async function gi(){let r=le(),e=Cc(r.server),t=await fetch(`${e}/api/admin/cleanup-orphans`,{method:"POST",headers:{Authorization:`Bearer ${r.token}`,"Content-Type":"application/json"},body:"{}"});t.ok||(console.error(`[cli] cleanup-orphans: HTTP ${t.status}`),process.exit(1));let{deleted:n}=await t.json();console.log(`[cli] cleanup-orphans: deleted ${n} orphaned path ${n===1?"entry":"entries"}`),process.exit(0)}var Ur=require("node:child_process"),nt=require("node:fs"),Wr=_(require("path"));Ve();var mi=require("node:os"),Pc=Wr.default.join((0,mi.homedir)(),"Library","LaunchAgents");function _i(){let r=xe(),e=r.replace(".plist",""),t=Wr.default.join(Pc,r);try{(0,Ur.execSync)(`launchctl bootout gui/$(id -u)/${e}`,{stdio:"pipe"}),console.log("[bridge] launchd.stopped \u2014 daemon unloaded")}catch{try{(0,nt.existsSync)(t)?((0,Ur.execSync)(`launchctl unload "${t}"`,{stdio:"pipe"}),console.log("[bridge] launchd.unloaded \u2014 daemon stopped")):console.warn("[bridge] launchd.stop.failed \u2014 plist not found, daemon may not be running via launchd")}catch{console.warn("[bridge] launchd.stop.failed \u2014 daemon may not be running via launchd"),console.warn(`[bridge] Manual: launchctl bootout gui/$(id -u)/${e}`)}}let n=qe();if((0,nt.existsSync)(n))try{(0,nt.unlinkSync)(n),console.log("[bridge] lock.cleaned")}catch{}}var te=new rn;te.name("bridge-agent").description("Bridge local agent \u2014 connects your AI tools to Jerico").version("0.6.1").option("--profile <name>","Config profile name (e.g. dev). Isolates config, lock, and fingerprint from the default prod profile.").hook("preAction",r=>{let e=r.opts().profile;e&&(process.env.BRIDGE_PROFILE=e)});te.command("start").description("Start the bridge-agent daemon").option("--health-port <port>","Health check HTTP port (default: 3101, or 3101+offset per profile)").action(r=>{r.healthPort&&(process.env.HEALTH_PORT=r.healthPort),ai()});te.command("auth").description("Authenticate with Bridge server").option("-s, --server <url>","Server URL (default: https://lcars.jerico.appnova.io)").option("-t, --token <token>","Use token non-interactively").option("--no-browser","Print auth URL without opening browser or interactive prompt").action(r=>{di(r.server,!r.browser,r.token)});te.command("link-project <workspace-id> <project-id> <local-path>").description("Link a local directory to a project for this machine (Issue #152)").action((r,e,t)=>{fi(r,e,t)});te.command("cleanup-orphans").description("Remove orphaned daemon_project_paths rows for this user").action(()=>{gi()});te.command("status").description("Show connection status").action(async()=>{try{let{loadConfig:r}=await Promise.resolve().then(()=>(Oe(),Gs)),e=r();console.log("[bridge] Config found"),console.log(" Server:",e.server),console.log(" Name:",e.name)}catch{console.log("[bridge] Not authenticated. Run: bridge-agent auth")}});te.command("stop").description("Stop the bridge-agent daemon").action(()=>{_i()});te.parse();
|