broods 0.49.2 → 0.49.3

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/cli/index.js CHANGED
@@ -87,7 +87,7 @@ Check the browser tab and the dashboard logs for an error. If the browser shows
87
87
  404 on /cli-auth/start, deploy the dashboard build that includes CLI auth or pass
88
88
  --dashboard-url for the environment you deployed. Other common causes are missing
89
89
  cliAuth Convex functions or no active API account (Organization settings -> API access).`,It=new Set(["--base-url","--cwd","--dashboard-url","--stage","--from","--level","--limit","--mcp","--project","--region","--sandbox","-n"]);function gs(e,n=process.platform){if(n==="darwin")return{command:"open",args:[e]};if(n==="win32")return{command:"rundll32",args:["url.dll,FileProtocolHandler",e]};return{command:"xdg-open",args:[e]}}function I(e,n){let t=It.has(n)?`${n}=`:null;return e.some((o)=>o===n||t!==null&&o.startsWith(t))}function we(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function b(e,n){for(let t=0;t<e.length;t+=1){let o=e[t];if(o===n)return e[t+1];if(o?.startsWith(`${n}=`))return o.slice(n.length+1)||void 0}return}function te(e){let n=[];for(let t=0;t<e.length;t+=1){let o=e[t];if(o===void 0)continue;if(It.has(o)){t+=1;continue}if(o.startsWith("-"))continue;n.push(o)}return n}async function Sn(e){let n=as(),t=is(32).toString("base64url"),o=ss("sha256").update(t).digest("base64url"),{code:r,close:s}=await Cn(n,{port:fs(),fixedPort:Boolean(process.env.BROODS_LOGIN_PORT),path:"/callback",read:ms,done:"broods CLI login complete. You can close this tab."});try{let i=r.callbackUrl,a=`${f(e)}/cli-auth/start?`+new URLSearchParams({callback:i,state:n,code_challenge:o});await ps(a),console.log(`Opening ${a}`),$n(a);let c=await Rn(r.promise),d=await qe(`${c.baseUrl}/v1/account/auth/exchange`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:c.code,code_verifier:t})});if(!d.ok)throw Error(`Login exchange failed: ${d.status} ${await d.text()}`);let l=await d.json(),p={baseUrl:c.baseUrl,dashboardUrl:f(e),token:l.token,createdAt:new Date().toISOString(),...l.user?{user:l.user}:{},...l.org?{org:l.org}:{},...l.account?{account:l.account}:{}};return await W(p),p}finally{s()}}async function q(e){h();let n=z(e);if(!n){let t=process.env.BROODS_DASHBOARD_URL,o=e??process.env.BROODS_BASE_URL??(t?L(t):void 0);throw Error(o?`Not logged in to ${f(o)}. Run \`broods login\`.`:"Run `broods login` first, or set BROODS_TOKEN and BROODS_BASE_URL.")}return n}async function Qe(e){if(!ne.isTTY)return!1;let n=Ie({input:ne,output:ee});try{let t=(await n.question(`${e} [y/N] `)).trim().toLowerCase();return t==="y"||t==="yes"}finally{n.close()}}async function _t(e){ee.write(`${e}: `);let n=new ls({write:(o,r,s)=>s()}),t=Ie({input:ne,output:n,terminal:ne.isTTY===!0});try{let o=await t.question("");if(!o)throw Error(`${e} is required`);return o}finally{t.close(),ee.write(`
90
- `)}}async function _e(e,n,t,o){if(n.length===0)throw Error(`${e}: no options available`);if(n.length===1)return n[0];let r=o!==void 0&&o>=0&&o<n.length?o:void 0;console.log(e),n.forEach((a,c)=>{console.log(Se(`${c+1}. ${t(a)}`,c===r))});let s=r===void 0?`Choose 1-${n.length}: `:`Choose 1-${n.length} [${r+1}]: `,i=Ie({input:ne,output:ee});try{for(;;){let a=(await i.question(s)).trim();if(a===""&&r!==void 0)return n[r];let c=Number(a);if(Number.isInteger(c)&&c>=1&&c<=n.length)return n[c-1];console.log(`Enter a number from 1 to ${n.length}.`)}}finally{i.close()}}async function Dt(e,n,t,o){console.log(e),n.forEach((i,a)=>{console.log(` ${a+1}. ${t(i)}`)});let r=n.length>0?`Choose 1-${n.length}, or `:"",s=Ie({input:ne,output:ee});try{let i=(await s.question(`${r}${o.hint} [${o.defaultValue}]: `)).trim();if(i==="")return o.defaultValue;let a=Number(i);if(Number.isInteger(a)&&a>=1&&a<=n.length)return n[a-1];return i}finally{s.close()}}async function be(e,n){if(!ne.isTTY)return n??"";let t=Ie({input:ne,output:ee});try{let o=t.question(`${e}: `);if(n){if(ne.isTTY&&ee.isTTY)ee.write("\x1B[90m");if(t.write(n),ne.isTTY&&ee.isTTY)ee.write("\x1B[0m")}return(await o).trim()||n||""}finally{t.close()}}function $n(e){let{command:n,args:t}=gs(e),o=cs(n,t,{stdio:"ignore",detached:!0});o.on("error",(r)=>{console.error(je(`Could not open a browser (${r.message}). Open the URL above to continue.`,{stream:"stderr"}))}),o.unref()}function Cn(e,n){return new Promise((t,o)=>{let r=rs((c,d)=>{let l=new URL(c.url??"/","http://127.0.0.1");if(l.pathname!==n.path||l.searchParams.get("state")!==e){d.writeHead(400).end("Invalid callback.");return}try{let p=n.read(l.searchParams);d.writeHead(200,{"Content-Type":"text/plain"}).end(n.done),s(p)}catch(p){d.writeHead(400,{"Content-Type":"text/plain"}).end(p instanceof Error?p.message:String(p)),i(p)}}),s,i,a=new Promise((c,d)=>{s=c,i=d});r.on("error",(c)=>{if(!n.fixedPort&&n.port!==0&&c.code==="EADDRINUSE"){r.listen(0,"127.0.0.1");return}o(c)}),r.listen(n.port,"127.0.0.1",()=>{let c=r.address();if(!c||typeof c==="string"){o(Error("Failed to allocate callback port"));return}t({code:{callbackUrl:`http://127.0.0.1:${c.port}${n.path}`,promise:a},close:()=>r.close()})})})}async function Rn(e,n=us){let t,o=new Promise((r,s)=>{t=setTimeout(()=>s(Error(n)),ds)});try{return await Promise.race([e,o])}finally{if(t)clearTimeout(t)}}async function ps(e){let n=await qe(e,{method:"GET",redirect:"manual"});if(n.status===404){let t=new URL(e);throw Error(`${t.origin} has no broods login page. Check that --dashboard-url points at your broods dashboard.`)}if(n.status>=500)throw Error(`The broods login page failed: ${n.status} ${await n.text()}`)}function fs(){let e=process.env.BROODS_LOGIN_PORT;if(e){let n=Number(e);if(Number.isInteger(n)&&n>0&&n<65536)return n;throw Error("BROODS_LOGIN_PORT must be a TCP port number")}return 18987}function ms(e){let n=e.get("error");if(n)throw Error(`Login failed: ${n}`);let t=e.get("code");if(!t)throw Error("Login callback carried no code.");let o=e.get("base_url");if(!o)throw Error("Login callback did not advertise the API base URL (base_url). Deploy a dashboard build that includes the Convex-direct CLI auth flow.");return{code:t,baseUrl:f(o)}}var bs=1455,ys="/auth/callback";async function Nt(e,n,t=$n){let o=he[n].label,r=Ut(),s=Ut(),i=ws(32).toString("base64url"),{code:a,close:c}=await Cn(r,{port:bs,fixedPort:!1,path:ys,read:vs,done:`${o} is connected to broods. You can close this tab.`});try{let d=a.callbackUrl,l=await e.startConnection(n,{redirectUri:d,codeChallenge:hs("sha256").update(i).digest("base64url"),state:r,nonce:s});t(l.authorizeUrl),console.log(`Opening ${l.authorizeUrl}`);let p=await Rn(a.promise,`Timed out waiting for the ${o} sign-in to finish in the browser.`);return await e.connect(n,{code:p.code,codeVerifier:i,redirectUri:d,nonce:s,clientId:p.clientId??l.clientId,hostId:l.hostId})}finally{c()}}function vs(e){let n=e.get("error");if(n)throw Error(`Sign-in failed: ${e.get("error_description")??n}`);let t=e.get("code");if(!t)throw Error("Sign-in callback carried no code.");return{code:t,clientId:e.get("client_id")??void 0}}import{existsSync as Mt}from"node:fs";import{mkdir as Es,readFile as Ss,writeFile as $s}from"node:fs/promises";import{dirname as Bt,join as xn,resolve as Cs,sep as ge}from"node:path";import{fileURLToPath as Rs}from"node:url";var De={name:"broods",version:"0.49.2",description:"CLI + TypeScript SDK for the broods agent platform.",keywords:["agents","ai","broods","cli","sdk"],homepage:"https://github.com/beeblastco/broods#readme",bugs:{url:"https://github.com/beeblastco/broods/issues"},license:"MIT",repository:{type:"git",url:"git+https://github.com/beeblastco/broods.git",directory:"packages/broods"},bin:{broods:"dist/cli/index.js"},files:["dist","README.md","LICENSE.md"],type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",typesVersions:{"*":{account:["./dist/account.d.ts"]}},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./account":{types:"./dist/account.d.ts",import:"./dist/account.js"}},scripts:{build:"bun scripts/build.ts && rollup -c rollup.dts.config.mjs && rm -rf .dts-temp",check:"tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json","pack:check":"bun run build && publint && attw --pack .",prepublishOnly:"bun run build",test:"bun test"},dependencies:{"@modelcontextprotocol/client":"^2.2.0",esbuild:"^0.28.2"},devDependencies:{"@ai-sdk/tui":"1.0.128","@arethetypeswrong/cli":"^0.18.5","@chat-adapter/discord":"^4.38.1","@chat-adapter/github":"^4.38.1","@chat-adapter/slack":"^4.38.1","@chat-adapter/telegram":"^4.38.1","@modelcontextprotocol/server":"2.2.0","@types/bun":"^1.3.14","@typescript/typescript6":"6.0.2",ai:"^7.0.127",publint:"^0.3.23",rollup:"^4.62.4","rollup-plugin-dts":"^6.5.1",typescript:"^7.0.2",zod:"^4.4.3"},peerDependencies:{ai:"^7.0.127"},engines:{node:">=22.15"}};var On=xn(Bt(O),"update-check.json"),Os=86400000,As="https://registry.npmjs.org/broods/latest",xs=2000,Ps=[["bun.lock","bun"],["bun.lockb","bun"],["pnpm-lock.yaml","pnpm"],["yarn.lock","yarn"]];function Pn(e,n){let t=An(e),o=An(n);for(let r=0;r<3;r+=1){let s=t[r]??0,i=o[r]??0;if(s!==i)return s>i}return!Lt(e)&&Lt(n)}async function Tn(e={}){let n=await js(),t=e.maxAgeMs??Os;if(n&&Date.now()-n.checkedAt<t)return n.latest;let o=await Ts();if(o===null)return n?.latest??null;return await _s({checkedAt:Date.now(),latest:o}),o}function Ue(e){return An(e)[0]??0}function Gt(e=Cs(process.cwd()),n=Rs(import.meta.url),t=De.version){let o=`${ge}node_modules${ge}`,r=n.indexOf(o),s=r===-1?null:n.slice(0,r),i=s===null?n.startsWith(`${e}${ge}`):e===s||e.startsWith(`${s}${ge}`),a=n.includes(`${ge}.bun${ge}install${ge}global${ge}`),c=s??e,d=i?Is(c):a?"bun":"npm",l=d==="npm"?"install":"add",p=d==="pnpm"&&Mt(xn(c,"pnpm-workspace.yaml"))?["-w"]:[],u=`broods@${Ue(t)}`;return{manager:d,global:!i,command:d,cwd:i?c:e,args:i?[l,...p,u]:[l,"-g",u]}}async function Ts(){try{let e=await fetch(As,{signal:AbortSignal.timeout(xs),headers:{accept:"application/json"}});if(!e.ok)return null;let n=await e.json();return typeof n.version==="string"?n.version:null}catch{return null}}function Lt(e){return e.includes("-")}async function js(){try{let e=JSON.parse(await Ss(On,"utf8"));if(typeof e.latest!=="string")return null;if(typeof e.checkedAt!=="number")return null;return{checkedAt:e.checkedAt,latest:e.latest}}catch{return null}}function Is(e){return Ps.find(([t])=>Mt(xn(e,t)))?.[1]??"npm"}function An(e){let[n]=e.trim().replace(/^v/,"").split("-");return(n??"").split(".").slice(0,3).map((t)=>Number.parseInt(t,10)||0)}async function _s(e){try{await Es(Bt(On),{recursive:!0}),await $s(On,`${JSON.stringify(e)}
90
+ `)}}async function _e(e,n,t,o){if(n.length===0)throw Error(`${e}: no options available`);if(n.length===1)return n[0];let r=o!==void 0&&o>=0&&o<n.length?o:void 0;console.log(e),n.forEach((a,c)=>{console.log(Se(`${c+1}. ${t(a)}`,c===r))});let s=r===void 0?`Choose 1-${n.length}: `:`Choose 1-${n.length} [${r+1}]: `,i=Ie({input:ne,output:ee});try{for(;;){let a=(await i.question(s)).trim();if(a===""&&r!==void 0)return n[r];let c=Number(a);if(Number.isInteger(c)&&c>=1&&c<=n.length)return n[c-1];console.log(`Enter a number from 1 to ${n.length}.`)}}finally{i.close()}}async function Dt(e,n,t,o){console.log(e),n.forEach((i,a)=>{console.log(` ${a+1}. ${t(i)}`)});let r=n.length>0?`Choose 1-${n.length}, or `:"",s=Ie({input:ne,output:ee});try{let i=(await s.question(`${r}${o.hint} [${o.defaultValue}]: `)).trim();if(i==="")return o.defaultValue;let a=Number(i);if(Number.isInteger(a)&&a>=1&&a<=n.length)return n[a-1];return i}finally{s.close()}}async function be(e,n){if(!ne.isTTY)return n??"";let t=Ie({input:ne,output:ee});try{let o=t.question(`${e}: `);if(n){if(ne.isTTY&&ee.isTTY)ee.write("\x1B[90m");if(t.write(n),ne.isTTY&&ee.isTTY)ee.write("\x1B[0m")}return(await o).trim()||n||""}finally{t.close()}}function $n(e){let{command:n,args:t}=gs(e),o=cs(n,t,{stdio:"ignore",detached:!0});o.on("error",(r)=>{console.error(je(`Could not open a browser (${r.message}). Open the URL above to continue.`,{stream:"stderr"}))}),o.unref()}function Cn(e,n){return new Promise((t,o)=>{let r=rs((c,d)=>{let l=new URL(c.url??"/","http://127.0.0.1");if(l.pathname!==n.path||l.searchParams.get("state")!==e){d.writeHead(400).end("Invalid callback.");return}try{let p=n.read(l.searchParams);d.writeHead(200,{"Content-Type":"text/plain"}).end(n.done),s(p)}catch(p){d.writeHead(400,{"Content-Type":"text/plain"}).end(p instanceof Error?p.message:String(p)),i(p)}}),s,i,a=new Promise((c,d)=>{s=c,i=d});r.on("error",(c)=>{if(!n.fixedPort&&n.port!==0&&c.code==="EADDRINUSE"){r.listen(0,"127.0.0.1");return}o(c)}),r.listen(n.port,"127.0.0.1",()=>{let c=r.address();if(!c||typeof c==="string"){o(Error("Failed to allocate callback port"));return}t({code:{callbackUrl:`http://127.0.0.1:${c.port}${n.path}`,promise:a},close:()=>r.close()})})})}async function Rn(e,n=us){let t,o=new Promise((r,s)=>{t=setTimeout(()=>s(Error(n)),ds)});try{return await Promise.race([e,o])}finally{if(t)clearTimeout(t)}}async function ps(e){let n=await qe(e,{method:"GET",redirect:"manual"});if(n.status===404){let t=new URL(e);throw Error(`${t.origin} has no broods login page. Check that --dashboard-url points at your broods dashboard.`)}if(n.status>=500)throw Error(`The broods login page failed: ${n.status} ${await n.text()}`)}function fs(){let e=process.env.BROODS_LOGIN_PORT;if(e){let n=Number(e);if(Number.isInteger(n)&&n>0&&n<65536)return n;throw Error("BROODS_LOGIN_PORT must be a TCP port number")}return 18987}function ms(e){let n=e.get("error");if(n)throw Error(`Login failed: ${n}`);let t=e.get("code");if(!t)throw Error("Login callback carried no code.");let o=e.get("base_url");if(!o)throw Error("Login callback did not advertise the API base URL (base_url). Deploy a dashboard build that includes the Convex-direct CLI auth flow.");return{code:t,baseUrl:f(o)}}var bs=1455,ys="/auth/callback";async function Nt(e,n,t=$n){let o=he[n].label,r=Ut(),s=Ut(),i=ws(32).toString("base64url"),{code:a,close:c}=await Cn(r,{port:bs,fixedPort:!1,path:ys,read:vs,done:`${o} is connected to broods. You can close this tab.`});try{let d=a.callbackUrl,l=await e.startConnection(n,{redirectUri:d,codeChallenge:hs("sha256").update(i).digest("base64url"),state:r,nonce:s});t(l.authorizeUrl),console.log(`Opening ${l.authorizeUrl}`);let p=await Rn(a.promise,`Timed out waiting for the ${o} sign-in to finish in the browser.`);return await e.connect(n,{code:p.code,codeVerifier:i,redirectUri:d,nonce:s,clientId:p.clientId??l.clientId,hostId:l.hostId})}finally{c()}}function vs(e){let n=e.get("error");if(n)throw Error(`Sign-in failed: ${e.get("error_description")??n}`);let t=e.get("code");if(!t)throw Error("Sign-in callback carried no code.");return{code:t,clientId:e.get("client_id")??void 0}}import{existsSync as Mt}from"node:fs";import{mkdir as Es,readFile as Ss,writeFile as $s}from"node:fs/promises";import{dirname as Bt,join as xn,resolve as Cs,sep as ge}from"node:path";import{fileURLToPath as Rs}from"node:url";var De={name:"broods",version:"0.49.3",description:"CLI + TypeScript SDK for the broods agent platform.",keywords:["agents","ai","broods","cli","sdk"],homepage:"https://github.com/beeblastco/broods#readme",bugs:{url:"https://github.com/beeblastco/broods/issues"},license:"MIT",repository:{type:"git",url:"git+https://github.com/beeblastco/broods.git",directory:"packages/broods"},bin:{broods:"dist/cli/index.js"},files:["dist","README.md","LICENSE.md"],type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",typesVersions:{"*":{account:["./dist/account.d.ts"]}},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./account":{types:"./dist/account.d.ts",import:"./dist/account.js"}},scripts:{build:"bun scripts/build.ts && rollup -c rollup.dts.config.mjs && rm -rf .dts-temp",check:"tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json","pack:check":"bun run build && publint && attw --pack .",prepublishOnly:"bun run build",test:"bun test"},dependencies:{"@modelcontextprotocol/client":"^2.2.0",esbuild:"^0.28.2"},devDependencies:{"@ai-sdk/tui":"1.0.138","@arethetypeswrong/cli":"^0.18.5","@chat-adapter/discord":"^4.38.1","@chat-adapter/github":"^4.38.1","@chat-adapter/slack":"^4.38.1","@chat-adapter/telegram":"^4.38.1","@modelcontextprotocol/server":"2.2.0","@types/bun":"^1.3.14","@typescript/typescript6":"6.0.2",ai:"^7.0.137",publint:"^0.3.23",rollup:"^4.62.4","rollup-plugin-dts":"^6.5.1",typescript:"^7.0.2",zod:"^4.4.3"},peerDependencies:{ai:"^7.0.137"},engines:{node:">=22.15"}};var On=xn(Bt(O),"update-check.json"),Os=86400000,As="https://registry.npmjs.org/broods/latest",xs=2000,Ps=[["bun.lock","bun"],["bun.lockb","bun"],["pnpm-lock.yaml","pnpm"],["yarn.lock","yarn"]];function Pn(e,n){let t=An(e),o=An(n);for(let r=0;r<3;r+=1){let s=t[r]??0,i=o[r]??0;if(s!==i)return s>i}return!Lt(e)&&Lt(n)}async function Tn(e={}){let n=await js(),t=e.maxAgeMs??Os;if(n&&Date.now()-n.checkedAt<t)return n.latest;let o=await Ts();if(o===null)return n?.latest??null;return await _s({checkedAt:Date.now(),latest:o}),o}function Ue(e){return An(e)[0]??0}function Gt(e=Cs(process.cwd()),n=Rs(import.meta.url),t=De.version){let o=`${ge}node_modules${ge}`,r=n.indexOf(o),s=r===-1?null:n.slice(0,r),i=s===null?n.startsWith(`${e}${ge}`):e===s||e.startsWith(`${s}${ge}`),a=n.includes(`${ge}.bun${ge}install${ge}global${ge}`),c=s??e,d=i?Is(c):a?"bun":"npm",l=d==="npm"?"install":"add",p=d==="pnpm"&&Mt(xn(c,"pnpm-workspace.yaml"))?["-w"]:[],u=`broods@${Ue(t)}`;return{manager:d,global:!i,command:d,cwd:i?c:e,args:i?[l,...p,u]:[l,"-g",u]}}async function Ts(){try{let e=await fetch(As,{signal:AbortSignal.timeout(xs),headers:{accept:"application/json"}});if(!e.ok)return null;let n=await e.json();return typeof n.version==="string"?n.version:null}catch{return null}}function Lt(e){return e.includes("-")}async function js(){try{let e=JSON.parse(await Ss(On,"utf8"));if(typeof e.latest!=="string")return null;if(typeof e.checkedAt!=="number")return null;return{checkedAt:e.checkedAt,latest:e.latest}}catch{return null}}function Is(e){return Ps.find(([t])=>Mt(xn(e,t)))?.[1]??"npm"}function An(e){let[n]=e.trim().replace(/^v/,"").split("-");return(n??"").split(".").slice(0,3).map((t)=>Number.parseInt(t,10)||0)}async function _s(e){try{await Es(Bt(On),{recursive:!0}),await $s(On,`${JSON.stringify(e)}
91
91
  `,"utf8")}catch{}}var Wt=`---
92
92
  name: broods
93
93
  description: Work on a broods account alongside a developer from Claude Code or a development agent. Covers onboarding and sign-in, creating a broods project, defining and deploying agents and their resources with the CLI, and integrating a deployed agent into existing code with the SDK. Use when asked to set up broods, create or work on a broods project, create or manage agents or any account resource, or call a deployed agent from application code.
@@ -400,13 +400,13 @@ ${Z("stage")}`);let i=h(),a=b(e,"--dashboard-url")??i.dashboardUrl??oe,c=rn(e),d
400
400
 
401
401
  ${Z("env")}`);if(a&&!t)throw Error(`broods env ${n} needs a variable name.
402
402
 
403
- ${Z("env")}`);let{manifest:c,config:d}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),l=await q(b(e,"--base-url")??d.baseUrl),p=new N({baseUrl:l.baseUrl,token:l.token}),u=`${c.project}/${c.stage}`;if(i){await Mi(p,c,u);return}if(o){let C=await p.listEnv(c.project,c.stage);if(C.length===0){console.log(`No environment variables set for ${u}.`);return}console.log(`Environment variables for ${u} (values hidden):`);for(let k of C)console.log(` ${k.name}`);return}if(s){let C=await p.getEnv(c.project,c.stage,t);if(C===null){console.error(`${t} is not set for ${u}`),process.exitCode=1;return}console.log(C);return}if(r){await p.removeEnv(c.project,c.stage,t),H(`Removed ${t} from ${u}`);return}let S=await _t(t);await p.setEnv(c.project,c.stage,t,S),H(`Stored ${t} for ${u}`)}async function Mi(e,n,t){let o=await Mn(e,n);if(o.length===0){console.log('No env("NAME") references in this project.');return}let r=await ao(e,n,o);if(r.length>0)En(r);let s=nn(o,"synced").length;console.log(r.length>0?`${s} other referenced variable(s) already in step with ${t}.`:`${s} referenced variable(s) already in step with ${t}.`);let i=nn(o,"stage-only");if(i.length>0)console.log(`${i.length} referenced variable(s) live only on ${t}: ${i.join(", ")}`);let a=nn(o,"unresolved");if(a.length>0)x(`${a.length} referenced variable(s) with no value here or on ${t}: ${a.join(", ")}. Put them in .env.local, or run \`broods env set <NAME> --stage ${n.stage}\`.`)}function Bn(e){if(I(e,"--all"))return"DEBUG";let n=b(e,"--level");if(n===void 0&&I(e,"--level"))throw Error("Missing value for --level. Use DEBUG, INFO, WARN, or ERROR.");if(!n)return"WARN";let t=n.toUpperCase();if(t==="DEBUG")return"DEBUG";if(t==="INFO")return"INFO";if(t==="WARN"||t==="WARNING")return"WARN";if(t==="ERROR")return"ERROR";throw Error(`Unknown log level: ${n}. Use DEBUG, INFO, WARN, or ERROR.`)}async function Bi(e){h();let n=b(e,"--project")??process.env.BROODS_PROJECT,t=b(e,"--stage")??v();if(!n)throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT in .env.local.");if(!t)throw Error("Stage name is required. Pass --stage <name> or set BROODS_STAGE in .env.local.");return{project:n,stage:t}}async function sn(e){let n=await Bi(e),t=h(),o=await Be(b(e,"--dashboard-url")??t.dashboardUrl??oe,b(e,"--base-url")),r=new N({baseUrl:o.baseUrl,token:o.token}),s=await r.mintStageSession(n.project,n.stage),i=s,a=async()=>{let c=i??await r.mintStageSession(n.project,n.stage);return i=void 0,c.token};return{baseUrl:o.baseUrl,credential:a,project:s.projectSlug,stage:s.stageSlug}}function co(e){return e==="WARN"?" (--all for INFO too)":""}function Gn(e,n){console.error(je(`Reconnecting to live logs (attempt ${e}): ${n}`,{stream:"stderr"}))}function Wn(e){let n=new Date(e.ts).toISOString().slice(11,23),t=e.level.padEnd(5),o=Ys(e.message);return`${n} ${t} ${e.eventType} ${o}`}async function Gi(e){let n=await sn(e),{project:t,stage:o}=n,r=Bn(e),s=new AbortController,i=()=>s.abort();process.on("SIGINT",i),console.log(`Streaming live logs for ${t}/${o} [${r}+]`+co(r)+", Ctrl+C to stop");try{for await(let a of Ve(n,{backfill:0,minLevel:r,signal:s.signal,onReconnect:Gn}))console.log(Wn(a))}catch(a){if(!s.signal.aborted)console.error(a instanceof Error?a.message:String(a)),process.exitCode=1}finally{process.off("SIGINT",i)}}async function Wi(e){if(I(e,"--doctor")){await Fi(I(e,"--request"));return}let n=te(e)[0];if(!n){console.log(ve("machine",e));return}let{runMachineDaemon:t}=await import("../chunk-rgrcsmq1.js"),{baseUrl:o,credential:r}=await sn(e),s=P(b(e,"--cwd")??process.cwd()),i=I(e,"--computer"),a=b(e,"--mcp"),c=I(e,"--force"),d=new AbortController,l=()=>d.abort();process.on("SIGINT",l),console.log(`Connecting ${n} to ${o} (cwd ${s}${i?", computer use on":""}), Ctrl+C to stop`);try{await t({baseUrl:o,computer:i,credential:r,cwd:s,force:c,log:(p)=>console.log(p),mcpFile:a?P(a):void 0,sandbox:n,signal:d.signal})}catch(p){console.error(p instanceof Error?p.message:String(p)),process.exitCode=1}finally{process.off("SIGINT",l)}}async function Fi(e){try{let{startDesktop:n}=await import("../chunk-5tnnqapc.js"),{display:t,driver:o,permissions:r}=await n(e);o.stop();let s=(i)=>i?"granted":"missing";if(console.log(`screenshot frame ${t.width}x${t.height} (scale ${t.scale.toFixed(2)})`),console.log(`screen recording ${s(r.screenRecording)}`),console.log(`accessibility ${s(r.accessibility)}`),!r.screenRecording||!r.accessibility)console.log(e?"Approve the prompts, or add this terminal under System Settings > Privacy & Security, then run again.":"Run `broods machine --doctor --request` to show the macOS prompts."),process.exitCode=1}catch(n){console.error(n instanceof Error?n.message:String(n)),process.exitCode=1}}async function Ki(e){let n=await sn(e),{project:t,stage:o}=n,r=b(e,"--sandbox");if(I(e,"--sandbox")&&!G(r))throw Error("--sandbox needs the instance log id, the UUID shown in the dashboard Instances sheet.");let s=r?"DEBUG":Bn(e),i=Number(b(e,"--limit")??b(e,"-n")??100),a=I(e,"--json"),c=new AbortController,d=()=>c.abort();process.on("SIGINT",d),console.log(`Logs for ${t}/${o}`+(r?` sandbox ${r}`:"")+` [${s}+]`+co(s)+` (backfill ${i}), Ctrl+C to stop`);try{for await(let l of Ve(n,{backfill:i,minLevel:s,...r?{sandboxId:r}:{},signal:c.signal,onReconnect:Gn}))if(a)console.log(JSON.stringify(l));else console.log(Wn(l))}catch(l){if(!c.signal.aborted)console.error(l instanceof Error?l.message:String(l)),process.exitCode=1}finally{process.off("SIGINT",d)}}async function Hi(e){let[n,t]=te(e);if(!n){console.log(ve("agent",e));return}if(n==="list"||n==="ls"){await Vi(e);return}if(n==="get"){await Yi(t,e);return}throw Error(`Unknown agent subcommand: ${n}
403
+ ${Z("env")}`);let{manifest:c,config:d}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),l=await q(b(e,"--base-url")??d.baseUrl),p=new N({baseUrl:l.baseUrl,token:l.token}),u=`${c.project}/${c.stage}`;if(i){await Mi(p,c,u);return}if(o){let C=await p.listEnv(c.project,c.stage);if(C.length===0){console.log(`No environment variables set for ${u}.`);return}console.log(`Environment variables for ${u} (values hidden):`);for(let k of C)console.log(` ${k.name}`);return}if(s){let C=await p.getEnv(c.project,c.stage,t);if(C===null){console.error(`${t} is not set for ${u}`),process.exitCode=1;return}console.log(C);return}if(r){await p.removeEnv(c.project,c.stage,t),H(`Removed ${t} from ${u}`);return}let S=await _t(t);await p.setEnv(c.project,c.stage,t,S),H(`Stored ${t} for ${u}`)}async function Mi(e,n,t){let o=await Mn(e,n);if(o.length===0){console.log('No env("NAME") references in this project.');return}let r=await ao(e,n,o);if(r.length>0)En(r);let s=nn(o,"synced").length;console.log(r.length>0?`${s} other referenced variable(s) already in step with ${t}.`:`${s} referenced variable(s) already in step with ${t}.`);let i=nn(o,"stage-only");if(i.length>0)console.log(`${i.length} referenced variable(s) live only on ${t}: ${i.join(", ")}`);let a=nn(o,"unresolved");if(a.length>0)x(`${a.length} referenced variable(s) with no value here or on ${t}: ${a.join(", ")}. Put them in .env.local, or run \`broods env set <NAME> --stage ${n.stage}\`.`)}function Bn(e){if(I(e,"--all"))return"DEBUG";let n=b(e,"--level");if(n===void 0&&I(e,"--level"))throw Error("Missing value for --level. Use DEBUG, INFO, WARN, or ERROR.");if(!n)return"WARN";let t=n.toUpperCase();if(t==="DEBUG")return"DEBUG";if(t==="INFO")return"INFO";if(t==="WARN"||t==="WARNING")return"WARN";if(t==="ERROR")return"ERROR";throw Error(`Unknown log level: ${n}. Use DEBUG, INFO, WARN, or ERROR.`)}async function Bi(e){h();let n=b(e,"--project")??process.env.BROODS_PROJECT,t=b(e,"--stage")??v();if(!n)throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT in .env.local.");if(!t)throw Error("Stage name is required. Pass --stage <name> or set BROODS_STAGE in .env.local.");return{project:n,stage:t}}async function sn(e){let n=await Bi(e),t=h(),o=await Be(b(e,"--dashboard-url")??t.dashboardUrl??oe,b(e,"--base-url")),r=new N({baseUrl:o.baseUrl,token:o.token}),s=await r.mintStageSession(n.project,n.stage),i=s,a=async()=>{let c=i??await r.mintStageSession(n.project,n.stage);return i=void 0,c.token};return{baseUrl:o.baseUrl,credential:a,project:s.projectSlug,stage:s.stageSlug}}function co(e){return e==="WARN"?" (--all for INFO too)":""}function Gn(e,n){console.error(je(`Reconnecting to live logs (attempt ${e}): ${n}`,{stream:"stderr"}))}function Wn(e){let n=new Date(e.ts).toISOString().slice(11,23),t=e.level.padEnd(5),o=Ys(e.message);return`${n} ${t} ${e.eventType} ${o}`}async function Gi(e){let n=await sn(e),{project:t,stage:o}=n,r=Bn(e),s=new AbortController,i=()=>s.abort();process.on("SIGINT",i),console.log(`Streaming live logs for ${t}/${o} [${r}+]`+co(r)+", Ctrl+C to stop");try{for await(let a of Ve(n,{backfill:0,minLevel:r,signal:s.signal,onReconnect:Gn}))console.log(Wn(a))}catch(a){if(!s.signal.aborted)console.error(a instanceof Error?a.message:String(a)),process.exitCode=1}finally{process.off("SIGINT",i)}}async function Wi(e){if(I(e,"--doctor")){await Fi(I(e,"--request"));return}let n=te(e)[0];if(!n){console.log(ve("machine",e));return}let{runMachineDaemon:t}=await import("../chunk-17zpcz3t.js"),{baseUrl:o,credential:r}=await sn(e),s=P(b(e,"--cwd")??process.cwd()),i=I(e,"--computer"),a=b(e,"--mcp"),c=I(e,"--force"),d=new AbortController,l=()=>d.abort();process.on("SIGINT",l),console.log(`Connecting ${n} to ${o} (cwd ${s}${i?", computer use on":""}), Ctrl+C to stop`);try{await t({baseUrl:o,computer:i,credential:r,cwd:s,force:c,log:(p)=>console.log(p),mcpFile:a?P(a):void 0,sandbox:n,signal:d.signal})}catch(p){console.error(p instanceof Error?p.message:String(p)),process.exitCode=1}finally{process.off("SIGINT",l)}}async function Fi(e){try{let{startDesktop:n}=await import("../chunk-5tnnqapc.js"),{display:t,driver:o,permissions:r}=await n(e);o.stop();let s=(i)=>i?"granted":"missing";if(console.log(`screenshot frame ${t.width}x${t.height} (scale ${t.scale.toFixed(2)})`),console.log(`screen recording ${s(r.screenRecording)}`),console.log(`accessibility ${s(r.accessibility)}`),!r.screenRecording||!r.accessibility)console.log(e?"Approve the prompts, or add this terminal under System Settings > Privacy & Security, then run again.":"Run `broods machine --doctor --request` to show the macOS prompts."),process.exitCode=1}catch(n){console.error(n instanceof Error?n.message:String(n)),process.exitCode=1}}async function Ki(e){let n=await sn(e),{project:t,stage:o}=n,r=b(e,"--sandbox");if(I(e,"--sandbox")&&!G(r))throw Error("--sandbox needs the instance log id, the UUID shown in the dashboard Instances sheet.");let s=r?"DEBUG":Bn(e),i=Number(b(e,"--limit")??b(e,"-n")??100),a=I(e,"--json"),c=new AbortController,d=()=>c.abort();process.on("SIGINT",d),console.log(`Logs for ${t}/${o}`+(r?` sandbox ${r}`:"")+` [${s}+]`+co(s)+` (backfill ${i}), Ctrl+C to stop`);try{for await(let l of Ve(n,{backfill:i,minLevel:s,...r?{sandboxId:r}:{},signal:c.signal,onReconnect:Gn}))if(a)console.log(JSON.stringify(l));else console.log(Wn(l))}catch(l){if(!c.signal.aborted)console.error(l instanceof Error?l.message:String(l)),process.exitCode=1}finally{process.off("SIGINT",d)}}async function Hi(e){let[n,t]=te(e);if(!n){console.log(ve("agent",e));return}if(n==="list"||n==="ls"){await Vi(e);return}if(n==="get"){await Yi(t,e);return}throw Error(`Unknown agent subcommand: ${n}
404
404
 
405
405
  ${Z("agent")}`)}async function lo(e){let{manifest:n,config:t}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),o=await q(b(e,"--base-url")??t.baseUrl),r=await new N({baseUrl:o.baseUrl,token:o.token}).getManifest(n.project,n.stage),s=n.resources.filter((i)=>i.kind==="agent").map((i)=>({name:i.name,config:i.config??{},agentId:r?.ids.agents[i.name]}));return{manifest:n,agents:s}}async function Vi(e){let{manifest:n,agents:t}=await lo(e);if(t.length===0){console.log(`No agents declared in ${n.project}/${n.stage}.`);return}console.log(`Agents in ${n.project}/${n.stage}:`);for(let o of t){let r=uo(o.config),s=o.config.publicAccess===!0?"public":"private",i=o.agentId?o.agentId:"not deployed";console.log(` ${o.name} [${s}] ${r} (${i})`)}}async function Yi(e,n){if(!e)throw Error(`Missing agent name.
406
406
 
407
407
  ${Z("agent")}`);let{manifest:t,agents:o}=await lo(n),r=o.find((u)=>u.name===e);if(!r)throw Error(`Unknown local agent: ${e}`);let s=r.config,i=[s.sandboxes].flat().filter((u)=>typeof u==="string").map((u,S)=>S===0?`${u} (default)`:u),a=Array.isArray(s.workspaces)?s.workspaces.map((u)=>typeof u==="string"?u:u.name).filter(Boolean):[],c=we(s.tools)?Object.keys(s.tools):[],d=we(s.channels)?Object.keys(s.channels):[],l=we(s.subagent)&&Array.isArray(s.subagent.allowed)?s.subagent.allowed.map((u)=>typeof u==="string"?u:u.name).filter(Boolean):[],p=we(s.hooks)&&Array.isArray(s.hooks.webhooks)?s.hooks.webhooks.filter(we):[];if(console.log(`Agent: ${r.name}`),console.log(` Project/Stage: ${t.project}/${t.stage}`),console.log(` Deployed id: ${r.agentId??"not deployed"}`),console.log(` Public access: ${s.publicAccess===!0?"public (SSE/WebSocket enabled)":"private (secured by default)"}`),console.log(` Model: ${uo(s)}`),console.log(` Sandboxes: ${i.length>0?i.join(", "):"none"}`),console.log(` Workspaces: ${a.length>0?a.join(", "):"none"}`),console.log(` Tools: ${c.length>0?c.join(", "):"none"}`),console.log(` Subagents: ${l.length>0?l.join(", "):"none"}`),console.log(` Channels: ${d.length>0?d.join(", "):"none"}`),p.length>0)console.log(" Webhooks:"),p.forEach((u,S)=>{let C=Array.isArray(u.events)&&u.events.length>0?u.events.join(", "):"all events",k=u.enabled===!1?"disabled":"enabled",A=typeof u.url==="string"?u.url:"none";console.log(` [${S}] ${k} → ${A} (${C})`)})}function uo(e){let n=we(e.model)?e.model:{},t=typeof n.provider==="string"?n.provider:void 0,o=typeof n.modelId==="string"?n.modelId:void 0;if(t&&o)return`${t}/${o}`;return o??t??"unconfigured model"}async function zi(e){let[n,...t]=te(e);if(!n)throw Error(`Missing agent name.
408
408
 
409
- ${Z("run")}`);let o=t.join(" "),r=Boolean(process.stdin.isTTY&&process.stdout.isTTY);if(!r&&!o)throw Error("A prompt is required when output is redirected: broods run <agent> <prompt>. Run it in a terminal to chat without one.");let{manifest:s,config:i}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),a=await q(b(e,"--base-url")??i.baseUrl),c=s.resources.find((A)=>A.kind==="agent"&&A.name===n);if(!c)throw Error(`Unknown local agent: ${n}`);let l=(await new N({baseUrl:a.baseUrl,token:a.token}).getManifest(s.project,s.stage))?.ids.agents[n];if(!l)throw Error(`Agent ${n} is not synced yet. Run broods dev --once or broods deploy first.`);let p=await new N({baseUrl:a.baseUrl,token:a.token}).getRuntimeKey(s.project,s.stage).catch(()=>null);if(p?.apiKey)await $e("BROODS_API_KEY",p.apiKey);if(c.config.publicAccess!==!0)x(`Agent "${n}" does not set publicAccess: true. The public endpoint is secured by default; if the deployed agent has not enabled it, this run will be refused.`);let u=new B({baseUrl:b(e,"--base-url")??process.env.BROODS_BASE_URL??process.env.BROODS_HOST??a.baseUrl,...p?.apiKey?{apiKey:p.apiKey}:{}}),S={kind:"agent",name:n,id:l,project:s.project,stage:s.stage,...p?.endpointId?{endpointId:p.endpointId}:{},...p?.projectSlug?{projectSlug:p.projectSlug}:{},...p?.stageSlug?{stageSlug:p.stageSlug}:{}},{runAgentTui:C,streamAgentText:k}=await import("../chunk-m7ws7kqc.js");try{if(r){await C({client:u,agent:S,...o?{prompt:o}:{}});return}await k({client:u,agent:S,prompt:o})}catch(A){if((A instanceof Error?A.message:String(A)).includes("public_access_disabled"))throw Error(`Agent "${n}" is not publicly accessible (secured by default). Set publicAccess: true in its config and redeploy, or enable Public access in the dashboard.`);throw A}}async function tn(e,n,t){try{await ye(e,n,{flag:t?"w":"wx"})}catch(o){if(o.code==="EEXIST")return;throw o}}async function go(){let e=P(process.cwd(),".gitignore"),n=await Ce(e);if(n.split(/\r?\n/).some((r)=>[".env.local","/.env.local",".env*.local",".env.*",".env*"].includes(r.trim())))return;let o=n?`${n.trimEnd()}
409
+ ${Z("run")}`);let o=t.join(" "),r=Boolean(process.stdin.isTTY&&process.stdout.isTTY);if(!r&&!o)throw Error("A prompt is required when output is redirected: broods run <agent> <prompt>. Run it in a terminal to chat without one.");let{manifest:s,config:i}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),a=await q(b(e,"--base-url")??i.baseUrl),c=s.resources.find((A)=>A.kind==="agent"&&A.name===n);if(!c)throw Error(`Unknown local agent: ${n}`);let l=(await new N({baseUrl:a.baseUrl,token:a.token}).getManifest(s.project,s.stage))?.ids.agents[n];if(!l)throw Error(`Agent ${n} is not synced yet. Run broods dev --once or broods deploy first.`);let p=await new N({baseUrl:a.baseUrl,token:a.token}).getRuntimeKey(s.project,s.stage).catch(()=>null);if(p?.apiKey)await $e("BROODS_API_KEY",p.apiKey);if(c.config.publicAccess!==!0)x(`Agent "${n}" does not set publicAccess: true. The public endpoint is secured by default; if the deployed agent has not enabled it, this run will be refused.`);let u=new B({baseUrl:b(e,"--base-url")??process.env.BROODS_BASE_URL??process.env.BROODS_HOST??a.baseUrl,...p?.apiKey?{apiKey:p.apiKey}:{}}),S={kind:"agent",name:n,id:l,project:s.project,stage:s.stage,...p?.endpointId?{endpointId:p.endpointId}:{},...p?.projectSlug?{projectSlug:p.projectSlug}:{},...p?.stageSlug?{stageSlug:p.stageSlug}:{}},{runAgentTui:C,streamAgentText:k}=await import("../chunk-5esx8msr.js");try{if(r){await C({client:u,agent:S,...o?{prompt:o}:{}});return}await k({client:u,agent:S,prompt:o})}catch(A){if((A instanceof Error?A.message:String(A)).includes("public_access_disabled"))throw Error(`Agent "${n}" is not publicly accessible (secured by default). Set publicAccess: true in its config and redeploy, or enable Public access in the dashboard.`);throw A}}async function tn(e,n,t){try{await ye(e,n,{flag:t?"w":"wx"})}catch(o){if(o.code==="EEXIST")return;throw o}}async function go(){let e=P(process.cwd(),".gitignore"),n=await Ce(e);if(n.split(/\r?\n/).some((r)=>[".env.local","/.env.local",".env*.local",".env.*",".env*"].includes(r.trim())))return;let o=n?`${n.trimEnd()}
410
410
  .env*.local
411
411
  `:`.env*.local
412
412
  `;await ye(e,o,"utf8")}async function po(){let e=P(process.cwd(),y,".gitignore"),n=await Ce(e),o=["_generated",".cache"].filter((s)=>!n.split(/\r?\n/).some((i)=>i.trim()===s));if(o.length===0)return;let r=n?n.trimEnd()+`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "broods",
3
- "version": "0.49.2",
3
+ "version": "0.49.3",
4
4
  "description": "CLI + TypeScript SDK for the broods agent platform.",
5
5
  "keywords": [
6
6
  "agents",
@@ -59,7 +59,7 @@
59
59
  "esbuild": "^0.28.2"
60
60
  },
61
61
  "devDependencies": {
62
- "@ai-sdk/tui": "1.0.128",
62
+ "@ai-sdk/tui": "1.0.138",
63
63
  "@arethetypeswrong/cli": "^0.18.5",
64
64
  "@chat-adapter/discord": "^4.38.1",
65
65
  "@chat-adapter/github": "^4.38.1",
@@ -68,7 +68,7 @@
68
68
  "@modelcontextprotocol/server": "2.2.0",
69
69
  "@types/bun": "^1.3.14",
70
70
  "@typescript/typescript6": "6.0.2",
71
- "ai": "^7.0.127",
71
+ "ai": "^7.0.137",
72
72
  "publint": "^0.3.23",
73
73
  "rollup": "^4.62.4",
74
74
  "rollup-plugin-dts": "^6.5.1",
@@ -76,7 +76,7 @@
76
76
  "zod": "^4.4.3"
77
77
  },
78
78
  "peerDependencies": {
79
- "ai": "^7.0.127"
79
+ "ai": "^7.0.137"
80
80
  },
81
81
  "engines": {
82
82
  "node": ">=22.15"
File without changes
File without changes