broods 0.53.0 → 0.53.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.
@@ -1,4 +1,4 @@
1
- import{O,E}from"./chunk-ybkav7qd.js";import{e,o,i,c,n,t,u,w,s,d,r}from"./chunk-8zcgnjs8.js";import{Q,se,x}from"./cli/index.js";import{spawn as ne}from"node:child_process";import{statfsSync as ie}from"node:fs";import{availableParallelism as ae,homedir as ce,hostname as le,totalmem as pe}from"node:os";import{performance as j}from"node:perf_hooks";var P=["cursor_position","double_click","hold_key","key","left_click","left_click_drag","left_mouse_down","left_mouse_up","middle_click","mouse_move","right_click","screenshot","scroll","triple_click","type","wait","zoom"];var T={badFrame:{code:4400,reason:"Malformed frame"},expired:{code:4419,reason:"Credential expired"},occupied:{code:4423,reason:"Already connected from another daemon"},replaced:{code:4409,reason:"Replaced by a newer connection"},unauthorized:{code:4401,reason:"Unauthorized; run broods login"},unknownSandbox:{code:4404,reason:"No machine sandbox with that name in this account"}};var U="/v1/machines/ws",B=t({action:d(P),coordinate:n(o().int()).length(2).optional().describe("[x, y] in screenshot pixels for mouse actions."),start_coordinate:n(o().int()).length(2).optional().describe("[x, y] where a left_click_drag starts."),text:e().optional().describe("Text for type, the key chord for key and hold_key, or modifiers to hold during a click, drag or scroll."),scroll_direction:d(["down","left","right","up"]).optional(),scroll_amount:o().int().min(1).optional().describe("Scroll clicks, default 3."),duration:o().min(0).max(300).optional().describe("Seconds for wait and hold_key."),region:n(o().int()).length(4).optional().describe("[x0, y0, x1, y1] of the screenshot to zoom into."),repeat:o().int().min(1).max(100).optional().describe("How many times to press the key.")}),G=B.extend({type:r("computer"),id:e()}),W=t({type:r("computer-result"),id:e(),text:e().optional(),image:t({data:e(),mediaType:e()}).optional(),app:e().optional(),error:e().optional()}),J=t({type:r("credential"),token:e().min(1)}),K=t({type:r("exec"),id:e(),code:e(),cwd:e().optional(),env:s(e(),e()).optional(),timeoutSeconds:o().positive(),outputLimitBytes:o().positive()}),X=t({type:r("hello"),sandbox:e().min(1),hostname:e().optional(),platform:e().optional(),computer:i().optional(),mcp:n(e()).optional(),instance:e().optional(),force:i().optional(),specs:t({vcpu:o().positive(),memoryMb:o().positive(),storageGb:o().positive().optional()}).optional().catch(void 0)}),Y=t({type:r("mcp-call"),id:e(),server:e(),tool:e(),args:s(e(),c())}),q=t({type:r("mcp-list"),id:e(),server:e()}),Z=t({type:r("mcp-result"),id:e(),result:u({content:n(c())}).optional(),error:e().optional()}),V=t({type:r("mcp-tools"),id:e(),tools:n(u({name:e(),inputSchema:s(e(),c())})).optional(),error:e().optional()}),ee=t({type:r("ready"),sandboxId:e(),expiresInMs:o().optional()}),te=t({type:r("result"),id:e(),exitCode:o().nullable(),stdout:e(),stderr:e(),durationMs:o(),timedOut:i(),truncated:i()}),oe=w("type",[G,K,Y,q,ee]),xe=w("type",[W,J,X,Z,V,te]);function I(a){let l=new URL(U,a);return l.protocol=l.protocol==="https:"?"wss:":"ws:",l.toString()}function A(a){return re(oe,a)}function re(a,l){if(typeof l!=="string")return null;try{let y=a.safeParse(JSON.parse(l));return y.success?y.data:null}catch{return null}}var de=new Set([T.occupied.code,T.replaced.code,T.unauthorized.code,T.unknownSandbox.code]),H=72,R=30000,L=1000;function me(a,l,y){return new Promise((g)=>{let h=j.now(),f=new z(a.outputLimitBytes),k=new z(a.outputLimitBytes),b=!1,v=!1,F=(m,p)=>{if(v)return;if(v=!0,clearTimeout(D),y?.removeEventListener("abort",C),p)k.append(Buffer.from(`${p}
1
+ import{O,E}from"./chunk-b0pdqkyk.js";import{e,o,i,c,n,t,u,w,s,d,r}from"./chunk-8zcgnjs8.js";import{Q,se,x}from"./cli/index.js";import{spawn as ne}from"node:child_process";import{statfsSync as ie}from"node:fs";import{availableParallelism as ae,homedir as ce,hostname as le,totalmem as pe}from"node:os";import{performance as j}from"node:perf_hooks";var P=["cursor_position","double_click","hold_key","key","left_click","left_click_drag","left_mouse_down","left_mouse_up","middle_click","mouse_move","right_click","screenshot","scroll","triple_click","type","wait","zoom"];var T={badFrame:{code:4400,reason:"Malformed frame"},expired:{code:4419,reason:"Credential expired"},occupied:{code:4423,reason:"Already connected from another daemon"},replaced:{code:4409,reason:"Replaced by a newer connection"},unauthorized:{code:4401,reason:"Unauthorized; run broods login"},unknownSandbox:{code:4404,reason:"No machine sandbox with that name in this account"}};var U="/v1/machines/ws",B=t({action:d(P),coordinate:n(o().int()).length(2).optional().describe("[x, y] in screenshot pixels for mouse actions."),start_coordinate:n(o().int()).length(2).optional().describe("[x, y] where a left_click_drag starts."),text:e().optional().describe("Text for type, the key chord for key and hold_key, or modifiers to hold during a click, drag or scroll."),scroll_direction:d(["down","left","right","up"]).optional(),scroll_amount:o().int().min(1).optional().describe("Scroll clicks, default 3."),duration:o().min(0).max(300).optional().describe("Seconds for wait and hold_key."),region:n(o().int()).length(4).optional().describe("[x0, y0, x1, y1] of the screenshot to zoom into."),repeat:o().int().min(1).max(100).optional().describe("How many times to press the key.")}),G=B.extend({type:r("computer"),id:e()}),W=t({type:r("computer-result"),id:e(),text:e().optional(),image:t({data:e(),mediaType:e()}).optional(),app:e().optional(),error:e().optional()}),J=t({type:r("credential"),token:e().min(1)}),K=t({type:r("exec"),id:e(),code:e(),cwd:e().optional(),env:s(e(),e()).optional(),timeoutSeconds:o().positive(),outputLimitBytes:o().positive()}),X=t({type:r("hello"),sandbox:e().min(1),hostname:e().optional(),platform:e().optional(),computer:i().optional(),mcp:n(e()).optional(),instance:e().optional(),force:i().optional(),specs:t({vcpu:o().positive(),memoryMb:o().positive(),storageGb:o().positive().optional()}).optional().catch(void 0)}),Y=t({type:r("mcp-call"),id:e(),server:e(),tool:e(),args:s(e(),c())}),q=t({type:r("mcp-list"),id:e(),server:e()}),Z=t({type:r("mcp-result"),id:e(),result:u({content:n(c())}).optional(),error:e().optional()}),V=t({type:r("mcp-tools"),id:e(),tools:n(u({name:e(),inputSchema:s(e(),c())})).optional(),error:e().optional()}),ee=t({type:r("ready"),sandboxId:e(),expiresInMs:o().optional()}),te=t({type:r("result"),id:e(),exitCode:o().nullable(),stdout:e(),stderr:e(),durationMs:o(),timedOut:i(),truncated:i()}),oe=w("type",[G,K,Y,q,ee]),xe=w("type",[W,J,X,Z,V,te]);function I(a){let l=new URL(U,a);return l.protocol=l.protocol==="https:"?"wss:":"ws:",l.toString()}function A(a){return re(oe,a)}function re(a,l){if(typeof l!=="string")return null;try{let y=a.safeParse(JSON.parse(l));return y.success?y.data:null}catch{return null}}var de=new Set([T.occupied.code,T.replaced.code,T.unauthorized.code,T.unknownSandbox.code]),H=72,R=30000,L=1000;function me(a,l,y){return new Promise((g)=>{let h=j.now(),f=new z(a.outputLimitBytes),k=new z(a.outputLimitBytes),b=!1,v=!1,F=(m,p)=>{if(v)return;if(v=!0,clearTimeout(D),y?.removeEventListener("abort",C),p)k.append(Buffer.from(`${p}
2
2
  `));g({type:"result",id:a.id,exitCode:m,stdout:f.text(),stderr:k.text(),durationMs:Math.round(j.now()-h),timedOut:b,truncated:f.truncated||k.truncated})},M=ne("bash",["-lc",a.code],{cwd:a.cwd??l,env:{...O(),...a.env},detached:!0,stdio:["ignore","pipe","pipe"]}),_=()=>{if(!M.pid)return;try{process.kill(-M.pid,"SIGKILL")}catch{M.kill("SIGKILL")}},D=setTimeout(()=>{b=!0,_()},a.timeoutSeconds*1000),C=()=>{_(),F(null,"stopped: the daemon closed its socket")};if(y?.addEventListener("abort",C,{once:!0}),M.stdout.on("data",(m)=>f.append(m)),M.stderr.on("data",(m)=>k.append(m)),M.on("error",(m)=>F(null,m.message)),M.on("close",(m)=>F(m)),y?.aborted)C()})}async function Oe(a){let l=se(),y=crypto.randomUUID(),g=a.mcpFile?await ge(a.mcpFile,a.log):null,h=a.computer?await fe(a.log):null,f=L;try{while(!a.signal.aborted){let k=Date.now(),b;try{b=await a.credential()}catch(F){if(F instanceof x)throw F;a.log(`stage session unavailable (${F instanceof Error?F.message:String(F)}), retrying in ${Math.round(f/1000)}s`),await Q(f,a.signal),f=Math.min(f*2,R);continue}let v=await Me(a,b,y,l,h,g);if(a.signal.aborted)return;if(de.has(v.code))throw Error(v.reason||`core closed the socket (${v.code})`);if(Date.now()-k>R)f=L;a.log(`disconnected (${v.reason||v.code}), reconnecting in ${Math.round(f/1000)}s`),await Q(f,a.signal),f=Math.min(f*2,R)}}finally{h?.stop(),await g?.stop()}}class z{#o=[];#e;#t=0;truncated=!1;constructor(a){this.#e=a}append(a){if(this.#t>=this.#e){this.truncated=!0;return}let l=this.#e-this.#t;if(a.byteLength>l){this.#o.push(a.subarray(0,l)),this.#t=this.#e,this.truncated=!0;return}this.#o.push(a),this.#t+=a.byteLength}text(){let a=Buffer.concat(this.#o).toString("utf8");return this.truncated?`${a}
3
3
  [output truncated]`:a}}function ue(a){let l=[a.action];if(a.coordinate)l.push(`at ${a.coordinate.join(",")}`);if(a.text!==void 0)l.push(JSON.stringify(N(a.text)));if(a.region)l.push(`region ${a.region.join(",")}`);return l.join(" ")}function he(){let a=ye();return{vcpu:ae(),memoryMb:Math.round(pe()/1048576),...a?{storageGb:a}:{}}}function ye(){try{let a=ie(ce());return Math.round(a.blocks*a.bsize/1073741824)}catch{return}}function N(a){let l=a.trim().split(`
4
- `)[0]??"";return l.length>H?`${l.slice(0,H)}…`:l}async function fe(a){let{startDesktop:l}=await import("./chunk-5tnnqapc.js"),{display:y,driver:g,permissions:h}=await l(!1);if(a(`computer use on, ${y.width}x${y.height} screenshots`),!h.screenRecording||!h.accessibility)a(" screen recording or accessibility is missing, run `broods machine --doctor --request`");return g}async function ge(a,l){let{McpHost:y,readMcpServersFile:g}=await import("./chunk-r94w8493.js"),h=new y(g(a),l);return l(`mcp servers from ${a}: ${h.names().join(", ")}`),h}async function be(a,l,y){try{if(a.type==="mcp-list"){let h=await l.listTools(a.server);return y(` mcp ${a.server}: ${h.length} tools`),{type:"mcp-tools",id:a.id,tools:h}}y(` mcp ${a.server}.${a.tool}`);let g=await l.callTool(a.server,a.tool,a.args);return{type:"mcp-result",id:a.id,result:g}}catch(g){let h=g instanceof Error?g.message:String(g);return y(` mcp ${a.server}: ${h}`),{type:a.type==="mcp-call"?"mcp-result":"mcp-tools",id:a.id,error:h}}}function Me(a,l,y,g,h,f){return new Promise((k)=>{let b=new g(I(a.baseUrl),E(l)),v=new AbortController,F=()=>b.close(1000,"daemon stopped"),M=(m)=>{if(b.readyState===b.OPEN)b.send(JSON.stringify(m))},_,D=(m)=>{if(clearTimeout(_),v.signal.aborted)return;_=setTimeout(()=>{a.credential().then((p)=>M({type:"credential",token:p}),(p)=>a.log(`credential refresh failed (${p instanceof Error?p.message:String(p)}), retrying`)).finally(()=>D(m))},Math.max((m-Date.now())/2,L))},C=(m,p)=>{a.signal.removeEventListener("abort",F),clearTimeout(_),v.abort(),k({code:m,reason:p})};a.signal.addEventListener("abort",F,{once:!0}),b.onopen=()=>M({type:"hello",sandbox:a.sandbox,hostname:le(),platform:process.platform,computer:h!==null,mcp:f?.names(),instance:y,force:a.force,specs:he()}),b.onmessage=(m)=>{let p=A(m.data);if(p?.type==="ready"){if(_===void 0)a.log(`connected as ${a.sandbox} (${p.sandboxId})`);if(p.expiresInMs!==void 0)D(Date.now()+p.expiresInMs);return}if(p?.type==="computer"&&h){a.log(` ${ue(p)}`),h.run(p).then((S)=>{if(S.error)a.log(` error: ${S.error}`);M(S)});return}if((p?.type==="mcp-call"||p?.type==="mcp-list")&&f){be(p,f,a.log).then(M);return}if(p?.type!=="exec")return;a.log(`$ ${N(p.code)}`),me(p,a.cwd,v.signal).then((S)=>{a.log(` exit ${S.exitCode??"none"} in ${S.durationMs}ms${S.timedOut?" (timed out)":""}`),M(S)})},b.onerror=()=>C(1006,"connection failed"),b.onclose=(m)=>C(m.code,m.reason)})}export{Oe as runMachineDaemon};
4
+ `)[0]??"";return l.length>H?`${l.slice(0,H)}…`:l}async function fe(a){let{startDesktop:l}=await import("./chunk-5tnnqapc.js"),{display:y,driver:g,permissions:h}=await l(!1);if(a(`computer use on, ${y.width}x${y.height} screenshots`),!h.screenRecording||!h.accessibility)a(" screen recording or accessibility is missing, run `broods machine --doctor --request`");return g}async function ge(a,l){let{McpHost:y,readMcpServersFile:g}=await import("./chunk-bbvew31z.js"),h=new y(g(a),l);return l(`mcp servers from ${a}: ${h.names().join(", ")}`),h}async function be(a,l,y){try{if(a.type==="mcp-list"){let h=await l.listTools(a.server);return y(` mcp ${a.server}: ${h.length} tools`),{type:"mcp-tools",id:a.id,tools:h}}y(` mcp ${a.server}.${a.tool}`);let g=await l.callTool(a.server,a.tool,a.args);return{type:"mcp-result",id:a.id,result:g}}catch(g){let h=g instanceof Error?g.message:String(g);return y(` mcp ${a.server}: ${h}`),{type:a.type==="mcp-call"?"mcp-result":"mcp-tools",id:a.id,error:h}}}function Me(a,l,y,g,h,f){return new Promise((k)=>{let b=new g(I(a.baseUrl),E(l)),v=new AbortController,F=()=>b.close(1000,"daemon stopped"),M=(m)=>{if(b.readyState===b.OPEN)b.send(JSON.stringify(m))},_,D=(m)=>{if(clearTimeout(_),v.signal.aborted)return;_=setTimeout(()=>{a.credential().then((p)=>M({type:"credential",token:p}),(p)=>a.log(`credential refresh failed (${p instanceof Error?p.message:String(p)}), retrying`)).finally(()=>D(m))},Math.max((m-Date.now())/2,L))},C=(m,p)=>{a.signal.removeEventListener("abort",F),clearTimeout(_),v.abort(),k({code:m,reason:p})};a.signal.addEventListener("abort",F,{once:!0}),b.onopen=()=>M({type:"hello",sandbox:a.sandbox,hostname:le(),platform:process.platform,computer:h!==null,mcp:f?.names(),instance:y,force:a.force,specs:he()}),b.onmessage=(m)=>{let p=A(m.data);if(p?.type==="ready"){if(_===void 0)a.log(`connected as ${a.sandbox} (${p.sandboxId})`);if(p.expiresInMs!==void 0)D(Date.now()+p.expiresInMs);return}if(p?.type==="computer"&&h){a.log(` ${ue(p)}`),h.run(p).then((S)=>{if(S.error)a.log(` error: ${S.error}`);M(S)});return}if((p?.type==="mcp-call"||p?.type==="mcp-list")&&f){be(p,f,a.log).then(M);return}if(p?.type!=="exec")return;a.log(`$ ${N(p.code)}`),me(p,a.cwd,v.signal).then((S)=>{a.log(` exit ${S.exitCode??"none"} in ${S.durationMs}ms${S.timedOut?" (timed out)":""}`),M(S)})},b.onerror=()=>C(1006,"connection failed"),b.onclose=(m)=>C(m.code,m.reason)})}export{Oe as runMachineDaemon};
@@ -1,5 +1,5 @@
1
1
  function q(e){if(e.events&&e.input!==void 0)throw Error("Run input accepts either `input` or `events`, not both");if(e.events&&e.events.length>0)return e.events;if(typeof e.input==="string")return[{role:"user",content:[{type:"text",text:e.input}]}];throw Error("Run input requires `input` (string) or a non-empty `events` array")}async function*ie(e){let n=e.getReader(),t=new TextDecoder,o="";try{while(!0){let{done:r,value:i}=await n.read();if(r)break;o+=t.decode(i,{stream:!0});let s=o.split(`
2
- `);o=s.pop()??"";for(let a of s)if(a.startsWith("data: "))yield a.slice(6)}}finally{await n.cancel().catch(()=>{return}),n.releaseLock()}}var ge=500,hn=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,Sn=/^(?!0{32}$)[0-9a-f]{32}$/;function pe(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function ye(e){if(typeof e!=="object"||e===null)return!1;let n=e;if(n.type==="subscribe")return Rn(n);if(n.type==="unsubscribe")return j(n.stream);if(n.type==="fetchTrace")return L(n.traceId);return!1}function Se(e){return e==="task"||e==="cron"||e==="subtask"}function D(e){return typeof e==="string"&&hn.test(e)}function L(e){return typeof e==="string"&&Sn.test(e)}function j(e){return e==="logs"||e==="traces"}function Rn(e){let n=e.stream;if(!j(n))return!1;let t=e.backfill;if(t!==void 0&&(typeof t!=="number"||!Number.isSafeInteger(t)||t<0||t>500))return!1;if(e.liveOnly!==void 0&&typeof e.liveOnly!=="boolean")return!1;let o=e.minLevel;if(o!==void 0&&!pe(o))return!1;let r=e.sandboxId;return r===void 0||n==="logs"&&D(r)}import{readFileSync as bn}from"node:fs";import{chmod as Q,mkdir as In,writeFile as xn}from"node:fs/promises";import{homedir as kn}from"node:os";import{dirname as J,join as An}from"node:path";var y="broods",b="_generated",z=An(kn(),".broods","config.json"),X="broods.app",Y="dashboard",vn="gateway";function k(e){let n=process.env.BROODS_TOKEN,t=e??process.env.BROODS_BASE_URL;if(n&&t)return{baseUrl:f(t),token:n,createdAt:new Date().toISOString()};let o=ne();if(!o)return null;if(t)return o.logins[f(t)]??null;let r=process.env.BROODS_DASHBOARD_URL;if(r){let i=f(r);return Object.values(o.logins).find((s)=>s.dashboardUrl===i)??null}return o.logins[o.current]??null}async function U(e){let n=ne()?.logins??{},t={current:e.baseUrl,logins:{...n,[e.baseUrl]:e}};await In(J(z),{recursive:!0,mode:448}),await Q(J(z),448),await B(z,`${JSON.stringify(t,null,2)}
3
- `)}async function B(e,n){await xn(e,n,{encoding:"utf8",mode:384}),await Q(e,384)}function S(){return process.env.BROODS_STAGE}function f(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function A(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${Y}.`))return;let t=n.hostname.slice(Y.length+1);if(t!==X&&!t.endsWith(`.${X}`))return;return n.hostname=`${vn}.${t}`,f(n.origin)}catch{return}}function ne(){try{let e=JSON.parse(bn(z,"utf8"));if(typeof e.current!=="string"||!e.logins)return null;return{current:e.current,logins:e.logins}}catch{return null}}import{existsSync as re,readFileSync as se,statSync as wn}from"node:fs";import{join as ce,resolve as ue}from"node:path";var W=new Map,Tn=new Set(Object.keys(process.env)),oe=new Set;function m(e=process.cwd()){En(e);let n=k();return{dashboardUrl:process.env.BROODS_DASHBOARD_URL??n?.dashboardUrl,baseUrl:process.env.BROODS_BASE_URL??n?.baseUrl,token:n?.token,project:process.env.BROODS_PROJECT,stage:S()}}function O(){let e={};for(let[n,t]of Object.entries(process.env))if(typeof t==="string"&&!n.startsWith("BROODS_"))e[n]=t;return e}function C(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=ue(n);for(let r of[".env.local",".env"]){let i=ce(o,r);if(!re(i))continue;let s=F(se(i,"utf8"));if(s[e]!==void 0)return s[e]!==t}return!0}function En(e){let n=ue(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=ce(n,o);if(!re(r)){W.delete(r);continue}let i=wn(r).mtimeMs,s=W.get(r);if(s&&s.mtimeMs===i)continue;W.set(r,{mtimeMs:i});for(let[a,c]of Object.entries(F(se(r,"utf8"))))if(t||!Tn.has(a)||oe.has(a))process.env[a]=c,oe.add(a)}}function F(e){let n={};for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;let r=o.startsWith("export ")?o.slice(7).trim():o,i=r.indexOf("=");if(i<=0)continue;let s=r.slice(0,i).trim();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(s))continue;n[s]=Nn(r.slice(i+1).trim())}return n}function Nn(e){if(e.startsWith('"')&&e.endsWith('"'))return e.slice(1,-1).replace(/\\n/g,`
4
- `).replace(/\\"/g,'"');if(e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);let n=e.indexOf(" #");return n>=0?e.slice(0,n).trimEnd():e}var G=new TextEncoder,de={name:"HMAC",hash:"SHA-256"};async function fe(e,n,t,o){let r=le(G.encode(JSON.stringify(t))),i=await crypto.subtle.sign(de,await Dn(n,o),G.encode(r));return`${e}${r}.${le(new Uint8Array(i))}`}function le(e){let n="";for(let t of e)n+=String.fromCharCode(t);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function Dn(e,n){let t=await crypto.subtle.digest("SHA-256",G.encode(`${e}${n}`));return crypto.subtle.importKey("raw",t,de,!1,["sign","verify"])}var On="buat_",Z="bsig_",ee="x-broods-user-token",he="broods.user.";var en=600000,H=3600000,Mn="broods-user-token:",nn=/^[A-Za-z0-9._@+=-]{1,128}$/,tn=100,_n=256,Un=60000;async function on(e,n,t=Date.now()){if(!n.startsWith(Z))throw Error(`The user token signing secret must start with ${Z}. It is not the bsk_ runtime key.`);let o=Pn(e,t);if(!o||e.expiresAt>t+H)throw Error(`Invalid user token: userId must match ${nn.source}, conversations must be at most ${tn} non-empty keys, and expiresAt must be in the next ${H/60000} minutes.`);return await fe(On,Mn,o,n)}function Pn(e,n){if(!e||typeof e!=="object")return null;let{userId:t,conversations:o,expiresAt:r}=e;if(typeof t!=="string"||!nn.test(t)||typeof r!=="number"||!Number.isFinite(r)||r<=n||r>n+H+Un)return null;if(o===void 0)return{userId:t,expiresAt:r};if(!Array.isArray(o)||o.length>tn||!o.every((i)=>typeof i==="string"&&i.trim()===i&&i.length>0&&i.length<=_n))return null;return{userId:t,conversations:o,expiresAt:r}}var g="BROODS_USER_TOKEN_SECRET";async function be(e){let n=e.secret??process.env[g];if(!n)throw Error(`signUserToken needs the stage's signing secret: pass secret or set ${g}. \`broods dev\` and \`broods deploy\` write it to .env.local; the dashboard's Runtime key tab rotates it.`);return await on({userId:e.userId,...e.conversations?{conversations:e.conversations}:{},expiresAt:Date.now()+(e.ttlMs??en)},n)}var T="https://gateway.broods.app";class ae extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class M{baseUrl;apiKey;userToken;fetchImpl;constructor(e={}){m(),this.baseUrl=V(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||T),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||void 0,this.userToken=e.userToken,this.fetchImpl=e.fetch??fetch}channelWebhookUrl(e){return`${this.baseUrl}${e.webhookPath.startsWith("/")?"":"/"}${e.webhookPath}`}accountWebhookUrl(e,n){let t=[e,n].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${t.join("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(i)=>this.run({...i,agentName:o,agentId:r}),runAsync:(i)=>this.runAsync({...i,agentName:o,agentId:r}),continue:(i)=>this.continue({...i,agentId:r}),stream:(i)=>this.stream({...i,agentName:o,agentId:r})}}let t=e;if(!t.id)throw Error(`Agent ${t.name} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:t.id,run:(o)=>this.run(t,o),runAsync:(o)=>this.runAsync(t,o),continue:(o)=>this.continue(t,o),stream:(o)=>this.stream(t,o)}}async run(e,n){let t=[],o="",r=n?this.stream(e,n):this.stream(e);for await(let i of r)if(t.push(i),i.type==="text-delta")o+=i.text;return{text:o,events:t}}async*stream(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=rn(t,"cli"),r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`,i=await this.openStream(o,r);if(!i.ok)throw Error(`Run failed: ${i.status} ${await i.text()}`);if(i.status===202)throw new ae(sn(await i.json(),o));if(!i.body)throw Error("Run response has no body");for await(let s of ie(i.body)){let a;try{a=JSON.parse(s)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${Wn(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o={...rn(t,"async"),background:!0},r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(r,o,"Async run")}async continue(e,n){let t=n?e:null,o=n??e,r={agentId:t?t.id:e.agentId,eventId:o.eventId??`continue-${crypto.randomUUID()}`,conversationKey:o.conversationKey,continue:!0},i=t?this.scopedUrl(t):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(i,r,"Continue")}async getAsyncStatus(e){let n=this.resolveStatusUrl(e),t=await this.fetchJson(n,{method:"GET",headers:await this.apiKeyHeaders()});if(t.status===404)return{status:"not_found"};if(!t.ok)throw Error(`Status check failed: ${t.status} ${await t.text()}`);return await t.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e);if(r.status==="awaiting_approval"||r.status==="awaiting_input"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await Ln(o,n.signal)}throw Error("Polling timeout")}scopedUrl(e){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/projects/${encodeURIComponent(e.projectSlug)}/stages/${encodeURIComponent(e.stageSlug)}/agents/${encodeURIComponent(e.endpointId)}`;return`${this.baseUrl}/v1/runs`}asyncAgentRun(e,n){return{...e,conversationKey:n,poll:()=>this.getAsyncStatus(e),wait:(t)=>this.waitForAsyncStatus(e,t)}}async postAcceptedRun(e,n,t){let o=await this.fetchJson(e,{method:"POST",headers:await this.apiKeyHeaders(),body:JSON.stringify(n)});if(o.status!==202)throw Error(`${t} failed: ${o.status} ${await Kn(o,"202 JSON")}`);return this.asyncAgentRun(sn(await o.json(),n),n.conversationKey)}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`,...await this.userTokenHeaders()});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${T} by default; set host/baseUrl or BROODS_HOST/BROODS_BASE_URL to your own core service URL if your account uses a custom deployment. Cause: ${o instanceof Error?o.message:String(o)}`)}}async apiKeyHeaders(){if(!this.apiKey)throw Error("BroodsClient requires apiKey or BROODS_API_KEY.");return{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,...await this.userTokenHeaders()}}async userTokenHeaders(){let e=typeof this.userToken==="function"?await this.userToken():this.userToken;return e?{[ee]:e}:{}}async fetchJson(e,n){try{return await this.fetchImpl(e,n)}catch(t){throw Error(`Cannot access the broods core service at ${e}. Cause: ${t instanceof Error?t.message:String(t)}`)}}resolveStatusUrl(e){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;return $n(this.baseUrl,e)}}function V(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return f(t)}function rn(e,n){let t=e.eventId??`${n}-${crypto.randomUUID()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:q(e),...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}}function Wn(e){if(typeof e==="string")return e;if(!e||typeof e!=="object")return String(e);let n=e,t=n.data?.error?.message??n.message??n.responseBody??JSON.stringify(e),o=n.name?`${n.name}: `:"",r=n.statusCode?` (HTTP ${n.statusCode})`:"";return`${o}${t}${r}`}function sn(e,n){if(!e||typeof e!=="object")throw Error("Async response must be an object");let t=e.statusUrl;if(typeof t!=="string"||t.length===0)throw Error("Async response missing statusUrl");let o=e.runId;if(typeof o!=="string"||o.length===0)throw Error("Async response missing runId");let r=typeof e.eventId==="string"?e.eventId:o,{status:i,requestedMode:s}=e;return{statusUrl:t,runId:o,eventId:r,agentId:n.agentId,...i==="accepted"||i==="queued"||i==="applied"||i==="processing"?{status:i}:{},...s==="reject"||s==="followup"||s==="collect"||s==="steer"?{requestedMode:s}:{}}}async function Kn(e,n){if((e.headers.get("content-type")??"").toLowerCase().includes("text/event-stream"))return await e.body?.cancel().catch(()=>{}),`expected ${n}, but the server returned an SSE stream. This usually means the core deployment ignored the background flag and ran the request on the direct streaming runner.`;let o=await e.text();if(o.length<=2000)return o;return`${o.slice(0,2000)}... [truncated ${o.length-2000} chars]`}function Ln(e,n){return new Promise((t,o)=>{if(n?.aborted){o(Error("Async status polling aborted."));return}let r=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(r),o(Error("Async status polling aborted."))},{once:!0})})}function $n(e,n){return`${V(e)}/v1/runs/${encodeURIComponent(n)}`}var Bn=2000,an=0,w=1;class me{baseUrl;apiKey;userToken;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(m(),this.baseUrl=pn(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||T),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||"",!this.apiKey)throw Error("BroodsWebSocketClient requires apiKey or BROODS_API_KEY.");this.userToken=e.userToken,this.WebSocketImpl=e.WebSocket,this.connectTimeoutMs=e.connectTimeoutMs??Bn}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=Hn(e),i=ln(this.baseUrl),s=new t(o,E(this.apiKey,e.userToken??this.userToken)),a=!1,c=!1,d=setTimeout(()=>{if(!a)x(i)},this.connectTimeoutMs),R=(p=1000,_="client closed")=>{if(c)return;if(c=!0,clearTimeout(d),e.signal?.removeEventListener("abort",N),s.readyState===w||s.readyState===an)s.close(p,_)},x=(p)=>{n.onError?.(p),R(1000,"websocket error")},Cn=()=>{n.onDone?.(),R(1000,"done")},N=()=>{if(s.readyState===w)s.send(JSON.stringify({type:"cancel"}));x(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",N,{once:!0}),s.onopen=()=>{if(a=!0,clearTimeout(d),e.signal?.aborted){N();return}s.send(JSON.stringify({type:"execute",agentId:r,...e.answers?{answers:e.answers}:{events:q(e)},sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},s.onmessage=(p)=>{if(typeof p.data!=="string")return;let _=un(p.data);if(!_)return;let P=gn(_,n);switch(n.onMessage?.(P),P.type){case"meta":n.onMeta?.(P);break;case"done":Cn();break;case"error":x(Error(cn(P.error)));break}},s.onerror=()=>{x(i)},s.onclose=(p)=>{if(clearTimeout(d),e.signal?.removeEventListener("abort",N),c||p.code===1000)return;x(Error(p.reason||"WebSocket connection closed."))},{url:o,sendControl:function(p){if(s.readyState!==w)throw Error("WebSocket is not open");s.send(JSON.stringify({type:"control",...p}))},close:R}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o,E(this.apiKey,e.userToken??this.userToken)),i=!1,s=(c=1000,d="client closed")=>{if(i)return;if(i=!0,e.signal?.removeEventListener("abort",a),r.readyState===w||r.readyState===an)r.close(c,d)},a=()=>{s(1000,"aborted"),n.onError?.(Error("WebSocket attach aborted."))};if(e.signal?.aborted)a();else e.signal?.addEventListener("abort",a,{once:!0});return r.onopen=()=>{if(i)return;r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0,userToken:void 0}))},r.onmessage=(c)=>{if(i||typeof c.data!=="string")return;let d=un(c.data);if(!d)return;let R=gn(d,n);if(i)return;if(n.onMessage?.(R),i)return;if(R.type==="done")n.onDone?.();if(R.type==="error")n.onError?.(Error(cn(R.error)))},r.onerror=()=>{if(i)return;s(1000,"websocket error"),n.onError?.(ln(this.baseUrl))},r.onclose=(c)=>{if(e.signal?.removeEventListener("abort",a),!i&&c.code!==1000)n.onError?.(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl:function(c){if(r.readyState!==w)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...c}))},close:s}}async*stream(e){let n=[],t=!1,o=null,r=null,i=()=>{r?.(),r=null},s=this.subscribe(e,{onMessage:function(a){n.push(a),i()},onDone:function(){t=!0,i()},onError:function(a){o=a,i()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{s.close()}}buildUrl(e){let n=Gn(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t&&o?`/projects/${encodeURIComponent(t)}/stages/${encodeURIComponent(o)}`:"";return`${K(this.baseUrl)}/v1${r}/agents/${encodeURIComponent(n)}/ws`}resolveWebSocket(){let e=this.WebSocketImpl??globalThis.WebSocket;if(!e)throw Error("WebSocket is not available. Pass a WebSocket implementation in BroodsWebSocketClient options.");return e}}function K(e){let n=new URL(pn(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return f(n.toString())}function E(e,n){return["broods.v1",`broods.token.${e}`,...n?[`${he}${n}`]:[]]}function cn(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&typeof e.message==="string")return e.message;return e===void 0?"WebSocket stream error.":JSON.stringify(e)}function pn(e){let n=e.trim();if(/^wss?:\/\//.test(n))return f(n);return V(n)}function un(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function Hn(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function Gn(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function gn(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function ln(e){return Error(`Cannot access the WebSocket service at ${e}.`)}var fn=Symbol.for("broods.resource"),yn=Symbol.for("broods.config"),mn=Symbol.for("broods.connection"),dn=/^[A-Z][A-Z0-9_]{0,63}$/,ve=new Proxy((e)=>{if(!dn.test(e))throw Error("env name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return{__beeblastEnv:!0,name:e}},{get:function(e,n,t){if(typeof n==="string"&&dn.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function _e(e){let{name:n,description:t,...o}=e;return I("agent",n,t,o)}function we(e){return{[yn]:!0,config:e}}function Re(e){let{name:n,description:t,...o}=e;return I("cron",n,t,o)}function $e(e){return e}function Ce(e){let{name:n,description:t,...o}=e;return I("mcp",n,t,o)}function Ee(e){let{name:n,description:t,...o}=e;return I("policy",n,t,o)}function ke(e){let{name:n,description:t,...o}=e;return I("sandbox",n,t,o)}function Te(e){let{name:n,description:t,...o}=e;return I("skill",n,t,o)}function Pe(e){let{name:n,description:t,...o}=e;return I("workspace",n,t,o)}function Ie(e){return l("discord",e)}function ze(e){return l("github",e)}function xe(e){return l("gchat",e)}function Ae(e){return l("instagram",e)}function Oe(e){return l("linear",e)}function Me(e){return l("matrix",e)}function Ne(e){return l("messenger",e)}function je(e){return l("pancake",e)}function qe(e){return l("slack",e)}function De(e){return l("teams",e)}function Le(e){return l("telegram",e)}function Ue(e){return l("twilio",e)}function Be(e){return l("whatsapp",e)}function Fe(e){return l("zalo",e)}function Ze(e){let{name:n,description:t,channelId:o,guildId:r,...i}=e;return u(n,t,o,r,i)}function He(e){let{name:n,description:t,repo:o,...r}=e,[i,...s]=o.split("/");if(!i||s.length!==1||!s[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return u(n,t,o,i,r)}function Ve(e){let{name:n,description:t,spaceName:o,...r}=e;return u(n,t,o,void 0,r)}function Ke(e){let{name:n,description:t,igsid:o,...r}=e;return u(n,t,o,void 0,r)}function Ge(e){let{name:n,description:t,team:o,...r}=e;return u(n,t,o,void 0,r)}function We(e){let{name:n,description:t,channelId:o,...r}=e;return u(n,t,o,void 0,r)}function Je(e){let{name:n,description:t,psid:o,...r}=e;return u(n,t,o,void 0,r)}function Ye(e){let{name:n,description:t,conversationId:o,...r}=e;return u(n,t,o,void 0,r)}function Xe(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return u(n,t,o,r,i)}function Qe(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return u(n,t,o,r,i)}function et(e){let{name:n,description:t,chatId:o,...r}=e;return u(n,t,o,void 0,r)}function tt(e){let{name:n,description:t,from:o,...r}=e;return u(n,t,o,void 0,r)}function nt(e){let{name:n,description:t,waId:o,...r}=e;return u(n,t,o,void 0,r)}function rt(e){let{name:n,description:t,chatId:o,...r}=e;return u(n,t,o,void 0,r)}function te(e){return Boolean(e&&typeof e==="object"&&e[yn])}function v(e){return Boolean(e&&typeof e==="object"&&e[mn])}function h(e){return Boolean(e&&typeof e==="object"&&e[fn])}function u(e,n,t,o,r){return I("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function l(e,n){let{partition:t,...o}=n;return{[mn]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function I(e,n,t,o){return{[fn]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}
5
- export{q,ie,ge,pe,ye,Se,D,L,y,b,z,k,U,B,S,f,A,m,O,C,F,Z,ee,H,g,be,T,ae,M,V,me,K,E,ve,_e,we,Re,$e,Ce,Ee,ke,Te,Pe,Ie,ze,xe,Ae,Oe,Me,Ne,je,qe,De,Le,Ue,Be,Fe,Ze,He,Ve,Ke,Ge,We,Je,Ye,Xe,Qe,et,tt,nt,rt,te,v,h};
2
+ `);o=s.pop()??"";for(let a of s)if(a.startsWith("data: "))yield a.slice(6)}}finally{await n.cancel().catch(()=>{return}),n.releaseLock()}}var ge=500,hn=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,Sn=/^(?!0{32}$)[0-9a-f]{32}$/;function pe(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function ye(e){if(typeof e!=="object"||e===null)return!1;let n=e;if(n.type==="subscribe")return Rn(n);if(n.type==="unsubscribe")return j(n.stream);if(n.type==="fetchTrace")return L(n.traceId);return!1}function Se(e){return e==="task"||e==="cron"||e==="subtask"}function D(e){return typeof e==="string"&&hn.test(e)}function L(e){return typeof e==="string"&&Sn.test(e)}function j(e){return e==="logs"||e==="traces"}function Rn(e){let n=e.stream;if(!j(n))return!1;let t=e.backfill;if(t!==void 0&&(typeof t!=="number"||!Number.isSafeInteger(t)||t<0||t>500))return!1;if(e.liveOnly!==void 0&&typeof e.liveOnly!=="boolean")return!1;let o=e.minLevel;if(o!==void 0&&!pe(o))return!1;let r=e.sandboxId;return r===void 0||n==="logs"&&D(r)}import{readFileSync as bn}from"node:fs";import{chmod as Q,mkdir as In,writeFile as xn}from"node:fs/promises";import{homedir as kn}from"node:os";import{dirname as J,join as An}from"node:path";var y="broods",b="_generated",z=An(kn(),".broods","config.json"),X="broods.app",Y="dashboard",vn="gateway";function k(e){let n=process.env.BROODS_TOKEN,t=e??process.env.BROODS_BASE_URL;if(n&&t)return{baseUrl:f(t),token:n,createdAt:new Date().toISOString()};let o=ne();if(!o)return null;if(t)return o.logins[f(t)]??null;let r=process.env.BROODS_DASHBOARD_URL;if(r){let i=f(r);return Object.values(o.logins).find((s)=>s.dashboardUrl===i)??null}return o.logins[o.current]??null}async function U(e){let n=ne()?.logins??{},t={current:e.baseUrl,logins:{...n,[e.baseUrl]:e}};await In(J(z),{recursive:!0,mode:448}),await Q(J(z),448),await F(z,`${JSON.stringify(t,null,2)}
3
+ `)}async function F(e,n){await xn(e,n,{encoding:"utf8",mode:384}),await Q(e,384)}function S(){return process.env.BROODS_STAGE}function f(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function A(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${Y}.`))return;let t=n.hostname.slice(Y.length+1);if(t!==X&&!t.endsWith(`.${X}`))return;return n.hostname=`${vn}.${t}`,f(n.origin)}catch{return}}function ne(){try{let e=JSON.parse(bn(z,"utf8"));if(typeof e.current!=="string"||!e.logins)return null;return{current:e.current,logins:e.logins}}catch{return null}}import{existsSync as re,readFileSync as se,statSync as wn}from"node:fs";import{join as ce,resolve as ue}from"node:path";var W=new Map,Tn=new Set(Object.keys(process.env)),oe=new Set;function m(e=process.cwd()){En(e);let n=k();return{dashboardUrl:process.env.BROODS_DASHBOARD_URL??n?.dashboardUrl,baseUrl:process.env.BROODS_BASE_URL??n?.baseUrl,token:n?.token,project:process.env.BROODS_PROJECT,stage:S()}}function O(){let e={};for(let[n,t]of Object.entries(process.env))if(typeof t==="string"&&!n.startsWith("BROODS_"))e[n]=t;return e}function C(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=ue(n);for(let r of[".env.local",".env"]){let i=ce(o,r);if(!re(i))continue;let s=B(se(i,"utf8"));if(s[e]!==void 0)return s[e]!==t}return!0}function En(e){let n=ue(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=ce(n,o);if(!re(r)){W.delete(r);continue}let i=wn(r).mtimeMs,s=W.get(r);if(s&&s.mtimeMs===i)continue;W.set(r,{mtimeMs:i});for(let[a,c]of Object.entries(B(se(r,"utf8"))))if(t||!Tn.has(a)||oe.has(a))process.env[a]=c,oe.add(a)}}function B(e){let n={};for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;let r=o.startsWith("export ")?o.slice(7).trim():o,i=r.indexOf("=");if(i<=0)continue;let s=r.slice(0,i).trim();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(s))continue;n[s]=Nn(r.slice(i+1).trim())}return n}function Nn(e){if(e.startsWith('"')&&e.endsWith('"'))return e.slice(1,-1).replace(/\\n/g,`
4
+ `).replace(/\\"/g,'"');if(e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);let n=e.indexOf(" #");return n>=0?e.slice(0,n).trimEnd():e}var G=new TextEncoder,de={name:"HMAC",hash:"SHA-256"};async function fe(e,n,t,o){let r=le(G.encode(JSON.stringify(t))),i=await crypto.subtle.sign(de,await Dn(n,o),G.encode(r));return`${e}${r}.${le(new Uint8Array(i))}`}function le(e){let n="";for(let t of e)n+=String.fromCharCode(t);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function Dn(e,n){let t=await crypto.subtle.digest("SHA-256",G.encode(`${e}${n}`));return crypto.subtle.importKey("raw",t,de,!1,["sign","verify"])}var On="buat_",H="bsig_",ee="x-broods-user-token",he="broods.user.";var en=600000,Z=3600000,Mn="broods-user-token:",nn=/^[A-Za-z0-9._@+=-]{1,128}$/,tn=100,_n=256,Un=60000;async function on(e,n,t=Date.now()){if(!n.startsWith(H))throw Error(`The user token signing secret must start with ${H}. It is not the bsk_ runtime key.`);let o=Pn(e,t);if(!o||e.expiresAt>t+Z)throw Error(`Invalid user token: userId must match ${nn.source}, conversations must be at most ${tn} non-empty keys, and expiresAt must be in the next ${Z/60000} minutes.`);return await fe(On,Mn,o,n)}function Pn(e,n){if(!e||typeof e!=="object")return null;let{userId:t,conversations:o,expiresAt:r}=e;if(typeof t!=="string"||!nn.test(t)||typeof r!=="number"||!Number.isFinite(r)||r<=n||r>n+Z+Un)return null;if(o===void 0)return{userId:t,expiresAt:r};if(!Array.isArray(o)||o.length>tn||!o.every((i)=>typeof i==="string"&&i.trim()===i&&i.length>0&&i.length<=_n))return null;return{userId:t,conversations:o,expiresAt:r}}var g="BROODS_USER_TOKEN_SECRET";async function be(e){let n=e.secret??process.env[g];if(!n)throw Error(`signUserToken needs the stage's signing secret: pass secret or set ${g}. \`broods dev\` and \`broods deploy\` write it to .env.local; the dashboard's Runtime key tab rotates it.`);return await on({userId:e.userId,...e.conversations?{conversations:e.conversations}:{},expiresAt:Date.now()+(e.ttlMs??en)},n)}var T="https://gateway.broods.app";class ae extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class M{baseUrl;apiKey;userToken;fetchImpl;constructor(e={}){m(),this.baseUrl=V(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||T),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||void 0,this.userToken=e.userToken,this.fetchImpl=e.fetch??fetch}channelWebhookUrl(e){return`${this.baseUrl}${e.webhookPath.startsWith("/")?"":"/"}${e.webhookPath}`}accountWebhookUrl(e,n){let t=[e,n].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${t.join("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(i)=>this.run({...i,agentName:o,agentId:r}),runAsync:(i)=>this.runAsync({...i,agentName:o,agentId:r}),continue:(i)=>this.continue({...i,agentId:r}),stream:(i)=>this.stream({...i,agentName:o,agentId:r})}}let t=e;if(!t.id)throw Error(`Agent ${t.name} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:t.id,run:(o)=>this.run(t,o),runAsync:(o)=>this.runAsync(t,o),continue:(o)=>this.continue(t,o),stream:(o)=>this.stream(t,o)}}async run(e,n){let t=[],o="",r=n?this.stream(e,n):this.stream(e);for await(let i of r)if(t.push(i),i.type==="text-delta")o+=i.text;return{text:o,events:t}}async*stream(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=rn(t,"cli"),r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`,i=await this.openStream(o,r);if(!i.ok)throw Error(`Run failed: ${i.status} ${await i.text()}`);if(i.status===202)throw new ae(sn(await i.json(),o));if(!i.body)throw Error("Run response has no body");for await(let s of ie(i.body)){let a;try{a=JSON.parse(s)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${Wn(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o={...rn(t,"async"),background:!0},r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(r,o,"Async run")}async continue(e,n){let t=n?e:null,o=n??e,r={agentId:t?t.id:e.agentId,eventId:o.eventId??`continue-${crypto.randomUUID()}`,conversationKey:o.conversationKey,continue:!0},i=t?this.scopedUrl(t):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(i,r,"Continue")}async getAsyncStatus(e){let n=this.resolveStatusUrl(e),t=await this.fetchJson(n,{method:"GET",headers:await this.apiKeyHeaders()});if(t.status===404)return{status:"not_found"};if(!t.ok)throw Error(`Status check failed: ${t.status} ${await t.text()}`);return await t.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e);if(r.status==="awaiting_approval"||r.status==="awaiting_input"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await Ln(o,n.signal)}throw Error("Polling timeout")}scopedUrl(e){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/projects/${encodeURIComponent(e.projectSlug)}/stages/${encodeURIComponent(e.stageSlug)}/agents/${encodeURIComponent(e.endpointId)}`;return`${this.baseUrl}/v1/runs`}asyncAgentRun(e,n){return{...e,conversationKey:n,poll:()=>this.getAsyncStatus(e),wait:(t)=>this.waitForAsyncStatus(e,t)}}async postAcceptedRun(e,n,t){let o=await this.fetchJson(e,{method:"POST",headers:await this.apiKeyHeaders(),body:JSON.stringify(n)});if(o.status!==202)throw Error(`${t} failed: ${o.status} ${await Kn(o,"202 JSON")}`);return this.asyncAgentRun(sn(await o.json(),n),n.conversationKey)}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`,...await this.userTokenHeaders()});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${T} by default; set host/baseUrl or BROODS_HOST/BROODS_BASE_URL to your own core service URL if your account uses a custom deployment. Cause: ${o instanceof Error?o.message:String(o)}`)}}async apiKeyHeaders(){if(!this.apiKey)throw Error("BroodsClient requires apiKey or BROODS_API_KEY.");return{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,...await this.userTokenHeaders()}}async userTokenHeaders(){let e=typeof this.userToken==="function"?await this.userToken():this.userToken;return e?{[ee]:e}:{}}async fetchJson(e,n){try{return await this.fetchImpl(e,n)}catch(t){throw Error(`Cannot access the broods core service at ${e}. Cause: ${t instanceof Error?t.message:String(t)}`)}}resolveStatusUrl(e){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;return $n(this.baseUrl,e)}}function V(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return f(t)}function rn(e,n){let t=e.eventId??`${n}-${crypto.randomUUID()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:q(e),...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}}function Wn(e){if(typeof e==="string")return e;if(!e||typeof e!=="object")return String(e);let n=e,t=n.data?.error?.message??n.message??n.responseBody??JSON.stringify(e),o=n.name?`${n.name}: `:"",r=n.statusCode?` (HTTP ${n.statusCode})`:"";return`${o}${t}${r}`}function sn(e,n){if(!e||typeof e!=="object")throw Error("Async response must be an object");let t=e.statusUrl;if(typeof t!=="string"||t.length===0)throw Error("Async response missing statusUrl");let o=e.runId;if(typeof o!=="string"||o.length===0)throw Error("Async response missing runId");let r=typeof e.eventId==="string"?e.eventId:o,{status:i,requestedMode:s}=e;return{statusUrl:t,runId:o,eventId:r,agentId:n.agentId,...i==="accepted"||i==="queued"||i==="applied"||i==="processing"?{status:i}:{},...s==="reject"||s==="followup"||s==="collect"||s==="steer"?{requestedMode:s}:{}}}async function Kn(e,n){if((e.headers.get("content-type")??"").toLowerCase().includes("text/event-stream"))return await e.body?.cancel().catch(()=>{}),`expected ${n}, but the server returned an SSE stream. This usually means the core deployment ignored the background flag and ran the request on the direct streaming runner.`;let o=await e.text();if(o.length<=2000)return o;return`${o.slice(0,2000)}... [truncated ${o.length-2000} chars]`}function Ln(e,n){return new Promise((t,o)=>{if(n?.aborted){o(Error("Async status polling aborted."));return}let r=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(r),o(Error("Async status polling aborted."))},{once:!0})})}function $n(e,n){return`${V(e)}/v1/runs/${encodeURIComponent(n)}`}var Bn=2000,an=0,w=1;class me{baseUrl;apiKey;userToken;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(m(),this.baseUrl=pn(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||T),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||"",!this.apiKey)throw Error("BroodsWebSocketClient requires apiKey or BROODS_API_KEY.");this.userToken=e.userToken,this.WebSocketImpl=e.WebSocket,this.connectTimeoutMs=e.connectTimeoutMs??Bn}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=Hn(e),i=ln(this.baseUrl),s=new t(o,E(this.apiKey,e.userToken??this.userToken)),a=!1,c=!1,d=setTimeout(()=>{if(!a)x(i)},this.connectTimeoutMs),R=(p=1000,_="client closed")=>{if(c)return;if(c=!0,clearTimeout(d),e.signal?.removeEventListener("abort",N),s.readyState===w||s.readyState===an)s.close(p,_)},x=(p)=>{n.onError?.(p),R(1000,"websocket error")},Cn=()=>{n.onDone?.(),R(1000,"done")},N=()=>{if(s.readyState===w)s.send(JSON.stringify({type:"cancel"}));x(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",N,{once:!0}),s.onopen=()=>{if(a=!0,clearTimeout(d),e.signal?.aborted){N();return}s.send(JSON.stringify({type:"execute",agentId:r,...e.answers?{answers:e.answers}:{events:q(e)},sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},s.onmessage=(p)=>{if(typeof p.data!=="string")return;let _=un(p.data);if(!_)return;let P=gn(_,n);switch(n.onMessage?.(P),P.type){case"meta":n.onMeta?.(P);break;case"done":Cn();break;case"error":x(Error(cn(P.error)));break}},s.onerror=()=>{x(i)},s.onclose=(p)=>{if(clearTimeout(d),e.signal?.removeEventListener("abort",N),c||p.code===1000)return;x(Error(p.reason||"WebSocket connection closed."))},{url:o,sendControl:function(p){if(s.readyState!==w)throw Error("WebSocket is not open");s.send(JSON.stringify({type:"control",...p}))},close:R}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o,E(this.apiKey,e.userToken??this.userToken)),i=!1,s=(c=1000,d="client closed")=>{if(i)return;if(i=!0,e.signal?.removeEventListener("abort",a),r.readyState===w||r.readyState===an)r.close(c,d)},a=()=>{s(1000,"aborted"),n.onError?.(Error("WebSocket attach aborted."))};if(e.signal?.aborted)a();else e.signal?.addEventListener("abort",a,{once:!0});return r.onopen=()=>{if(i)return;r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0,userToken:void 0}))},r.onmessage=(c)=>{if(i||typeof c.data!=="string")return;let d=un(c.data);if(!d)return;let R=gn(d,n);if(i)return;if(n.onMessage?.(R),i)return;if(R.type==="done")n.onDone?.();if(R.type==="error")n.onError?.(Error(cn(R.error)))},r.onerror=()=>{if(i)return;s(1000,"websocket error"),n.onError?.(ln(this.baseUrl))},r.onclose=(c)=>{if(e.signal?.removeEventListener("abort",a),!i&&c.code!==1000)n.onError?.(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl:function(c){if(r.readyState!==w)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...c}))},close:s}}async*stream(e){let n=[],t=!1,o=null,r=null,i=()=>{r?.(),r=null},s=this.subscribe(e,{onMessage:function(a){n.push(a),i()},onDone:function(){t=!0,i()},onError:function(a){o=a,i()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{s.close()}}buildUrl(e){let n=Gn(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t&&o?`/projects/${encodeURIComponent(t)}/stages/${encodeURIComponent(o)}`:"";return`${K(this.baseUrl)}/v1${r}/agents/${encodeURIComponent(n)}/ws`}resolveWebSocket(){let e=this.WebSocketImpl??globalThis.WebSocket;if(!e)throw Error("WebSocket is not available. Pass a WebSocket implementation in BroodsWebSocketClient options.");return e}}function K(e){let n=new URL(pn(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return f(n.toString())}function E(e,n){return["broods.v1",`broods.token.${e}`,...n?[`${he}${n}`]:[]]}function cn(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&typeof e.message==="string")return e.message;return e===void 0?"WebSocket stream error.":JSON.stringify(e)}function pn(e){let n=e.trim();if(/^wss?:\/\//.test(n))return f(n);return V(n)}function un(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function Hn(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function Gn(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function gn(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function ln(e){return Error(`Cannot access the WebSocket service at ${e}.`)}var fn=Symbol.for("broods.resource"),yn=Symbol.for("broods.config"),mn=Symbol.for("broods.connection"),dn=/^[A-Z][A-Z0-9_]{0,63}$/,ve=new Proxy((e)=>{if(!dn.test(e))throw Error("env name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return{__beeblastEnv:!0,name:e}},{get:function(e,n,t){if(typeof n==="string"&&dn.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function _e(e){let{name:n,description:t,...o}=e;return I("agent",n,t,o)}function we(e){return{[yn]:!0,config:e}}function Re(e){let{name:n,description:t,...o}=e;return I("cron",n,t,o)}function $e(e){return e}function Ce(e){let{name:n,description:t,...o}=e;return I("mcp",n,t,o)}function Ee(e){let{name:n,description:t,...o}=e;return I("policy",n,t,o)}function ke(e){let{name:n,description:t,...o}=e;return I("sandbox",n,t,o)}function Te(e){let{name:n,description:t,...o}=e;return I("skill",n,t,o)}function Pe(e){let{name:n,description:t,...o}=e;return I("workspace",n,t,o)}function Ie(e){return l("discord",e)}function ze(e){return l("github",e)}function xe(e){return l("gchat",e)}function Ae(e){return l("instagram",e)}function Oe(e){return l("linear",e)}function Me(e){return l("matrix",e)}function Ne(e){return l("messenger",e)}function je(e){return l("pancake",e)}function qe(e){return l("slack",e)}function De(e){return l("teams",e)}function Le(e){return l("telegram",e)}function Ue(e){return l("twilio",e)}function Fe(e){return l("whatsapp",e)}function Be(e){return l("zalo",e)}function He(e){let{name:n,description:t,channelId:o,guildId:r,...i}=e;return u(n,t,o,r,i)}function Ze(e){let{name:n,description:t,repo:o,...r}=e,[i,...s]=o.split("/");if(!i||s.length!==1||!s[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return u(n,t,o,i,r)}function Ve(e){let{name:n,description:t,spaceName:o,...r}=e;return u(n,t,o,void 0,r)}function Ke(e){let{name:n,description:t,igsid:o,...r}=e;return u(n,t,o,void 0,r)}function Ge(e){let{name:n,description:t,team:o,...r}=e;return u(n,t,o,void 0,r)}function We(e){let{name:n,description:t,channelId:o,...r}=e;return u(n,t,o,void 0,r)}function Je(e){let{name:n,description:t,psid:o,...r}=e;return u(n,t,o,void 0,r)}function Ye(e){let{name:n,description:t,conversationId:o,...r}=e;return u(n,t,o,void 0,r)}function Xe(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return u(n,t,o,r,i)}function Qe(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return u(n,t,o,r,i)}function et(e){let{name:n,description:t,chatId:o,...r}=e;return u(n,t,o,void 0,r)}function tt(e){let{name:n,description:t,from:o,...r}=e;return u(n,t,o,void 0,r)}function nt(e){let{name:n,description:t,waId:o,...r}=e;return u(n,t,o,void 0,r)}function rt(e){let{name:n,description:t,chatId:o,...r}=e;return u(n,t,o,void 0,r)}function te(e){return Boolean(e&&typeof e==="object"&&e[yn])}function v(e){return Boolean(e&&typeof e==="object"&&e[mn])}function h(e){return Boolean(e&&typeof e==="object"&&e[fn])}function u(e,n,t,o,r){return I("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function l(e,n){let{partition:t,...o}=n;return{[mn]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function I(e,n,t,o){return{[fn]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}
5
+ export{q,ie,ge,pe,ye,Se,D,L,y,b,z,k,U,F,S,f,A,m,O,C,B,H,ee,Z,g,be,T,ae,M,V,me,K,E,ve,_e,we,Re,$e,Ce,Ee,ke,Te,Pe,Ie,ze,xe,Ae,Oe,Me,Ne,je,qe,De,Le,Ue,Fe,Be,He,Ze,Ve,Ke,Ge,We,Je,Ye,Xe,Qe,et,tt,nt,rt,te,v,h};
@@ -1 +1 @@
1
- import{O}from"./chunk-ybkav7qd.js";import{he,e,n,t,s}from"./chunk-8zcgnjs8.js";import{readFileSync as d}from"node:fs";import{dirname as g,resolve as m}from"node:path";import{Client as h}from"@modelcontextprotocol/client";import{StdioClientTransport as f}from"@modelcontextprotocol/client/stdio";var p="2026-07-28";var u={name:"broods-machine",version:"1.0.0"},w=1e4,S=t({command:e().min(1),args:n(e()).default([]),env:s(e(),e()).optional(),cwd:e().optional()}),y=t({mcpServers:s(e(),S).refine((r)=>Object.keys(r).length>0,"lists no MCP servers")});class v{#t=new Map;#e;#r;constructor(r,o){this.#r=r,this.#e=o}async callTool(r,o,i){return await(await this.#n(r)).callTool({name:o,arguments:i})}async listTools(r){return(await(await this.#n(r)).listTools()).tools}names(){return[...this.#r.keys()]}async stop(){let r=[...this.#t.values()];this.#t.clear(),await Promise.all(r.map((o)=>o.then((i)=>i.close()).catch(()=>{})))}#n(r){let o=this.#r.get(r);if(!o)return Promise.reject(Error(`no MCP server named "${r}" in the --mcp file`));let i=this.#t.get(r);if(i)return i;let c=(async()=>{this.#e(`mcp ${r}: ${[o.command,...o.args].join(" ")}`);let a=new f({...o,env:{...O(),...o.env},stderr:"inherit"});a.onclose=()=>{if(this.#e(`mcp ${r}: exited`),this.#t.get(r)===c)this.#t.delete(r)};let l=new h(u,{versionNegotiation:{mode:{pin:p},probe:{timeoutMs:w}}});return await l.connect(a),l})();return c.catch(()=>{if(this.#t.get(r)===c)this.#t.delete(r)}),this.#t.set(r,c),c}}function I(r){let o=m(r),i=y.safeParse(M(o));if(!i.success)throw Error(`${o}: ${he(i.error)}`);return new Map(Object.entries(i.data.mcpServers).map(([c,a])=>[c,a.cwd?{...a,cwd:m(g(o),a.cwd)}:a]))}function M(r){try{return JSON.parse(d(r,"utf8"))}catch(o){throw Error(`could not read ${r}: ${o instanceof Error?o.message:String(o)}`)}}export{v as McpHost,I as readMcpServersFile};
1
+ import{O}from"./chunk-b0pdqkyk.js";import{he,e,n,t,s}from"./chunk-8zcgnjs8.js";import{readFileSync as d}from"node:fs";import{dirname as g,resolve as m}from"node:path";import{Client as h}from"@modelcontextprotocol/client";import{StdioClientTransport as f}from"@modelcontextprotocol/client/stdio";var p="2026-07-28";var u={name:"broods-machine",version:"1.0.0"},w=1e4,S=t({command:e().min(1),args:n(e()).default([]),env:s(e(),e()).optional(),cwd:e().optional()}),y=t({mcpServers:s(e(),S).refine((r)=>Object.keys(r).length>0,"lists no MCP servers")});class v{#t=new Map;#e;#r;constructor(r,o){this.#r=r,this.#e=o}async callTool(r,o,i){return await(await this.#n(r)).callTool({name:o,arguments:i})}async listTools(r){return(await(await this.#n(r)).listTools()).tools}names(){return[...this.#r.keys()]}async stop(){let r=[...this.#t.values()];this.#t.clear(),await Promise.all(r.map((o)=>o.then((i)=>i.close()).catch(()=>{})))}#n(r){let o=this.#r.get(r);if(!o)return Promise.reject(Error(`no MCP server named "${r}" in the --mcp file`));let i=this.#t.get(r);if(i)return i;let c=(async()=>{this.#e(`mcp ${r}: ${[o.command,...o.args].join(" ")}`);let a=new f({...o,env:{...O(),...o.env},stderr:"inherit"});a.onclose=()=>{if(this.#e(`mcp ${r}: exited`),this.#t.get(r)===c)this.#t.delete(r)};let l=new h(u,{versionNegotiation:{mode:{pin:p},probe:{timeoutMs:w}}});return await l.connect(a),l})();return c.catch(()=>{if(this.#t.get(r)===c)this.#t.delete(r)}),this.#t.set(r,c),c}}function I(r){let o=m(r),i=y.safeParse(M(o));if(!i.success)throw Error(`${o}: ${he(i.error)}`);return new Map(Object.entries(i.data.mcpServers).map(([c,a])=>[c,a.cwd?{...a,cwd:m(g(o),a.cwd)}:a]))}function M(r){try{return JSON.parse(d(r,"utf8"))}catch(o){throw Error(`could not read ${r}: ${o instanceof Error?o.message:String(o)}`)}}export{v as McpHost,I as readMcpServersFile};