broods 0.49.3 → 0.50.0
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/account.d.ts +22 -4
- package/dist/account.js +1 -1
- package/dist/{chunk-17zpcz3t.js → chunk-187pvsnt.js} +4 -4
- package/dist/chunk-2xb3wm7w.js +15 -0
- package/dist/{chunk-n890pdvc.js → chunk-463bn8qa.js} +22 -22
- package/dist/{chunk-hxky9s3f.js → chunk-4jqe5w5p.js} +1 -1
- package/dist/{chunk-ctt7r720.js → chunk-7ajf29ec.js} +1 -1
- package/dist/chunk-njxsdp91.js +2 -0
- package/dist/{chunk-m96g7766.js → chunk-qtvbrzvd.js} +1 -1
- package/dist/chunk-rv0n0evv.js +5 -0
- package/dist/chunk-tgw6cmbm.js +1 -0
- package/dist/cli/index.js +58 -57
- package/dist/index.d.ts +88 -9
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-0057x2fk.js +0 -1
- package/dist/chunk-6kgtx9kv.js +0 -5
- package/dist/chunk-bb3jfhv3.js +0 -2
- package/dist/chunk-kx38nst5.js +0 -15
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{K,S,w,N,P,W,J,_,h,U,f,T,Y,X,y,I,B,te,z,de,R,g}from"../chunk-rv0n0evv.js";import{m,C}from"../chunk-njxsdp91.js";import{chmod as Gs,lstat as Ws,mkdir as Gn,readFile as Qt,readdir as Fs,stat as Ks,writeFile as Ee}from"node:fs/promises";import{createHash as eo}from"node:crypto";import Hs from"node:module";import{basename as Ys,join as Ge,relative as Vs,resolve as x,sep as zs}from"node:path";import{watch as Js}from"node:fs";import{spawn as no}from"node:child_process";import{tmpdir as qs}from"node:os";import{performance as zt}from"node:perf_hooks";import{stripVTControlCharacters as Zs}from"node:util";import{fileURLToPath as Ro,pathToFileURL as gt}from"node:url";import{createHash as Oo}from"node:crypto";import{existsSync as Ao,readFileSync as xo}from"node:fs";import{mkdtemp as Po,readdir as pt,readFile as To,rm as _o,writeFile as jo}from"node:fs/promises";import tt from"node:module";import{tmpdir as Io}from"node:os";import{basename as Do,isAbsolute as Uo,join as He,relative as Re,resolve as Ye}from"node:path";import{build as No,transformSync as ft}from"esbuild";var qn=/\$\{([A-Z][A-Z0-9_]*)\}/;var Zn={alibaba:{label:"Alibaba Qwen",modelPlaceholder:"qwen3-max"},anthropic:{label:"Anthropic",modelPlaceholder:"claude-sonnet-4-5-20250929"},azure:{label:"Azure OpenAI",modelPlaceholder:"gpt-4.1-mini"},baseten:{label:"Baseten",modelPlaceholder:"deepseek-ai/DeepSeek-V3"},bedrock:{label:"Amazon Bedrock",modelPlaceholder:"anthropic.claude-sonnet-4-5-20250929-v1:0"},cerebras:{label:"Cerebras",modelPlaceholder:"llama3.1-8b"},chatgpt:{label:"ChatGPT plan",modelPlaceholder:"gpt-5.5"},cloudflare:{label:"Cloudflare",modelPlaceholder:"@cf/meta/llama-3.3-70b-instruct-fp8-fast"},cohere:{label:"Cohere",modelPlaceholder:"command-a-03-2025"},custom:{label:"Custom OpenAI-compatible",modelPlaceholder:"gpt-oss-120b"},deepinfra:{label:"DeepInfra",modelPlaceholder:"deepseek-ai/DeepSeek-V3"},deepseek:{label:"DeepSeek",modelPlaceholder:"deepseek-chat"},fireworks:{label:"Fireworks",modelPlaceholder:"accounts/fireworks/models/deepseek-v3"},google:{label:"Google",modelPlaceholder:"gemini-2.5-flash"},groq:{label:"Groq",modelPlaceholder:"llama-3.3-70b-versatile"},huggingface:{label:"Hugging Face",modelPlaceholder:"meta-llama/Llama-3.3-70B-Instruct"},llmgateway:{label:"LLM Gateway",modelPlaceholder:"openai/gpt-4.1-mini"},minimax:{label:"MiniMax",modelPlaceholder:"MiniMax-M2.7"},mistral:{label:"Mistral",modelPlaceholder:"mistral-large-latest"},moonshotai:{label:"Moonshot AI Kimi",modelPlaceholder:"kimi-k2.6"},ollama:{label:"Ollama",modelPlaceholder:"gpt-oss:120b"},openai:{label:"OpenAI",modelPlaceholder:"gpt-4.1-mini"},openrouter:{label:"OpenRouter",modelPlaceholder:"anthropic/claude-sonnet-4.5"},perplexity:{label:"Perplexity",modelPlaceholder:"low"},togetherai:{label:"Together.ai",modelPlaceholder:"deepseek-ai/DeepSeek-V3"},v0:{label:"Vercel v0",modelPlaceholder:"v0-1.0-md"},vercel:{label:"Vercel AI Gateway",modelPlaceholder:"openai/gpt-4.1-mini"},vertex:{label:"Google Vertex AI",modelPlaceholder:"gemini-2.5-flash"},xai:{label:"xAI Grok",modelPlaceholder:"grok-4"},zai:{label:"Z.ai GLM",modelPlaceholder:"glm-4.7"}},Xn=Object.keys(Zn);function Qn(e){return Object.hasOwn(Zn,e)}var ko=/(?:^|[\n;])\s*import\s+(?:[^;"'`]*?\s+from\s*)?["'](?!\.{1,2}\/|\/|node:)[^"']+["']|import\s*\(\s*["'](?!\.{1,2}\/|\/|node:)[^"']+["']\s*\)/,Eo=/(?:import\s+(?:[^;"'`]*?\s+from\s*)?["']node:|import\s*\(\s*["']node:)/,So=/(?<![.\w$])(?:process|Buffer)\s*(?:\?\.|\.|\[)/,$o=[/\b(?:__)?require\s*\(/,/(?<![.\w$])setImmediate\s*\(/,Eo,So,/\b__dirname\b/,ko],Co=/(?<![.\w$])eval\s*\(|\bnew\s+Function\s*\(/;function et(e){return![...$o,Co].some((n)=>n.test(e))}var gn=32;var pn=["conversation","agent"];function nt(e){return pn.some((n)=>n===e)}var Pe="*",Lo=new RegExp(qn.source,"g"),Mo=`const passthrough = (input) => input;
|
|
3
3
|
export const defineAgent = passthrough;
|
|
4
4
|
export const defineBroods = passthrough;
|
|
5
5
|
export const defineCron = passthrough;
|
|
@@ -39,15 +39,15 @@ export const defineZaloChannel = passthrough;
|
|
|
39
39
|
export const defineZaloConnection = passthrough;
|
|
40
40
|
export const env = (name) => ({ __beeblastEnv: true, name });
|
|
41
41
|
export default {};
|
|
42
|
-
`,Fe=1e7,et=50000000,pn=1e7,nt=20000000,tt=200,Uo=new Set(["node_modules",".git"]),No=[/^\.env(?:\.|$)/i,/^id_(?:rsa|dsa|ecdsa|ed25519)(?:\.pub)?$/i,/\.(?:pem|key|p12|pfx)$/i],dn={onStart:"agent.started",onStepFinish:"agent.step.finished",onToolCall:"tool.call.started",onToolResult:"tool.result",onFinish:"agent.finished",onApproval:"agent.approval.required",onError:"agent.failed",onSubagentFinish:"subagent.task.finished",onMessageReceived:"channel.message.received",onMessageSending:"channel.message.sending"};async function le(e={}){let n=e.cwd??process.cwd();h(n);let t=We(n,y);if(!$o(t))throw Error(`No ${y}/ folder in ${n}. Run \`broods dev\` to scaffold one.`);let o=await Mo(t),r=await Bo(o),s=await Wo(r,n,e.project),i=r.filter((k)=>g(k.value)).map((k)=>({exportName:k.exportName,file:k.file,resource:k.value})),a=i.map((k)=>k.resource);st(a),Qo(a);let c=nr(i,r),d=or(a);for(let k of a)Ko(k);for(let k of a)Ho(k);for(let k of a)Vo(k);Yo(a),Jo(a),tr(i,d);let l=er(i),p=Lo(s,e.stage??(e.useRuntimeStage===!1?void 0:v()),e.command??"dev"),u=(await Promise.all(i.map((k)=>rr(k,t,d)))).flat().sort((k,A)=>`${k.kind}:${k.name}`.localeCompare(`${A.kind}:${A.name}`)),S=new Map(u.filter((k)=>k.kind==="mcp").map((k)=>[k.name,k.config])),C=u.map((k)=>$r(k,S));return st(C),{config:s,resources:a,resourceAliases:l,channels:c,manifest:{version:1,project:s.project,stage:p,resources:C}}}function gt(e){let n=new Set;for(let t of e.resources){Ae(t.config,n,t.kind==="workspace");let o=t.config;if(t.kind==="agent")Ae(o.mcp,n,!0);if(t.kind==="mcp")Ae(o.headers,n,!0)}return[...n].sort()}function Ae(e,n,t){if(t&&typeof e==="string"){for(let o of e.matchAll(_o))n.add(o[1]);return}if(Array.isArray(e)){for(let o of e)Ae(o,n,t);return}if(e&&typeof e==="object"){let o=e;if(o.__beeblastEnv===!0&&typeof o.name==="string"){n.add(o.name);return}for(let r of Object.values(o))Ae(r,n,t)}}function Lo(e,n,t){if(n)return n;let o=e.stages?.[t];if(o)return o;return t==="deploy"?"production":"development"}async function Mo(e){let n=[];async function t(o){let r=await dt(o,{withFileTypes:!0});for(let s of r){let i=Ge(o,s.name);if(s.isDirectory()){if(s.name===_||s.name==="generated")continue;await t(i)}else if(s.isFile()&&s.name.endsWith(".ts"))n.push(i)}}return await t(e),n.sort((o,r)=>ke(e,o).localeCompare(ke(e,r)))}async function Bo(e){Go();let n=[];for(let t of e){let r=await import(`${lt(t).href}?t=${Date.now()}`);n.push(...Object.entries(r).map(([s,i])=>({exportName:s,file:t,value:i})))}return n}var ot=!1;function Go(){if(ot)return;if(ot=!0,typeof Qn.registerHooks!=="function")return;Qn.registerHooks({load:(e,n,t)=>{let[o]=e.split("?");if(o===void 0||!o.startsWith("file:")||!o.endsWith(".ts"))return t(e,n);let r=Eo(o);return{format:"module",shortCircuit:!0,source:ut(Co(r,"utf8"),{loader:"ts",format:"esm",sourcefile:r,sourcemap:"inline"}).code}}})}async function Wo(e,n,t){let r=e.find((i)=>ie(i.value))?.value?.config??{},s=t??process.env.BROODS_PROJECT??r.project??jr(To(We(n)));if(!s.trim())throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT.");return{...r,project:s}}var rt=new Set(["agent","harness","model","provider","session","hooks","connections","tools","mcp","denyTools","sandboxes","workspaces","subagent","skills","scheduler","browser","policies","publicAccess","allowRunOverrides"]),Fo={workspace:"workspaces",skill:"skills",policy:"policies",tool:"tools",mcpServers:"mcp",channel:"connections",channels:"connections",hook:"hooks",subagents:"subagent",systemPrompt:"agent",system:"agent"};function Ko(e){if(e.kind!=="agent")return;let n=e.config;for(let t of Object.keys(n)){if(rt.has(t))continue;if(t==="sandbox")throw Error(`Agent "${e.name}" config.sandbox was removed; use sandboxes, the first is the default`);let o=Fo[t],r=o?` Did you mean "${o}"?`:` Allowed keys: ${[...rt].sort().join(", ")}.`;throw Error(`Agent "${e.name}" has an unknown config key "${t}".${r}`)}}function Ho(e){if(e.kind!=="workspace")return;let t=e.config.storage;if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`Workspace "${e.name}" config.storage must be an object`);let o=t.provider;if(o===void 0||o==="s3")return;if(o==="vercel")throw Error(`Workspace "${e.name}" uses storage.provider "vercel", but Vercel Drive workspace storage is not supported yet. Use storage.provider "s3" or omit storage until Vercel Drive is wired.`);throw Error(`Workspace "${e.name}" config.storage.provider must be one of: s3`)}function Vo(e){if(e.kind!=="workspace")return;let n=e.config;if(n.partitioned!==void 0&&!Xn(n.partitioned))throw Error(`Workspace "${e.name}" config.partitioned must be one of: ${ln.join(", ")}`);if(n.isolation!==void 0)throw Error(`Workspace "${e.name}" config.isolation is no longer supported; use partitioned.`)}function Yo(e){let n=new Map(e.filter((t)=>t.kind==="workspace").map((t)=>[t.name,t]));for(let t of e){if(t.kind!=="agent")continue;let o=t.config,r=o.connections;if(r!==void 0&&!Array.isArray(r))throw Error(`Agent "${t.name}" config.connections must be an array of connection definitions`);let s=Array.isArray(r)?r.filter(w):[],i=new Set;for(let l of s){let p=l.config,u=typeof p.id==="string"?p.id:void 0;if(u){if(i.has(u))throw Error(`Duplicate channel id: ${u}`);i.add(u)}if(l.partition)pt(l.partition,`Agent "${t.name}" connection "${l.type}"`);if(l.config&&typeof l.config==="object"&&(("workspaceIsolationScope"in l.config)||("workspaceScope"in l.config)))throw Error(`Agent "${t.name}" connection "${l.type}" uses workspaceScope, which is no longer supported; use partition.`)}let c=(Array.isArray(o.workspaces)?o.workspaces.map((l)=>zo(l,n)).filter((l)=>Boolean(l)):[]).filter((l)=>l.config.partitioned==="conversation"),d=s.filter((l)=>l.partition);if(d.length>0&&c.length===0){let l=d[0];throw Error(`Agent "${t.name}" connection "${l.type}" defines partition, but no attached workspace has partitioned: "conversation".`)}if(c.length>0){for(let l of s)if(!l.partition)throw Error(`Agent "${t.name}" attaches partitioned workspace "${c[0].name}", but connection "${l.type}" does not define partition.`)}}}function pt(e,n){if(!e)return;if(e.by==="shared"){if("alias"in e&&e.alias!==void 0)throw Error(`${n} partition.alias is only supported when partition.by is conversation`);return}if(e.by!=="conversation")throw Error(`${n} partition.by must be one of: shared, conversation`);if(typeof e.alias!=="string"||e.alias.length===0)throw Error(`${n} partition.alias is required when partition.by is conversation`);if(!/^[A-Za-z0-9._-]+$/.test(e.alias))throw Error(`${n} partition.alias must use only letters, numbers, dots, underscores, or hyphens`);if(e.alias==="."||e.alias==="..")throw Error(`${n} partition.alias must not be "." or ".."`)}function zo(e,n){if(g(e)&&e.kind==="workspace")return e;if(typeof e==="string")return n.get(e);if(e&&typeof e==="object"&&"workspace"in e){let t=e.workspace;if(g(t)&&t.kind==="workspace")return t;if(typeof t==="string")return n.get(t)}return}function Jo(e){let n=new Map(e.filter((t)=>t.kind==="sandbox").map((t)=>[t.name,t]));for(let t of e){if(t.kind!=="agent")continue;let o=t.config,r=ft(Array.isArray(o.sandboxes)?o.sandboxes[0]:void 0,n),s=o.workspaces;if(!Array.isArray(s))continue;for(let i of s){let a=Zo(i),c=qo(i,r,n);if(!c||Xo(c))continue;throw Error(`Agent "${t.name}" workspace "${a}" uses sandbox "${c.name}" (${mt(c)}) which does not support S3 workspace mounts. Use lambda/sandbox, or daytona with options.mountAwsS3Buckets: true, or set this workspace ref to sandbox: null for read-only S3 access.`)}}}function ft(e,n){if(g(e)&&e.kind==="sandbox")return e;if(typeof e==="string")return n.get(e);return}function qo(e,n,t){if(e&&typeof e==="object"&&"sandbox"in e){let o=e.sandbox;if(o===null)return;return ft(o,t)}return n}function Zo(e){if(g(e)&&e.kind==="workspace")return e.name;if(e&&typeof e==="object"&&"workspace"in e){let n=e.workspace;if(g(n))return n.name;if(typeof n==="string")return n}return"<unknown>"}function Xo(e){let n=mt(e);if(n==="lambda"||n==="sandbox")return!0;if(n!=="daytona")return!1;let t=e.config.options;return Boolean(t&&typeof t==="object"&&!Array.isArray(t)&&t.mountAwsS3Buckets===!0)}function mt(e){return typeof e.config.provider==="string"?e.config.provider:"lambda"}function Qo(e){let n=new Set(e.filter((t)=>t.kind==="sandbox").map((t)=>t.name));for(let t of e){if(t.kind!=="agent")continue;let o=t.config.sandboxes;if(o===void 0)continue;if(!Array.isArray(o))throw Error(`Agent "${t.name}" sandboxes must be an array of sandbox resources or names`);let r=o;for(let[s,i]of r.entries()){let a=typeof i==="string"&&i.trim().length>0,c=g(i)&&i.kind==="sandbox";if(!a&&!c)throw Error(`Agent "${t.name}" sandboxes[${s}] must be a sandbox resource or a non-empty name`);if(c&&!n.has(i.name))throw Error(`Agent "${t.name}" sandboxes references sandbox "${i.name}", but that sandbox is not exported from broods/`)}}}function st(e){let n=new Set;for(let t of e){let o=`${t.kind}:${t.name}`;if(n.has(o))throw Error(`Duplicate resource: ${o}`);n.add(o)}}function er(e){let n={},t=new Set;for(let{exportName:o,resource:r}of e){if(o==="default"||!un(o))continue;let s=`${r.kind}:${o}`;if(t.has(s))throw Error(`Duplicate export alias for ${r.kind}: ${o}`);t.add(s),n[r.kind]??={},n[r.kind][r.name]=o}return n}function nr(e,n){let t=new Map;for(let i of n){if(!w(i.value)||i.exportName==="default"||!un(i.exportName))continue;let a=t.get(i.value);if(a&&a!==i.exportName)throw Error(`Channel is exported more than once: ${a}, ${i.exportName}`);t.set(i.value,i.exportName)}let o=new Map,r=new Set,s=[];for(let{exportName:i,resource:a}of e){if(a.kind!=="agent")continue;let c=a.config.connections;if(c===void 0)continue;if(!Array.isArray(c))throw Error(`Agent "${a.name}" config.connections must be an array of connection definitions`);let d=new Set;for(let l of c){if(!w(l))throw Error(`Agent "${a.name}" config.connections must contain connection definitions`);let p=o.get(l);if(p&&p!==a.name)throw Error(`Channel ${l.type} is already attached to agent "${p}" and cannot also attach to "${a.name}"`);if(d.has(l.type))throw Error(`Agent "${a.name}" cannot configure more than one ${l.type} channel`);o.set(l,a.name),d.add(l.type);let u=i!=="default"&&un(i)?i:a.name,S=t.get(l)??`${u}${wt(l.type)}Channel`;if(r.has(S))throw Error(`Duplicate channel export alias: ${S}`);r.add(S),s.push({alias:S,type:l.type,id:S,agentName:a.name})}}for(let[i,a]of t)if(!o.has(i))throw Error(`Channel "${a}" must be attached to exactly one agent`);return s.sort((i,a)=>i.alias.localeCompare(a.alias))}function tr(e,n){for(let{resource:t}of e){if(t.kind!=="agent")continue;let o=t.config.connections;if(!Array.isArray(o))continue;for(let r of o){if(!w(r))continue;if(ht(r,n).length>0)continue;throw Error(`Agent "${t.name}" connection "${r.type}" reaches no rooms: declare a ${r.type} channel for it, or set allowedChannelIds: ["*"] to answer everywhere`)}}}function ht(e,n){let t=e.config.allowedChannelIds??[];if(t.includes(Oe))return[Oe];return[...new Set([...n.get(e)??[],...t])]}function or(e){let n=new Map;for(let t of e){if(t.kind!=="channelRecord")continue;let o=t.config;if(!w(o.connection))continue;let r=bt(t.name,o.externalId);if(r.length===0)continue;let s=n.get(o.connection)??new Set;for(let i of r)s.add(i);n.set(o.connection,s)}return n}function wt(e){return e.charAt(0).toUpperCase()+e.slice(1)}function un(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}async function rr(e,n,t){let o=e.resource;if(o.kind==="agent"){let r=fr(o,n,t);return[...r.hookResource?[r.hookResource]:[],{kind:o.kind,name:o.name,...o.description?{description:o.description}:{},config:r.config}]}if(o.kind==="channelRecord"){let r=o.config,s=bt(o.name,r.externalId);return s.map((i)=>({kind:o.kind,name:s.length===1?o.name:`${o.name}-${i}`,...o.description?{description:o.description}:{},config:Or(o.name,{...r,externalId:i})}))}return[{kind:o.kind,name:o.name,...o.description?{description:o.description}:{},config:await sr(e,n)}]}function bt(e,n){if(n===void 0)return[];if(typeof n==="string")return it(e,n),[n];if(!Array.isArray(n))throw Error(`Channel "${e}" externalId must be a string or an array`);if(n.length===0)throw Error(`Channel "${e}" externalId must not be an empty array`);let t=new Set;for(let o of n){if(typeof o!=="string"||o.length===0)throw Error(`Channel "${e}" externalId must be an array of non-empty strings`);if(t.has(o))throw Error(`Channel "${e}" externalId lists ${o} twice`);it(e,o),t.add(o)}return n}function it(e,n){if(n!==Oe)return;throw Error(`Channel "${e}" cannot use "${Oe}" as its id: a record matches one exact room. To answer everywhere, set allowedChannelIds: ["${Oe}"] on the connection; undeclared rooms already fall back to its agent.`)}async function sr(e,n){let t=e.resource;if(t.kind==="skill")return await vr(t.config,n);if(t.kind==="workspace"){let o={...t.config},r=o.partitioned;if(delete o.partitioned,r!==void 0)o.isolation=r;return Q(o)}if(t.kind==="mcp")return await kr(e,t.config,n);if(t.kind==="policy"){let o={...t.config};return o.version=o.version??1,Q(o)}if(t.kind==="cron"){let o={...t.config},r=o.agent;if(o.agentId=g(r)?r.name:r,o.name=o.name??t.name,o.status===void 0)o.status="active";if(delete o.agent,typeof o.input==="string")o.events=[{role:"user",content:[{type:"text",text:o.input}]}],delete o.input;return Q(o)}return Q(t.config)}var ir=new Set(["apiKey","base_url","baseURL","gatewayId"]),ar=new Set(["activeTools","debug","inactiveTools","permissionMode","startupTimeoutMs","type","webSearch"]),cr=new Set(["enabled","level","subsystems"]);function lr(e){if(ir.has(e))return"";let n=e.replace(/[^a-z0-9]/gi,"").toLowerCase();if(n==="baseurl")return'"base_url" or "baseURL"';if(n==="apikey")return'"apiKey"';if(n==="gatewayid")return'"gatewayId"';return""}function dr(e,n){if(n===void 0||n===null)return;if(typeof n!=="object"||Array.isArray(n))throw Error(`Agent "${e}" config.provider must be an object`);for(let[t,o]of Object.entries(n)){if(!qn(t))throw Error(`Agent "${e}" config.provider.${t} is not a supported provider (expected one of: ${Jn.join(", ")})`);if(typeof o!=="object"||o===null||Array.isArray(o))throw Error(`Agent "${e}" config.provider.${t} must be an object`);let r=o;for(let s of Object.keys(r)){let i=lr(s);if(i)throw Error(`Agent "${e}" config.provider.${t} has unknown option "${s}". Did you mean ${i}?`)}if(t==="custom"&&r.base_url===void 0&&r.baseURL===void 0)throw Error(`Agent "${e}" config.provider.custom.base_url is required (use "base_url" or "baseURL")`)}}function ur(e,n){if(n===void 0||n===null)return;if(typeof n!=="object"||Array.isArray(n))throw Error(`Agent "${e}" config.harness must be an object`);let t=n;if("sandbox"in t)throw Error(`Agent "${e}" harness sandbox was removed; list it first in the agent's sandboxes`);for(let o of Object.keys(t))if(!ar.has(o))throw Error(`Agent "${e}" config.harness has unknown option "${o}"`);if(t.type!=="claude-code"&&t.type!=="codex"&&t.type!=="deepagents"&&t.type!=="opencode"&&t.type!=="pi")throw Error(`Agent "${e}" config.harness.type must be claude-code, codex, deepagents, opencode, or pi`);if(t.permissionMode!==void 0&&t.permissionMode!=="allow-reads"&&t.permissionMode!=="allow-edits"&&t.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-reads, allow-edits, or allow-all`);if(t.type==="codex"&&t.permissionMode!==void 0&&t.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-all for codex`);if(t.startupTimeoutMs!==void 0&&(typeof t.startupTimeoutMs!=="number"||!Number.isSafeInteger(t.startupTimeoutMs)||t.startupTimeoutMs<1||t.startupTimeoutMs>600000))throw Error(`Agent "${e}" config.harness.startupTimeoutMs must be an integer from 1 to 600000`);if(t.webSearch!==void 0&&typeof t.webSearch!=="boolean")throw Error(`Agent "${e}" config.harness.webSearch must be a boolean`);if(t.type!=="codex"&&t.webSearch!==void 0)throw Error(`Agent "${e}" config.harness.webSearch is only supported by codex`);if(t.type==="pi"&&t.startupTimeoutMs!==void 0)throw Error(`Agent "${e}" config.harness.startupTimeoutMs is not supported by pi`);if(gn(e,t.activeTools,"activeTools"),gn(e,t.inactiveTools,"inactiveTools"),t.activeTools!==void 0&&t.inactiveTools!==void 0)throw Error(`Agent "${e}" config.harness must use either activeTools or inactiveTools, not both`);gr(e,t.debug)}function gr(e,n){if(n===void 0)return;if(typeof n!=="object"||n===null||Array.isArray(n))throw Error(`Agent "${e}" config.harness.debug must be an object`);let t=n;for(let o of Object.keys(t))if(!cr.has(o))throw Error(`Agent "${e}" config.harness.debug has unknown option "${o}"`);if(t.enabled!==void 0&&typeof t.enabled!=="boolean")throw Error(`Agent "${e}" config.harness.debug.enabled must be a boolean`);if(t.level!==void 0&&t.level!=="error"&&t.level!=="warn"&&t.level!=="info"&&t.level!=="debug"&&t.level!=="trace")throw Error(`Agent "${e}" config.harness.debug.level must be error, warn, info, debug, or trace`);gn(e,t.subsystems,"debug.subsystems")}function gn(e,n,t){if(n!==void 0&&(!Array.isArray(n)||!n.every((o)=>typeof o==="string"&&o.trim().length>0)))throw Error(`Agent "${e}" config.harness.${t} must be an array of non-empty strings`)}function pr(e){if(new Set(e.config.skills?.allowed?.map((t)=>g(t)?t.name:t)).size<=cn)return;throw Error(`Agent "${e.name}" config.skills.allowed must list at most ${cn} skills`)}function fr(e,n,t){let o={...e.config};dr(e.name,o.provider),ur(e.name,o.harness);let r=Array.isArray(o.sandboxes)?o.sandboxes.map((i)=>g(i)?i.name:i):void 0;if(r)o.sandboxes=r;r?.forEach((i,a)=>{if(r.indexOf(i)===a)return;throw Error(`Agent "${e.name}" sandboxes[${a}] "${String(i)}" is listed more than once`)}),pr(e);let s=mr(e.name,o.hooks);if(s)o.hooks=s.agentHooksConfig;else if(o.hooks!==void 0)o.hooks=yt(o.hooks,e.name);if(o.connections!==void 0){if(!Array.isArray(o.connections))throw Error(`Agent "${e.name}" config.connections must be an array of connection definitions`);o.channels=Object.fromEntries(o.connections.map((i)=>{if(!w(i))throw Error(`Agent "${e.name}" config.connections must contain connection definitions`);let a=`${e.name}${wt(i.type)}Channel`,c=ht(i,t);return[i.type,{id:a,...i.config,...i.partition?{partition:i.partition}:{},allowedChannelIds:c}]})),delete o.connections}if(Array.isArray(o.workspaces)){let i=o.workspaces.map((a)=>Cr(a,e.name));for(let a of i){let c=r?.indexOf(a.sandbox)??-1;if(c>=1)throw Error(`Agent "${e.name}" sandboxes[${c}] "${String(a.sandbox)}" also backs workspace "${String(a.name)}"; only the first sandbox can back a workspace`)}o.workspaces=i}if(o.harness&&!r?.length)throw Error(`Agent "${e.name}" runs a harness, so it needs sandboxes; the first runs the harness`);if(o.policies!==void 0){let i=br(o.policies,e.name);if(i)o.policies=i;else delete o.policies}return{config:Q(o),...s?.hookResource?{hookResource:s.hookResource}:{}}}function mr(e,n){if(n===void 0)return;if(!n||typeof n!=="object"||Array.isArray(n))throw Error(`Agent "${e}" config.hooks must be an object`);let t=n,o=Object.keys(dn).flatMap((d)=>{let l=t[d];if(l===void 0)return[];if(typeof l!=="function")throw Error(`Agent "${e}" config.hooks.${d} must be a function`);return[{name:d,event:dn[d],source:hr(l.toString())}]});if(o.length===0)return;let r=`${e}-hooks`,s=wr(e,o),i=Buffer.byteLength(s);if(i>Fe)throw Error(`Agent "${e}" hook bundle is too large (${i} bytes, max ${Fe})`);let a=o.map((d)=>d.event),c=yt(t,e);return c.code=[{hookId:r}],{agentHooksConfig:c,hookResource:{kind:"hook",name:r,description:`Inline hooks for agent ${e}`,config:{events:a,bundle:s,sha256:xe(s)}}}}function yt(e,n){if(!e||typeof e!=="object"||Array.isArray(e))throw Error(`Agent "${n}" config.hooks must be an object`);let t=Object.entries(e);for(let[r]of t){if(r==="webhooks"||r in dn)continue;throw Error(`Agent "${n}" config.hooks.${r} is not supported. Use inline hook callbacks or hooks.webhooks.`)}return Object.fromEntries(t.filter(([r])=>r==="webhooks"))}function hr(e){let n=e.trim();if(/^(async\s+)?function\b/.test(n)||/^(async\s*)?\(/.test(n)||/^(async\s+)?[A-Za-z_$][\w$]*\s*=>/.test(n))return n;if(/^(async\s+)?[A-Za-z_$][\w$]*\s*\(/.test(n))return n.replace(/^(async\s+)?/,"$1function ");return n}function wr(e,n){let t=`export default {
|
|
42
|
+
`,Ve=1e7,ot=50000000,wn=1e7,rt=20000000,st=200,Bo=new Set(["node_modules",".git"]),Go=[/^\.env(?:\.|$)/i,/^id_(?:rsa|dsa|ecdsa|ed25519)(?:\.pub)?$/i,/\.(?:pem|key|p12|pfx)$/i],fn={onStart:"agent.started",onStepFinish:"agent.step.finished",onToolCall:"tool.call.started",onToolResult:"tool.result",onFinish:"agent.finished",onApproval:"agent.approval.required",onError:"agent.failed",onSubagentFinish:"subagent.task.finished",onMessageReceived:"channel.message.received",onMessageSending:"channel.message.sending"};async function ge(e={}){let n=e.cwd??process.cwd();f(n);let t=Ye(n,S);if(!Ao(t))throw Error(`No ${S}/ folder in ${n}. Run \`broods dev\` to scaffold one.`);let o=await Fo(t),r=await Ko(o),s=await Yo(r,n,e.project),i=r.filter((v)=>g(v.value)).map((v)=>({exportName:v.exportName,file:v.file,resource:v.value})),a=i.map((v)=>v.resource);ct(a),or(a);let c=sr(i,r),d=ar(a);for(let v of a)zo(v);for(let v of a)Jo(v);for(let v of a)qo(v);Zo(a),Qo(a),ir(i,d);let l=rr(i),p=Wo(s,e.stage??(e.useRuntimeStage===!1?void 0:_()),e.command??"dev"),u=(await Promise.all(i.map((v)=>cr(v,t,d)))).flat().sort((v,O)=>`${v.kind}:${v.name}`.localeCompare(`${O.kind}:${O.name}`)),k=new Map(u.filter((v)=>v.kind==="mcp").map((v)=>[v.name,v.config])),E=u.map((v)=>Ar(v,k));return ct(E),{config:s,resources:a,resourceAliases:l,channels:c,manifest:{version:1,project:s.project,stage:p,resources:E}}}function mt(e){let n=new Set;for(let t of e.resources){Te(t.config,n,t.kind==="workspace");let o=t.config;if(t.kind==="agent")Te(o.mcp,n,!0);if(t.kind==="mcp")Te(o.headers,n,!0)}return[...n].sort()}function Te(e,n,t){if(t&&typeof e==="string"){for(let o of e.matchAll(Lo))n.add(o[1]);return}if(Array.isArray(e)){for(let o of e)Te(o,n,t);return}if(e&&typeof e==="object"){let o=e;if(o.__beeblastEnv===!0&&typeof o.name==="string"){n.add(o.name);return}for(let r of Object.values(o))Te(r,n,t)}}function Wo(e,n,t){if(n)return n;let o=e.stages?.[t];if(o)return o;return t==="deploy"?"production":"development"}async function Fo(e){let n=[];async function t(o){let r=await pt(o,{withFileTypes:!0});for(let s of r){let i=He(o,s.name);if(s.isDirectory()){if(s.name===w||s.name==="generated")continue;await t(i)}else if(s.isFile()&&s.name.endsWith(".ts"))n.push(i)}}return await t(e),n.sort((o,r)=>Re(e,o).localeCompare(Re(e,r)))}async function Ko(e){Ho();let n=[];for(let t of e){let r=await import(`${gt(t).href}?t=${Date.now()}`);n.push(...Object.entries(r).map(([s,i])=>({exportName:s,file:t,value:i})))}return n}var it=!1;function Ho(){if(it)return;if(it=!0,typeof tt.registerHooks!=="function")return;tt.registerHooks({load:(e,n,t)=>{let[o]=e.split("?");if(o===void 0||!o.startsWith("file:")||!o.endsWith(".ts"))return t(e,n);let r=Ro(o);return{format:"module",shortCircuit:!0,source:ft(xo(r,"utf8"),{loader:"ts",format:"esm",sourcefile:r,sourcemap:"inline"}).code}}})}async function Yo(e,n,t){let r=e.find((i)=>de(i.value))?.value?.config??{},s=t??process.env.BROODS_PROJECT??r.project??Ur(Do(Ye(n)));if(!s.trim())throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT.");return{...r,project:s}}var at=new Set(["agent","harness","model","provider","session","hooks","connections","tools","mcp","denyTools","sandboxes","workspaces","subagent","skills","scheduler","browser","policies","publicAccess","allowRunOverrides"]),Vo={workspace:"workspaces",skill:"skills",policy:"policies",tool:"tools",mcpServers:"mcp",channel:"connections",channels:"connections",hook:"hooks",subagents:"subagent",systemPrompt:"agent",system:"agent"};function zo(e){if(e.kind!=="agent")return;let n=e.config;for(let t of Object.keys(n)){if(at.has(t))continue;if(t==="sandbox")throw Error(`Agent "${e.name}" config.sandbox was removed; use sandboxes, the first is the default`);let o=Vo[t],r=o?` Did you mean "${o}"?`:` Allowed keys: ${[...at].sort().join(", ")}.`;throw Error(`Agent "${e.name}" has an unknown config key "${t}".${r}`)}}function Jo(e){if(e.kind!=="workspace")return;let t=e.config.storage;if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`Workspace "${e.name}" config.storage must be an object`);let o=t.provider;if(o===void 0||o==="s3")return;if(o==="vercel")throw Error(`Workspace "${e.name}" uses storage.provider "vercel", but Vercel Drive workspace storage is not supported yet. Use storage.provider "s3" or omit storage until Vercel Drive is wired.`);throw Error(`Workspace "${e.name}" config.storage.provider must be one of: s3`)}function qo(e){if(e.kind!=="workspace")return;let n=e.config;if(n.partitioned!==void 0&&!nt(n.partitioned))throw Error(`Workspace "${e.name}" config.partitioned must be one of: ${pn.join(", ")}`);if(n.isolation!==void 0)throw Error(`Workspace "${e.name}" config.isolation is no longer supported; use partitioned.`)}function Zo(e){let n=new Map(e.filter((t)=>t.kind==="workspace").map((t)=>[t.name,t]));for(let t of e){if(t.kind!=="agent")continue;let o=t.config,r=o.connections;if(r!==void 0&&!Array.isArray(r))throw Error(`Agent "${t.name}" config.connections must be an array of connection definitions`);let s=Array.isArray(r)?r.filter(R):[],i=new Set;for(let l of s){let p=l.config,u=typeof p.id==="string"?p.id:void 0;if(u){if(i.has(u))throw Error(`Duplicate channel id: ${u}`);i.add(u)}if(l.partition)ht(l.partition,`Agent "${t.name}" connection "${l.type}"`);if(l.config&&typeof l.config==="object"&&(("workspaceIsolationScope"in l.config)||("workspaceScope"in l.config)))throw Error(`Agent "${t.name}" connection "${l.type}" uses workspaceScope, which is no longer supported; use partition.`)}let c=(Array.isArray(o.workspaces)?o.workspaces.map((l)=>Xo(l,n)).filter((l)=>Boolean(l)):[]).filter((l)=>l.config.partitioned==="conversation"),d=s.filter((l)=>l.partition);if(d.length>0&&c.length===0){let l=d[0];throw Error(`Agent "${t.name}" connection "${l.type}" defines partition, but no attached workspace has partitioned: "conversation".`)}if(c.length>0){for(let l of s)if(!l.partition)throw Error(`Agent "${t.name}" attaches partitioned workspace "${c[0].name}", but connection "${l.type}" does not define partition.`)}}}function ht(e,n){if(!e)return;if(e.by==="shared"){if("alias"in e&&e.alias!==void 0)throw Error(`${n} partition.alias is only supported when partition.by is conversation`);return}if(e.by!=="conversation")throw Error(`${n} partition.by must be one of: shared, conversation`);if(typeof e.alias!=="string"||e.alias.length===0)throw Error(`${n} partition.alias is required when partition.by is conversation`);if(!/^[A-Za-z0-9._-]+$/.test(e.alias))throw Error(`${n} partition.alias must use only letters, numbers, dots, underscores, or hyphens`);if(e.alias==="."||e.alias==="..")throw Error(`${n} partition.alias must not be "." or ".."`)}function Xo(e,n){if(g(e)&&e.kind==="workspace")return e;if(typeof e==="string")return n.get(e);if(e&&typeof e==="object"&&"workspace"in e){let t=e.workspace;if(g(t)&&t.kind==="workspace")return t;if(typeof t==="string")return n.get(t)}return}function Qo(e){let n=new Map(e.filter((t)=>t.kind==="sandbox").map((t)=>[t.name,t]));for(let t of e){if(t.kind!=="agent")continue;let o=t.config,r=wt(Array.isArray(o.sandboxes)?o.sandboxes[0]:void 0,n),s=o.workspaces;if(!Array.isArray(s))continue;for(let i of s){let a=nr(i),c=er(i,r,n);if(!c||tr(c))continue;throw Error(`Agent "${t.name}" workspace "${a}" uses sandbox "${c.name}" (${bt(c)}) which does not support S3 workspace mounts. Use lambda/sandbox, or daytona with options.mountAwsS3Buckets: true, or set this workspace ref to sandbox: null for read-only S3 access.`)}}}function wt(e,n){if(g(e)&&e.kind==="sandbox")return e;if(typeof e==="string")return n.get(e);return}function er(e,n,t){if(e&&typeof e==="object"&&"sandbox"in e){let o=e.sandbox;if(o===null)return;return wt(o,t)}return n}function nr(e){if(g(e)&&e.kind==="workspace")return e.name;if(e&&typeof e==="object"&&"workspace"in e){let n=e.workspace;if(g(n))return n.name;if(typeof n==="string")return n}return"<unknown>"}function tr(e){let n=bt(e);if(n==="lambda"||n==="sandbox")return!0;if(n!=="daytona")return!1;let t=e.config.options;return Boolean(t&&typeof t==="object"&&!Array.isArray(t)&&t.mountAwsS3Buckets===!0)}function bt(e){return typeof e.config.provider==="string"?e.config.provider:"lambda"}function or(e){let n=new Set(e.filter((t)=>t.kind==="sandbox").map((t)=>t.name));for(let t of e){if(t.kind!=="agent")continue;let o=t.config.sandboxes;if(o===void 0)continue;if(!Array.isArray(o))throw Error(`Agent "${t.name}" sandboxes must be an array of sandbox resources or names`);let r=o;for(let[s,i]of r.entries()){let a=typeof i==="string"&&i.trim().length>0,c=g(i)&&i.kind==="sandbox";if(!a&&!c)throw Error(`Agent "${t.name}" sandboxes[${s}] must be a sandbox resource or a non-empty name`);if(c&&!n.has(i.name))throw Error(`Agent "${t.name}" sandboxes references sandbox "${i.name}", but that sandbox is not exported from broods/`)}}}function ct(e){let n=new Set;for(let t of e){let o=`${t.kind}:${t.name}`;if(n.has(o))throw Error(`Duplicate resource: ${o}`);n.add(o)}}function rr(e){let n={},t=new Set;for(let{exportName:o,resource:r}of e){if(o==="default"||!mn(o))continue;let s=`${r.kind}:${o}`;if(t.has(s))throw Error(`Duplicate export alias for ${r.kind}: ${o}`);t.add(s),n[r.kind]??={},n[r.kind][r.name]=o}return n}function sr(e,n){let t=new Map;for(let i of n){if(!R(i.value)||i.exportName==="default"||!mn(i.exportName))continue;let a=t.get(i.value);if(a&&a!==i.exportName)throw Error(`Channel is exported more than once: ${a}, ${i.exportName}`);t.set(i.value,i.exportName)}let o=new Map,r=new Set,s=[];for(let{exportName:i,resource:a}of e){if(a.kind!=="agent")continue;let c=a.config.connections;if(c===void 0)continue;if(!Array.isArray(c))throw Error(`Agent "${a.name}" config.connections must be an array of connection definitions`);let d=new Set;for(let l of c){if(!R(l))throw Error(`Agent "${a.name}" config.connections must contain connection definitions`);let p=o.get(l);if(p&&p!==a.name)throw Error(`Channel ${l.type} is already attached to agent "${p}" and cannot also attach to "${a.name}"`);if(d.has(l.type))throw Error(`Agent "${a.name}" cannot configure more than one ${l.type} channel`);o.set(l,a.name),d.add(l.type);let u=i!=="default"&&mn(i)?i:a.name,k=t.get(l)??`${u}${vt(l.type)}Channel`;if(r.has(k))throw Error(`Duplicate channel export alias: ${k}`);r.add(k),s.push({alias:k,type:l.type,id:k,agentName:a.name})}}for(let[i,a]of t)if(!o.has(i))throw Error(`Channel "${a}" must be attached to exactly one agent`);return s.sort((i,a)=>i.alias.localeCompare(a.alias))}function ir(e,n){for(let{resource:t}of e){if(t.kind!=="agent")continue;let o=t.config.connections;if(!Array.isArray(o))continue;for(let r of o){if(!R(r))continue;if(yt(r,n).length>0)continue;throw Error(`Agent "${t.name}" connection "${r.type}" reaches no rooms: declare a ${r.type} channel for it, or set allowedChannelIds: ["*"] to answer everywhere`)}}}function yt(e,n){let t=e.config.allowedChannelIds??[];if(t.includes(Pe))return[Pe];return[...new Set([...n.get(e)??[],...t])]}function ar(e){let n=new Map;for(let t of e){if(t.kind!=="channelRecord")continue;let o=t.config;if(!R(o.connection))continue;let r=kt(t.name,o.externalId);if(r.length===0)continue;let s=n.get(o.connection)??new Set;for(let i of r)s.add(i);n.set(o.connection,s)}return n}function vt(e){return e.charAt(0).toUpperCase()+e.slice(1)}function mn(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}async function cr(e,n,t){let o=e.resource;if(o.kind==="agent"){let r=br(o,n,t);return[...r.hookResource?[r.hookResource]:[],{kind:o.kind,name:o.name,...o.description?{description:o.description}:{},config:r.config}]}if(o.kind==="channelRecord"){let r=o.config,s=kt(o.name,r.externalId);return s.map((i)=>({kind:o.kind,name:s.length===1?o.name:`${o.name}-${i}`,...o.description?{description:o.description}:{},config:Tr(o.name,{...r,externalId:i})}))}return[{kind:o.kind,name:o.name,...o.description?{description:o.description}:{},config:await lr(e,n)}]}function kt(e,n){if(n===void 0)return[];if(typeof n==="string")return lt(e,n),[n];if(!Array.isArray(n))throw Error(`Channel "${e}" externalId must be a string or an array`);if(n.length===0)throw Error(`Channel "${e}" externalId must not be an empty array`);let t=new Set;for(let o of n){if(typeof o!=="string"||o.length===0)throw Error(`Channel "${e}" externalId must be an array of non-empty strings`);if(t.has(o))throw Error(`Channel "${e}" externalId lists ${o} twice`);lt(e,o),t.add(o)}return n}function lt(e,n){if(n!==Pe)return;throw Error(`Channel "${e}" cannot use "${Pe}" as its id: a record matches one exact room. To answer everywhere, set allowedChannelIds: ["${Pe}"] on the connection; undeclared rooms already fall back to its agent.`)}async function lr(e,n){let t=e.resource;if(t.kind==="skill")return await $r(t.config,n);if(t.kind==="workspace"){let o={...t.config},r=o.partitioned;if(delete o.partitioned,r!==void 0)o.isolation=r;return ne(o)}if(t.kind==="mcp")return await Cr(e,t.config,n);if(t.kind==="policy"){let o={...t.config};return o.version=o.version??1,ne(o)}if(t.kind==="cron"){let o={...t.config},r=o.agent;if(o.agentId=g(r)?r.name:r,o.name=o.name??t.name,o.status===void 0)o.status="active";if(delete o.agent,typeof o.input==="string")o.events=[{role:"user",content:[{type:"text",text:o.input}]}],delete o.input;return ne(o)}return ne(t.config)}var dr=new Set(["apiKey","base_url","baseURL","gatewayId"]),ur=new Set(["activeTools","debug","inactiveTools","permissionMode","startupTimeoutMs","type","webSearch"]),gr=new Set(["enabled","level","subsystems"]);function pr(e){if(dr.has(e))return"";let n=e.replace(/[^a-z0-9]/gi,"").toLowerCase();if(n==="baseurl")return'"base_url" or "baseURL"';if(n==="apikey")return'"apiKey"';if(n==="gatewayid")return'"gatewayId"';return""}function fr(e,n){if(n===void 0||n===null)return;if(typeof n!=="object"||Array.isArray(n))throw Error(`Agent "${e}" config.provider must be an object`);for(let[t,o]of Object.entries(n)){if(!Qn(t))throw Error(`Agent "${e}" config.provider.${t} is not a supported provider (expected one of: ${Xn.join(", ")})`);if(typeof o!=="object"||o===null||Array.isArray(o))throw Error(`Agent "${e}" config.provider.${t} must be an object`);let r=o;for(let s of Object.keys(r)){let i=pr(s);if(i)throw Error(`Agent "${e}" config.provider.${t} has unknown option "${s}". Did you mean ${i}?`)}if(t==="custom"&&r.base_url===void 0&&r.baseURL===void 0)throw Error(`Agent "${e}" config.provider.custom.base_url is required (use "base_url" or "baseURL")`)}}function mr(e,n){if(n===void 0||n===null)return;if(typeof n!=="object"||Array.isArray(n))throw Error(`Agent "${e}" config.harness must be an object`);let t=n;if("sandbox"in t)throw Error(`Agent "${e}" harness sandbox was removed; list it first in the agent's sandboxes`);for(let o of Object.keys(t))if(!ur.has(o))throw Error(`Agent "${e}" config.harness has unknown option "${o}"`);if(t.type!=="claude-code"&&t.type!=="codex"&&t.type!=="deepagents"&&t.type!=="opencode"&&t.type!=="pi")throw Error(`Agent "${e}" config.harness.type must be claude-code, codex, deepagents, opencode, or pi`);if(t.permissionMode!==void 0&&t.permissionMode!=="allow-reads"&&t.permissionMode!=="allow-edits"&&t.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-reads, allow-edits, or allow-all`);if(t.type==="codex"&&t.permissionMode!==void 0&&t.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-all for codex`);if(t.startupTimeoutMs!==void 0&&(typeof t.startupTimeoutMs!=="number"||!Number.isSafeInteger(t.startupTimeoutMs)||t.startupTimeoutMs<1||t.startupTimeoutMs>600000))throw Error(`Agent "${e}" config.harness.startupTimeoutMs must be an integer from 1 to 600000`);if(t.webSearch!==void 0&&typeof t.webSearch!=="boolean")throw Error(`Agent "${e}" config.harness.webSearch must be a boolean`);if(t.type!=="codex"&&t.webSearch!==void 0)throw Error(`Agent "${e}" config.harness.webSearch is only supported by codex`);if(t.type==="pi"&&t.startupTimeoutMs!==void 0)throw Error(`Agent "${e}" config.harness.startupTimeoutMs is not supported by pi`);if(hn(e,t.activeTools,"activeTools"),hn(e,t.inactiveTools,"inactiveTools"),t.activeTools!==void 0&&t.inactiveTools!==void 0)throw Error(`Agent "${e}" config.harness must use either activeTools or inactiveTools, not both`);hr(e,t.debug)}function hr(e,n){if(n===void 0)return;if(typeof n!=="object"||n===null||Array.isArray(n))throw Error(`Agent "${e}" config.harness.debug must be an object`);let t=n;for(let o of Object.keys(t))if(!gr.has(o))throw Error(`Agent "${e}" config.harness.debug has unknown option "${o}"`);if(t.enabled!==void 0&&typeof t.enabled!=="boolean")throw Error(`Agent "${e}" config.harness.debug.enabled must be a boolean`);if(t.level!==void 0&&t.level!=="error"&&t.level!=="warn"&&t.level!=="info"&&t.level!=="debug"&&t.level!=="trace")throw Error(`Agent "${e}" config.harness.debug.level must be error, warn, info, debug, or trace`);hn(e,t.subsystems,"debug.subsystems")}function hn(e,n,t){if(n!==void 0&&(!Array.isArray(n)||!n.every((o)=>typeof o==="string"&&o.trim().length>0)))throw Error(`Agent "${e}" config.harness.${t} must be an array of non-empty strings`)}function wr(e){if(new Set(e.config.skills?.allowed?.map((t)=>g(t)?t.name:t)).size<=gn)return;throw Error(`Agent "${e.name}" config.skills.allowed must list at most ${gn} skills`)}function br(e,n,t){let o={...e.config};fr(e.name,o.provider),mr(e.name,o.harness);let r=Array.isArray(o.sandboxes)?o.sandboxes.map((i)=>g(i)?i.name:i):void 0;if(r)o.sandboxes=r;r?.forEach((i,a)=>{if(r.indexOf(i)===a)return;throw Error(`Agent "${e.name}" sandboxes[${a}] "${String(i)}" is listed more than once`)}),wr(e);let s=yr(e.name,o.hooks);if(s)o.hooks=s.agentHooksConfig;else if(o.hooks!==void 0)o.hooks=Et(o.hooks,e.name);if(o.connections!==void 0){if(!Array.isArray(o.connections))throw Error(`Agent "${e.name}" config.connections must be an array of connection definitions`);o.channels=Object.fromEntries(o.connections.map((i)=>{if(!R(i))throw Error(`Agent "${e.name}" config.connections must contain connection definitions`);let a=`${e.name}${vt(i.type)}Channel`,c=yt(i,t);return[i.type,{id:a,...i.config,...i.partition?{partition:i.partition}:{},allowedChannelIds:c}]})),delete o.connections}if(Array.isArray(o.workspaces)){let i=o.workspaces.map((a)=>xr(a,e.name));for(let a of i){let c=r?.indexOf(a.sandbox)??-1;if(c>=1)throw Error(`Agent "${e.name}" sandboxes[${c}] "${String(a.sandbox)}" also backs workspace "${String(a.name)}"; only the first sandbox can back a workspace`)}o.workspaces=i}if(o.harness&&!r?.length)throw Error(`Agent "${e.name}" runs a harness, so it needs sandboxes; the first runs the harness`);if(o.policies!==void 0){let i=Er(o.policies,e.name);if(i)o.policies=i;else delete o.policies}return{config:ne(o),...s?.hookResource?{hookResource:s.hookResource}:{}}}function yr(e,n){if(n===void 0)return;if(!n||typeof n!=="object"||Array.isArray(n))throw Error(`Agent "${e}" config.hooks must be an object`);let t=n,o=Object.keys(fn).flatMap((d)=>{let l=t[d];if(l===void 0)return[];if(typeof l!=="function")throw Error(`Agent "${e}" config.hooks.${d} must be a function`);return[{name:d,event:fn[d],source:vr(l.toString())}]});if(o.length===0)return;let r=`${e}-hooks`,s=kr(e,o),i=Buffer.byteLength(s);if(i>Ve)throw Error(`Agent "${e}" hook bundle is too large (${i} bytes, max ${Ve})`);let a=o.map((d)=>d.event),c=Et(t,e);return c.code=[{hookId:r}],{agentHooksConfig:c,hookResource:{kind:"hook",name:r,description:`Inline hooks for agent ${e}`,config:{events:a,bundle:s,sha256:_e(s)}}}}function Et(e,n){if(!e||typeof e!=="object"||Array.isArray(e))throw Error(`Agent "${n}" config.hooks must be an object`);let t=Object.entries(e);for(let[r]of t){if(r==="webhooks"||r in fn)continue;throw Error(`Agent "${n}" config.hooks.${r} is not supported. Use inline hook callbacks or hooks.webhooks.`)}return Object.fromEntries(t.filter(([r])=>r==="webhooks"))}function vr(e){let n=e.trim();if(/^(async\s+)?function\b/.test(n)||/^(async\s*)?\(/.test(n)||/^(async\s+)?[A-Za-z_$][\w$]*\s*=>/.test(n))return n;if(/^(async\s+)?[A-Za-z_$][\w$]*\s*\(/.test(n))return n.replace(/^(async\s+)?/,"$1function ");return n}function kr(e,n){let t=`export default {
|
|
43
43
|
${n.map((o)=>` ${JSON.stringify(o.event)}: ${o.source},`).join(`
|
|
44
44
|
`)}
|
|
45
45
|
};
|
|
46
|
-
`;try{return
|
|
46
|
+
`;try{return ft(t,{loader:"ts"}).code}catch(o){let r=o instanceof Error?o.message:String(o);throw Error(`Agent "${e}" inline hooks failed to transpile: ${r}`)}}function Er(e,n){if(!Array.isArray(e))throw Error(`Agent "${n}" config.policies must be an array`);let t=e.map((o)=>{if(g(o)&&o.kind==="policy")return o.name;if(typeof o==="string")return o;throw Error(`Agent "${n}" config.policies must contain definePolicy(...) resources or strings`)});return t.length>0?t:void 0}async function dt(e,n){let t=await Po(He(Io(),"broods-mcp-"));try{let o=He(t,"server.mjs");await jo(o,n,"utf8");let r;try{r=await import(gt(o).href)}catch(a){throw Error(`MCP server bundle ${e} failed to import: ${a instanceof Error?a.message:String(a)}`)}let s=r.default;if(!(typeof s==="function"||typeof s==="object"&&s!==null&&typeof s.fetch==="function"))throw Error(`MCP server bundle ${e} default export must be a fetch handler (createMcpHandler)`)}finally{await _o(t,{recursive:!0,force:!0})}}async function Sr(e){let n=await No({stdin:e.stdin,absWorkingDir:e.stdin.resolveDir,bundle:!0,...e.workers?{platform:"browser",conditions:["workerd","worker","browser"]}:{platform:"node"},format:"esm",minify:!1,write:!1,logLevel:"silent",plugins:e.plugins??[]}).catch((t)=>{let o=Ir(t)?t.errors.map((r)=>r.text).filter(Boolean).join("; "):t instanceof Error?t.message:String(t);throw Error(`${e.label} ${e.manifestPath} failed to build${o?`: ${o}`:""}`)});if(n.outputFiles.length!==1)throw Error(`${e.label} ${e.manifestPath} failed to build: expected one output file`);return n.outputFiles[0].text}async function $r(e,n){let t=Pr(n,e.path,"Skill"),o=Re(n,t).split("\\").join("/"),r=await _r(t);if(!r.some((s)=>s.path==="SKILL.md"))throw Error(`Skill folder ${e.path} must contain SKILL.md`);return{source:"files",path:o,files:r}}async function Cr(e,n,t){let{handler:o,...r}=n,s=[o,n.url,n.sandbox].filter((p)=>p!==void 0).length;if(s>1)throw Error(`MCP server "${e.resource.name}" declares more than one of url, handler and sandbox; pick one`);if(o===void 0){if(s===0)throw Error(`MCP server "${e.resource.name}" needs url (external), handler (hosted) or sandbox (on a machine)`);return ne(r)}let i=Re(t,e.file).split("\\").join("/");jr(i,"MCP server");let a=(p)=>Sr({stdin:{contents:Rr(e),resolveDir:t,sourcefile:"mcp-handler.mjs",loader:"js"},label:"MCP server bundle",manifestPath:i,plugins:[Or()],workers:p}),c=n.runtime==="lambda"?void 0:await a(!0).catch(()=>{return}),d=c!==void 0&&Buffer.byteLength(c)<=wn&&et(c)&&await dt(i,c).then(()=>!0,()=>!1)?c:await a(!1),l=Buffer.byteLength(d);if(l>ot)throw Error(`MCP server bundle ${i} is too large (${l} bytes, max ${ot})`);return await dt(i,d),{...ne(r),bundle:d,sha256:_e(d)}}function Rr(e){return`import * as __exports from ${JSON.stringify(e.file)};
|
|
47
47
|
const __mcp = __exports[${JSON.stringify(e.exportName)}];
|
|
48
48
|
export default __mcp?.config?.handler ?? __mcp?.handler;
|
|
49
|
-
`}function
|
|
50
|
-
`),c=o?r.map((d)=>{let l=encodeURIComponent(o.accountId),p=o.stageKind===void 0||o.stageKind==="production"?`/v1/webhooks/${l}/${encodeURIComponent(d.type)}`:`/v1/webhooks/${l}/dev/${encodeURIComponent(o.endpointId)}/${encodeURIComponent(d.type)}`;return` ${
|
|
49
|
+
`}function Or(){return{name:"broods-sdk-stub",setup:function(e){e.onResolve({filter:/^broods(\/.*)?$/},()=>({path:"broods",namespace:"broods-stub"})),e.onLoad({filter:/.*/,namespace:"broods-stub"},()=>({contents:Mo,loader:"js"}))}}}function Ar(e,n){if(e.kind!=="agent")return e;let t=e.config.mcp;if(!t)return e;let o=Object.entries(t).map(([r,s])=>{let i=n.get(r),a=new Set(Object.keys(s.headers??{}).map((p)=>p.toLowerCase())),c=Object.entries(i?.headers??{}).filter(([p])=>!a.has(p.toLowerCase())),{tokenUrl:d,...l}=i?.oauth??{};return[r,{...s,...c.length>0?{headers:{...Object.fromEntries(c),...s.headers}}:{},...i?.oauth?{oauth:{...l,...s.oauth}}:{}}]});return{...e,config:{...e.config,mcp:Object.fromEntries(o)}}}function xr(e,n){if(g(e))return{name:e.name,workspaceId:e.name};if(e&&typeof e==="object"&&"workspace"in e){let t=e.workspace,o=g(t)?t.name:t;if(typeof o!=="string")throw Error(`Agent ${n} workspace ref must be a defineWorkspace(...) resource or its name`);let r={name:o,workspaceId:o};if("sandbox"in e){let s=e.sandbox;r.sandbox=s===null?null:g(s)?s.name:s}return r}throw Error(`Agent ${n} workspaces must be defineWorkspace(...) resources or { workspace, sandbox } refs`)}function Pr(e,n,t){if(n.trim().length===0)throw Error(`${t} path is required`);if(n.includes("\x00"))throw Error(`${t} path must not contain null bytes`);let o=Ye(e),r=Ye(o,n),s=Re(o,r);if(s===""||!s.startsWith("..")&&!Uo(s))return r;throw Error(`${t} path ${n} must stay inside ${S}/`)}function Tr(e,n){let t={...n},o=t.connection;if(!R(o))throw Error(`Channel "${e}" config.connection must be a connection definition`);return delete t.connection,t.platform=o.type,ht(t.partition,`Channel "${e}"`),ne(t)}function ne(e){if(Array.isArray(e))return e.map((n)=>ne(n));if(g(e))return e.name;if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).map(([n,t])=>[n,ne(t)]));return e}async function _r(e){let n=[],t=0;async function o(r){let s=await pt(r,{withFileTypes:!0});for(let i of s){let a=He(r,i.name),c=Re(e,a).split("\\").join("/");if(i.isDirectory()){if(ut(i.name))continue;await o(a)}else if(i.isFile()){if(ut(i.name)||St(c))continue;let d=await To(a);if(d.byteLength>Ve)throw Error(`Skill bundle file ${c} is too large (${d.byteLength} bytes, max ${Ve})`);if(t+=d.byteLength,t>rt)throw Error(`Skill bundle at ${e} is too large (${t} bytes, max ${rt})`);if(n.length>=st)throw Error(`Skill bundle at ${e} has too many files (max ${st})`);n.push({path:c,size:d.byteLength,sha256:_e(d),contentBase64:d.toString("base64"),contentType:Dr(c)})}}}return await o(e),n.sort((r,s)=>String(r.path).localeCompare(String(s.path)))}function ut(e){return e.startsWith(".")||Bo.has(e)}function jr(e,n){if(St(e))throw Error(`${n} bundle path ${e} looks like a hidden file or secret and will not be bundled`)}function Ir(e){return e instanceof Error&&Array.isArray(e.errors)}function St(e){return e.split("/").some((t)=>t.startsWith(".")||Go.some((o)=>o.test(t)))}function _e(e){return Oo("sha256").update(e).digest("hex")}function Dr(e){if(e.endsWith(".md"))return"text/markdown; charset=utf-8";if(e.endsWith(".json"))return"application/json";if(e.endsWith(".js")||e.endsWith(".mjs"))return"application/javascript";if(e.endsWith(".ts"))return"text/typescript; charset=utf-8";if(e.endsWith(".txt"))return"text/plain; charset=utf-8";return"application/octet-stream"}function Ur(e){return e.replace(/^@/,"").replace(/\//g,"-").replace(/[^A-Za-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")}import{mkdir as Nr,writeFile as ze}from"node:fs/promises";import{resolve as je}from"node:path";async function Je(e,n,t=process.cwd(),o={},r=null,s=[]){let i=je(t,S,w),a=Lr(n,e);await Nr(i,{recursive:!0}),await ze(je(i,"ids.ts"),Gr(a),"utf8"),await ze(je(i,"api.ts"),Mr(e,a,o,r,s),"utf8"),await ze(je(i,"resources.ts"),Wr(e),"utf8"),await ze(je(i,"dataModel.ts"),Br(),"utf8")}function Lr(e,n){let t={agents:pe(n,"agent"),workspaces:pe(n,"workspace"),sandboxes:pe(n,"sandbox"),crons:pe(n,"cron"),skills:pe(n,"skill"),mcp:pe(n,"mcp"),policies:pe(n,"policy"),channelRecords:pe(n,"channelRecord")};return{agents:fe(e.agents,t.agents),workspaces:fe(e.workspaces,t.workspaces),sandboxes:fe(e.sandboxes,t.sandboxes),crons:fe(e.crons,t.crons),skills:fe(e.skills,t.skills),hooks:{},mcp:fe(e.mcp,t.mcp),policies:fe(e.policies,t.policies),channelRecords:fe(e.channelRecords,t.channelRecords)}}function pe(e,n){return new Set(e.resources.filter((t)=>t.kind===n).map((t)=>t.name))}function fe(e,n){return Object.fromEntries(Object.entries(e??{}).filter(([t])=>n.has(t)))}function Mr(e,n,t,o,r){let s=Object.keys(n.agents),i=o?`, endpointId: ${JSON.stringify(o.endpointId)}, projectSlug: ${JSON.stringify(o.projectSlug)}, stageSlug: ${JSON.stringify(o.stageSlug)}`:"",a=s.map((d)=>` ${bn(t.agent?.[d]??d)}: { kind: "agent", name: ${JSON.stringify(d)}, id: ids.agents[${JSON.stringify(d)}], project: ${JSON.stringify(e.project)}, stage: ${JSON.stringify(e.stage)}${i} },`).join(`
|
|
50
|
+
`),c=o?r.map((d)=>{let l=encodeURIComponent(o.accountId),p=o.stageKind===void 0||o.stageKind==="production"?`/v1/webhooks/${l}/${encodeURIComponent(d.type)}`:`/v1/webhooks/${l}/dev/${encodeURIComponent(o.endpointId)}/${encodeURIComponent(d.type)}`;return` ${bn(d.alias)}: { kind: "channel", type: ${JSON.stringify(d.type)}, agentName: ${JSON.stringify(d.agentName)}, agentId: ids.agents[${JSON.stringify(d.agentName)}], accountId: ${JSON.stringify(o.accountId)}, webhookPath: ${JSON.stringify(p)} },`}).join(`
|
|
51
51
|
`):"";return`// Generated by broods. Do not edit by hand.
|
|
52
52
|
import type { ResourceApi } from "broods";
|
|
53
53
|
import { ids } from "./ids";
|
|
@@ -60,15 +60,15 @@ ${a}
|
|
|
60
60
|
channels: {
|
|
61
61
|
${c}
|
|
62
62
|
},
|
|
63
|
-
workspaces: ${
|
|
64
|
-
sandboxes: ${
|
|
65
|
-
crons: ${
|
|
66
|
-
skills: ${
|
|
67
|
-
policies: ${
|
|
63
|
+
workspaces: ${Ie("workspaces",n.workspaces,t.workspace)},
|
|
64
|
+
sandboxes: ${Ie("sandboxes",n.sandboxes,t.sandbox)},
|
|
65
|
+
crons: ${Ie("crons",n.crons,t.cron)},
|
|
66
|
+
skills: ${Ie("skills",n.skills,t.skill)},
|
|
67
|
+
policies: ${Ie("policies",n.policies,t.policy)},
|
|
68
68
|
} as const satisfies ResourceApi;
|
|
69
|
-
`}function
|
|
69
|
+
`}function Br(){return`// Generated by broods. Do not edit by hand.
|
|
70
70
|
export type { AgentReference, ChannelReference, AgentRunInput, AgentRunResult, ResourceApi } from "broods";
|
|
71
|
-
`}function
|
|
71
|
+
`}function Gr(e){return`// Generated by broods. Do not edit by hand.
|
|
72
72
|
export const ids = ${JSON.stringify(e,null,2)} as const;
|
|
73
73
|
export const agents = ids.agents;
|
|
74
74
|
export const workspaces = ids.workspaces;
|
|
@@ -76,19 +76,19 @@ export const sandboxes = ids.sandboxes;
|
|
|
76
76
|
export const crons = ids.crons;
|
|
77
77
|
export const skills = ids.skills;
|
|
78
78
|
export const policies = ids.policies;
|
|
79
|
-
`}function
|
|
79
|
+
`}function Wr(e){return`// Generated by broods. Do not edit by hand.
|
|
80
80
|
export const manifest = ${JSON.stringify(e,null,2)} as const;
|
|
81
|
-
`}function
|
|
82
|
-
${o.map((s)=>` ${
|
|
81
|
+
`}function Ie(e,n,t){let o=Object.keys(n);if(o.length===0)return"{}";return`{
|
|
82
|
+
${o.map((s)=>` ${bn(t?.[s]??s)}: ids.${e}[${JSON.stringify(s)}],`).join(`
|
|
83
83
|
`)}
|
|
84
|
-
}`}function fn(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}var Mr=1,Br=0,kt=60000,Et=15000;function se(e,n){return new Promise((t)=>{if(n?.aborted)return t();let o=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(o),t()},{once:!0})})}function fe(){let e=globalThis.WebSocket;if(!e)throw Error("WebSocket is not available in this environment.");return e}class D extends Error{}async function*Ve(e,n={}){let t=new Set,o=500,r=0,s=Date.now();while(!n.signal?.aborted){let i=!1,a="the log stream closed";try{for await(let c of Gr(e,n,()=>{i=!0})){let d=`${c.ts}|${c.eventType}|${c.message}`;if(t.has(d))continue;if(t.add(d),t.size>5000)t.delete(t.values().next().value);yield c}}catch(c){if(n.signal?.aborted)return;if(a=c instanceof Error?c.message:String(c),c instanceof D||/unauthorized|invalid websocket token|scope does not match/i.test(a))throw c}if(n.signal?.aborted)return;if(i)o=500,r=0,s=Date.now();if(!n.keepReconnecting&&Date.now()-s>=kt)throw Error(`Gave up reconnecting to the live logs after ${kt/1000} s. Last error: ${a}`);r+=1,n.onReconnect?.(r,a),await se(o,n.signal),o=Math.min(o*2,5000)}}async function*Gr(e,n,t){let{baseUrl:o,credential:r,project:s,stage:i}=e,{backfill:a=0,minLevel:c,sandboxId:d,signal:l}=n,p=n.liveOnly??a<=0;if(l?.aborted)return;let u=Wr(o,s,i),S=u,C=fe(),k=[],A=null,V=!1,re=null,pe=()=>{re?.(),re=null},ce=new C(u,E(await r())),Hn=setTimeout(()=>{A=Error(`The observability gateway did not answer within ${Et/1000} s.`),V=!0,pe()},Et),an=()=>{if(clearTimeout(Hn),ce.readyState===Mr||ce.readyState===Br)ce.close(1000,"client closed");l?.removeEventListener("abort",Vn)},Vn=()=>{V=!0,pe(),an()};l?.addEventListener("abort",Vn,{once:!0}),ce.onopen=()=>{if(l?.aborted){an();return}let X={type:"subscribe",stream:"logs",...a>0?{backfill:a}:{},...p?{liveOnly:!0}:{},...c!==void 0?{minLevel:c}:{},...d!==void 0?{sandboxId:d}:{}};ce.send(JSON.stringify(X))},ce.onmessage=(X)=>{let me=Fr(X.data);if(!me)return;if(clearTimeout(Hn),me.type!=="error")t();switch(me.type){case"backfill":if(me.stream==="logs"){for(let ho of me.entries)k.push(ho);pe()}break;case"log":k.push(me.entry),pe();break;case"error":A=Error(`Observability gateway error: ${me.error}`),V=!0,pe();break;case"ready":break;default:break}},ce.onerror=()=>{A=Error(`Cannot connect to the observability gateway at ${S}.`),V=!0,pe()},ce.onclose=(X)=>{if(!V){if(X.code!==1000)A=Error(X.reason?`Observability WebSocket closed: ${X.reason}`:`Observability WebSocket closed with code ${X.code}.`);V=!0,pe()}};try{while(!0){if(k.length>0){yield k.shift();continue}if(A)throw A;if(V)return;await new Promise((X)=>{re=X})}}finally{an()}}function Wr(e,n,t){return`${Y(e)}/v1/projects/${encodeURIComponent(n)}/stages/${encodeURIComponent(t)}/observability/ws`}function Fr(e){if(typeof e!=="string")return null;try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}var Kr=new Set(["bundle","bundleStorageId","contentBase64"]),Hr=new Set(["hook","mcp","skill"]),Vr=30000;class ze extends Error{}class Je extends Error{}class N{baseUrl;token;fetchImpl;constructor(e){this.baseUrl=f(e.baseUrl),this.token=e.token,this.fetchImpl=e.fetch??fetch}async getManifest(e,n){let t=await this.request(e,n,"/manifest",{method:"GET"});if(t.status===404)return null;return await U(t,"Fetch manifest failed"),await t.json()}async putManifest(e,n,t=!1,o){let r=await this.externalizeLargeMcpBundles(e),s=await this.request(e.project,e.stage,"/manifest",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({manifest:r,prune:n,rotateRuntimeKey:t,...o!==void 0?{revision:o}:{}})},null);return await U(s,"Sync manifest failed"),await s.json()}async externalizeLargeMcpBundles(e){if(e.resources.every((t)=>Ct(t)===null))return e;let n=await Promise.all(e.resources.map(async(t)=>{let o=Ct(t);if(o===null)return t;let{bundle:r,...s}=t.config,i=await this.uploadMcpBundle(e.project,e.stage,o);return{...t,config:{...s,bundleStorageId:i,sha256:xe(o)}}}));return{...e,resources:n}}async uploadMcpBundle(e,n,t){let o=await this.request(e,n,"/mcp-bundle-uploads",{method:"POST"});await U(o,"Mint bundle upload URL failed");let{uploadUrl:r}=await o.json();if(!r)throw Error("Mint bundle upload URL failed: response omitted uploadUrl");let s=await this.send(r,{method:"POST",headers:{"Content-Type":"application/javascript"},body:t},null);await U(s,"Bundle upload failed");let{storageId:i}=await s.json();if(!i)throw Error("Bundle upload failed: response omitted storageId");return i}async getRuntimeKey(e,n){let t=await this.request(e,n,"/runtime-key",{method:"GET"});if(t.status===404)return null;await U(t,"Fetch runtime key failed");let o=await t.json();if(!o.apiKey)throw Error("Fetch runtime key failed: response omitted apiKey");return{apiKey:o.apiKey,keyHint:o.keyHint??"",...o.endpointId?{endpointId:o.endpointId}:{},...o.projectSlug?{projectSlug:o.projectSlug}:{},...o.stageSlug?{stageSlug:o.stageSlug}:{}}}async setEnv(e,n,t,o){let r=await this.request(e,n,`/env/${encodeURIComponent(t)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({value:o})});await U(r,"Set environment variable failed")}async listEnv(e,n){let t=await this.request(e,n,"/env",{method:"GET"});return await U(t,"List environment variables failed"),(await t.json()).variables??[]}async getEnv(e,n,t){let o=await this.request(e,n,`/env/${encodeURIComponent(t)}`,{method:"GET"});if(o.status===404)return null;return await U(o,"Read environment variable failed"),(await o.json()).value??null}async removeEnv(e,n,t){let o=await this.request(e,n,`/env/${encodeURIComponent(t)}`,{method:"DELETE"});await U(o,"Remove environment variable failed")}async getOnboarding(){let e=await this.send(`${this.baseUrl}/v1/account/onboarding`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`}});return Ee(e,"/v1/account/onboarding","broods org"),await U(e,"Fetch CLI onboarding context failed"),await e.json()}async selectOnboardingOrg(e){let n=await this.send(`${this.baseUrl}/v1/account/onboarding`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({orgId:e})});return await U(n,"Select CLI org failed"),await n.json()}async listStages(e){let n=await this.send(`${this.baseUrl}/v1/account/stages?project=${encodeURIComponent(e)}`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`}});return Ee(n,"/v1/account/stages","broods stage"),await U(n,"List stages failed"),(await n.json()).stages??[]}async createStage(e,n,t){let o=await this.send(`${this.baseUrl}/v1/account/stages`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({project:e,name:n,...t?{from:t}:{}})});return Ee(o,"/v1/account/stages","broods stage"),await U(o,"Create stage failed"),await o.json()}async mintStageSession(e,n){let t=await this.send(`${this.baseUrl}/v1/account/stage-session`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({project:e,stage:n})});Ee(t,"/v1/account/stage-session","broods logs");try{await U(t,"Open stage session failed")}catch(o){if(t.status===401||t.status===404)throw new D(o instanceof Error?o.message:String(o));throw o}return await t.json()}async listProjects(){let e=await this.send(`${this.baseUrl}/v1/account/projects`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`}});return Ee(e,"/v1/account/projects","broods project"),await U(e,"List projects failed"),(await e.json()).projects??[]}async deleteProject(e){let n=await this.send(`${this.baseUrl}/v1/account/projects?projectId=${encodeURIComponent(e)}`,{method:"DELETE",headers:{Authorization:`Bearer ${this.token}`}});if(Ee(n,"/v1/account/projects","broods project"),n.status===404)return null;return await U(n,"Delete project failed"),(await n.json()).deleted??null}async createOnboardingOrg(e){let n=await this.send(`${this.baseUrl}/v1/account/onboarding`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({createOrgName:e})});return await U(n,"Create CLI org failed"),await n.json()}async request(e,n,t,o,r){let s=`${this.baseUrl}/v1/account/projects/${encodeURIComponent(e)}/stages/${encodeURIComponent(n)}${t}`;return await this.send(s,{...o,headers:{Authorization:`Bearer ${this.token}`,...o.headers}},r)}async send(e,n,t){return await qe(e,n,{fetch:this.fetchImpl,timeoutMs:t})}}async function qe(e,n,t={}){let o=t.fetch??fetch,r=t.timeoutMs===void 0?Vr:t.timeoutMs;try{return await o(e,r===null?n:{...n,signal:AbortSignal.timeout(r)})}catch(s){throw Error(`Cannot reach ${new URL(e).origin}: ${Jr(s,r)}`,{cause:s})}}function yn(e,n){let t=new Map((n?.resources??[]).map((d)=>[`${d.kind}:${d.name}`,d])),o=new Map(e.resources.map((d)=>[`${d.kind}:${d.name}`,d])),r=[],s=[],i=[];for(let[d,l]of o){let p=t.get(d);if(!p)s.push({key:d,resource:l});else if(Ye(hn(p))!==Ye(hn(l)))r.push({operation:"update",kind:l.kind,name:l.name})}for(let[d,l]of t)if(!o.has(d))i.push({key:d,resource:l});let a=new Set,c=new Set;for(let d of s){let l=i.find((p)=>!a.has(p.key)&&Yr(d.resource.kind)&&d.resource.kind===p.resource.kind&&Ye($t(d.resource))===Ye($t(p.resource)));if(!l)continue;c.add(d.key),a.add(l.key),r.push({operation:"rename",kind:d.resource.kind,name:d.resource.name,previousName:l.resource.name})}for(let{key:d,resource:l}of s)if(!c.has(d))r.push({operation:"create",kind:l.kind,name:l.name});for(let{key:d,resource:l}of i)if(!a.has(d))r.push({operation:"delete",kind:l.kind,name:l.name});return r.sort((d,l)=>St(d).localeCompare(St(l)))}function St(e){return`${{create:0,rename:1,update:2,delete:3}[e.operation]}:${e.kind}:${e.previousName??""}:${e.name}`}function Yr(e){return e==="agent"||e==="workspace"||e==="sandbox"||e==="policy"}function mn(e){if(Array.isArray(e))return e.map(mn);if(e&&typeof e==="object"){let n=e;if(n.__beeblastEnv===!0&&typeof n.name==="string")return`\${${n.name}}`;return Object.fromEntries(Object.entries(n).map(([t,o])=>[t,mn(o)]))}return e}function $t(e){let n=hn(e),{name:t,...o}=n;return o}function hn(e){let n=mn(e);if(!Hr.has(e.kind))return n;return{...n,config:bn(n.config)}}function wn(e){if(Array.isArray(e))return e.map(wn);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).sort(([n],[t])=>n.localeCompare(t)).map(([n,t])=>[n,wn(t)]));return e}function Ye(e){return JSON.stringify(wn(e))}function bn(e){if(Array.isArray(e))return e.map(bn);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).flatMap(([n,t])=>{if(Kr.has(n))return[];return[[n,bn(t)]]}));return e}async function U(e,n){if(e.ok)return;let t=await e.text(),{message:o=t,code:r}=zr(t);if(r==="manifest_conflict")throw new ze(o);let s=e.status===401?"\nRun `broods login` to sign in again.":"";throw Error(`${n}: ${e.status} ${o}${s}`)}function zr(e){let n;try{n=JSON.parse(e)}catch{return{}}let t=typeof n==="object"&&n!==null&&"error"in n?n.error:void 0;if(typeof t!=="object"||t===null)return{};return{..."message"in t&&typeof t.message==="string"?{message:t.message}:{},..."code"in t&&typeof t.code==="string"?{code:t.code}:{}}}function Ee(e,n,t){if(e.status!==404)return;if((e.headers.get("Content-Type")??"").includes("application/json"))return;throw new Je(`This broods server is older than your CLI and does not support \`${t}\` yet (no ${n} route).`)}function Jr(e,n){if(!(e instanceof Error))return String(e);if(e.name==="TimeoutError"&&n!==null)return`no answer within ${n/1000} s`;let t=e.cause;if(!(t instanceof Error))return e.message;if(t.message)return t.message;return"code"in t&&typeof t.code==="string"?t.code:e.message}function Ct(e){if(e.kind!=="mcp")return null;let n=e.config?.bundle;if(typeof n!=="string")return null;return Buffer.byteLength(n)>pn?n:null}var Ze=["chatgpt"];var he={chatgpt:{label:"ChatGPT plan",description:"Run agents on model.provider chatgpt with your ChatGPT plan",authorizeUrl:"https://auth.openai.com/api/accounts/authorize",tokenUrl:"https://auth.openai.com/api/accounts/oauth/token",revokeUrl:"https://auth.openai.com/api/accounts/oauth/revoke",jwksUrl:"https://auth.openai.com/.well-known/jwks.json",issuer:"https://auth.openai.com",scopes:["openid","profile","email","offline_access","resource.invoke","chatgpt.tokens.use.direct"],resource:"https://api.openai.com/v1",requiredScope:"chatgpt.tokens.use.direct",selfHostedOnly:"ChatGPT plan usage is only available on self-hosted Broods for now. Use an OpenAI API key with the `openai` provider instead.",managedOptIn:"CHATGPT_PLAN_ENABLED",modelsUrl:"https://api.openai.com/v1/models",usageUrl:"https://chatgpt.com/settings/usage"}};function vn(e){return Ze.some((n)=>n===e)}import{createHash as hs,randomBytes as ws,randomUUID as Ut}from"node:crypto";import{createServer as rs}from"node:http";import{createHash as ss,randomBytes as is,randomUUID as as}from"node:crypto";import{spawn as cs}from"node:child_process";import{createInterface as Ie}from"node:readline/promises";import{stdin as ne,stdout as ee}from"node:process";import{Writable as ls}from"node:stream";function Se(e,n,t={}){let o=`${n?"*":" "} ${e}`;return n?j(o,"\x1B[1m\x1B[36m",J(t)):o}function Rt(e,n={}){let t=J(n),o=(i)=>j(i.padEnd(9),"\x1B[2m",t),r=!e.loggedIn?j("not logged in","\x1B[33m",t):e.org??j("unknown, run broods whoami","\x1B[2m",t),s=e.project??`none ${j(`(${e.projectGuess} from folder name)`,"\x1B[2m",t)}`;return[` ${o("org")}${r}`,` ${o("project")}${s}`,` ${o("stage")}${Tt(e.stage,t)}`,` ${o("server")}${e.server}`]}function qr(e,n={}){let t=J(n),o=jt(e.stage),r=o==="Development",s=j("▌",r?"\x1B[32m":"\x1B[33m",t),i=t?`${r?"\x1B[42m\x1B[30m\x1B[1m":"\x1B[43m\x1B[30m\x1B[1m"} ${o} \x1B[0m`:`[${o}]`,a=t?j("dashboard","\x1B[4m",t):"dashboard",c=`${e.dashboardUrl}?project=${encodeURIComponent(e.project)}&stage=${encodeURIComponent(e.stage)}`,d=j(c,"\x1B[2m\x1B[4m",t);return[`${s} Syncing ${o}: ${j(e.project,"",t)}`,`${s} ${i} ${e.stage} (${a})`,`${s} ${j("└─","\x1B[2m",t)} ${d}`].join(`
|
|
85
|
-
`)}function
|
|
84
|
+
}`}function bn(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}function $t(e,n){return`${e}…${n.slice(-4)}`}var Fr=1,Kr=0,Ct=60000,Rt=15000;function le(e,n){return new Promise((t)=>{if(n?.aborted)return t();let o=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(o),t()},{once:!0})})}function ve(){let e=globalThis.WebSocket;if(!e)throw Error("WebSocket is not available in this environment.");return e}class L extends Error{}async function*qe(e,n={}){let t=new Set,o=500,r=0,s=Date.now();while(!n.signal?.aborted){let i=!1,a="the log stream closed";try{for await(let c of Hr(e,n,()=>{i=!0})){let d=`${c.ts}|${c.eventType}|${c.message}`;if(t.has(d))continue;if(t.add(d),t.size>5000)t.delete(t.values().next().value);yield c}}catch(c){if(n.signal?.aborted)return;if(a=c instanceof Error?c.message:String(c),c instanceof L||/unauthorized|invalid websocket token|scope does not match/i.test(a))throw c}if(n.signal?.aborted)return;if(i)o=500,r=0,s=Date.now();if(!n.keepReconnecting&&Date.now()-s>=Ct)throw Error(`Gave up reconnecting to the live logs after ${Ct/1000} s. Last error: ${a}`);r+=1,n.onReconnect?.(r,a),await le(o,n.signal),o=Math.min(o*2,5000)}}async function*Hr(e,n,t){let{baseUrl:o,credential:r,project:s,stage:i}=e,{backfill:a=0,minLevel:c,sandboxId:d,signal:l}=n,p=n.liveOnly??a<=0;if(l?.aborted)return;let u=Yr(o,s,i),k=u,E=ve(),v=[],O=null,V=!1,ae=null,he=()=>{ae?.(),ae=null},ue=new E(u,z(await r())),zn=setTimeout(()=>{O=Error(`The observability gateway did not answer within ${Rt/1000} s.`),V=!0,he()},Rt),un=()=>{if(clearTimeout(zn),ue.readyState===Fr||ue.readyState===Kr)ue.close(1000,"client closed");l?.removeEventListener("abort",Jn)},Jn=()=>{V=!0,he(),un()};l?.addEventListener("abort",Jn,{once:!0}),ue.onopen=()=>{if(l?.aborted){un();return}let ee={type:"subscribe",stream:"logs",...a>0?{backfill:a}:{},...p?{liveOnly:!0}:{},...c!==void 0?{minLevel:c}:{},...d!==void 0?{sandboxId:d}:{}};ue.send(JSON.stringify(ee))},ue.onmessage=(ee)=>{let we=Vr(ee.data);if(!we)return;if(clearTimeout(zn),we.type!=="error")t();switch(we.type){case"backfill":if(we.stream==="logs"){for(let vo of we.entries)v.push(vo);he()}break;case"log":v.push(we.entry),he();break;case"error":O=Error(`Observability gateway error: ${we.error}`),V=!0,he();break;case"ready":break;default:break}},ue.onerror=()=>{O=Error(`Cannot connect to the observability gateway at ${k}.`),V=!0,he()},ue.onclose=(ee)=>{if(!V){if(ee.code!==1000)O=Error(ee.reason?`Observability WebSocket closed: ${ee.reason}`:`Observability WebSocket closed with code ${ee.code}.`);V=!0,he()}};try{while(!0){if(v.length>0){yield v.shift();continue}if(O)throw O;if(V)return;await new Promise((ee)=>{ae=ee})}}finally{un()}}function Yr(e,n,t){return`${te(e)}/v1/projects/${encodeURIComponent(n)}/stages/${encodeURIComponent(t)}/observability/ws`}function Vr(e){if(typeof e!=="string")return null;try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}var zr=new Set(["bundle","bundleStorageId","contentBase64"]),Jr=new Set(["hook","mcp","skill"]),qr=30000;class Xe extends Error{}class Qe extends Error{}class G{baseUrl;token;fetchImpl;constructor(e){this.baseUrl=h(e.baseUrl),this.token=e.token,this.fetchImpl=e.fetch??fetch}async getManifest(e,n){let t=await this.request(e,n,"/manifest",{method:"GET"});if(t.status===404)return null;return await D(t,"Fetch manifest failed"),await t.json()}async putManifest(e,n,t=!1,o){let r=await this.externalizeLargeMcpBundles(e),s=await this.request(e.project,e.stage,"/manifest",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({manifest:r,prune:n,rotateRuntimeKey:t,...o!==void 0?{revision:o}:{}})},null);return await D(s,"Sync manifest failed"),await s.json()}async externalizeLargeMcpBundles(e){if(e.resources.every((t)=>xt(t)===null))return e;let n=await Promise.all(e.resources.map(async(t)=>{let o=xt(t);if(o===null)return t;let{bundle:r,...s}=t.config,i=await this.uploadMcpBundle(e.project,e.stage,o);return{...t,config:{...s,bundleStorageId:i,sha256:_e(o)}}}));return{...e,resources:n}}async uploadMcpBundle(e,n,t){let o=await this.request(e,n,"/mcp-bundle-uploads",{method:"POST"});await D(o,"Mint bundle upload URL failed");let{uploadUrl:r}=await o.json();if(!r)throw Error("Mint bundle upload URL failed: response omitted uploadUrl");let s=await this.send(r,{method:"POST",headers:{"Content-Type":"application/javascript"},body:t},null);await D(s,"Bundle upload failed");let{storageId:i}=await s.json();if(!i)throw Error("Bundle upload failed: response omitted storageId");return i}async getRuntimeKey(e,n){let t=await this.request(e,n,"/runtime-key",{method:"GET"});if(t.status===404)return null;await D(t,"Fetch runtime key failed");let o=await t.json();if(!o.apiKey)throw Error("Fetch runtime key failed: response omitted apiKey");return{apiKey:o.apiKey,keyHint:o.keyHint??"",...o.endpointId?{endpointId:o.endpointId}:{},...o.projectSlug?{projectSlug:o.projectSlug}:{},...o.stageSlug?{stageSlug:o.stageSlug}:{}}}async rotateUserTokenSecret(e,n){let t=await this.request(e,n,"/user-token-secret",{method:"POST"});if(t.status===404)return null;await D(t,"Rotate user token signing secret failed");let o=await t.json();if(!o.secret||!o.hint)throw Error("Rotate user token signing secret failed: response omitted the secret");return{secret:o.secret,hint:o.hint}}async setEnv(e,n,t,o){let r=await this.request(e,n,`/env/${encodeURIComponent(t)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({value:o})});await D(r,"Set environment variable failed")}async listEnv(e,n){let t=await this.request(e,n,"/env",{method:"GET"});return await D(t,"List environment variables failed"),(await t.json()).variables??[]}async getEnv(e,n,t){let o=await this.request(e,n,`/env/${encodeURIComponent(t)}`,{method:"GET"});if(o.status===404)return null;return await D(o,"Read environment variable failed"),(await o.json()).value??null}async removeEnv(e,n,t){let o=await this.request(e,n,`/env/${encodeURIComponent(t)}`,{method:"DELETE"});await D(o,"Remove environment variable failed")}async getOnboarding(){let e=await this.send(`${this.baseUrl}/v1/account/onboarding`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`}});return Oe(e,"/v1/account/onboarding","broods org"),await D(e,"Fetch CLI onboarding context failed"),await e.json()}async selectOnboardingOrg(e){let n=await this.send(`${this.baseUrl}/v1/account/onboarding`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({orgId:e})});return await D(n,"Select CLI org failed"),await n.json()}async listStages(e){let n=await this.send(`${this.baseUrl}/v1/account/stages?project=${encodeURIComponent(e)}`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`}});return Oe(n,"/v1/account/stages","broods stage"),await D(n,"List stages failed"),(await n.json()).stages??[]}async createStage(e,n,t){let o=await this.send(`${this.baseUrl}/v1/account/stages`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({project:e,name:n,...t?{from:t}:{}})});return Oe(o,"/v1/account/stages","broods stage"),await D(o,"Create stage failed"),await o.json()}async mintStageSession(e,n){let t=await this.send(`${this.baseUrl}/v1/account/stage-session`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({project:e,stage:n})});Oe(t,"/v1/account/stage-session","broods logs");try{await D(t,"Open stage session failed")}catch(o){if(t.status===401||t.status===404)throw new L(o instanceof Error?o.message:String(o));throw o}return await t.json()}async listProjects(){let e=await this.send(`${this.baseUrl}/v1/account/projects`,{method:"GET",headers:{Authorization:`Bearer ${this.token}`}});return Oe(e,"/v1/account/projects","broods project"),await D(e,"List projects failed"),(await e.json()).projects??[]}async deleteProject(e){let n=await this.send(`${this.baseUrl}/v1/account/projects?projectId=${encodeURIComponent(e)}`,{method:"DELETE",headers:{Authorization:`Bearer ${this.token}`}});if(Oe(n,"/v1/account/projects","broods project"),n.status===404)return null;return await D(n,"Delete project failed"),(await n.json()).deleted??null}async createOnboardingOrg(e){let n=await this.send(`${this.baseUrl}/v1/account/onboarding`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({createOrgName:e})});return await D(n,"Create CLI org failed"),await n.json()}async request(e,n,t,o,r){let s=`${this.baseUrl}/v1/account/projects/${encodeURIComponent(e)}/stages/${encodeURIComponent(n)}${t}`;return await this.send(s,{...o,headers:{Authorization:`Bearer ${this.token}`,...o.headers}},r)}async send(e,n,t){return await en(e,n,{fetch:this.fetchImpl,timeoutMs:t})}}async function en(e,n,t={}){let o=t.fetch??fetch,r=t.timeoutMs===void 0?qr:t.timeoutMs;try{return await o(e,r===null?n:{...n,signal:AbortSignal.timeout(r)})}catch(s){throw Error(`Cannot reach ${new URL(e).origin}: ${Qr(s,r)}`,{cause:s})}}function Sn(e,n){let t=new Map((n?.resources??[]).map((d)=>[`${d.kind}:${d.name}`,d])),o=new Map(e.resources.map((d)=>[`${d.kind}:${d.name}`,d])),r=[],s=[],i=[];for(let[d,l]of o){let p=t.get(d);if(!p)s.push({key:d,resource:l});else if(Ze(vn(p))!==Ze(vn(l)))r.push({operation:"update",kind:l.kind,name:l.name})}for(let[d,l]of t)if(!o.has(d))i.push({key:d,resource:l});let a=new Set,c=new Set;for(let d of s){let l=i.find((p)=>!a.has(p.key)&&Zr(d.resource.kind)&&d.resource.kind===p.resource.kind&&Ze(At(d.resource))===Ze(At(p.resource)));if(!l)continue;c.add(d.key),a.add(l.key),r.push({operation:"rename",kind:d.resource.kind,name:d.resource.name,previousName:l.resource.name})}for(let{key:d,resource:l}of s)if(!c.has(d))r.push({operation:"create",kind:l.kind,name:l.name});for(let{key:d,resource:l}of i)if(!a.has(d))r.push({operation:"delete",kind:l.kind,name:l.name});return r.sort((d,l)=>Ot(d).localeCompare(Ot(l)))}function Ot(e){return`${{create:0,rename:1,update:2,delete:3}[e.operation]}:${e.kind}:${e.previousName??""}:${e.name}`}function Zr(e){return e==="agent"||e==="workspace"||e==="sandbox"||e==="policy"}function yn(e){if(Array.isArray(e))return e.map(yn);if(e&&typeof e==="object"){let n=e;if(n.__beeblastEnv===!0&&typeof n.name==="string")return`\${${n.name}}`;return Object.fromEntries(Object.entries(n).map(([t,o])=>[t,yn(o)]))}return e}function At(e){let n=vn(e),{name:t,...o}=n;return o}function vn(e){let n=yn(e);if(!Jr.has(e.kind))return n;return{...n,config:En(n.config)}}function kn(e){if(Array.isArray(e))return e.map(kn);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).sort(([n],[t])=>n.localeCompare(t)).map(([n,t])=>[n,kn(t)]));return e}function Ze(e){return JSON.stringify(kn(e))}function En(e){if(Array.isArray(e))return e.map(En);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).flatMap(([n,t])=>{if(zr.has(n))return[];return[[n,En(t)]]}));return e}async function D(e,n){if(e.ok)return;let t=await e.text(),{message:o=t,code:r}=Xr(t);if(r==="manifest_conflict")throw new Xe(o);let s=e.status===401?"\nRun `broods login` to sign in again.":"";throw Error(`${n}: ${e.status} ${o}${s}`)}function Xr(e){let n;try{n=JSON.parse(e)}catch{return{}}let t=typeof n==="object"&&n!==null&&"error"in n?n.error:void 0;if(typeof t!=="object"||t===null)return{};return{..."message"in t&&typeof t.message==="string"?{message:t.message}:{},..."code"in t&&typeof t.code==="string"?{code:t.code}:{}}}function Oe(e,n,t){if(e.status!==404)return;if((e.headers.get("Content-Type")??"").includes("application/json"))return;throw new Qe(`This broods server is older than your CLI and does not support \`${t}\` yet (no ${n} route).`)}function Qr(e,n){if(!(e instanceof Error))return String(e);if(e.name==="TimeoutError"&&n!==null)return`no answer within ${n/1000} s`;let t=e.cause;if(!(t instanceof Error))return e.message;if(t.message)return t.message;return"code"in t&&typeof t.code==="string"?t.code:e.message}function xt(e){if(e.kind!=="mcp")return null;let n=e.config?.bundle;if(typeof n!=="string")return null;return Buffer.byteLength(n)>wn?n:null}var nn=["chatgpt"];var be={chatgpt:{label:"ChatGPT plan",description:"Run agents on model.provider chatgpt with your ChatGPT plan",authorizeUrl:"https://auth.openai.com/api/accounts/authorize",tokenUrl:"https://auth.openai.com/api/accounts/oauth/token",revokeUrl:"https://auth.openai.com/api/accounts/oauth/revoke",jwksUrl:"https://auth.openai.com/.well-known/jwks.json",issuer:"https://auth.openai.com",scopes:["openid","profile","email","offline_access","resource.invoke","chatgpt.tokens.use.direct"],resource:"https://api.openai.com/v1",requiredScope:"chatgpt.tokens.use.direct",selfHostedOnly:"ChatGPT plan usage is only available on self-hosted Broods for now. Use an OpenAI API key with the `openai` provider instead.",managedOptIn:"CHATGPT_PLAN_ENABLED",modelsUrl:"https://api.openai.com/v1/models",usageUrl:"https://chatgpt.com/settings/usage"}};function $n(e){return nn.some((n)=>n===e)}import{createHash as vs,randomBytes as ks,randomUUID as Bt}from"node:crypto";import{createServer as cs}from"node:http";import{createHash as ls,randomBytes as ds,randomUUID as us}from"node:crypto";import{spawn as gs}from"node:child_process";import{createInterface as Ue}from"node:readline/promises";import{stdin as re,stdout as oe}from"node:process";import{Writable as ps}from"node:stream";function Ae(e,n,t={}){let o=`${n?"*":" "} ${e}`;return n?j(o,"\x1B[1m\x1B[36m",q(t)):o}function Pt(e,n={}){let t=q(n),o=(i)=>j(i.padEnd(9),"\x1B[2m",t),r=!e.loggedIn?j("not logged in","\x1B[33m",t):e.org??j("unknown, run broods whoami","\x1B[2m",t),s=e.project??`none ${j(`(${e.projectGuess} from folder name)`,"\x1B[2m",t)}`;return[` ${o("org")}${r}`,` ${o("project")}${s}`,` ${o("stage")}${Dt(e.stage,t)}`,` ${o("server")}${e.server}`]}function es(e,n={}){let t=q(n),o=Ut(e.stage),r=o==="Development",s=j("▌",r?"\x1B[32m":"\x1B[33m",t),i=t?`${r?"\x1B[42m\x1B[30m\x1B[1m":"\x1B[43m\x1B[30m\x1B[1m"} ${o} \x1B[0m`:`[${o}]`,a=t?j("dashboard","\x1B[4m",t):"dashboard",c=`${e.dashboardUrl}?project=${encodeURIComponent(e.project)}&stage=${encodeURIComponent(e.stage)}`,d=j(c,"\x1B[2m\x1B[4m",t);return[`${s} Syncing ${o}: ${j(e.project,"",t)}`,`${s} ${i} ${e.stage} (${a})`,`${s} ${j("└─","\x1B[2m",t)} ${d}`].join(`
|
|
85
|
+
`)}function ns(e,n={}){let t=q(n);return e.map((o)=>{let r=is(o.operation,t);if(o.operation==="rename"&&o.previousName)return` ${r} ${o.kind}:${o.previousName} -> ${o.name}`;return` ${r} ${o.kind}:${o.name}`})}function ts(e,n={}){let t=q(n),o=j("▌","\x1B[32m",t),r=j("↑","\x1B[32m",t);return`${o} ${r} Synced ${e.length} env var(s) from .env.local: ${e.join(", ")}`}function os(e,n={}){return`${j("✖","\x1B[31m",q(n))} ${e}`}function Tt(e,n={}){let t=q(n),o=Math.max(...e.map(([r])=>r.length))+2;return e.map(([r,s])=>` ${r.padEnd(o)}${j(s,"\x1B[2m",t)}`)}function rs(e,n={}){let t=(n.now??new Date).toTimeString().slice(0,8);return`${j("✔","\x1B[32m",q(n))} ${t} Resources ready! (${as(e)})`}function ss(e,n={}){return`${j("✔","\x1B[32m",q(n))} ${e}`}function Cn(e,n,t={}){let o=q(t),r=t.note?` ${j(`(${t.note})`,"\x1B[2m",o)}`:"";return` ${j("now","\x1B[2m",o)} ${e} → ${Dt(n,o)}${r}`}function De(e,n={}){return j(`! ${e}`,"\x1B[33m",q(n))}function _t(e){console.error(es(e))}function tn(e){for(let n of ns(e))console.log(n)}function Rn(e){console.error(ts(e))}function jt(e){console.error(os(e,{stream:"stderr"}))}function It(e){console.error(rs(e))}function H(e){console.log(ss(e,{stream:"stdout"}))}function A(e){console.log(De(e,{stream:"stdout"}))}function is(e,n){if(e==="create")return`[${j("+","\x1B[32m",n)}]`;if(e==="rename")return`[${j("~","\x1B[33m",n)}]`;if(e==="update")return`[${j("*","\x1B[36m",n)}]`;return`[${j("-","\x1B[31m",n)}]`}function as(e){if(e>=1000)return`${(e/1000).toFixed(2)}s`;return`${Math.max(e,0).toFixed(1)}ms`}function j(e,n,t){return t?`${n}${e}\x1B[0m`:e}function Dt(e,n){let t=Ut(e)==="Development";return j(e,t?"\x1B[32m":"\x1B[33m",n)}function q(e){if(e.color!==void 0)return e.color;if(Object.hasOwn(process.env,"NO_COLOR"))return!1;if(process.env.FORCE_COLOR&&process.env.FORCE_COLOR!=="0")return!0;return(e.stream==="stdout"?process.stdout:process.stderr).isTTY&&process.env.TERM!=="dumb"}function Ut(e){let n=e.trim().toLowerCase();if(n==="development")return"Development";if(n==="production")return"Production";return e.trim()}var fs=180000,ms=`Timed out waiting for browser login to complete.
|
|
86
86
|
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
|
-
cliAuth Convex functions or no active API account (Organization settings -> API access).`,
|
|
90
|
-
`)}}async function
|
|
91
|
-
`,"utf8")}catch{}}var
|
|
89
|
+
cliAuth Convex functions or no active API account (Organization settings -> API access).`,Nt=new Set(["--base-url","--cwd","--dashboard-url","--stage","--from","--level","--limit","--mcp","--project","--region","--sandbox","-n"]);function hs(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 M(e,n){let t=Nt.has(n)?`${n}=`:null;return e.some((o)=>o===n||t!==null&&o.startsWith(t))}function ye(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 se(e){let n=[];for(let t=0;t<e.length;t+=1){let o=e[t];if(o===void 0)continue;if(Nt.has(o)){t+=1;continue}if(o.startsWith("-"))continue;n.push(o)}return n}async function On(e){let n=us(),t=ds(32).toString("base64url"),o=ls("sha256").update(t).digest("base64url"),{code:r,close:s}=await xn(n,{port:bs(),fixedPort:Boolean(process.env.BROODS_LOGIN_PORT),path:"/callback",read:ys,done:"broods CLI login complete. You can close this tab."});try{let i=r.callbackUrl,a=`${h(e)}/cli-auth/start?`+new URLSearchParams({callback:i,state:n,code_challenge:o});await ws(a),console.log(`Opening ${a}`),An(a);let c=await Pn(r.promise),d=await en(`${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:h(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 Z(e){f();let n=P(e);if(!n){let t=process.env.BROODS_DASHBOARD_URL,o=e??process.env.BROODS_BASE_URL??(t?U(t):void 0);throw Error(o?`Not logged in to ${h(o)}. Run \`broods login\`.`:"Run `broods login` first, or set BROODS_TOKEN and BROODS_BASE_URL.")}return n}async function on(e){if(!re.isTTY)return!1;let n=Ue({input:re,output:oe});try{let t=(await n.question(`${e} [y/N] `)).trim().toLowerCase();return t==="y"||t==="yes"}finally{n.close()}}async function Lt(e){oe.write(`${e}: `);let n=new ps({write:(o,r,s)=>s()}),t=Ue({input:re,output:n,terminal:re.isTTY===!0});try{let o=await t.question("");if(!o)throw Error(`${e} is required`);return o}finally{t.close(),oe.write(`
|
|
90
|
+
`)}}async function Ne(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(Ae(`${c+1}. ${t(a)}`,c===r))});let s=r===void 0?`Choose 1-${n.length}: `:`Choose 1-${n.length} [${r+1}]: `,i=Ue({input:re,output:oe});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 Mt(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=Ue({input:re,output:oe});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 ke(e,n){if(!re.isTTY)return n??"";let t=Ue({input:re,output:oe});try{let o=t.question(`${e}: `);if(n){if(re.isTTY&&oe.isTTY)oe.write("\x1B[90m");if(t.write(n),re.isTTY&&oe.isTTY)oe.write("\x1B[0m")}return(await o).trim()||n||""}finally{t.close()}}function An(e){let{command:n,args:t}=hs(e),o=gs(n,t,{stdio:"ignore",detached:!0});o.on("error",(r)=>{console.error(De(`Could not open a browser (${r.message}). Open the URL above to continue.`,{stream:"stderr"}))}),o.unref()}function xn(e,n){return new Promise((t,o)=>{let r=cs((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 Pn(e,n=ms){let t,o=new Promise((r,s)=>{t=setTimeout(()=>s(Error(n)),fs)});try{return await Promise.race([e,o])}finally{if(t)clearTimeout(t)}}async function ws(e){let n=await en(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 bs(){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 ys(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:h(o)}}var Es=1455,Ss="/auth/callback";async function Gt(e,n,t=An){let o=be[n].label,r=Bt(),s=Bt(),i=ks(32).toString("base64url"),{code:a,close:c}=await xn(r,{port:Es,fixedPort:!1,path:Ss,read:$s,done:`${o} is connected to broods. You can close this tab.`});try{let d=a.callbackUrl,l=await e.startConnection(n,{redirectUri:d,codeChallenge:vs("sha256").update(i).digest("base64url"),state:r,nonce:s});t(l.authorizeUrl),console.log(`Opening ${l.authorizeUrl}`);let p=await Pn(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 $s(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 Ft}from"node:fs";import{mkdir as Rs,readFile as Os,writeFile as As}from"node:fs/promises";import{dirname as Kt,join as jn,resolve as xs,sep as me}from"node:path";import{fileURLToPath as Ps}from"node:url";var Le={name:"broods",version:"0.50.0",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 Tn=jn(Kt(N),"update-check.json"),Ts=86400000,_s="https://registry.npmjs.org/broods/latest",js=2000,Is=[["bun.lock","bun"],["bun.lockb","bun"],["pnpm-lock.yaml","pnpm"],["yarn.lock","yarn"]];function In(e,n){let t=_n(e),o=_n(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!Wt(e)&&Wt(n)}async function Dn(e={}){let n=await Us(),t=e.maxAgeMs??Ts;if(n&&Date.now()-n.checkedAt<t)return n.latest;let o=await Ds();if(o===null)return n?.latest??null;return await Ls({checkedAt:Date.now(),latest:o}),o}function Me(e){return _n(e)[0]??0}function Ht(e=xs(process.cwd()),n=Ps(import.meta.url),t=Le.version){let o=`${me}node_modules${me}`,r=n.indexOf(o),s=r===-1?null:n.slice(0,r),i=s===null?n.startsWith(`${e}${me}`):e===s||e.startsWith(`${s}${me}`),a=n.includes(`${me}.bun${me}install${me}global${me}`),c=s??e,d=i?Ns(c):a?"bun":"npm",l=d==="npm"?"install":"add",p=d==="pnpm"&&Ft(jn(c,"pnpm-workspace.yaml"))?["-w"]:[],u=`broods@${Me(t)}`;return{manager:d,global:!i,command:d,cwd:i?c:e,args:i?[l,...p,u]:[l,"-g",u]}}async function Ds(){try{let e=await fetch(_s,{signal:AbortSignal.timeout(js),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 Wt(e){return e.includes("-")}async function Us(){try{let e=JSON.parse(await Os(Tn,"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 Ns(e){return Is.find(([t])=>Ft(jn(e,t)))?.[1]??"npm"}function _n(e){let[n]=e.trim().replace(/^v/,"").split("-");return(n??"").split(".").slice(0,3).map((t)=>Number.parseInt(t,10)||0)}async function Ls(e){try{await Rs(Kt(Tn),{recursive:!0}),await As(Tn,`${JSON.stringify(e)}
|
|
91
|
+
`,"utf8")}catch{}}var Yt=`---
|
|
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.
|
|
94
94
|
---
|
|
@@ -136,7 +136,7 @@ Crons, skills, sandboxes, policies, roles, channels, and hooks have no CLI verb.
|
|
|
136
136
|
- Env values are write-only. Reference them from configs as \`\${NAME}\`. If the user pastes a secret at you, put it in the env store and use the ref.
|
|
137
137
|
- Deletes are confirmed, named, and singular. Never loop a delete over a list.
|
|
138
138
|
- Editing a manifest-declared resource outside the project drifts from the definition, and the next deploy silently reverts it.
|
|
139
|
-
`;var
|
|
139
|
+
`;var Vt=`#!/usr/bin/env bash
|
|
140
140
|
# Onboard this machine onto broods: check the CLI, check auth, and run the
|
|
141
141
|
# browser login when needed. Login is a human step, so run this where the
|
|
142
142
|
# user can see the browser open and finish it themselves.
|
|
@@ -171,17 +171,17 @@ elif [ "$STATUS" -ne 0 ]; then
|
|
|
171
171
|
# Not the expected signed-out state: surface the real failure.
|
|
172
172
|
exit "$STATUS"
|
|
173
173
|
fi
|
|
174
|
-
`;var
|
|
174
|
+
`;var ce=Le.version,rn=Ge(".agents","skills","broods"),ie="https://dashboard.broods.app",Xs=3,Be="eu-west-1",Qs=[{region:"eu-west-1",label:"eu-west-1 (Ireland)"},{region:"us-east-1",label:"us-east-1 (US East)"},{region:"ap-southeast-1",label:"ap-southeast-1 (Singapore)"}],F=`Global options:
|
|
175
175
|
--project <name> Project name override (default: package name or folder)
|
|
176
176
|
--stage <name> Target stage override (BROODS_STAGE otherwise)
|
|
177
177
|
--base-url <url> broods API base URL for sync/env calls (default: discovered at login)
|
|
178
|
-
--dashboard-url <url> Dashboard base URL for login and deep links (default: ${
|
|
179
|
-
-h, --help Show this help`,
|
|
178
|
+
--dashboard-url <url> Dashboard base URL for login and deep links (default: ${ie})
|
|
179
|
+
-h, --help Show this help`,ei=`Commands
|
|
180
180
|
Develop dev diff run logs stream
|
|
181
181
|
Ship deploy env stage
|
|
182
182
|
Inspect agent whoami
|
|
183
183
|
Account login connect disconnect org project
|
|
184
|
-
Tools init machine mcp update`,
|
|
184
|
+
Tools init machine mcp update`,Un={stream:"stdout"},to={color:!1},ni=new Set(["agent","deploy","dev","diff","env","logs","machine","run","stage","stream"]),oo={agent:`Usage: broods agent <list|get> [name]
|
|
185
185
|
|
|
186
186
|
Subcommands:
|
|
187
187
|
list List the agents in the current project/stage scope
|
|
@@ -195,12 +195,13 @@ connections. Uses the account key in BROODS_ACCOUNT_SECRET when set, otherwise
|
|
|
195
195
|
your broods login.
|
|
196
196
|
|
|
197
197
|
Types:
|
|
198
|
-
${
|
|
198
|
+
${nn.map((e)=>` ${e.padEnd(11)} ${be[e].description}`).join(`
|
|
199
199
|
`)}
|
|
200
200
|
|
|
201
201
|
${F}`,deploy:`Usage: broods deploy [options]
|
|
202
202
|
|
|
203
|
-
Syncs Production once and writes BROODS_API_KEY to .env.local
|
|
203
|
+
Syncs Production once and writes BROODS_API_KEY to .env.local, plus
|
|
204
|
+
BROODS_USER_TOKEN_SECRET when the stage has no signing secret yet. Ignores
|
|
204
205
|
BROODS_STAGE by design. Pass --stage to deploy anywhere else.
|
|
205
206
|
|
|
206
207
|
Options:
|
|
@@ -217,7 +218,7 @@ Options:
|
|
|
217
218
|
--once Sync a single time and exit (no watch, no log stream)
|
|
218
219
|
--level <lvl> Minimum level for the log tail DEBUG|INFO|WARN|ERROR (default: WARN)
|
|
219
220
|
--all Tail INFO and up (DEBUG is dashboard-only)
|
|
220
|
-
--region <region> Service region for a new project (default: ${
|
|
221
|
+
--region <region> Service region for a new project (default: ${Be})
|
|
221
222
|
|
|
222
223
|
${F}`,diff:`Usage: broods diff [options]
|
|
223
224
|
|
|
@@ -249,7 +250,7 @@ ${F}`,init:`Usage: broods init [options]
|
|
|
249
250
|
Creates the broods/ project shell and .env.local defaults.
|
|
250
251
|
|
|
251
252
|
Options:
|
|
252
|
-
--region <region> Broods service region preference (default: ${
|
|
253
|
+
--region <region> Broods service region preference (default: ${Be})
|
|
253
254
|
--force Overwrite existing starter files
|
|
254
255
|
|
|
255
256
|
${F}`,login:`Usage: broods login [options]
|
|
@@ -258,7 +259,7 @@ Authenticates through the dashboard and stores the token in
|
|
|
258
259
|
~/.broods/config.json.
|
|
259
260
|
|
|
260
261
|
Options:
|
|
261
|
-
--region <region> Broods service region preference (default: ${
|
|
262
|
+
--region <region> Broods service region preference (default: ${Be})
|
|
262
263
|
|
|
263
264
|
${F}`,logs:`Usage: broods logs [options]
|
|
264
265
|
|
|
@@ -372,55 +373,55 @@ project the dependency is upgraded instead. A new major is only announced.`,whoa
|
|
|
372
373
|
|
|
373
374
|
Shows the login, server, org, plan, project and stage the next command uses.
|
|
374
375
|
|
|
375
|
-
${F}`};async function
|
|
376
|
+
${F}`};async function ti(){na();let[,,e,...n]=process.argv;switch(e){case void 0:case"--help":case"-h":console.log(Nn(n,Un));return;case"--version":case"-v":console.log(ce);return}if(ta(e,n),oo[e]&&(M(n,"--help")||M(n,"-h"))){console.log($e(e,n));return}switch(e){case"init":await ri(n);return;case"login":await si(n);return;case"connect":await ai(n);return;case"disconnect":await ci(n);return;case"whoami":await ui(n);return;case"org":await pi(n);return;case"project":await fi(n);return;case"stage":await mi(n);return;case"diff":await hi(n);return;case"deploy":await wi(n);return;case"dev":await yi(n);return;case"env":await Wi(n);return;case"stream":await Hi(n);return;case"logs":await zi(n);return;case"machine":await Yi(n);return;case"agent":await Ji(n);return;case"run":await Xi(n);return;case"mcp":await oa();return;case"update":await bi();return;default:throw Error(`Unknown command: ${e}
|
|
376
377
|
|
|
377
|
-
${
|
|
378
|
+
${Nn(n,to)}`)}}function Q(e){return oo[e]??Nn([],to)}function ro(e){let n=f(),t=b(e,"--base-url")??n.baseUrl,o=P(t),r=h(t??o?.baseUrl??I);return{loggedIn:o!==null,org:o?.org?.name,project:b(e,"--project")??n.project,projectGuess:xe(process.cwd()),server:r.replace(/^https?:\/\//,""),stage:b(e,"--stage")??n.stage??"development"}}function oi(e){if(!e.loggedIn)return[["broods login","sign in through the dashboard"]];if(!e.project)return[["broods dev","create a project and sync on save"]];return[["broods dev","sync on save, tail logs"],["broods run <agent>","chat with an agent"]]}function $e(e,n){let t=Q(e);if(!ni.has(e))return t;let o=ro(n),r=o.project??o.projectGuess;if(e!=="deploy"||b(n,"--stage")!==void 0)return`${Cn(r,o.stage,Un)}
|
|
378
379
|
|
|
379
|
-
${t}`;let s=
|
|
380
|
+
${t}`;let s=_(),i=s&&s!=="production"?`ignores stage ${s}`:void 0;return`${Cn(r,"production",{...Un,note:i})}
|
|
380
381
|
|
|
381
|
-
${t}`}function
|
|
382
|
-
`)}async function
|
|
382
|
+
${t}`}function Nn(e,n){let t=ro(e);return[`broods v${ce}`,"",...Pt(t,n),"","Next",...Tt(oi(t),n),"",ei,"","Usage: broods <command> [options] -h, --help -v, --version","Run `broods <command> --help` for a command's flags."].join(`
|
|
383
|
+
`)}async function ri(e){let n=M(e,"--force"),t=x(process.cwd(),S);await Gn(x(t,w),{recursive:!0}),await an(x(t,"index.ts"),yo(),n),await an(x(t,".gitignore"),`_generated
|
|
383
384
|
.cache
|
|
384
|
-
`,n),await
|
|
385
|
+
`,n),await co(n);let o=b(e,"--dashboard-url")??ie;await Yn({dashboardUrl:o,baseUrl:U(o),project:b(e,"--project")??xe(process.cwd()),stage:b(e,"--stage")??"development",region:b(e,"--region")??Be,force:n}),H(`Created ${S}/`)}async function si(e){let n=f(),t=b(e,"--dashboard-url")??n.dashboardUrl??ie,o=await On(t);await Yn({dashboardUrl:o.dashboardUrl??t,baseUrl:o.baseUrl,project:b(e,"--project"),stage:b(e,"--stage"),region:b(e,"--region"),force:!1});let r=o.user?.email||o.user?.name||o.user?.authId,s=o.org?`${o.org.name} (${o.org.slug})`:void 0,i=o.account?.username;if(H(`Logged in to ${o.dashboardUrl}`),r)console.log(`User: ${r}`);if(s)console.log(`Org: ${s}`);if(i)console.log(`Account: ${i}`);let a=b(e,"--project")??process.env.BROODS_PROJECT;if(!a)return;let c=b(e,"--stage")??_()??"development";await di(o.baseUrl,o.token,a,c)}function ii(e){if(!(e instanceof m))return e instanceof Error?e.message:String(e);try{return JSON.parse(e.body).error?.message??e.message}catch{return e.message}}async function ai(e){let[n]=se(e),t=await so(e);if(n===void 0){await li(t);return}if(!$n(n))throw Error(`Unknown connection type ${n}.
|
|
385
386
|
|
|
386
|
-
${
|
|
387
|
-
Connect one: broods connect <${
|
|
387
|
+
${Q("connect")}`);let o=be[n],r=await Gt(t,n).catch((s)=>{throw Error(ii(s))});if(H(`Connected ${o.label}${r.email?` as ${r.email}`:""}.`),console.log(`Agents on model.provider "${n}" now run on it.`),o.usageUrl)console.log(`Manage usage: ${o.usageUrl}`);if(!r.models?.length)return;console.log("Models (use the id as model.modelId):");for(let s of r.models)console.log(` ${s}`)}async function so(e){f();let n=b(e,"--base-url"),t=process.env.BROODS_ACCOUNT_SECRET;if(t)return new C({accountSecret:t,...n?{baseUrl:n}:{}});let o=await Z(n);return new C({accountSecret:o.token,baseUrl:n??o.baseUrl})}async function ci(e){let[n]=se(e);if(!n||!$n(n))throw Error(Q("disconnect"));if(await(await so(e)).disconnect(n)){H(`Disconnected ${be[n].label}`);return}console.log(`No ${n} connection.`)}async function li(e){let n=await e.listConnections();if(n.length===0)console.log("No connections yet.");else console.log(`${"TYPE".padEnd(16)} ACCOUNT`);for(let t of n)console.log(`${be[t.type].label.padEnd(16)} ${t.email??t.clientId}`);console.log(`
|
|
388
|
+
Connect one: broods connect <${nn.join("|")}>`)}async function di(e,n,t,o){try{let s=await new G({baseUrl:e,token:n}).getRuntimeKey(t,o);if(s?.apiKey)await Se("BROODS_API_KEY",s.apiKey),H(`Wrote BROODS_API_KEY (${s.keyHint}) to .env.local`)}catch{}}async function ui(e){let n=f(),t=ln(e),o=b(e,"--dashboard-url")??n.dashboardUrl??ie,r=Boolean(b(e,"--project")??n.project);console.log(`broods v${ce}`),console.log(`Dashboard: ${o}`),console.log(`Project: ${r?t.project:`none (${t.project} from folder name)`}`),console.log(`Stage: ${t.stage}`);let s;try{s=await Z(b(e,"--base-url"))}catch(l){A(l instanceof Error?l.message:String(l));return}console.log(`Server: ${s.baseUrl}`);let i=new G({baseUrl:s.baseUrl,token:s.token}),a=await i.getOnboarding(),c=a.orgs.find((l)=>l.id===a.currentOrgId);if(a.user)console.log(`User: ${a.user.email}`);if(console.log(`Org: ${c?Fe(c):a.currentOrgId}`),a.account)console.log(`Account: ${a.account.username} (${a.account.status})`);if(!r){A("No project set. `broods dev` picks one.");return}await gi(i,t,c?.name);let d=a.projects.map((l)=>l.name);if(!d.includes(t.project))A(`This org has no project named ${t.project}. It has: ${d.length>0?d.join(", "):"none"}.`)}async function gi(e,n,t){let o=process.env.BROODS_API_KEY,r=T("BROODS_API_KEY")?"your shell":".env.local",s=null,i=null;try{s=await e.getRuntimeKey(n.project,n.stage)}catch(a){i=a instanceof Error?a.message:String(a)}if(i)console.log("Runtime key: unavailable"),A(`Could not read the runtime key: ${i}`);else if(!s?.apiKey)console.log("Runtime key: none for this scope"),A(`${n.project}/${n.stage} does not exist in ${t??"this org"} yet. \`broods dev\` will create it.`);else if(!o)console.log(`Runtime key: ${s.keyHint} (not in .env.local)`),A("BROODS_API_KEY is not set locally. Run `broods dev`.");else if(o===s.apiKey)console.log(`Runtime key: ${s.keyHint} (matches this org and stage)`);else console.log(`Runtime key: ${s.keyHint} expected`),A(`BROODS_API_KEY from ${r} belongs to a different org or stage. Run \`broods stage use ${n.stage}\` to repoint it.`)}async function pi(e){let[n,t]=se(e);if(!n){console.log($e("org",e));return}let o=n==="list"||n==="ls",r=n==="use"||n==="select";if(!o&&!r&&!(n==="create"||n==="new"))throw Error(`Unknown org subcommand: ${n}
|
|
388
389
|
|
|
389
|
-
${
|
|
390
|
-
Only orgs where you are owner or admin can be selected from the CLI.`);return}if(r){let u=l.orgs.filter((
|
|
390
|
+
${Q("org")}`);let i=f(),a=b(e,"--dashboard-url")??i.dashboardUrl??ie,c=await Ke(a,b(e,"--base-url")),d=new G({baseUrl:c.baseUrl,token:c.token}),l=await d.getOnboarding();if(o){for(let u of l.orgs){let k=u.accountStatus==="active"?"":` [${u.accountStatus} account]`;console.log(Ae(`${Fe(u)}${k}`,u.id===l.currentOrgId))}console.log(`
|
|
391
|
+
Only orgs where you are owner or admin can be selected from the CLI.`);return}if(r){let u=l.orgs.filter((E)=>E.accountStatus==="active"),k=t?u.find((E)=>E.slug===t||E.name===t||E.id===t):await Ne("Select organization",u,Fe,u.findIndex((E)=>E.id===l.currentOrgId));if(!k)throw Error(`No selectable organization matches "${t}". Run \`broods org list\`.`);await Zt(d,c,await d.selectOnboardingOrg(k.id),e);return}let p=t??await ke("Organization name",xe(process.cwd()));if(!p.trim())throw Error("Organization name is required.");await Zt(d,c,await d.createOnboardingOrg(p),e)}async function fi(e){let[n,t]=se(e);if(!n){console.log($e("project",e));return}let o=n==="list"||n==="ls";if(!o&&!(n==="delete"||n==="rm"))throw Error(`Unknown project subcommand: ${n}
|
|
391
392
|
|
|
392
|
-
${
|
|
393
|
-
${
|
|
393
|
+
${Q("project")}`);let s=f(),i=b(e,"--dashboard-url")??s.dashboardUrl??ie,a=ln(e),c=await Ke(i,b(e,"--base-url")),d=new G({baseUrl:c.baseUrl,token:c.token});if(o){let E=await d.listProjects();if(E.length===0){console.log("This org has no projects yet. `broods dev` creates one.");return}console.log("Projects:");for(let O of E)console.log(Oi(O,a.project));let v=E.filter((O)=>O.empty);if(v.length>0)console.log(`
|
|
394
|
+
${v.length} empty project(s). Delete one with \`broods project delete <name>\`.`);return}let l=t??await ke("Project to delete","");if(!l.trim())throw Error("Project name is required.");let p=await d.listProjects(),u=p.find((E)=>E.name===l||E.slug===l);if(!u)throw Error(`No project named "${l}". Existing: ${p.map((E)=>E.name).join(", ")}.`);if(!M(e,"--yes")){if(console.log(`Deleting ${u.name} removes ${Mn(u)}.`),!await on(`Permanently delete project ${u.name}?`)){console.log("Left it alone. Pass --yes to skip this prompt.");return}}let k=await d.deleteProject(u.id);if(!k)throw Error(`Project ${u.name} was not found.`);if(H(`Deleted project ${k.name} (${Mn(k)})`),k.name===a.project||k.slug===a.project)console.log("That was the project this directory points at. Update BROODS_PROJECT in .env.local.")}async function mi(e){let[n,t]=se(e);if(!n){console.log($e("stage",e));return}let o=n==="list"||n==="ls",r=n==="use"||n==="select";if(!o&&!r&&!(n==="create"||n==="new"))throw Error(`Unknown stage subcommand: ${n}
|
|
394
395
|
|
|
395
|
-
${
|
|
396
|
+
${Q("stage")}`);let i=f(),a=b(e,"--dashboard-url")??i.dashboardUrl??ie,c=ln(e),d=await Ke(a,b(e,"--base-url")),l=new G({baseUrl:d.baseUrl,token:d.token});if(o){let v=await l.listStages(c.project);if(v.length===0){console.log(`${c.project} has no stages yet. \`broods dev\` creates Development.`);return}console.log(`Stages for ${c.project}:`);for(let O of v)console.log(Ai(O,c.stage));return}if(r){let v=await l.listStages(c.project),O=t?v.find((ae)=>Bn(ae.name,t)):await Ne("Select stage",v,lo,v.findIndex((ae)=>Bn(ae.name,c.stage)));if(!O)throw Error(`${c.project} has no stage "${t}". Existing: ${v.map((ae)=>ae.name).join(", ")}. Create it with \`broods stage create ${t} --from ${c.stage}\`.`);let V=T("BROODS_STAGE");await Se("BROODS_STAGE",O.name),console.log(`Stage: ${O.name} (wrote BROODS_STAGE)`),We("BROODS_STAGE",V),await Ln(l,{project:c.project,stage:O.name});return}let p=t??await ke("Stage name","staging");if(!p.trim())throw Error("Stage name is required.");let u=b(e,"--from"),k=await l.createStage(c.project,p,u);if(H(`Created stage ${k.stage.name} in ${c.project}${k.clonedFrom?` from ${k.clonedFrom}`:""}`),k.clonedFrom)console.log(` ${k.stage.agentCount} agent(s), ${k.stage.variableCount} env var(s) copied`);if(!M(e,"--use")){console.log(`Switch to it with \`broods stage use ${k.stage.name}\`.`);return}let E=T("BROODS_STAGE");await Se("BROODS_STAGE",k.stage.name),console.log(`Stage: ${k.stage.name} (wrote BROODS_STAGE)`),We("BROODS_STAGE",E),await Ln(l,{project:c.project,stage:k.stage.name})}async function hi(e){let{manifest:n,config:t}=await ge({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),o=await Z(b(e,"--base-url")??t.baseUrl),r=new G({baseUrl:o.baseUrl,token:o.token}),s=await r.getManifest(n.project,n.stage);tn(Sn(n,s?.manifest??null)),Ui(await Wn(r,n),`${n.project}/${n.stage}`)}async function wi(e){let{manifest:n,config:t,resourceAliases:o,channels:r}=await ge({project:b(e,"--project"),stage:b(e,"--stage"),command:"deploy",useRuntimeStage:!1}),s=await Z(b(e,"--base-url")??t.baseUrl),i=new G({baseUrl:s.baseUrl,token:s.token}),a=await i.putManifest(n,M(e,"--prune"),M(e,"--rotate-key"));await Je(n,a.ids,process.cwd(),o,a.deployment,r),await wo(),H(`Synced ${a.manifest.resources.length} resources to ${n.project}/${n.stage}`),await io(i,n,a.deployment),uo(r,a),ao(a)}async function io(e,n,t){if(!t)return;if(t.apiKey)await Se("BROODS_API_KEY",t.apiKey),H(`Wrote BROODS_API_KEY (${t.keyHint}) to .env.local`);let o=t.userTokenSecretHint,r=(c)=>c!==void 0&&$t(X,c)===o,s=Y(await Ce(x(process.cwd(),".env.local")))[y];if(o&&(r(process.env[y])||r(s))){We(y,!r(process.env[y])&&T(y));return}if(o){A(`${n.project}/${n.stage} already has a user token signing secret (${o}), and ${y} here is unset or another one. Use the secret your backend signs with, or rotate it on the dashboard's Runtime key tab.`);return}let i=await e.rotateUserTokenSecret(n.project,n.stage).catch((c)=>(A(`${c instanceof Error?c.message:String(c)}. Set ${y} from the dashboard's Runtime key tab to sign user tokens.`),null));if(!i)return;let a=T(y);await Se(y,i.secret),H(`Wrote a new user token signing secret to ${y} in .env.local`),We(y,a)}function ao(e){let n=e.warnings?.missingPolicies??[];if(n.length>0)A(`${n.length} policy ref(s) in agent config match no policy resource in this deploy. One that is not an existing policy id refuses every action at runtime: ${n.join(", ")}`);let t=e.warnings?.reservedResources??[];if(t.length>0)A(`Kept on prune, a reserved sandbox instance is still live: ${t.join(", ")}. Terminate it from the dashboard, then deploy again.`)}async function bi(){let e=await Dn({maxAgeMs:0});if(e===null)throw Error("Could not reach the npm registry to check for a newer broods.");if(!In(e,ce)){console.log(`broods v${ce} is already the newest release.`);return}let n=Ht(),t=Me(ce),o=Me(e)===t,r=o?e:`the newest ${t}.x`;if(console.log(`Updating broods ${ce} → ${r} ${n.global?"globally":"in this project"}`),console.log(`$ ${[n.command,...n.args].join(" ")}`),await new Promise((s,i)=>{let a=no(n.command,n.args,{cwd:n.cwd,stdio:"inherit",shell:process.platform==="win32"});a.on("error",i),a.on("exit",(c)=>{if(c===0){s();return}i(Error(`${n.command} exited with code ${c??"unknown"}`))})}),console.log(`broods ${o?e:`${t}.x`} installed.`),!o)A(`broods ${e} is a new major version. Install broods@${Me(e)} yourself to move to it.`)}async function Jt(){let e=await Dn();if(e===null||!In(e,ce))return;A(`broods ${e} is out, you are on ${ce}. Run \`broods update\`.`)}async function yi(e){if(await ki(e),M(e,"--once")){if(!process.env.BROODS_SUPPRESS_DEV_TARGET)await Xt(e),await Jt();let u=zt.now();await Ii(e),It(zt.now()-u);return}let n=Ge(qs(),`broods-declined-${process.pid}.txt`),t={...process.env,BROODS_DECLINED_FILE:n,BROODS_SUPPRESS_DEV_TARGET:"1",BROODS_RELOAD_ENV:"1"};await Xt(e),await Jt();let o,r=!1,s=!1,i,a=async()=>{let u=await Qi();if(u===i)return;await ji(e,t),i=u},c=(u)=>console.error(u instanceof Error?u.message:String(u));await a().catch(c);let d=()=>{if(r){s=!0;return}r=!0,a().catch(c).finally(()=>{if(r=!1,s)s=!1,d()})},l=Js(x(process.cwd(),S),{recursive:!0},(u,k)=>{if(!k||ea(k))return;clearTimeout(o),o=setTimeout(d,150)}),p=new AbortController;vi(e,p.signal),process.on("SIGINT",()=>{p.abort(),l.close(),process.exit(0)})}async function vi(e,n){let t;try{t=await dn(e)}catch(r){console.log(`· live logs off. ${r instanceof Error?r.message:String(r)}`);return}let o=Fn(e);try{for await(let r of qe(t,{backfill:0,keepReconnecting:!0,minLevel:o,signal:n,onReconnect:Kn}))console.log(Hn(r))}catch(r){if(!n.aborted)console.error(`live logs: ${r instanceof Error?r.message:String(r)}`)}}async function ki(e){await Si(),await co(!1),await $i(e)}async function co(e){let n=process.cwd();if(!(await Promise.all([".agent",".agents",".claude","AGENTS.md","CLAUDE.md"].map((c)=>qt(x(n,c))))).includes(!0))return;let r=x(n,rn);if(!e&&await qt(x(r,"SKILL.md")))return;let s=Ge(rn,"SKILL.md"),i=Ge(rn,"scripts","onboard.sh");for(let c of[s,i])if(await Ei(n,c)){A(`Skipped the agent skill: ${c} crosses a symlink.`);return}await Gn(x(r,"scripts"),{recursive:!0}),await Ee(x(r,"SKILL.md"),Yt);let a=x(r,"scripts","onboard.sh");await Ee(a,Vt),await Gs(a,493),H(`Installed the broods agent skill at ${rn}/`)}async function Ei(e,n){let t=e;for(let o of n.split(zs)){t=x(t,o);try{if((await Ws(t)).isSymbolicLink())return!0}catch{return!1}}return!1}async function qt(e){try{return await Ks(e),!0}catch{return!1}}async function Si(){let e=x(process.cwd(),S);await Gn(x(e,w),{recursive:!0});let n=[];if(await Vn(e,n),n.length>0)return;await an(x(e,"index.ts"),yo(),!1),await an(x(e,".gitignore"),`_generated
|
|
396
397
|
.cache
|
|
397
|
-
`,!1),H(`Created starter ${
|
|
398
|
+
`,!1),H(`Created starter ${S}/`)}async function $i(e){let n=x(process.cwd(),".env.local"),t=await Ce(n),o=bo(t),r=o.BROODS_STAGE;if(["BROODS_DASHBOARD_URL","BROODS_BASE_URL","BROODS_PROJECT","BROODS_REGION"].filter((E)=>o[E]===void 0).length===0&&r!==void 0)return;let i=o.BROODS_PROJECT===void 0,a=r===void 0,c=o.BROODS_REGION===void 0,d=f(),l=b(e,"--dashboard-url")??d.dashboardUrl??ie,p=b(e,"--project")??process.env.BROODS_PROJECT??xe(process.cwd()),u=b(e,"--stage")??_()??"development",k=b(e,"--region")??process.env.BROODS_REGION??Be;if(process.stdin.isTTY&&i){let E=await Ke(l,b(e,"--base-url")),v=new G({baseUrl:E.baseUrl,token:E.token}),O=await Ci(v,E),V=await xi(v,O);if(p=await _i(V,p),!p.trim())throw Error("Project name is required.")}if(process.stdin.isTTY&&a){if(u=await ke("Stage",u),!u.trim())throw Error("Stage is required.")}if(process.stdin.isTTY&&c){let E=[...Qs];k=await Ne("Select service region",E,(v)=>v.label,E.findIndex((v)=>v.region===k)).then((v)=>v.region)}await Yn({dashboardUrl:l,baseUrl:d.baseUrl??U(l),project:p,stage:u,region:k,force:!1})}async function Ke(e,n){try{return await Z(n)}catch(t){if(!process.stdin.isTTY)throw t;return A(`${t instanceof Error?t.message:String(t)} Starting browser login.`),await On(e)}}async function Ci(e,n){try{return await e.getOnboarding()}catch(t){if(!(t instanceof Qe)||!n.org)throw t;return A("This broods server cannot list your orgs yet; using the org from your login."),{currentOrgId:n.org.id,orgs:[{id:n.org.id,name:n.org.name,slug:n.org.slug,role:"admin",accountStatus:"active"}],projects:[]}}}async function Zt(e,n,t,o){let r=t.orgs.find((s)=>s.id===t.currentOrgId);if(!r)throw Error("Selected organization is not visible to this login");if(process.env.BROODS_TOKEN)A("BROODS_TOKEN is set, so the switch applies to this token only and was not stored.");else await W({...n,org:{id:r.id,name:r.name,slug:r.slug},...t.account?{account:{id:t.account.id,username:t.account.username}}:{}});console.log(`Org: ${Fe(r)}`),console.log(`Projects: ${t.projects.length>0?t.projects.map((s)=>s.name).join(", "):"none yet"}`),await Ln(e,ln(o))}async function Ln(e,n){let t;try{t=await e.getRuntimeKey(n.project,n.stage)}catch(r){A(`Could not read the runtime key for ${n.project}/${n.stage} (${r instanceof Error?r.message:String(r)}). BROODS_API_KEY still points at the previous scope. Run \`broods whoami\` to check it.`);return}if(!t?.apiKey){A(`${n.project}/${n.stage} is not synced here yet, so BROODS_API_KEY still points at the previous scope. Run \`broods dev\`.`);return}let o=T("BROODS_API_KEY");if(!o&&process.env.BROODS_API_KEY===t.apiKey)return;await Se("BROODS_API_KEY",t.apiKey),H(`Wrote BROODS_API_KEY (${t.keyHint}) to .env.local`),We("BROODS_API_KEY",o)}function We(e,n){if(!n)return;A(`${e} is exported in your shell, which wins over .env.local. Run \`unset ${e}\` or the next broods command keeps the old value.`)}function Fe(e){let n=e.role==="owner"||e.role==="admin"?e.role:"member",t=e.plan?`, ${e.plan} plan`:"";return`${e.name} (${e.slug}, ${n}${t})`}function Ri(e){return e.slug===e.name?e.name:`${e.name} (${e.slug})`}function Mn(e){return e.empty?"nothing (it is already empty)":`${e.stageCount} stage(s), ${e.agentCount} agent(s), ${e.variableCount} env var(s), ${e.deploymentCount} deployment(s), ${e.fileCount} workspace file(s)`}function Oi(e,n){let t=e.empty?"empty":Mn(e);return Ae(`${e.name}: ${t}`,e.name===n||e.slug===n)}function Ai(e,n){return Ae(lo(e),Bn(e.name,n))}function lo(e){let n=e.deploymentRegion?`, ${e.deploymentRegion}`:"";return`${e.name} (${e.kind}${n}): ${e.agentCount} agent(s), ${e.variableCount} env var(s)`}function Bn(e,n){return e.trim().toLowerCase()===n.trim().toLowerCase()}function ln(e){return f(),{project:b(e,"--project")??process.env.BROODS_PROJECT??xe(process.cwd()),stage:b(e,"--stage")??_()??"development"}}async function xi(e,n){let t=n.orgs.filter((s)=>s.accountStatus==="active"),o={kind:"create",name:"New organization"},r=await Ne("Select organization",[...t,o],(s)=>("kind"in s)?"Create new organization":Fe(s),t.findIndex((s)=>s.id===n.currentOrgId));if("kind"in r){let s=await ke("Organization name",xe(process.cwd()));if(!s.trim())throw Error("Organization name is required.");return await e.createOnboardingOrg(s)}return r.id===n.currentOrgId?n:await e.selectOnboardingOrg(r.id)}function Pi(e,n){return e.projects.find((o)=>o.name===n||o.slug===n)?.name??n}function Ti(e,n){return e.projects.find((t)=>t.name===n||t.slug===n)}async function _i(e,n){let t=Pi(e,n);if(e.projects.length===0)return ke("Project name",t);for(;;){let o=await Mt("Select project",e.projects,Ri,{hint:"type a new project name",defaultValue:t}),r=typeof o==="string"?o:o.name,s=Ti(e,r);if(!s)return r;if(await on(`Continue with the existing project ${s.name}?`))return s.name}}function ji(e,n){return new Promise((t,o)=>{let r=process.argv[1]??"",s=no(process.execPath,[r,"dev","--once",...e],{stdio:"inherit",env:n});s.on("error",o),s.on("exit",(i,a)=>{if(i===0){t();return}o(Error(a?`Sync child exited from signal ${a}`:`Sync child exited with code ${i??"unknown"}`))})})}async function Ii(e){let n=await ge({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),t=await Z(b(e,"--base-url")??n.config.baseUrl),o=new G({baseUrl:t.baseUrl,token:t.token}),r=await go(o,n.manifest,await Wn(o,n.manifest));if(r.length>0)Rn(r);for(let s=1;;s+=1)try{return await Di(o,n)}catch(i){if(!(i instanceof Xe)||s===Xs)throw i;A("Stage changed in another session. Re-reading...")}}async function Di(e,n){let{manifest:t,resourceAliases:o,channels:r}=n,s=await e.getManifest(t.project,t.stage),i=Sn(t,s?.manifest??null);tn(i.filter((u)=>u.operation!=="delete"));let a=await e.putManifest(t,!1,!1,s===null?0:s.revision);await Je(t,a.ids,process.cwd(),o,a.deployment,r),await wo();let c=await Mi(),d=i.filter((u)=>u.operation==="delete"),l=d.filter((u)=>!c.has(`${u.kind}:${u.name}`)),p=!1;if(l.length>0)if(A("These remote resources are no longer declared locally:"),tn(l),await on(`Delete ${l.length} resource(s) from ${t.project}/${t.stage}?`))a=await e.putManifest(t,!0,!1,a.revision),await Je(t,a.ids,process.cwd(),o,a.deployment,r),await Gi(),p=!0;else await Bi(l.map((u)=>`${u.kind}:${u.name}`));if(!p&&d.length>0){let u=d.map((k)=>`${k.kind}:${k.name}`).join(", ");A(`${d.length} undeclared resource(s) kept remotely: ${u}. Re-declare in code or run \`deploy --prune\` to remove.`)}return await io(e,t,a.deployment),uo(r,a),ao(a),a}function uo(e,n){let t=n.deployment;if(!t||e.length===0)return;let o=new B,r=new Map;for(let i of e){if(!n.ids.agents[i.agentName])continue;let a=r.get(i.type)??[];a.push(i.alias),r.set(i.type,a)}let s=t.stageKind===void 0||t.stageKind==="production";for(let[i,a]of r){let c=s?o.accountWebhookUrl(t.accountId,i):o.stageWebhookUrl(t.accountId,t.endpointId,i);console.log(`Channel ${a.join(", ")} (${i}): ${c}${i==="pancake"?"?secret=<PANCAKE_WEBHOOK_SECRET>":""}`)}}async function Wn(e,n){let t=mt(n).filter((r)=>!r.startsWith("BROODS_"));if(t.length===0)return[];let o=new Map((await e.listEnv(n.project,n.stage)).map((r)=>[r.name,r.valueDigest]));return t.map((r)=>({name:r,state:Ni(r,o)}))}async function go(e,n,t){let o=t.filter((r)=>r.state==="unset"||r.state==="drifted").map((r)=>r.name);if(o.length===0)return[];return await Promise.all(o.map((r)=>e.setEnv(n.project,n.stage,r,process.env[r]))),o}function Ui(e,n){let t=sn(e,"drifted");if(t.length>0)A(`.env.local and ${n} disagree on ${t.length} variable(s): ${t.join(", ")}. Run \`broods env sync\` to push the local values.`)}function Ni(e,n){let t=process.env[e],o=n.get(e);if(t===void 0||t==="")return o===void 0?"unresolved":"stage-only";if(o===void 0)return"unset";return o===Li(t)?"synced":"drifted"}function Li(e){return eo("sha256").update(e).digest("hex")}function sn(e,n){return e.filter((t)=>t.state===n).map((t)=>t.name)}async function Xt(e){let n=f(),{manifest:t,config:o}=await ge({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),r=await Z(b(e,"--base-url")??o.baseUrl);_t({project:t.project,stage:t.stage,dashboardUrl:b(e,"--dashboard-url")??n.dashboardUrl??r.dashboardUrl??o.dashboardUrl??ie})}async function Mi(){let e=process.env.BROODS_DECLINED_FILE;if(!e)return new Set;let n=await Ce(e);return new Set(n.split(/\r?\n/).map((t)=>t.trim()).filter(Boolean))}async function Bi(e){let n=process.env.BROODS_DECLINED_FILE;if(!n||e.length===0)return;await Ee(n,`${e.join(`
|
|
398
399
|
`)}
|
|
399
|
-
`,{flag:"a"})}async function
|
|
400
|
+
`,{flag:"a"})}async function Gi(){let e=process.env.BROODS_DECLINED_FILE;if(!e)return;await Ee(e,"","utf8")}async function Wi(e){let[n,t]=se(e);if(!n){console.log($e("env",e));return}let o=n==="list"||n==="ls",r=n==="rm"||n==="remove",s=n==="get",i=n==="sync",a=n==="set"||r||s;if(!o&&!i&&!a)throw Error(`Unknown env subcommand: ${n}
|
|
400
401
|
|
|
401
|
-
${
|
|
402
|
+
${Q("env")}`);if(a&&!t)throw Error(`broods env ${n} needs a variable name.
|
|
402
403
|
|
|
403
|
-
${
|
|
404
|
+
${Q("env")}`);let{manifest:c,config:d}=await ge({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),l=await Z(b(e,"--base-url")??d.baseUrl),p=new G({baseUrl:l.baseUrl,token:l.token}),u=`${c.project}/${c.stage}`;if(i){await Fi(p,c,u);return}if(o){let E=await p.listEnv(c.project,c.stage);if(E.length===0){console.log(`No environment variables set for ${u}.`);return}console.log(`Environment variables for ${u} (values hidden):`);for(let v of E)console.log(` ${v.name}`);return}if(s){let E=await p.getEnv(c.project,c.stage,t);if(E===null){console.error(`${t} is not set for ${u}`),process.exitCode=1;return}console.log(E);return}if(r){await p.removeEnv(c.project,c.stage,t),H(`Removed ${t} from ${u}`);return}let k=await Lt(t);await p.setEnv(c.project,c.stage,t,k),H(`Stored ${t} for ${u}`)}async function Fi(e,n,t){let o=await Wn(e,n);if(o.length===0){console.log('No env("NAME") references in this project.');return}let r=await go(e,n,o);if(r.length>0)Rn(r);let s=sn(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=sn(o,"stage-only");if(i.length>0)console.log(`${i.length} referenced variable(s) live only on ${t}: ${i.join(", ")}`);let a=sn(o,"unresolved");if(a.length>0)A(`${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 Fn(e){if(M(e,"--all"))return"DEBUG";let n=b(e,"--level");if(n===void 0&&M(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 Ki(e){f();let n=b(e,"--project")??process.env.BROODS_PROJECT,t=b(e,"--stage")??_();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 dn(e){let n=await Ki(e),t=f(),o=await Ke(b(e,"--dashboard-url")??t.dashboardUrl??ie,b(e,"--base-url")),r=new G({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 po(e){return e==="WARN"?" (--all for INFO too)":""}function Kn(e,n){console.error(De(`Reconnecting to live logs (attempt ${e}): ${n}`,{stream:"stderr"}))}function Hn(e){let n=new Date(e.ts).toISOString().slice(11,23),t=e.level.padEnd(5),o=Zs(e.message);return`${n} ${t} ${e.eventType} ${o}`}async function Hi(e){let n=await dn(e),{project:t,stage:o}=n,r=Fn(e),s=new AbortController,i=()=>s.abort();process.on("SIGINT",i),console.log(`Streaming live logs for ${t}/${o} [${r}+]`+po(r)+", Ctrl+C to stop");try{for await(let a of qe(n,{backfill:0,minLevel:r,signal:s.signal,onReconnect:Kn}))console.log(Hn(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 Yi(e){if(M(e,"--doctor")){await Vi(M(e,"--request"));return}let n=se(e)[0];if(!n){console.log($e("machine",e));return}let{runMachineDaemon:t}=await import("../chunk-187pvsnt.js"),{baseUrl:o,credential:r}=await dn(e),s=x(b(e,"--cwd")??process.cwd()),i=M(e,"--computer"),a=b(e,"--mcp"),c=M(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?x(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 Vi(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 zi(e){let n=await dn(e),{project:t,stage:o}=n,r=b(e,"--sandbox");if(M(e,"--sandbox")&&!K(r))throw Error("--sandbox needs the instance log id, the UUID shown in the dashboard Instances sheet.");let s=r?"DEBUG":Fn(e),i=Number(b(e,"--limit")??b(e,"-n")??100),a=M(e,"--json"),c=new AbortController,d=()=>c.abort();process.on("SIGINT",d),console.log(`Logs for ${t}/${o}`+(r?` sandbox ${r}`:"")+` [${s}+]`+po(s)+` (backfill ${i}), Ctrl+C to stop`);try{for await(let l of qe(n,{backfill:i,minLevel:s,...r?{sandboxId:r}:{},signal:c.signal,onReconnect:Kn}))if(a)console.log(JSON.stringify(l));else console.log(Hn(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 Ji(e){let[n,t]=se(e);if(!n){console.log($e("agent",e));return}if(n==="list"||n==="ls"){await qi(e);return}if(n==="get"){await Zi(t,e);return}throw Error(`Unknown agent subcommand: ${n}
|
|
404
405
|
|
|
405
|
-
${
|
|
406
|
+
${Q("agent")}`)}async function fo(e){let{manifest:n,config:t}=await ge({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),o=await Z(b(e,"--base-url")??t.baseUrl),r=await new G({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 qi(e){let{manifest:n,agents:t}=await fo(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=mo(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 Zi(e,n){if(!e)throw Error(`Missing agent name.
|
|
406
407
|
|
|
407
|
-
${
|
|
408
|
+
${Q("agent")}`);let{manifest:t,agents:o}=await fo(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,k)=>k===0?`${u} (default)`:u),a=Array.isArray(s.workspaces)?s.workspaces.map((u)=>typeof u==="string"?u:u.name).filter(Boolean):[],c=ye(s.tools)?Object.keys(s.tools):[],d=ye(s.channels)?Object.keys(s.channels):[],l=ye(s.subagent)&&Array.isArray(s.subagent.allowed)?s.subagent.allowed.map((u)=>typeof u==="string"?u:u.name).filter(Boolean):[],p=ye(s.hooks)&&Array.isArray(s.hooks.webhooks)?s.hooks.webhooks.filter(ye):[];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: ${mo(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,k)=>{let E=Array.isArray(u.events)&&u.events.length>0?u.events.join(", "):"all events",v=u.enabled===!1?"disabled":"enabled",O=typeof u.url==="string"?u.url:"none";console.log(` [${k}] ${v} → ${O} (${E})`)})}function mo(e){let n=ye(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 Xi(e){let[n,...t]=se(e);if(!n)throw Error(`Missing agent name.
|
|
408
409
|
|
|
409
|
-
${
|
|
410
|
+
${Q("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 ge({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),a=await Z(b(e,"--base-url")??i.baseUrl),c=s.resources.find((O)=>O.kind==="agent"&&O.name===n);if(!c)throw Error(`Unknown local agent: ${n}`);let l=(await new G({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 G({baseUrl:a.baseUrl,token:a.token}).getRuntimeKey(s.project,s.stage).catch(()=>null);if(p?.apiKey)await Se("BROODS_API_KEY",p.apiKey);if(c.config.publicAccess!==!0)A(`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}:{}}),k={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:E,streamAgentText:v}=await import("../chunk-5esx8msr.js");try{if(r){await E({client:u,agent:k,...o?{prompt:o}:{}});return}await v({client:u,agent:k,prompt:o})}catch(O){if((O instanceof Error?O.message:String(O)).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 O}}async function an(e,n,t){try{await Ee(e,n,{flag:t?"w":"wx"})}catch(o){if(o.code==="EEXIST")return;throw o}}async function ho(){let e=x(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
411
|
.env*.local
|
|
411
412
|
`:`.env*.local
|
|
412
|
-
`;await
|
|
413
|
+
`;await Ee(e,o,"utf8")}async function wo(){let e=x(process.cwd(),S,".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()+`
|
|
413
414
|
`+o.join(`
|
|
414
415
|
`)+`
|
|
415
416
|
`:o.join(`
|
|
416
417
|
`)+`
|
|
417
|
-
`;await
|
|
418
|
-
`).split(/\n/):["# Local broods CLI settings. Tokens are stored outside the repo."],i=!1;for(let[c,d]of Object.entries(r)){if(!d)continue;if(o[c]!==void 0&&!e.force)continue;let l=s.findIndex((p)=>p.trim().startsWith(`${c}=`));if(l>=0)s[l]=`${c}=${
|
|
418
|
+
`;await Ee(e,r,"utf8")}async function Yn(e){let n=x(process.cwd(),".env.local"),t=await Ce(n),o=bo(t),r={BROODS_DASHBOARD_URL:e.dashboardUrl,BROODS_BASE_URL:e.baseUrl,BROODS_PROJECT:e.project,BROODS_STAGE:e.stage,BROODS_REGION:e.region},s=t?t.replace(/\n?$/,`
|
|
419
|
+
`).split(/\n/):["# Local broods CLI settings. Tokens are stored outside the repo."],i=!1;for(let[c,d]of Object.entries(r)){if(!d)continue;if(o[c]!==void 0&&!e.force)continue;let l=s.findIndex((p)=>p.trim().startsWith(`${c}=`));if(l>=0)s[l]=`${c}=${cn(d)}`;else s.push(`${c}=${cn(d)}`);if(process.env[c]===void 0)process.env[c]=d;i=!0}if(!i&&t)return;let a=`${s.filter((c,d,l)=>!(c===""&&d===l.length-1)).join(`
|
|
419
420
|
`)}
|
|
420
|
-
`;await
|
|
421
|
-
`).split(/\n/):["# Local broods CLI settings. Tokens are stored outside the repo."],s=r.findIndex((a)=>a.trim().startsWith(`${e}=`));if(s>=0)r[s]=`${e}=${
|
|
421
|
+
`;await J(n,a),await ho()}async function Se(e,n){let t=x(process.cwd(),".env.local"),o=await Ce(t),r=o?o.replace(/\n?$/,`
|
|
422
|
+
`).split(/\n/):["# Local broods CLI settings. Tokens are stored outside the repo."],s=r.findIndex((a)=>a.trim().startsWith(`${e}=`));if(s>=0)r[s]=`${e}=${cn(n)}`;else r.push(`${e}=${cn(n)}`);process.env[e]=n;let i=`${r.filter((a,c,d)=>!(a===""&&c===d.length-1)).join(`
|
|
422
423
|
`)}
|
|
423
|
-
`;await
|
|
424
|
+
`;await J(t,i),await ho()}async function Ce(e){try{return await Qt(e,"utf8")}catch(n){if(n.code==="ENOENT")return"";throw n}}function bo(e){let n={};for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;let r=o.indexOf("=");if(r<=0)continue;n[o.slice(0,r).trim()]=o.slice(r+1).trim()}return n}function cn(e){return JSON.stringify(e)}function xe(e){return Ys(x(e)).replace(/^@/,"").replace(/\//g,"-").replace(/[^A-Za-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")||"broods-app"}async function Qi(){let e=x(process.cwd(),S),n=[];await Vn(e,n);let t=eo("sha256");for(let o of n.sort())t.update(Vs(e,o)),t.update("\x00"),t.update(await Qt(o)),t.update("\x00");return t.digest("hex")}async function Vn(e,n){let t=await Fs(e,{withFileTypes:!0});for(let o of t){let r=Ge(e,o.name);if(o.isDirectory()){if(o.name===w||o.name==="generated"||o.name===".cache")continue;await Vn(r,n);continue}if(o.isFile()&&(o.name.endsWith(".ts")||o.name.endsWith(".md")))n.push(r)}}function ea(e){return e.split(/[\\/]/).some((n)=>n===w||n==="generated"||n===".cache")}function yo(){return`import { defineAgent, defineSandbox, env } from "broods";
|
|
424
425
|
|
|
425
426
|
// A Lambda sandbox: a fresh, ephemeral bash environment created per run.
|
|
426
427
|
export const lambdaSandbox = defineSandbox({
|
|
@@ -449,4 +450,4 @@ export const myAgent = defineAgent({
|
|
|
449
450
|
// only reachable via internal endpoints or channel webhooks.
|
|
450
451
|
publicAccess: true,
|
|
451
452
|
});
|
|
452
|
-
`}function
|
|
453
|
+
`}function na(){if("bun"in process.versions)return;if(typeof Hs.registerHooks==="function")return;throw Error(`broods needs Node ${Le.engines.node.replace(">=","")} or newer, or Bun. This is Node ${process.version}.`)}function ta(e,n){if(e==="status")throw Error("status was renamed to whoami. Run `broods whoami`.");if(M(n,"--env")||b(n,"--env")!==void 0)throw Error("--env was renamed to --stage. Pass --stage <name> instead.");f();let t=process.env.BROODS_ENVIRONMENT;if(t!==void 0&&process.env.BROODS_STAGE===void 0)throw Error(`BROODS_ENVIRONMENT was renamed to BROODS_STAGE. Rename the key in .env.local (it is currently set to "${t}").`)}async function oa(){let e=f(),n=P(),[{createBroodsMcpServer:t},{serveStdio:o}]=await Promise.all([import("../chunk-qtvbrzvd.js"),import("../chunk-tgw6cmbm.js")]),r=n?new G({baseUrl:n.baseUrl,token:n.token}):null,s=t({allowDestructive:process.env.BROODS_MCP_ALLOW_DESTRUCTIVE==="1"&&T("BROODS_MCP_ALLOW_DESTRUCTIVE"),cli:r,scope:{project:e.project,stage:e.stage}});o(()=>s),await new Promise((i)=>{process.stdin.on("close",i)})}ti().catch((e)=>{jt(e instanceof Error?e.message:String(e)),process.exit(1)});export{le,ve,L};
|