broods 0.47.0 → 0.48.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 +4 -4
- package/dist/{chunk-cz62v9cj.js → chunk-11g7dgvw.js} +2 -2
- package/dist/{chunk-b68w0qr7.js → chunk-46v60rbx.js} +1 -1
- package/dist/{chunk-sqt7qff6.js → chunk-fb10617g.js} +1 -1
- package/dist/chunk-hb3c3xt9.js +5 -0
- package/dist/cli/index.js +5 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-agza3wkj.js +0 -5
package/dist/account.d.ts
CHANGED
|
@@ -334,9 +334,9 @@ interface AgentSessionPruningConfig {
|
|
|
334
334
|
}
|
|
335
335
|
/**
|
|
336
336
|
* Compaction after a finished turn, on unless `enabled: false`. It runs once
|
|
337
|
-
* the turn's last model call
|
|
338
|
-
* 500000)
|
|
339
|
-
* this says.
|
|
337
|
+
* the turn's last model call read `maxContextLength` input tokens or more
|
|
338
|
+
* (default 500000), or after the provider refused a turn for context length.
|
|
339
|
+
* `/compact` works whatever this says.
|
|
340
340
|
*/
|
|
341
341
|
interface AgentSessionAutoCompactionConfig {
|
|
342
342
|
enabled?: boolean;
|
|
@@ -1553,7 +1553,7 @@ declare class BroodsAccountClient {
|
|
|
1553
1553
|
resumeSandbox(sandboxId: string, reservationKey: string): Promise<SandboxLifecycleResult>;
|
|
1554
1554
|
/** Terminate a persistent sandbox reservation and drop its live-instance row. Throws on 404/403/409. */
|
|
1555
1555
|
terminateSandbox(sandboxId: string, reservationKey: string): Promise<SandboxLifecycleResult>;
|
|
1556
|
-
/** Snapshot a persistent sandbox reservation into a reusable image (
|
|
1556
|
+
/** Snapshot a persistent sandbox reservation into a reusable image (`sandbox`, or `lambda`, which answers `building` until its image build lands). Throws on 404/403/409. */
|
|
1557
1557
|
snapshotSandbox(sandboxId: string, reservationKey: string, name: string): Promise<SandboxSnapshotResult>;
|
|
1558
1558
|
/** Mint a short-lived sealed ticket for an interactive PTY session on a persistent sandbox (`sandbox`/`lambda`/`cloudflare` providers). Throws on 404/403/409. */
|
|
1559
1559
|
openSandboxTerminal(sandboxId: string, reservationKey: string): Promise<SandboxTerminalTicket>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{U,z}from"./chunk-
|
|
1
|
+
import{U,z}from"./chunk-hb3c3xt9.js";import{e,o,a,l,n,t,d,C,s,p,r}from"./chunk-n890pdvc.js";import{se,fe,D}from"./cli/index.js";import{spawn as te}from"node:child_process";import{hostname as oe}from"node:os";import{performance as L}from"node:perf_hooks";var N=["cursor_position","double_click","hold_key","key","left_click","left_click_drag","left_mouse_down","left_mouse_up","middle_click","mouse_move","right_click","screenshot","scroll","triple_click","type","wait","zoom"];var _={badFrame:{code:4400,reason:"Malformed frame"},occupied:{code:4423,reason:"Already connected from another daemon"},replaced:{code:4409,reason:"Replaced by a newer connection"},unauthorized:{code:4401,reason:"Unauthorized; run broods login"},unknownSandbox:{code:4404,reason:"No machine sandbox with that name in this account"}};var H="/v1/machines/ws",P=t({action:p(N),coordinate:n(o().int()).length(2).optional().describe("[x, y] in screenshot pixels for mouse actions."),start_coordinate:n(o().int()).length(2).optional().describe("[x, y] where a left_click_drag starts."),text:e().optional().describe("Text for type, the key chord for key and hold_key, or modifiers to hold during a click, drag or scroll."),scroll_direction:p(["down","left","right","up"]).optional(),scroll_amount:o().int().min(1).optional().describe("Scroll clicks, default 3."),duration:o().min(0).max(300).optional().describe("Seconds for wait and hold_key."),region:n(o().int()).length(4).optional().describe("[x0, y0, x1, y1] of the screenshot to zoom into."),repeat:o().int().min(1).max(100).optional().describe("How many times to press the key.")}),B=P.extend({type:r("computer"),id:e()}),W=t({type:r("computer-result"),id:e(),text:e().optional(),image:t({data:e(),mediaType:e()}).optional(),app:e().optional(),error:e().optional()}),G=t({type:r("exec"),id:e(),code:e(),cwd:e().optional(),env:s(e(),e()).optional(),timeoutSeconds:o().positive(),outputLimitBytes:o().positive()}),J=t({type:r("hello"),sandbox:e().min(1),hostname:e().optional(),platform:e().optional(),computer:a().optional(),mcp:n(e()).optional(),instance:e().optional(),force:a().optional()}),K=t({type:r("mcp-call"),id:e(),server:e(),tool:e(),args:s(e(),l())}),X=t({type:r("mcp-list"),id:e(),server:e()}),Y=t({type:r("mcp-result"),id:e(),result:d({content:n(l())}).optional(),error:e().optional()}),q=t({type:r("mcp-tools"),id:e(),tools:n(d({name:e(),inputSchema:s(e(),l())})).optional(),error:e().optional()}),Z=t({type:r("ready"),sandboxId:e()}),Q=t({type:r("result"),id:e(),exitCode:o().nullable(),stdout:e(),stderr:e(),durationMs:o(),timedOut:a(),truncated:a()}),V=C("type",[B,G,K,X,Z]),ue=C("type",[W,J,Y,q,Q]);function T(i){let c=new URL(H,i);return c.protocol=c.protocol==="https:"?"wss:":"ws:",c.toString()}function R(i){return ee(V,i)}function ee(i,c){if(typeof c!=="string")return null;try{let u=i.safeParse(JSON.parse(c));return u.success?u.data:null}catch{return null}}var re=new Set([_.occupied.code,_.replaced.code,_.unauthorized.code,_.unknownSandbox.code]),A=72,k=30000,I=1000;function ne(i,c,u){return new Promise((f)=>{let m=L.now(),h=new E(i.outputLimitBytes),w=new E(i.outputLimitBytes),b=!1,x=!1,M=(y,O)=>{if(x)return;if(x=!0,clearTimeout(v),u?.removeEventListener("abort",g),O)w.append(Buffer.from(`${O}
|
|
2
2
|
`));f({type:"result",id:i.id,exitCode:y,stdout:h.text(),stderr:w.text(),durationMs:Math.round(L.now()-m),timedOut:b,truncated:h.truncated||w.truncated})},F=te("bash",["-lc",i.code],{cwd:i.cwd??c,env:{...U(),...i.env},detached:!0,stdio:["ignore","pipe","pipe"]}),S=()=>{if(!F.pid)return;try{process.kill(-F.pid,"SIGKILL")}catch{F.kill("SIGKILL")}},v=setTimeout(()=>{b=!0,S()},i.timeoutSeconds*1000),g=()=>{S(),M(null,"stopped: the daemon closed its socket")};if(u?.addEventListener("abort",g,{once:!0}),F.stdout.on("data",(y)=>h.append(y)),F.stderr.on("data",(y)=>w.append(y)),F.on("error",(y)=>M(null,y.message)),F.on("close",(y)=>M(y)),u?.aborted)g()})}async function we(i){let c=fe(),u=crypto.randomUUID(),f=i.mcpFile?await ce(i.mcpFile,i.log):null,m=i.computer?await ae(i.log):null,h=I;try{while(!i.signal.aborted){let w=Date.now(),b;try{b=await i.credential()}catch(M){if(M instanceof D)throw M;i.log(`stage session unavailable (${M instanceof Error?M.message:String(M)}), retrying in ${Math.round(h/1000)}s`),await se(h,i.signal),h=Math.min(h*2,k);continue}let x=await pe(i,b,u,c,m,f);if(i.signal.aborted)return;if(re.has(x.code))throw Error(x.reason||`core closed the socket (${x.code})`);if(Date.now()-w>k)h=I;i.log(`disconnected (${x.reason||x.code}), reconnecting in ${Math.round(h/1000)}s`),await se(h,i.signal),h=Math.min(h*2,k)}}finally{m?.stop(),await f?.stop()}}class E{#o=[];#e;#t=0;truncated=!1;constructor(i){this.#e=i}append(i){if(this.#t>=this.#e){this.truncated=!0;return}let c=this.#e-this.#t;if(i.byteLength>c){this.#o.push(i.subarray(0,c)),this.#t=this.#e,this.truncated=!0;return}this.#o.push(i),this.#t+=i.byteLength}text(){let i=Buffer.concat(this.#o).toString("utf8");return this.truncated?`${i}
|
|
3
3
|
[output truncated]`:i}}function ie(i){let c=[i.action];if(i.coordinate)c.push(`at ${i.coordinate.join(",")}`);if(i.text!==void 0)c.push(JSON.stringify(j(i.text)));if(i.region)c.push(`region ${i.region.join(",")}`);return c.join(" ")}function j(i){let c=i.trim().split(`
|
|
4
|
-
`)[0]??"";return c.length>A?`${c.slice(0,A)}…`:c}async function ae(i){let{startDesktop:c}=await import("./chunk-5tnnqapc.js"),{display:u,driver:f,permissions:m}=await c(!1);if(i(`computer use on, ${u.width}x${u.height} screenshots`),!m.screenRecording||!m.accessibility)i(" screen recording or accessibility is missing, run `broods machine --doctor --request`");return f}async function ce(i,c){let{McpHost:u,readMcpServersFile:f}=await import("./chunk-
|
|
4
|
+
`)[0]??"";return c.length>A?`${c.slice(0,A)}…`:c}async function ae(i){let{startDesktop:c}=await import("./chunk-5tnnqapc.js"),{display:u,driver:f,permissions:m}=await c(!1);if(i(`computer use on, ${u.width}x${u.height} screenshots`),!m.screenRecording||!m.accessibility)i(" screen recording or accessibility is missing, run `broods machine --doctor --request`");return f}async function ce(i,c){let{McpHost:u,readMcpServersFile:f}=await import("./chunk-46v60rbx.js"),m=new u(f(i),c);return c(`mcp servers from ${i}: ${m.names().join(", ")}`),m}async function le(i,c,u){try{if(i.type==="mcp-list"){let m=await c.listTools(i.server);return u(` mcp ${i.server}: ${m.length} tools`),{type:"mcp-tools",id:i.id,tools:m}}u(` mcp ${i.server}.${i.tool}`);let f=await c.callTool(i.server,i.tool,i.args);return{type:"mcp-result",id:i.id,result:f}}catch(f){let m=f instanceof Error?f.message:String(f);return u(` mcp ${i.server}: ${m}`),{type:i.type==="mcp-call"?"mcp-result":"mcp-tools",id:i.id,error:m}}}function pe(i,c,u,f,m,h){return new Promise((w)=>{let b=new f(T(i.baseUrl),z(c)),x=new AbortController,M=()=>b.close(1000,"daemon stopped"),F=(v)=>{if(b.readyState===b.OPEN)b.send(JSON.stringify(v))},S=(v,g)=>{i.signal.removeEventListener("abort",M),x.abort(),w({code:v,reason:g})};i.signal.addEventListener("abort",M,{once:!0}),b.onopen=()=>F({type:"hello",sandbox:i.sandbox,hostname:oe(),platform:process.platform,computer:m!==null,mcp:h?.names(),instance:u,force:i.force}),b.onmessage=(v)=>{let g=R(v.data);if(g?.type==="ready"){i.log(`connected as ${i.sandbox} (${g.sandboxId})`);return}if(g?.type==="computer"&&m){i.log(` ${ie(g)}`),m.run(g).then((y)=>{if(y.error)i.log(` error: ${y.error}`);F(y)});return}if((g?.type==="mcp-call"||g?.type==="mcp-list")&&h){le(g,h,i.log).then(F);return}if(g?.type!=="exec")return;i.log(`$ ${j(g.code)}`),ne(g,i.cwd,x.signal).then((y)=>{i.log(` exit ${y.exitCode??"none"} in ${y.durationMs}ms${y.timedOut?" (timed out)":""}`),F(y)})},b.onerror=()=>S(1006,"connection failed"),b.onclose=(v)=>S(v.code,v.reason)})}export{we as runMachineDaemon};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{U}from"./chunk-
|
|
1
|
+
import{U}from"./chunk-hb3c3xt9.js";import{Oe,e,n,t,s}from"./chunk-n890pdvc.js";import{readFileSync as m}from"node:fs";import{dirname as d,resolve as p}from"node:path";import{Client as g}from"@modelcontextprotocol/client";import{StdioClientTransport as h}from"@modelcontextprotocol/client/stdio";var f={name:"broods-machine",version:"1.0.0"},u=t({command:e().min(1),args:n(e()).default([]),env:s(e(),e()).optional(),cwd:e().optional()}),w=t({mcpServers:s(e(),u).refine((r)=>Object.keys(r).length>0,"lists no MCP servers")});class y{#t=new Map;#e;#r;constructor(r,o){this.#r=r,this.#e=o}async callTool(r,o,i){return await(await this.#n(r)).callTool({name:o,arguments:i})}async listTools(r){return(await(await this.#n(r)).listTools()).tools}names(){return[...this.#r.keys()]}async stop(){let r=[...this.#t.values()];this.#t.clear(),await Promise.all(r.map((o)=>o.then((i)=>i.close()).catch(()=>{})))}#n(r){let o=this.#r.get(r);if(!o)return Promise.reject(Error(`no MCP server named "${r}" in the --mcp file`));let i=this.#t.get(r);if(i)return i;let c=(async()=>{this.#e(`mcp ${r}: ${[o.command,...o.args].join(" ")}`);let a=new h({...o,env:{...U(),...o.env},stderr:"inherit"});a.onclose=()=>{if(this.#e(`mcp ${r}: exited`),this.#t.get(r)===c)this.#t.delete(r)};let l=new g(f);return await l.connect(a),l})();return c.catch(()=>{if(this.#t.get(r)===c)this.#t.delete(r)}),this.#t.set(r,c),c}}function b(r){let o=p(r),i=w.safeParse(v(o));if(!i.success)throw Error(`${o}: ${Oe(i.error)}`);return new Map(Object.entries(i.data.mcpServers).map(([c,a])=>[c,a.cwd?{...a,cwd:p(d(o),a.cwd)}:a]))}function v(r){try{return JSON.parse(m(r,"utf8"))}catch(o){throw Error(`could not read ${r}: ${o instanceof Error?o.message:String(o)}`)}}export{y as McpHost,b as readMcpServersFile};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j}from"./chunk-r86n05ec.js";import{Z,R}from"./chunk-bb3jfhv3.js";import{e,o,a,l,s}from"./chunk-n890pdvc.js";var E={project:e().optional(),stage:e().optional()},M={sandboxId:e().min(1),reservationKey:e().min(1)},v=a().describe("Must be true, after the owner has agreed to this delete."),b="'********' keeps a stored secret and null deletes a field: never send a placeholder you did not read from a get.",A=[{singular:"agent",plural:"agents",key:"agentId",createHint:"Needs name and config; a 409 returns the existing agentId.",deleteHint:"Deleting an agent also drops its runtime rows.",updateHint:b,list:(t)=>t.listAgents(),get:(t,r)=>t.getAgent(r),create:(t,r)=>t.createAgent(r),update:(t,r,n)=>t.updateAgent(r,n),remove:(t,r)=>t.deleteAgent(r)},{singular:"cron",plural:"crons",key:"cronId",createHint:"Needs name, agentId, scheduleExpression (rate/cron/at) and input or events.",list:(t)=>t.listCrons(),get:(t,r)=>t.getCron(r),create:(t,r)=>t.createCron(r),update:(t,r,n)=>t.updateCron(r,n),remove:(t,r)=>t.deleteCron(r)},{singular:"sandbox",plural:"sandboxes",key:"sandboxId",updateHint:b,list:(t)=>t.listSandboxes(),get:(t,r)=>t.getSandbox(r),create:(t,r)=>t.createSandbox(r),update:(t,r,n)=>t.updateSandbox(r,n),remove:(t,r)=>t.deleteSandbox(r)},{singular:"workspace",plural:"workspaces",key:"workspaceId",list:(t)=>t.listWorkspaces(),get:(t,r)=>t.getWorkspace(r),create:(t,r)=>t.createWorkspace(r),update:(t,r,n)=>t.updateWorkspace(r,n),remove:(t,r)=>t.deleteWorkspace(r)},{singular:"policy",plural:"policies",key:"policyId",createHint:"Agent-runtime policy document (tool.call, skill.load), not API credential scoping.",list:(t)=>t.listPolicies(),get:(t,r)=>t.getPolicy(r),create:(t,r)=>t.createPolicy(r),update:(t,r,n)=>t.updatePolicy(r,n),remove:(t,r)=>t.deletePolicy(r)},{singular:"role",plural:"roles",key:"roleId",createHint:"Needs name and a version-1 policy over the API namespace, e.g. agents:read. Account key only.",list:(t)=>t.listRoles(),get:(t,r)=>t.getRole(r),create:(t,r)=>t.createRole(r),update:(t,r,n)=>t.updateRole(r,n),remove:(t,r)=>t.deleteRole(r)},{singular:"channel",plural:"channels",key:"channelId",list:(t)=>t.listChannels(),get:(t,r)=>t.getChannel(r),create:(t,r)=>t.createChannel(r),update:(t,r,n)=>t.updateChannel(r,n),remove:(t,r)=>t.deleteChannel(r)},{singular:"skill",plural:"skills",key:"skillName",createHint:'source is "files" (base64), "json" or "github". The stored name comes from the SKILL.md frontmatter.',list:(t)=>t.listSkills(),get:(t,r)=>t.getSkill(r),create:(t,r)=>t.createSkill(r),remove:(t,r)=>t.deleteSkill(r)},{singular:"mcp",plural:"mcp",key:"serverId",scoped:!0,list:(t,r)=>t.listMcp(r),get:(t,r)=>t.getMcp(r),create:(t,r,n)=>t.createMcp(n,r),update:(t,r,n)=>t.updateMcp(r,n),remove:(t,r)=>t.deleteMcp(r)}];function Pt(t={}){let r=Z()?new R({}):null;if(!r&&!t.cli)throw Error("broods mcp needs a credential: set BROODS_SESSION_TOKEN or BROODS_ACCOUNT_SECRET, or run `broods login`.");let n=new j({name:"broods",version:"1"},{capabilities:{tools:{}}});if(r){for(let i of A)x(n,r,i,t.scope??{});N(n,r)}if(t.cli)O(n,t.cli);if(t.allowDestructive)q(n,r,t.cli??null);return n}function y(t,r){if(!t)throw Error(`Refusing without confirm:true. ${r}`)}async function d(t){try{return P(await t())}catch(r){return k(r)}}function k(t){return{content:[{type:"text",text:t instanceof Error?t.message:String(t)}],isError:!0}}function P(t){return{content:[{type:"text",text:JSON.stringify(t??null,null,2)}]}}function T(t,r,n,i){if(!t.scoped)return;let c=n??r.project,p=i??r.stage;if(!c||!p)throw Error(`${t.plural} live in one stage, so this call needs both 'project' and 'stage'`);return{project:c,stage:p}}function O(t,r){t.registerTool("list-orgs",{description:"Every organization this login can reach, with the current one marked.",inputSchema:{}},async()=>await d(async()=>{let n=await r.getOnboarding();return{currentOrgId:n.currentOrgId,orgs:n.orgs}})),t.registerTool("create-org",{description:"Create an organization and switch this login to it. Later calls act in the new org.",inputSchema:{name:e().min(1)}},async({name:n})=>await d(async()=>await r.createOnboardingOrg(n))),t.registerTool("select-org",{description:"Switch this login to another organization, by an orgId from list-orgs.",inputSchema:{orgId:e().min(1)}},async({orgId:n})=>await d(async()=>await r.selectOnboardingOrg(n))),t.registerTool("list-projects",{description:"Every project in the current org, empty ones last. Project names are not unique, so take the id from here.",inputSchema:{}},async()=>await d(async()=>await r.listProjects())),t.registerTool("list-stages",{description:"Every stage of one project, by project name.",inputSchema:{project:e().min(1)}},async({project:n})=>await d(async()=>await r.listStages(n))),t.registerTool("create-stage",{description:"Create a stage in a project, optionally cloning another stage's architecture and env vars. A project name that does not exist yet is created with it, which is the only way to make a project without deploying a manifest.",inputSchema:{project:e().min(1),name:e().min(1),from:e().optional().describe("Stage to clone architecture and env vars from.")}},async({project:n,name:i,from:c})=>await d(async()=>await r.createStage(n,i,c)))}function q(t,r,n){if(r)t.registerTool("rotate-secret",{description:"Rotate the account key. The current key stops working immediately and the new one is shown once, so this breaks every deployment and CI job still holding the old one. Requires confirm:true.",inputSchema:{confirm:v}},async({confirm:i})=>await d(async()=>(y(i,"Everything holding the current secret breaks the moment this runs."),await r.rotateSecret())));if(n)t.registerTool("delete-project",{description:"Delete a project and everything under it: stages, agents, canvas, env vars, crons and workspace files. Takes a projectId from list-projects and requires confirm:true.",inputSchema:{projectId:e().min(1),confirm:v}},async({projectId:i,confirm:c})=>await d(async()=>(y(c,`Project '${i}' and everything under it goes away: name it, get the owner's agreement, then retry.`),await n.deleteProject(i))))}function N(t,r){t.registerTool("list-cron-runs",{description:"Run history for one cron, newest first. Check this before telling anyone a cron fired.",inputSchema:{cronId:e().min(1),limit:o().int().positive().max(100).optional()}},async({cronId:i,limit:c})=>await d(async()=>await r.listCronRuns(i,c===void 0?{}:{limit:c})));let n=[["suspend-sandbox","Suspend a persistent sandbox reservation.",(i,c)=>r.suspendSandbox(i,c)],["resume-sandbox","Resume a suspended sandbox reservation.",(i,c)=>r.resumeSandbox(i,c)],["terminate-sandbox","Terminate a sandbox reservation and drop its live-instance row. Terminate only a sandbox you created, and never one holding state you did not put there.",(i,c)=>r.terminateSandbox(i,c)],["open-sandbox-terminal","Mint a short-lived sealed ticket for an interactive PTY session on a persistent sandbox.",(i,c)=>r.openSandboxTerminal(i,c)]];for(let[i,c,p]of n)t.registerTool(i,{description:c,inputSchema:M},async({sandboxId:f,reservationKey:g})=>await d(async()=>await p(f,g)));t.registerTool("snapshot-sandbox",{description:"Snapshot a sandbox reservation into a reusable image (self-hosted provider).",inputSchema:{sandboxId:e().min(1),reservationKey:e().min(1),name:e().min(1)}},async({sandboxId:i,reservationKey:c,name:p})=>await d(async()=>await r.snapshotSandbox(i,c,p))),t.registerTool("upload-skill",{description:"Replace one skill's bundle wholesale (PUT, not a merge) by skillName. 'body' is the same source shape create-skill takes.",inputSchema:{id:e().min(1).describe("The skillName."),body:s(e(),l())}},async({id:i,body:c})=>await d(async()=>await r.uploadSkill(i,c))),t.registerTool("list-env-vars",{description:"List environment variable names. Values are write-only: the plane never returns them, so there is no read.",inputSchema:{}},async()=>await d(async()=>await r.listEnvVars())),t.registerTool("set-env-var",{description:"Create or replace one write-only environment variable. Reference it from a config as ${NAME} rather than inlining the value.",inputSchema:{name:e().min(1),value:e()}},async({name:i,value:c})=>await d(async()=>(await r.setEnvVar(i,c),{name:i,stored:!0}))),t.registerTool("delete-env-var",{description:"Delete one environment variable.",inputSchema:{name:e().min(1),confirm:v}},async({name:i,confirm:c})=>await d(async()=>(y(c,`Anything referencing \${${i}} breaks the moment this env var goes.`),{deleted:await r.deleteEnvVar(i),name:i}))),t.registerTool("assume-role",{description:"Exchange a role for a short-lived session token (default 1h, max 12h). Hand the returned token to whatever tool needs narrow access, as BROODS_SESSION_TOKEN. It is shown once and is not stored here.",inputSchema:{roleId:e().min(1),ttlSeconds:o().int().positive().max(43200).optional()}},async({roleId:i,ttlSeconds:c})=>await d(async()=>await r.assumeRole(i,c===void 0?{}:{ttlSeconds:c}))),t.registerTool("update-account",{description:"Rename this account or change its description. Everything else about an account is derived, not settable.",inputSchema:{username:e().optional(),description:e().nullable().optional()}},async({username:i,description:c})=>await d(async()=>await r.updateAccount({...i===void 0?{}:{username:i},...c===void 0?{}:{description:c}}))),t.registerTool("get-account",{description:"The account this server's credential resolves to. Run it first to confirm which tenant you are about to change.",inputSchema:{}},async()=>await d(async()=>await r.getAccount()))}function x(t,r,n,i){let c=e().min(1).describe(`The ${n.key}.`),p=n.scoped?` ${n.plural} live in one stage, so this also takes 'project' and 'stage'.`:"",{list:f,get:g,create:w,update:S,remove:_}=n;if(f){let u=`List every ${n.singular} on the account.${p}`;if(n.scoped)t.registerTool(`list-${n.plural}`,{description:u,inputSchema:E},async({project:h,stage:m})=>await d(async()=>await f(r,T(n,i,h,m))));else t.registerTool(`list-${n.plural}`,{description:u,inputSchema:{}},async()=>await d(async()=>await f(r)))}if(g)t.registerTool(`get-${n.singular}`,{description:`Read one ${n.singular} by ${n.key}.`,inputSchema:{id:c}},async({id:u})=>await d(async()=>await g(r,u)));if(w){let u=`Create one ${n.singular}. 'body' is the request body the config plane documents.`+(n.createHint?` ${n.createHint}`:"")+p+" Prefer changing the broods/ manifest and deploying for anything the project already declares.",h=s(e(),l());if(n.scoped)t.registerTool(`create-${n.singular}`,{description:u,inputSchema:{body:h,...E}},async({body:m,project:I,stage:C})=>await d(async()=>await w(r,m,T(n,i,I,C))));else t.registerTool(`create-${n.singular}`,{description:u,inputSchema:{body:h}},async({body:m})=>await d(async()=>await w(r,m)))}if(S)t.registerTool(`update-${n.singular}`,{description:`Deep-merge a patch into one ${n.singular} and return the updated record, so there is no need to read it back.`+(n.updateHint?` ${n.updateHint}`:""),inputSchema:{id:c,body:s(e(),l())}},async({id:u,body:h})=>await d(async()=>await S(r,u,h)));if(_)t.registerTool(`delete-${n.singular}`,{description:`Delete one ${n.singular}. Requires confirm:true, and takes one ${n.key} per call: never loop this over a list.`+(n.deleteHint?` ${n.deleteHint}`:""),inputSchema:{id:c,confirm:v}},async({id:u,confirm:h})=>await d(async()=>(y(h,`Deleting ${n.singular} '${u}' goes away for good: name it, get the owner's agreement, then retry.`),{deleted:await _(r,u),id:u})))}export{Pt as createBroodsMcpServer};
|
|
1
|
+
import{j}from"./chunk-r86n05ec.js";import{Z,R}from"./chunk-bb3jfhv3.js";import{e,o,a,l,s}from"./chunk-n890pdvc.js";var E={project:e().optional(),stage:e().optional()},M={sandboxId:e().min(1),reservationKey:e().min(1)},v=a().describe("Must be true, after the owner has agreed to this delete."),b="'********' keeps a stored secret and null deletes a field: never send a placeholder you did not read from a get.",A=[{singular:"agent",plural:"agents",key:"agentId",createHint:"Needs name and config; a 409 returns the existing agentId.",deleteHint:"Deleting an agent also drops its runtime rows.",updateHint:b,list:(t)=>t.listAgents(),get:(t,r)=>t.getAgent(r),create:(t,r)=>t.createAgent(r),update:(t,r,n)=>t.updateAgent(r,n),remove:(t,r)=>t.deleteAgent(r)},{singular:"cron",plural:"crons",key:"cronId",createHint:"Needs name, agentId, scheduleExpression (rate/cron/at) and input or events.",list:(t)=>t.listCrons(),get:(t,r)=>t.getCron(r),create:(t,r)=>t.createCron(r),update:(t,r,n)=>t.updateCron(r,n),remove:(t,r)=>t.deleteCron(r)},{singular:"sandbox",plural:"sandboxes",key:"sandboxId",updateHint:b,list:(t)=>t.listSandboxes(),get:(t,r)=>t.getSandbox(r),create:(t,r)=>t.createSandbox(r),update:(t,r,n)=>t.updateSandbox(r,n),remove:(t,r)=>t.deleteSandbox(r)},{singular:"workspace",plural:"workspaces",key:"workspaceId",list:(t)=>t.listWorkspaces(),get:(t,r)=>t.getWorkspace(r),create:(t,r)=>t.createWorkspace(r),update:(t,r,n)=>t.updateWorkspace(r,n),remove:(t,r)=>t.deleteWorkspace(r)},{singular:"policy",plural:"policies",key:"policyId",createHint:"Agent-runtime policy document (tool.call, skill.load), not API credential scoping.",list:(t)=>t.listPolicies(),get:(t,r)=>t.getPolicy(r),create:(t,r)=>t.createPolicy(r),update:(t,r,n)=>t.updatePolicy(r,n),remove:(t,r)=>t.deletePolicy(r)},{singular:"role",plural:"roles",key:"roleId",createHint:"Needs name and a version-1 policy over the API namespace, e.g. agents:read. Account key only.",list:(t)=>t.listRoles(),get:(t,r)=>t.getRole(r),create:(t,r)=>t.createRole(r),update:(t,r,n)=>t.updateRole(r,n),remove:(t,r)=>t.deleteRole(r)},{singular:"channel",plural:"channels",key:"channelId",list:(t)=>t.listChannels(),get:(t,r)=>t.getChannel(r),create:(t,r)=>t.createChannel(r),update:(t,r,n)=>t.updateChannel(r,n),remove:(t,r)=>t.deleteChannel(r)},{singular:"skill",plural:"skills",key:"skillName",createHint:'source is "files" (base64), "json" or "github". The stored name comes from the SKILL.md frontmatter.',list:(t)=>t.listSkills(),get:(t,r)=>t.getSkill(r),create:(t,r)=>t.createSkill(r),remove:(t,r)=>t.deleteSkill(r)},{singular:"mcp",plural:"mcp",key:"serverId",scoped:!0,list:(t,r)=>t.listMcp(r),get:(t,r)=>t.getMcp(r),create:(t,r,n)=>t.createMcp(n,r),update:(t,r,n)=>t.updateMcp(r,n),remove:(t,r)=>t.deleteMcp(r)}];function Pt(t={}){let r=Z()?new R({}):null;if(!r&&!t.cli)throw Error("broods mcp needs a credential: set BROODS_SESSION_TOKEN or BROODS_ACCOUNT_SECRET, or run `broods login`.");let n=new j({name:"broods",version:"1"},{capabilities:{tools:{}}});if(r){for(let i of A)x(n,r,i,t.scope??{});N(n,r)}if(t.cli)O(n,t.cli);if(t.allowDestructive)q(n,r,t.cli??null);return n}function y(t,r){if(!t)throw Error(`Refusing without confirm:true. ${r}`)}async function d(t){try{return P(await t())}catch(r){return k(r)}}function k(t){return{content:[{type:"text",text:t instanceof Error?t.message:String(t)}],isError:!0}}function P(t){return{content:[{type:"text",text:JSON.stringify(t??null,null,2)}]}}function T(t,r,n,i){if(!t.scoped)return;let c=n??r.project,p=i??r.stage;if(!c||!p)throw Error(`${t.plural} live in one stage, so this call needs both 'project' and 'stage'`);return{project:c,stage:p}}function O(t,r){t.registerTool("list-orgs",{description:"Every organization this login can reach, with the current one marked.",inputSchema:{}},async()=>await d(async()=>{let n=await r.getOnboarding();return{currentOrgId:n.currentOrgId,orgs:n.orgs}})),t.registerTool("create-org",{description:"Create an organization and switch this login to it. Later calls act in the new org.",inputSchema:{name:e().min(1)}},async({name:n})=>await d(async()=>await r.createOnboardingOrg(n))),t.registerTool("select-org",{description:"Switch this login to another organization, by an orgId from list-orgs.",inputSchema:{orgId:e().min(1)}},async({orgId:n})=>await d(async()=>await r.selectOnboardingOrg(n))),t.registerTool("list-projects",{description:"Every project in the current org, empty ones last. Project names are not unique, so take the id from here.",inputSchema:{}},async()=>await d(async()=>await r.listProjects())),t.registerTool("list-stages",{description:"Every stage of one project, by project name.",inputSchema:{project:e().min(1)}},async({project:n})=>await d(async()=>await r.listStages(n))),t.registerTool("create-stage",{description:"Create a stage in a project, optionally cloning another stage's architecture and env vars. A project name that does not exist yet is created with it, which is the only way to make a project without deploying a manifest.",inputSchema:{project:e().min(1),name:e().min(1),from:e().optional().describe("Stage to clone architecture and env vars from.")}},async({project:n,name:i,from:c})=>await d(async()=>await r.createStage(n,i,c)))}function q(t,r,n){if(r)t.registerTool("rotate-secret",{description:"Rotate the account key. The current key stops working immediately and the new one is shown once, so this breaks every deployment and CI job still holding the old one. Requires confirm:true.",inputSchema:{confirm:v}},async({confirm:i})=>await d(async()=>(y(i,"Everything holding the current secret breaks the moment this runs."),await r.rotateSecret())));if(n)t.registerTool("delete-project",{description:"Delete a project and everything under it: stages, agents, canvas, env vars, crons and workspace files. Takes a projectId from list-projects and requires confirm:true.",inputSchema:{projectId:e().min(1),confirm:v}},async({projectId:i,confirm:c})=>await d(async()=>(y(c,`Project '${i}' and everything under it goes away: name it, get the owner's agreement, then retry.`),await n.deleteProject(i))))}function N(t,r){t.registerTool("list-cron-runs",{description:"Run history for one cron, newest first. Check this before telling anyone a cron fired.",inputSchema:{cronId:e().min(1),limit:o().int().positive().max(100).optional()}},async({cronId:i,limit:c})=>await d(async()=>await r.listCronRuns(i,c===void 0?{}:{limit:c})));let n=[["suspend-sandbox","Suspend a persistent sandbox reservation.",(i,c)=>r.suspendSandbox(i,c)],["resume-sandbox","Resume a suspended sandbox reservation.",(i,c)=>r.resumeSandbox(i,c)],["terminate-sandbox","Terminate a sandbox reservation and drop its live-instance row. Terminate only a sandbox you created, and never one holding state you did not put there.",(i,c)=>r.terminateSandbox(i,c)],["open-sandbox-terminal","Mint a short-lived sealed ticket for an interactive PTY session on a persistent sandbox.",(i,c)=>r.openSandboxTerminal(i,c)]];for(let[i,c,p]of n)t.registerTool(i,{description:c,inputSchema:M},async({sandboxId:f,reservationKey:g})=>await d(async()=>await p(f,g)));t.registerTool("snapshot-sandbox",{description:"Snapshot a sandbox reservation into a reusable image (sandbox or lambda provider; lambda builds for a few minutes).",inputSchema:{sandboxId:e().min(1),reservationKey:e().min(1),name:e().min(1)}},async({sandboxId:i,reservationKey:c,name:p})=>await d(async()=>await r.snapshotSandbox(i,c,p))),t.registerTool("upload-skill",{description:"Replace one skill's bundle wholesale (PUT, not a merge) by skillName. 'body' is the same source shape create-skill takes.",inputSchema:{id:e().min(1).describe("The skillName."),body:s(e(),l())}},async({id:i,body:c})=>await d(async()=>await r.uploadSkill(i,c))),t.registerTool("list-env-vars",{description:"List environment variable names. Values are write-only: the plane never returns them, so there is no read.",inputSchema:{}},async()=>await d(async()=>await r.listEnvVars())),t.registerTool("set-env-var",{description:"Create or replace one write-only environment variable. Reference it from a config as ${NAME} rather than inlining the value.",inputSchema:{name:e().min(1),value:e()}},async({name:i,value:c})=>await d(async()=>(await r.setEnvVar(i,c),{name:i,stored:!0}))),t.registerTool("delete-env-var",{description:"Delete one environment variable.",inputSchema:{name:e().min(1),confirm:v}},async({name:i,confirm:c})=>await d(async()=>(y(c,`Anything referencing \${${i}} breaks the moment this env var goes.`),{deleted:await r.deleteEnvVar(i),name:i}))),t.registerTool("assume-role",{description:"Exchange a role for a short-lived session token (default 1h, max 12h). Hand the returned token to whatever tool needs narrow access, as BROODS_SESSION_TOKEN. It is shown once and is not stored here.",inputSchema:{roleId:e().min(1),ttlSeconds:o().int().positive().max(43200).optional()}},async({roleId:i,ttlSeconds:c})=>await d(async()=>await r.assumeRole(i,c===void 0?{}:{ttlSeconds:c}))),t.registerTool("update-account",{description:"Rename this account or change its description. Everything else about an account is derived, not settable.",inputSchema:{username:e().optional(),description:e().nullable().optional()}},async({username:i,description:c})=>await d(async()=>await r.updateAccount({...i===void 0?{}:{username:i},...c===void 0?{}:{description:c}}))),t.registerTool("get-account",{description:"The account this server's credential resolves to. Run it first to confirm which tenant you are about to change.",inputSchema:{}},async()=>await d(async()=>await r.getAccount()))}function x(t,r,n,i){let c=e().min(1).describe(`The ${n.key}.`),p=n.scoped?` ${n.plural} live in one stage, so this also takes 'project' and 'stage'.`:"",{list:f,get:g,create:w,update:S,remove:_}=n;if(f){let u=`List every ${n.singular} on the account.${p}`;if(n.scoped)t.registerTool(`list-${n.plural}`,{description:u,inputSchema:E},async({project:h,stage:m})=>await d(async()=>await f(r,T(n,i,h,m))));else t.registerTool(`list-${n.plural}`,{description:u,inputSchema:{}},async()=>await d(async()=>await f(r)))}if(g)t.registerTool(`get-${n.singular}`,{description:`Read one ${n.singular} by ${n.key}.`,inputSchema:{id:c}},async({id:u})=>await d(async()=>await g(r,u)));if(w){let u=`Create one ${n.singular}. 'body' is the request body the config plane documents.`+(n.createHint?` ${n.createHint}`:"")+p+" Prefer changing the broods/ manifest and deploying for anything the project already declares.",h=s(e(),l());if(n.scoped)t.registerTool(`create-${n.singular}`,{description:u,inputSchema:{body:h,...E}},async({body:m,project:I,stage:C})=>await d(async()=>await w(r,m,T(n,i,I,C))));else t.registerTool(`create-${n.singular}`,{description:u,inputSchema:{body:h}},async({body:m})=>await d(async()=>await w(r,m)))}if(S)t.registerTool(`update-${n.singular}`,{description:`Deep-merge a patch into one ${n.singular} and return the updated record, so there is no need to read it back.`+(n.updateHint?` ${n.updateHint}`:""),inputSchema:{id:c,body:s(e(),l())}},async({id:u,body:h})=>await d(async()=>await S(r,u,h)));if(_)t.registerTool(`delete-${n.singular}`,{description:`Delete one ${n.singular}. Requires confirm:true, and takes one ${n.key} per call: never loop this over a list.`+(n.deleteHint?` ${n.deleteHint}`:""),inputSchema:{id:c,confirm:v}},async({id:u,confirm:h})=>await d(async()=>(y(h,`Deleting ${n.singular} '${u}' goes away for good: name it, get the owner's agreement, then retry.`),{deleted:await _(r,u),id:u})))}export{Pt as createBroodsMcpServer};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
function V(e){if(e.events&&e.input!==void 0)throw Error("Run input accepts either `input` or `events`, not both");if(e.events&&e.events.length>0)return e.events;if(typeof e.input==="string")return[{role:"user",content:[{type:"text",text:e.input}]}];throw Error("Run input requires `input` (string) or a non-empty `events` array")}async function*ge(e){let n=e.getReader(),t=new TextDecoder,o="";try{while(!0){let{done:r,value:i}=await n.read();if(r)break;o+=t.decode(i,{stream:!0});let s=o.split(`
|
|
2
|
+
`);o=s.pop()??"";for(let a of s)if(a.startsWith("data: "))yield a.slice(6)}}finally{n.releaseLock()}}var Me=500,Ce=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,he=/^(?!0{32}$)[0-9a-f]{32}$/;function Pe(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function Ne(e){if(typeof e!=="object"||e===null)return!1;let n=e;if(n.type==="subscribe")return Re(n);if(n.type==="unsubscribe")return k(n.stream);if(n.type==="fetchTrace")return Ie(n.traceId);return!1}function je(e){return e==="task"||e==="cron"||e==="subtask"}function G(e){return typeof e==="string"&&Ce.test(e)}function Ie(e){return typeof e==="string"&&he.test(e)}function k(e){return e==="logs"||e==="traces"}function Re(e){let n=e.stream;if(!k(n))return!1;let t=e.backfill;if(t!==void 0&&(typeof t!=="number"||!Number.isSafeInteger(t)||t<0||t>500))return!1;if(e.liveOnly!==void 0&&typeof e.liveOnly!=="boolean")return!1;let o=e.minLevel;if(o!==void 0&&!Pe(o))return!1;let r=e.sandboxId;return r===void 0||n==="logs"&&G(r)}import{readFileSync as Se}from"node:fs";import{chmod as B,mkdir as be,writeFile as Ae}from"node:fs/promises";import{homedir as ke}from"node:os";import{dirname as D,join as ve}from"node:path";var y="broods",_="_generated",O=ve(ke(),".broods","config.json"),N="broods.app",P="dashboard",we="gateway";function T(e){let n=process.env.BROODS_TOKEN,t=e??process.env.BROODS_BASE_URL;if(n&&t)return{baseUrl:f(t),token:n,createdAt:new Date().toISOString()};let o=H();if(!o)return null;if(t)return o.logins[f(t)]??null;let r=process.env.BROODS_DASHBOARD_URL;if(r){let i=f(r);return Object.values(o.logins).find((s)=>s.dashboardUrl===i)??null}return o.logins[o.current]??null}async function W(e){let n=H()?.logins??{},t={current:e.baseUrl,logins:{...n,[e.baseUrl]:e}};await be(D(O),{recursive:!0,mode:448}),await B(D(O),448),await K(O,`${JSON.stringify(t,null,2)}
|
|
3
|
+
`)}async function K(e,n){await Ae(e,n,{encoding:"utf8",mode:384}),await B(e,384)}function v(){return process.env.BROODS_STAGE}function f(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function L(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${P}.`))return;let t=n.hostname.slice(P.length+1);if(t!==N&&!t.endsWith(`.${N}`))return;return n.hostname=`${we}.${t}`,f(n.origin)}catch{return}}function H(){try{let e=JSON.parse(Se(O,"utf8"));if(typeof e.current!=="string"||!e.logins)return null;return{current:e.current,logins:e.logins}}catch{return null}}import{existsSync as q,readFileSync as Z,statSync as Ee}from"node:fs";import{join as X,resolve as Q}from"node:path";var A=new Map,Te=new Set(Object.keys(process.env)),j=new Set;function h(e=process.cwd()){Oe(e);let n=T();return{dashboardUrl:process.env.BROODS_DASHBOARD_URL??n?.dashboardUrl,baseUrl:process.env.BROODS_BASE_URL??n?.baseUrl,token:n?.token,project:process.env.BROODS_PROJECT,stage:v()}}function U(){let e={};for(let[n,t]of Object.entries(process.env))if(typeof t==="string"&&!n.startsWith("BROODS_"))e[n]=t;return e}function M(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=Q(n);for(let r of[".env.local",".env"]){let i=X(o,r);if(!q(i))continue;let s=ee(Z(i,"utf8"));if(s[e]!==void 0)return s[e]!==t}return!0}function Oe(e){let n=Q(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=X(n,o);if(!q(r)){A.delete(r);continue}let i=Ee(r).mtimeMs,s=A.get(r);if(s&&s.mtimeMs===i)continue;A.set(r,{mtimeMs:i});for(let[a,p]of Object.entries(ee(Z(r,"utf8"))))if(t||!Te.has(a)||j.has(a))process.env[a]=p,j.add(a)}}function ee(e){let n={};for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;let r=o.startsWith("export ")?o.slice(7).trim():o,i=r.indexOf("=");if(i<=0)continue;let s=r.slice(0,i).trim();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(s))continue;n[s]=_e(r.slice(i+1).trim())}return n}function _e(e){if(e.startsWith('"')&&e.endsWith('"'))return e.slice(1,-1).replace(/\\n/g,`
|
|
4
|
+
`).replace(/\\"/g,'"');if(e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);let n=e.indexOf(" #");return n>=0?e.slice(0,n).trimEnd():e}var E="https://gateway.broods.app";class ye extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class F{baseUrl;apiKey;fetchImpl;constructor(e={}){h(),this.baseUrl=J(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||E),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||void 0,this.fetchImpl=e.fetch??fetch}channelWebhookUrl(e){return`${this.baseUrl}${e.webhookPath.startsWith("/")?"":"/"}${e.webhookPath}`}accountWebhookUrl(e,n){let t=[e,n].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${t.join("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(i)=>this.run({...i,agentName:o,agentId:r}),runAsync:(i)=>this.runAsync({...i,agentName:o,agentId:r}),continue:(i)=>this.continue({...i,agentId:r}),stream:(i)=>this.stream({...i,agentName:o,agentId:r})}}let t=e;if(!t.id)throw Error(`Agent ${t.name} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:t.id,run:(o)=>this.run(t,o),runAsync:(o)=>this.runAsync(t,o),continue:(o)=>this.continue(t,o),stream:(o)=>this.stream(t,o)}}async run(e,n){let t=[],o="",r=n?this.stream(e,n):this.stream(e);for await(let i of r)if(t.push(i),i.type==="text-delta")o+=i.text;return{text:o,events:t}}async*stream(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=ne(t,"cli"),r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`,i=await this.openStream(o,r);if(!i.ok)throw Error(`Run failed: ${i.status} ${await i.text()}`);if(i.status===202)throw new ye(te(await i.json(),o));if(!i.body)throw Error("Run response has no body");for await(let s of ge(i.body)){let a;try{a=JSON.parse(s)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${$e(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o={...ne(t,"async"),background:!0},r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(r,o,"Async run")}async continue(e,n){let t=n?e:null,o=n??e,r={agentId:t?t.id:e.agentId,eventId:o.eventId??`continue-${crypto.randomUUID()}`,conversationKey:o.conversationKey,continue:!0},i=t?this.scopedUrl(t):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(i,r,"Continue")}async getAsyncStatus(e){let n=this.resolveStatusUrl(e),t=await this.fetchJson(n,{method:"GET",headers:this.apiKeyHeaders()});if(t.status===404)return{status:"not_found"};if(!t.ok)throw Error(`Status check failed: ${t.status} ${await t.text()}`);return await t.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e);if(r.status==="awaiting_approval"||r.status==="awaiting_input"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await en(o,n.signal)}throw Error("Polling timeout")}scopedUrl(e){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/projects/${encodeURIComponent(e.projectSlug)}/stages/${encodeURIComponent(e.stageSlug)}/agents/${encodeURIComponent(e.endpointId)}`;return`${this.baseUrl}/v1/runs`}asyncAgentRun(e,n){return{...e,conversationKey:n,poll:()=>this.getAsyncStatus(e),wait:(t)=>this.waitForAsyncStatus(e,t)}}async postAcceptedRun(e,n,t){let o=await this.fetchJson(e,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(n)});if(o.status!==202)throw Error(`${t} failed: ${o.status} ${await ze(o,"202 JSON")}`);return this.asyncAgentRun(te(await o.json(),n),n.conversationKey)}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${E} by default; set host/baseUrl or BROODS_HOST/BROODS_BASE_URL to your own core service URL if your account uses a custom deployment. Cause: ${o instanceof Error?o.message:String(o)}`)}}apiKeyHeaders(){if(!this.apiKey)throw Error("BroodsClient requires apiKey or BROODS_API_KEY.");return{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}async fetchJson(e,n){try{return await this.fetchImpl(e,n)}catch(t){throw Error(`Cannot access the broods core service at ${e}. Cause: ${t instanceof Error?t.message:String(t)}`)}}resolveStatusUrl(e){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;return nn(this.baseUrl,e)}}function J(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return f(t)}function ne(e,n){let t=e.eventId??`${n}-${crypto.randomUUID()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:V(e),...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}}function $e(e){if(typeof e==="string")return e;if(!e||typeof e!=="object")return String(e);let n=e,t=n.data?.error?.message??n.message??n.responseBody??JSON.stringify(e),o=n.name?`${n.name}: `:"",r=n.statusCode?` (HTTP ${n.statusCode})`:"";return`${o}${t}${r}`}function te(e,n){if(!e||typeof e!=="object")throw Error("Async response must be an object");let t=e.statusUrl;if(typeof t!=="string"||t.length===0)throw Error("Async response missing statusUrl");let o=e.runId;if(typeof o!=="string"||o.length===0)throw Error("Async response missing runId");let r=typeof e.eventId==="string"?e.eventId:o,{status:i,requestedMode:s}=e;return{statusUrl:t,runId:o,eventId:r,agentId:n.agentId,...i==="accepted"||i==="queued"||i==="applied"||i==="processing"?{status:i}:{},...s==="reject"||s==="followup"||s==="collect"||s==="steer"?{requestedMode:s}:{}}}async function ze(e,n){if((e.headers.get("content-type")??"").toLowerCase().includes("text/event-stream"))return await e.body?.cancel().catch(()=>{}),`expected ${n}, but the server returned an SSE stream. This usually means the core deployment ignored the background flag and ran the request on the direct streaming runner.`;let o=await e.text();if(o.length<=2000)return o;return`${o.slice(0,2000)}... [truncated ${o.length-2000} chars]`}function en(e,n){return new Promise((t,o)=>{if(n?.aborted){o(Error("Async status polling aborted."));return}let r=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(r),o(Error("Async status polling aborted."))},{once:!0})})}function nn(e,n){return`${J(e)}/v1/runs/${encodeURIComponent(n)}`}var tn=2000,oe=0,R=1;class xe{baseUrl;apiKey;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(h(),this.baseUrl=ue(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||E),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||"",!this.apiKey)throw Error("BroodsWebSocketClient requires apiKey or BROODS_API_KEY.");this.WebSocketImpl=e.WebSocket,this.connectTimeoutMs=e.connectTimeoutMs??tn}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=on(e),i=ce(this.baseUrl),s=new t(o,z(this.apiKey)),a=!1,p=!1,d=setTimeout(()=>{if(!a)C(i)},this.connectTimeoutMs),x=(l=1000,b="client closed")=>{if(p)return;if(p=!0,clearTimeout(d),e.signal?.removeEventListener("abort",S),s.readyState===R||s.readyState===oe)s.close(l,b)},C=(l)=>{n.onError?.(l),x(1011,"websocket error")},me=()=>{n.onDone?.(),x(1000,"done")},S=()=>{if(s.readyState===R)s.send(JSON.stringify({type:"cancel"}));C(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",S,{once:!0}),s.onopen=()=>{if(a=!0,clearTimeout(d),e.signal?.aborted){S();return}s.send(JSON.stringify({type:"execute",agentId:r,...e.answers?{answers:e.answers}:{events:V(e)},sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},s.onmessage=(l)=>{if(typeof l.data!=="string")return;let b=se(l.data);if(!b)return;let I=ae(b,n);switch(n.onMessage?.(I),I.type){case"meta":n.onMeta?.(I);break;case"done":me();break;case"error":C(Error(re(I.error)));break}},s.onerror=()=>{C(i)},s.onclose=(l)=>{if(clearTimeout(d),e.signal?.removeEventListener("abort",S),p||l.code===1000)return;C(Error(l.reason||"WebSocket connection closed."))},{url:o,sendControl:function(l){if(s.readyState!==R)throw Error("WebSocket is not open");s.send(JSON.stringify({type:"control",...l}))},close:x}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o,z(this.apiKey)),i=!1,s=(a=1000,p="client closed")=>{if(i)return;if(i=!0,r.readyState===R||r.readyState===oe)r.close(a,p)};return r.onopen=()=>r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0})),r.onmessage=(a)=>{if(typeof a.data!=="string")return;let p=se(a.data);if(!p)return;let d=ae(p,n);if(n.onMessage?.(d),d.type==="done")n.onDone?.();if(d.type==="error")n.onError?.(Error(re(d.error)))},r.onerror=()=>n.onError?.(ce(this.baseUrl)),r.onclose=(a)=>{if(!i&&a.code!==1000)n.onError?.(Error(a.reason||"WebSocket connection closed."))},{url:o,sendControl:function(a){if(r.readyState!==R)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...a}))},close:s}}async*stream(e){let n=[],t=!1,o=null,r=null,i=()=>{r?.(),r=null},s=this.subscribe(e,{onMessage:function(a){n.push(a),i()},onDone:function(){t=!0,i()},onError:function(a){o=a,i()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{s.close()}}buildUrl(e){let n=rn(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t&&o?`/projects/${encodeURIComponent(t)}/stages/${encodeURIComponent(o)}`:"";return`${Y(this.baseUrl)}/v1${r}/agents/${encodeURIComponent(n)}/ws`}resolveWebSocket(){let e=this.WebSocketImpl??globalThis.WebSocket;if(!e)throw Error("WebSocket is not available. Pass a WebSocket implementation in BroodsWebSocketClient options.");return e}}function Y(e){let n=new URL(ue(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return f(n.toString())}function z(e){return["broods.v1",`broods.token.${e}`]}function re(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&typeof e.message==="string")return e.message;return e===void 0?"WebSocket stream error.":JSON.stringify(e)}function ue(e){let n=e.trim();if(/^wss?:\/\//.test(n))return f(n);return J(n)}function se(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function on(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function rn(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function ae(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function ce(e){return Error(`Cannot access the WebSocket service at ${e}.`)}var pe=Symbol.for("broods.resource"),de=Symbol.for("broods.config"),fe=Symbol.for("broods.connection"),le=/^[A-Z][A-Z0-9_]{0,63}$/,qe=new Proxy((e)=>{if(!le.test(e))throw Error("env name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return{__beeblastEnv:!0,name:e}},{get:function(e,n,t){if(typeof n==="string"&&le.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function De(e){let{name:n,description:t,...o}=e;return m("agent",n,t,o)}function Le(e){return{[de]:!0,config:e}}function Ue(e){let{name:n,description:t,...o}=e;return m("cron",n,t,o)}function Fe(e){return e}function Be(e){let{name:n,description:t,...o}=e;return m("mcp",n,t,o)}function Ze(e){let{name:n,description:t,...o}=e;return m("policy",n,t,o)}function He(e){let{name:n,description:t,...o}=e;return m("sandbox",n,t,o)}function Ve(e){let{name:n,description:t,...o}=e;return m("skill",n,t,o)}function Ge(e){let{name:n,description:t,...o}=e;return m("workspace",n,t,o)}function We(e){return u("discord",e)}function Ke(e){return u("github",e)}function Je(e){return u("gchat",e)}function Ye(e){return u("instagram",e)}function Xe(e){return u("linear",e)}function Qe(e){return u("matrix",e)}function et(e){return u("messenger",e)}function tt(e){return u("pancake",e)}function nt(e){return u("slack",e)}function rt(e){return u("teams",e)}function ot(e){return u("telegram",e)}function st(e){return u("twilio",e)}function it(e){return u("whatsapp",e)}function at(e){return u("zalo",e)}function ct(e){let{name:n,description:t,channelId:o,guildId:r,...i}=e;return c(n,t,o,r,i)}function lt(e){let{name:n,description:t,repo:o,...r}=e,[i,...s]=o.split("/");if(!i||s.length!==1||!s[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return c(n,t,o,i,r)}function ut(e){let{name:n,description:t,spaceName:o,...r}=e;return c(n,t,o,void 0,r)}function dt(e){let{name:n,description:t,igsid:o,...r}=e;return c(n,t,o,void 0,r)}function pt(e){let{name:n,description:t,team:o,...r}=e;return c(n,t,o,void 0,r)}function mt(e){let{name:n,description:t,channelId:o,...r}=e;return c(n,t,o,void 0,r)}function ht(e){let{name:n,description:t,psid:o,...r}=e;return c(n,t,o,void 0,r)}function ft(e){let{name:n,description:t,conversationId:o,...r}=e;return c(n,t,o,void 0,r)}function gt(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return c(n,t,o,r,i)}function yt(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return c(n,t,o,r,i)}function St(e){let{name:n,description:t,chatId:o,...r}=e;return c(n,t,o,void 0,r)}function bt(e){let{name:n,description:t,from:o,...r}=e;return c(n,t,o,void 0,r)}function vt(e){let{name:n,description:t,waId:o,...r}=e;return c(n,t,o,void 0,r)}function _t(e){let{name:n,description:t,chatId:o,...r}=e;return c(n,t,o,void 0,r)}function ie(e){return Boolean(e&&typeof e==="object"&&e[de])}function w(e){return Boolean(e&&typeof e==="object"&&e[fe])}function g(e){return Boolean(e&&typeof e==="object"&&e[pe])}function c(e,n,t,o,r){return m("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function u(e,n){let{partition:t,...o}=n;return{[fe]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function m(e,n,t,o){return{[pe]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}
|
|
5
|
+
export{V,ge,Me,Pe,Ne,je,G,Ie,y,_,O,T,W,K,v,f,L,h,U,M,E,ye,F,J,xe,Y,z,qe,De,Le,Ue,Fe,Be,Ze,He,Ve,Ge,We,Ke,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,st,it,at,ct,lt,ut,dt,pt,mt,ht,ft,gt,yt,St,bt,vt,_t,ie,w,g};
|
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{G,y,_,O,T,W,K,v,f,L,h,M,E,F,Y,z,ie,w,g}from"../chunk-
|
|
2
|
+
import{G,y,_,O,T,W,K,v,f,L,h,M,E,F,Y,z,ie,w,g}from"../chunk-hb3c3xt9.js";import{m,R}from"../chunk-bb3jfhv3.js";import{chmod as Ds,lstat as Us,mkdir as Nn,readFile as zt,readdir as Ns,stat as Ls,writeFile as ye}from"node:fs/promises";import{createHash as Jt}from"node:crypto";import Ms from"node:module";import{basename as Bs,join as Le,relative as Gs,resolve as P,sep as Ws}from"node:path";import{watch as Fs}from"node:fs";import{spawn as qt}from"node:child_process";import{tmpdir as Ks}from"node:os";import{performance as Ft}from"node:perf_hooks";import{stripVTControlCharacters as Hs}from"node:util";import{fileURLToPath as ko,pathToFileURL as ct}from"node:url";import{createHash as Eo}from"node:crypto";import{existsSync as So,readFileSync as $o}from"node:fs";import{mkdtemp as Co,readdir as lt,readFile as Ro,rm as Oo,writeFile as Ao}from"node:fs/promises";import Xn from"node:module";import{tmpdir as xo}from"node:os";import{basename as Po,isAbsolute as To,join as Ge,relative as ke,resolve as We}from"node:path";import{build as jo,transformSync as dt}from"esbuild";var Vn=/\$\{([A-Z][A-Z0-9_]*)\}/;var Yn={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"}},zn=Object.keys(Yn);function Jn(e){return Object.hasOwn(Yn,e)}var ho=/(?:^|[\n;])\s*import\s+(?:[^;"'`]*?\s+from\s*)?["'](?!\.{1,2}\/|\/|node:)[^"']+["']|import\s*\(\s*["'](?!\.{1,2}\/|\/|node:)[^"']+["']\s*\)/,wo=/(?:import\s+(?:[^;"'`]*?\s+from\s*)?["']node:|import\s*\(\s*["']node:)/,bo=/(?<![.\w$])(?:process|Buffer)\s*(?:\?\.|\.|\[)/,yo=[/\b(?:__)?require\s*\(/,/(?<![.\w$])setImmediate\s*\(/,wo,bo,/\b__dirname\b/,ho],vo=/(?<![.\w$])eval\s*\(|\bnew\s+Function\s*\(/;function qn(e){return![...yo,vo].some((n)=>n.test(e))}var cn=["conversation","agent"];function Zn(e){return cn.some((n)=>n===e)}var Oe="*",Io=new RegExp(Vn.source,"g"),_o=`const passthrough = (input) => input;
|
|
3
3
|
export const defineAgent = passthrough;
|
|
4
4
|
export const defineBroods = passthrough;
|
|
5
5
|
export const defineCron = passthrough;
|
|
@@ -81,13 +81,13 @@ export const manifest = ${JSON.stringify(e,null,2)} as const;
|
|
|
81
81
|
`}function Te(e,n,t){let o=Object.keys(n);if(o.length===0)return"{}";return`{
|
|
82
82
|
${o.map((s)=>` ${pn(t?.[s]??s)}: ids.${e}[${JSON.stringify(s)}],`).join(`
|
|
83
83
|
`)}
|
|
84
|
-
}`}function pn(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}var Nr=1,Lr=0,vt=60000,kt=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 Mr(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>=vt)throw Error(`Gave up reconnecting to the live logs after ${vt/1000} s. Last error: ${a}`);r+=1,n.onReconnect?.(r,a),await se(o,n.signal),o=Math.min(o*2,5000)}}async function*Mr(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=Br(o,s,i),S=u,C=fe(),k=[],A=null,V=!1,re=null,pe=()=>{re?.(),re=null},ce=new C(u,z(await r())),Kn=setTimeout(()=>{A=Error(`The observability gateway did not answer within ${kt/1000} s.`),V=!0,pe()},kt),an=()=>{if(clearTimeout(Kn),ce.readyState===Nr||ce.readyState===Lr)ce.close(1000,"client closed");l?.removeEventListener("abort",Hn)},Hn=()=>{V=!0,pe(),an()};l?.addEventListener("abort",Hn,{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=Gr(X.data);if(!me)return;if(clearTimeout(Kn),me.type!=="error")t();switch(me.type){case"backfill":if(me.stream==="logs"){for(let mo of me.entries)k.push(mo);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 Br(e,n,t){return`${Y(e)}/v1/projects/${encodeURIComponent(n)}/stages/${encodeURIComponent(t)}/observability/ws`}function Gr(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 Wr=new Set(["bundle","bundleStorageId","contentBase64"]),Fr=new Set(["hook","mcp","skill"]),Kr=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)=>$t(t)===null))return e;let n=await Promise.all(e.resources.map(async(t)=>{let o=$t(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}`,i=o.headers instanceof Headers||Array.isArray(o.headers)?Object.fromEntries(new Headers(o.headers).entries()):Object.fromEntries(Object.entries(o.headers??{}).map(([a,c])=>[a,typeof c==="string"?c:c.join(", ")]));if(!Object.keys(i).some((a)=>a.toLowerCase()==="authorization"))i.Authorization=`Bearer ${this.token}`;return await this.send(s,{...o,headers:i},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?Kr: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}: ${Yr(s,r)}`,{cause:s})}}function bn(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(mn(p))!==Ye(mn(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)&&Hr(d.resource.kind)&&d.resource.kind===p.resource.kind&&Ye(St(d.resource))===Ye(St(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)=>Et(d).localeCompare(Et(l)))}function Et(e){return`${{create:0,rename:1,update:2,delete:3}[e.operation]}:${e.kind}:${e.previousName??""}:${e.name}`}function Hr(e){return e==="agent"||e==="workspace"||e==="sandbox"||e==="policy"}function fn(e){if(Array.isArray(e))return e.map(fn);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,fn(o)]))}return e}function St(e){let n=mn(e),{name:t,...o}=n;return o}function mn(e){let n=fn(e);if(!Fr.has(e.kind))return n;return{...n,config:wn(n.config)}}function hn(e){if(Array.isArray(e))return e.map(hn);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).sort(([n],[t])=>n.localeCompare(t)).map(([n,t])=>[n,hn(t)]));return e}function Ye(e){return JSON.stringify(hn(e))}function wn(e){if(Array.isArray(e))return e.map(wn);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).flatMap(([n,t])=>{if(Wr.has(n))return[];return[[n,wn(t)]]}));return e}async function U(e,n){if(e.ok)return;let t=await e.text(),{message:o=t,code:r}=Vr(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 Vr(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 Yr(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 $t(e){if(e.kind!=="mcp")return null;let n=e.config?.bundle;if(typeof n!=="string")return null;return Buffer.byteLength(n)>gn?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 yn(e){return Ze.some((n)=>n===e)}import{createHash as fs,randomBytes as ms,randomUUID as Dt}from"node:crypto";import{createServer as ts}from"node:http";import{createHash as os,randomBytes as rs,randomUUID as ss}from"node:crypto";import{spawn as is}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 as}from"node:stream";function Se(e,n,t={}){let o=`${n?"*":" "} ${e}`;return n?j(o,"\x1B[1m\x1B[36m",J(t)):o}function Ct(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")}${Pt(e.stage,t)}`,` ${o("server")}${e.server}`]}function zr(e,n={}){let t=J(n),o=Tt(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(`
|
|
84
|
+
}`}function pn(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:JSON.stringify(e)}var Nr=1,Lr=0,vt=60000,kt=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 Mr(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>=vt)throw Error(`Gave up reconnecting to the live logs after ${vt/1000} s. Last error: ${a}`);r+=1,n.onReconnect?.(r,a),await se(o,n.signal),o=Math.min(o*2,5000)}}async function*Mr(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=Br(o,s,i),S=u,C=fe(),k=[],A=null,V=!1,re=null,pe=()=>{re?.(),re=null},ce=new C(u,z(await r())),Kn=setTimeout(()=>{A=Error(`The observability gateway did not answer within ${kt/1000} s.`),V=!0,pe()},kt),an=()=>{if(clearTimeout(Kn),ce.readyState===Nr||ce.readyState===Lr)ce.close(1000,"client closed");l?.removeEventListener("abort",Hn)},Hn=()=>{V=!0,pe(),an()};l?.addEventListener("abort",Hn,{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=Gr(X.data);if(!me)return;if(clearTimeout(Kn),me.type!=="error")t();switch(me.type){case"backfill":if(me.stream==="logs"){for(let mo of me.entries)k.push(mo);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 Br(e,n,t){return`${Y(e)}/v1/projects/${encodeURIComponent(n)}/stages/${encodeURIComponent(t)}/observability/ws`}function Gr(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 Wr=new Set(["bundle","bundleStorageId","contentBase64"]),Fr=new Set(["hook","mcp","skill"]),Kr=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)=>$t(t)===null))return e;let n=await Promise.all(e.resources.map(async(t)=>{let o=$t(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?Kr: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}: ${Yr(s,r)}`,{cause:s})}}function bn(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(mn(p))!==Ye(mn(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)&&Hr(d.resource.kind)&&d.resource.kind===p.resource.kind&&Ye(St(d.resource))===Ye(St(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)=>Et(d).localeCompare(Et(l)))}function Et(e){return`${{create:0,rename:1,update:2,delete:3}[e.operation]}:${e.kind}:${e.previousName??""}:${e.name}`}function Hr(e){return e==="agent"||e==="workspace"||e==="sandbox"||e==="policy"}function fn(e){if(Array.isArray(e))return e.map(fn);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,fn(o)]))}return e}function St(e){let n=mn(e),{name:t,...o}=n;return o}function mn(e){let n=fn(e);if(!Fr.has(e.kind))return n;return{...n,config:wn(n.config)}}function hn(e){if(Array.isArray(e))return e.map(hn);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).sort(([n],[t])=>n.localeCompare(t)).map(([n,t])=>[n,hn(t)]));return e}function Ye(e){return JSON.stringify(hn(e))}function wn(e){if(Array.isArray(e))return e.map(wn);if(e&&typeof e==="object")return Object.fromEntries(Object.entries(e).flatMap(([n,t])=>{if(Wr.has(n))return[];return[[n,wn(t)]]}));return e}async function U(e,n){if(e.ok)return;let t=await e.text(),{message:o=t,code:r}=Vr(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 Vr(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 Yr(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 $t(e){if(e.kind!=="mcp")return null;let n=e.config?.bundle;if(typeof n!=="string")return null;return Buffer.byteLength(n)>gn?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 yn(e){return Ze.some((n)=>n===e)}import{createHash as fs,randomBytes as ms,randomUUID as Dt}from"node:crypto";import{createServer as ts}from"node:http";import{createHash as os,randomBytes as rs,randomUUID as ss}from"node:crypto";import{spawn as is}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 as}from"node:stream";function Se(e,n,t={}){let o=`${n?"*":" "} ${e}`;return n?j(o,"\x1B[1m\x1B[36m",J(t)):o}function Ct(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")}${Pt(e.stage,t)}`,` ${o("server")}${e.server}`]}function zr(e,n={}){let t=J(n),o=Tt(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
85
|
`)}function Jr(e,n={}){let t=J(n);return e.map((o)=>{let r=es(o.operation,t);if(o.operation==="rename"&&o.previousName)return` ${r} ${o.kind}:${o.previousName} -> ${o.name}`;return` ${r} ${o.kind}:${o.name}`})}function qr(e,n={}){let t=J(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 Zr(e,n={}){return`${j("✖","\x1B[31m",J(n))} ${e}`}function Rt(e,n={}){let t=J(n),o=Math.max(...e.map(([r])=>r.length))+2;return e.map(([r,s])=>` ${r.padEnd(o)}${j(s,"\x1B[2m",t)}`)}function Xr(e,n={}){let t=(n.now??new Date).toTimeString().slice(0,8);return`${j("✔","\x1B[32m",J(n))} ${t} Resources ready! (${ns(e)})`}function Qr(e,n={}){return`${j("✔","\x1B[32m",J(n))} ${e}`}function vn(e,n,t={}){let o=J(t),r=t.note?` ${j(`(${t.note})`,"\x1B[2m",o)}`:"";return` ${j("now","\x1B[2m",o)} ${e} → ${Pt(n,o)}${r}`}function je(e,n={}){return j(`! ${e}`,"\x1B[33m",J(n))}function Ot(e){console.error(zr(e))}function Xe(e){for(let n of Jr(e))console.log(n)}function kn(e){console.error(qr(e))}function At(e){console.error(Zr(e,{stream:"stderr"}))}function xt(e){console.error(Xr(e))}function H(e){console.log(Qr(e,{stream:"stdout"}))}function x(e){console.log(je(e,{stream:"stdout"}))}function es(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 ns(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 Pt(e,n){let t=Tt(e)==="Development";return j(e,t?"\x1B[32m":"\x1B[33m",n)}function J(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 Tt(e){let n=e.trim().toLowerCase();if(n==="development")return"Development";if(n==="production")return"Production";return e.trim()}var cs=180000,ls=`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
89
|
cliAuth Convex functions or no active API account (Settings -> API Access).`,jt=new Set(["--base-url","--cwd","--dashboard-url","--stage","--from","--level","--limit","--mcp","--project","--region","--sandbox","-n"]);function ds(e,n=process.platform){if(n==="darwin")return{command:"open",args:[e]};if(n==="win32")return{command:"rundll32",args:["url.dll,FileProtocolHandler",e]};return{command:"xdg-open",args:[e]}}function I(e,n){let t=jt.has(n)?`${n}=`:null;return e.some((o)=>o===n||t!==null&&o.startsWith(t))}function we(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function b(e,n){for(let t=0;t<e.length;t+=1){let o=e[t];if(o===n)return e[t+1];if(o?.startsWith(`${n}=`))return o.slice(n.length+1)||void 0}return}function te(e){let n=[];for(let t=0;t<e.length;t+=1){let o=e[t];if(o===void 0)continue;if(jt.has(o)){t+=1;continue}if(o.startsWith("-"))continue;n.push(o)}return n}async function En(e){let n=ss(),t=rs(32).toString("base64url"),o=os("sha256").update(t).digest("base64url"),{code:r,close:s}=await $n(n,{port:gs(),fixedPort:Boolean(process.env.BROODS_LOGIN_PORT),path:"/callback",read:ps,done:"broods CLI login complete. You can close this tab."});try{let i=r.callbackUrl,a=`${f(e)}/cli-auth/start?`+new URLSearchParams({callback:i,state:n,code_challenge:o});await us(a),console.log(`Opening ${a}`),Sn(a);let c=await Cn(r.promise),d=await qe(`${c.baseUrl}/v1/account/auth/exchange`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:c.code,code_verifier:t})});if(!d.ok)throw Error(`Login exchange failed: ${d.status} ${await d.text()}`);let l=await d.json(),p={baseUrl:c.baseUrl,dashboardUrl:f(e),token:l.token,createdAt:new Date().toISOString(),...l.user?{user:l.user}:{},...l.org?{org:l.org}:{},...l.account?{account:l.account}:{}};return await W(p),p}finally{s()}}async function q(e){h();let n=T(e);if(!n){let t=process.env.BROODS_DASHBOARD_URL,o=e??process.env.BROODS_BASE_URL??(t?L(t):void 0);throw Error(o?`Not logged in to ${f(o)}. Run \`broods login\`.`:"Run `broods login` first, or set BROODS_TOKEN and BROODS_BASE_URL.")}return n}async function Qe(e){if(!ne.isTTY)return!1;let n=Ie({input:ne,output:ee});try{let t=(await n.question(`${e} [y/N] `)).trim().toLowerCase();return t==="y"||t==="yes"}finally{n.close()}}async function It(e){ee.write(`${e}: `);let n=new as({write:(o,r,s)=>s()}),t=Ie({input:ne,output:n,terminal:ne.isTTY===!0});try{let o=await t.question("");if(!o)throw Error(`${e} is required`);return o}finally{t.close(),ee.write(`
|
|
90
|
-
`)}}async function _e(e,n,t,o){if(n.length===0)throw Error(`${e}: no options available`);if(n.length===1)return n[0];let r=o!==void 0&&o>=0&&o<n.length?o:void 0;console.log(e),n.forEach((a,c)=>{console.log(Se(`${c+1}. ${t(a)}`,c===r))});let s=r===void 0?`Choose 1-${n.length}: `:`Choose 1-${n.length} [${r+1}]: `,i=Ie({input:ne,output:ee});try{for(;;){let a=(await i.question(s)).trim();if(a===""&&r!==void 0)return n[r];let c=Number(a);if(Number.isInteger(c)&&c>=1&&c<=n.length)return n[c-1];console.log(`Enter a number from 1 to ${n.length}.`)}}finally{i.close()}}async function _t(e,n,t,o){console.log(e),n.forEach((i,a)=>{console.log(` ${a+1}. ${t(i)}`)});let r=n.length>0?`Choose 1-${n.length}, or `:"",s=Ie({input:ne,output:ee});try{let i=(await s.question(`${r}${o.hint} [${o.defaultValue}]: `)).trim();if(i==="")return o.defaultValue;let a=Number(i);if(Number.isInteger(a)&&a>=1&&a<=n.length)return n[a-1];return i}finally{s.close()}}async function be(e,n){if(!ne.isTTY)return n??"";let t=Ie({input:ne,output:ee});try{let o=t.question(`${e}: `);if(n){if(ne.isTTY&&ee.isTTY)ee.write("\x1B[90m");if(t.write(n),ne.isTTY&&ee.isTTY)ee.write("\x1B[0m")}return(await o).trim()||n||""}finally{t.close()}}function Sn(e){let{command:n,args:t}=ds(e),o=is(n,t,{stdio:"ignore",detached:!0});o.on("error",(r)=>{console.error(je(`Could not open a browser (${r.message}). Open the URL above to continue.`,{stream:"stderr"}))}),o.unref()}function $n(e,n){return new Promise((t,o)=>{let r=ts((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 Cn(e,n=ls){let t,o=new Promise((r,s)=>{t=setTimeout(()=>s(Error(n)),cs)});try{return await Promise.race([e,o])}finally{if(t)clearTimeout(t)}}async function us(e){let n=await qe(e,{method:"GET",redirect:"manual"});if(n.status===404){let t=new URL(e);throw Error(`${t.origin} has no broods login page. Check that --dashboard-url points at your broods dashboard.`)}if(n.status>=500)throw Error(`The broods login page failed: ${n.status} ${await n.text()}`)}function gs(){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 ps(e){let n=e.get("error");if(n)throw Error(`Login failed: ${n}`);let t=e.get("code");if(!t)throw Error("Login callback carried no code.");let o=e.get("base_url");if(!o)throw Error("Login callback did not advertise the API base URL (base_url). Deploy a dashboard build that includes the Convex-direct CLI auth flow.");return{code:t,baseUrl:f(o)}}var hs=1455,ws="/auth/callback";async function Ut(e,n,t=Sn){let o=he[n].label,r=Dt(),s=Dt(),i=ms(32).toString("base64url"),{code:a,close:c}=await $n(r,{port:hs,fixedPort:!1,path:ws,read:bs,done:`${o} is connected to broods. You can close this tab.`});try{let d=a.callbackUrl,l=await e.startConnection(n,{redirectUri:d,codeChallenge:fs("sha256").update(i).digest("base64url"),state:r,nonce:s});t(l.authorizeUrl),console.log(`Opening ${l.authorizeUrl}`);let p=await Cn(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 bs(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 Lt}from"node:fs";import{mkdir as vs,readFile as ks,writeFile as Es}from"node:fs/promises";import{dirname as Mt,join as An,resolve as Ss,sep as ge}from"node:path";import{fileURLToPath as $s}from"node:url";var De={name:"broods",version:"0.
|
|
90
|
+
`)}}async function _e(e,n,t,o){if(n.length===0)throw Error(`${e}: no options available`);if(n.length===1)return n[0];let r=o!==void 0&&o>=0&&o<n.length?o:void 0;console.log(e),n.forEach((a,c)=>{console.log(Se(`${c+1}. ${t(a)}`,c===r))});let s=r===void 0?`Choose 1-${n.length}: `:`Choose 1-${n.length} [${r+1}]: `,i=Ie({input:ne,output:ee});try{for(;;){let a=(await i.question(s)).trim();if(a===""&&r!==void 0)return n[r];let c=Number(a);if(Number.isInteger(c)&&c>=1&&c<=n.length)return n[c-1];console.log(`Enter a number from 1 to ${n.length}.`)}}finally{i.close()}}async function _t(e,n,t,o){console.log(e),n.forEach((i,a)=>{console.log(` ${a+1}. ${t(i)}`)});let r=n.length>0?`Choose 1-${n.length}, or `:"",s=Ie({input:ne,output:ee});try{let i=(await s.question(`${r}${o.hint} [${o.defaultValue}]: `)).trim();if(i==="")return o.defaultValue;let a=Number(i);if(Number.isInteger(a)&&a>=1&&a<=n.length)return n[a-1];return i}finally{s.close()}}async function be(e,n){if(!ne.isTTY)return n??"";let t=Ie({input:ne,output:ee});try{let o=t.question(`${e}: `);if(n){if(ne.isTTY&&ee.isTTY)ee.write("\x1B[90m");if(t.write(n),ne.isTTY&&ee.isTTY)ee.write("\x1B[0m")}return(await o).trim()||n||""}finally{t.close()}}function Sn(e){let{command:n,args:t}=ds(e),o=is(n,t,{stdio:"ignore",detached:!0});o.on("error",(r)=>{console.error(je(`Could not open a browser (${r.message}). Open the URL above to continue.`,{stream:"stderr"}))}),o.unref()}function $n(e,n){return new Promise((t,o)=>{let r=ts((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 Cn(e,n=ls){let t,o=new Promise((r,s)=>{t=setTimeout(()=>s(Error(n)),cs)});try{return await Promise.race([e,o])}finally{if(t)clearTimeout(t)}}async function us(e){let n=await qe(e,{method:"GET",redirect:"manual"});if(n.status===404){let t=new URL(e);throw Error(`${t.origin} has no broods login page. Check that --dashboard-url points at your broods dashboard.`)}if(n.status>=500)throw Error(`The broods login page failed: ${n.status} ${await n.text()}`)}function gs(){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 ps(e){let n=e.get("error");if(n)throw Error(`Login failed: ${n}`);let t=e.get("code");if(!t)throw Error("Login callback carried no code.");let o=e.get("base_url");if(!o)throw Error("Login callback did not advertise the API base URL (base_url). Deploy a dashboard build that includes the Convex-direct CLI auth flow.");return{code:t,baseUrl:f(o)}}var hs=1455,ws="/auth/callback";async function Ut(e,n,t=Sn){let o=he[n].label,r=Dt(),s=Dt(),i=ms(32).toString("base64url"),{code:a,close:c}=await $n(r,{port:hs,fixedPort:!1,path:ws,read:bs,done:`${o} is connected to broods. You can close this tab.`});try{let d=a.callbackUrl,l=await e.startConnection(n,{redirectUri:d,codeChallenge:fs("sha256").update(i).digest("base64url"),state:r,nonce:s});t(l.authorizeUrl),console.log(`Opening ${l.authorizeUrl}`);let p=await Cn(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 bs(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 Lt}from"node:fs";import{mkdir as vs,readFile as ks,writeFile as Es}from"node:fs/promises";import{dirname as Mt,join as An,resolve as Ss,sep as ge}from"node:path";import{fileURLToPath as $s}from"node:url";var De={name:"broods",version:"0.48.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","pack:check":"bun run build && publint && attw --pack .",prepublishOnly:"bun run build",test:"bun test"},dependencies:{"@modelcontextprotocol/client":"^2.0.0",esbuild:"^0.28.2"},devDependencies:{"@ai-sdk/tui":"1.0.128","@arethetypeswrong/cli":"^0.18.5","@chat-adapter/discord":"^4.38.1","@chat-adapter/github":"^4.38.1","@chat-adapter/slack":"^4.38.1","@chat-adapter/telegram":"^4.38.1","@modelcontextprotocol/server":"2.0.0","@types/bun":"^1.3.14","@typescript/typescript6":"6.0.2",ai:"^7.0.127",publint:"^0.3.23",rollup:"^4.62.4","rollup-plugin-dts":"^6.5.1",typescript:"^7.0.2",zod:"^4.4.3"},peerDependencies:{ai:"^7.0.127"},engines:{node:">=22.15"}};var Rn=An(Mt(O),"update-check.json"),Cs=86400000,Rs="https://registry.npmjs.org/broods/latest",Os=2000,As=[["bun.lock","bun"],["bun.lockb","bun"],["pnpm-lock.yaml","pnpm"],["yarn.lock","yarn"]];function xn(e,n){let t=On(e),o=On(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!Nt(e)&&Nt(n)}async function Pn(e={}){let n=await Ps(),t=e.maxAgeMs??Cs;if(n&&Date.now()-n.checkedAt<t)return n.latest;let o=await xs();if(o===null)return n?.latest??null;return await js({checkedAt:Date.now(),latest:o}),o}function Ue(e){return On(e)[0]??0}function Bt(e=Ss(process.cwd()),n=$s(import.meta.url),t=De.version){let o=`${ge}node_modules${ge}`,r=n.indexOf(o),s=r===-1?null:n.slice(0,r),i=s===null?n.startsWith(`${e}${ge}`):e===s||e.startsWith(`${s}${ge}`),a=n.includes(`${ge}.bun${ge}install${ge}global${ge}`),c=s??e,d=i?Ts(c):a?"bun":"npm",l=d==="npm"?"install":"add",p=d==="pnpm"&&Lt(An(c,"pnpm-workspace.yaml"))?["-w"]:[],u=`broods@${Ue(t)}`;return{manager:d,global:!i,command:d,cwd:i?c:e,args:i?[l,...p,u]:[l,"-g",u]}}async function xs(){try{let e=await fetch(Rs,{signal:AbortSignal.timeout(Os),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 Nt(e){return e.includes("-")}async function Ps(){try{let e=JSON.parse(await ks(Rn,"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 Ts(e){return As.find(([t])=>Lt(An(e,t)))?.[1]??"npm"}function On(e){let[n]=e.trim().replace(/^v/,"").split("-");return(n??"").split(".").slice(0,3).map((t)=>Number.parseInt(t,10)||0)}async function js(e){try{await vs(Mt(Rn),{recursive:!0}),await Es(Rn,`${JSON.stringify(e)}
|
|
91
91
|
`,"utf8")}catch{}}var Gt=`---
|
|
92
92
|
name: broods
|
|
93
93
|
description: Work on a broods account alongside a developer from Claude Code or a development agent. Covers onboarding and sign-in, creating a broods project, defining and deploying agents and their resources with the CLI, and integrating a deployed agent into existing code with the SDK. Use when asked to set up broods, create or work on a broods project, create or manage agents or any account resource, or call a deployed agent from application code.
|
|
@@ -400,7 +400,7 @@ ${Z("stage")}`);let i=h(),a=b(e,"--dashboard-url")??i.dashboardUrl??oe,c=rn(e),d
|
|
|
400
400
|
|
|
401
401
|
${Z("env")}`);if(a&&!t)throw Error(`broods env ${n} needs a variable name.
|
|
402
402
|
|
|
403
|
-
${Z("env")}`);let{manifest:c,config:d}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),l=await q(b(e,"--base-url")??d.baseUrl),p=new N({baseUrl:l.baseUrl,token:l.token}),u=`${c.project}/${c.stage}`;if(i){await Li(p,c,u);return}if(o){let C=await p.listEnv(c.project,c.stage);if(C.length===0){console.log(`No environment variables set for ${u}.`);return}console.log(`Environment variables for ${u} (values hidden):`);for(let k of C)console.log(` ${k.name}`);return}if(s){let C=await p.getEnv(c.project,c.stage,t);if(C===null){console.error(`${t} is not set for ${u}`),process.exitCode=1;return}console.log(C);return}if(r){await p.removeEnv(c.project,c.stage,t),H(`Removed ${t} from ${u}`);return}let S=await It(t);await p.setEnv(c.project,c.stage,t,S),H(`Stored ${t} for ${u}`)}async function Li(e,n,t){let o=await Ln(e,n);if(o.length===0){console.log('No env("NAME") references in this project.');return}let r=await io(e,n,o);if(r.length>0)kn(r);let s=nn(o,"synced").length;console.log(r.length>0?`${s} other referenced variable(s) already in step with ${t}.`:`${s} referenced variable(s) already in step with ${t}.`);let i=nn(o,"stage-only");if(i.length>0)console.log(`${i.length} referenced variable(s) live only on ${t}: ${i.join(", ")}`);let a=nn(o,"unresolved");if(a.length>0)x(`${a.length} referenced variable(s) with no value here or on ${t}: ${a.join(", ")}. Put them in .env.local, or run \`broods env set <NAME> --stage ${n.stage}\`.`)}function Mn(e){if(I(e,"--all"))return"DEBUG";let n=b(e,"--level");if(n===void 0&&I(e,"--level"))throw Error("Missing value for --level. Use DEBUG, INFO, WARN, or ERROR.");if(!n)return"WARN";let t=n.toUpperCase();if(t==="DEBUG")return"DEBUG";if(t==="INFO")return"INFO";if(t==="WARN"||t==="WARNING")return"WARN";if(t==="ERROR")return"ERROR";throw Error(`Unknown log level: ${n}. Use DEBUG, INFO, WARN, or ERROR.`)}async function Mi(e){h();let n=b(e,"--project")??process.env.BROODS_PROJECT,t=b(e,"--stage")??v();if(!n)throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT in .env.local.");if(!t)throw Error("Stage name is required. Pass --stage <name> or set BROODS_STAGE in .env.local.");return{project:n,stage:t}}async function sn(e){let n=await Mi(e),t=h(),o=await Be(b(e,"--dashboard-url")??t.dashboardUrl??oe,b(e,"--base-url")),r=new N({baseUrl:o.baseUrl,token:o.token}),s=await r.mintStageSession(n.project,n.stage),i=async()=>{if(s.expiresAt-Date.now()<Vs)s=await r.mintStageSession(n.project,n.stage);return s.token};return{baseUrl:process.env.BROODS_BASE_URL??process.env.BROODS_HOST??E,credential:i,project:s.projectSlug,stage:s.stageSlug}}function ao(e){return e==="WARN"?" (--all for INFO too)":""}function Bn(e,n){console.error(je(`Reconnecting to live logs (attempt ${e}): ${n}`,{stream:"stderr"}))}function Gn(e){let n=new Date(e.ts).toISOString().slice(11,23),t=e.level.padEnd(5),o=Hs(e.message);return`${n} ${t} ${e.eventType} ${o}`}async function Bi(e){let n=await sn(e),{project:t,stage:o}=n,r=Mn(e),s=new AbortController,i=()=>s.abort();process.on("SIGINT",i),console.log(`Streaming live logs for ${t}/${o} [${r}+]`+ao(r)+", Ctrl+C to stop");try{for await(let a of Ve(n,{backfill:0,minLevel:r,signal:s.signal,onReconnect:Bn}))console.log(Gn(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 Gi(e){if(I(e,"--doctor")){await Wi(I(e,"--request"));return}let n=te(e)[0];if(!n){console.log(ve("machine",e));return}let{runMachineDaemon:t}=await import("../chunk-
|
|
403
|
+
${Z("env")}`);let{manifest:c,config:d}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),l=await q(b(e,"--base-url")??d.baseUrl),p=new N({baseUrl:l.baseUrl,token:l.token}),u=`${c.project}/${c.stage}`;if(i){await Li(p,c,u);return}if(o){let C=await p.listEnv(c.project,c.stage);if(C.length===0){console.log(`No environment variables set for ${u}.`);return}console.log(`Environment variables for ${u} (values hidden):`);for(let k of C)console.log(` ${k.name}`);return}if(s){let C=await p.getEnv(c.project,c.stage,t);if(C===null){console.error(`${t} is not set for ${u}`),process.exitCode=1;return}console.log(C);return}if(r){await p.removeEnv(c.project,c.stage,t),H(`Removed ${t} from ${u}`);return}let S=await It(t);await p.setEnv(c.project,c.stage,t,S),H(`Stored ${t} for ${u}`)}async function Li(e,n,t){let o=await Ln(e,n);if(o.length===0){console.log('No env("NAME") references in this project.');return}let r=await io(e,n,o);if(r.length>0)kn(r);let s=nn(o,"synced").length;console.log(r.length>0?`${s} other referenced variable(s) already in step with ${t}.`:`${s} referenced variable(s) already in step with ${t}.`);let i=nn(o,"stage-only");if(i.length>0)console.log(`${i.length} referenced variable(s) live only on ${t}: ${i.join(", ")}`);let a=nn(o,"unresolved");if(a.length>0)x(`${a.length} referenced variable(s) with no value here or on ${t}: ${a.join(", ")}. Put them in .env.local, or run \`broods env set <NAME> --stage ${n.stage}\`.`)}function Mn(e){if(I(e,"--all"))return"DEBUG";let n=b(e,"--level");if(n===void 0&&I(e,"--level"))throw Error("Missing value for --level. Use DEBUG, INFO, WARN, or ERROR.");if(!n)return"WARN";let t=n.toUpperCase();if(t==="DEBUG")return"DEBUG";if(t==="INFO")return"INFO";if(t==="WARN"||t==="WARNING")return"WARN";if(t==="ERROR")return"ERROR";throw Error(`Unknown log level: ${n}. Use DEBUG, INFO, WARN, or ERROR.`)}async function Mi(e){h();let n=b(e,"--project")??process.env.BROODS_PROJECT,t=b(e,"--stage")??v();if(!n)throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT in .env.local.");if(!t)throw Error("Stage name is required. Pass --stage <name> or set BROODS_STAGE in .env.local.");return{project:n,stage:t}}async function sn(e){let n=await Mi(e),t=h(),o=await Be(b(e,"--dashboard-url")??t.dashboardUrl??oe,b(e,"--base-url")),r=new N({baseUrl:o.baseUrl,token:o.token}),s=await r.mintStageSession(n.project,n.stage),i=async()=>{if(s.expiresAt-Date.now()<Vs)s=await r.mintStageSession(n.project,n.stage);return s.token};return{baseUrl:process.env.BROODS_BASE_URL??process.env.BROODS_HOST??E,credential:i,project:s.projectSlug,stage:s.stageSlug}}function ao(e){return e==="WARN"?" (--all for INFO too)":""}function Bn(e,n){console.error(je(`Reconnecting to live logs (attempt ${e}): ${n}`,{stream:"stderr"}))}function Gn(e){let n=new Date(e.ts).toISOString().slice(11,23),t=e.level.padEnd(5),o=Hs(e.message);return`${n} ${t} ${e.eventType} ${o}`}async function Bi(e){let n=await sn(e),{project:t,stage:o}=n,r=Mn(e),s=new AbortController,i=()=>s.abort();process.on("SIGINT",i),console.log(`Streaming live logs for ${t}/${o} [${r}+]`+ao(r)+", Ctrl+C to stop");try{for await(let a of Ve(n,{backfill:0,minLevel:r,signal:s.signal,onReconnect:Bn}))console.log(Gn(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 Gi(e){if(I(e,"--doctor")){await Wi(I(e,"--request"));return}let n=te(e)[0];if(!n){console.log(ve("machine",e));return}let{runMachineDaemon:t}=await import("../chunk-11g7dgvw.js"),{baseUrl:o,credential:r}=await sn(e),s=P(b(e,"--cwd")??process.cwd()),i=I(e,"--computer"),a=b(e,"--mcp"),c=I(e,"--force"),d=new AbortController,l=()=>d.abort();process.on("SIGINT",l),console.log(`Connecting ${n} to ${o} (cwd ${s}${i?", computer use on":""}), Ctrl+C to stop`);try{await t({baseUrl:o,computer:i,credential:r,cwd:s,force:c,log:(p)=>console.log(p),mcpFile:a?P(a):void 0,sandbox:n,signal:d.signal})}catch(p){console.error(p instanceof Error?p.message:String(p)),process.exitCode=1}finally{process.off("SIGINT",l)}}async function Wi(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 Fi(e){let n=await sn(e),{project:t,stage:o}=n,r=b(e,"--sandbox");if(I(e,"--sandbox")&&!G(r))throw Error("--sandbox needs the instance log id, the UUID shown in the dashboard Instances sheet.");let s=r?"DEBUG":Mn(e),i=Number(b(e,"--limit")??b(e,"-n")??100),a=I(e,"--json"),c=new AbortController,d=()=>c.abort();process.on("SIGINT",d),console.log(`Logs for ${t}/${o}`+(r?` sandbox ${r}`:"")+` [${s}+]`+ao(s)+` (backfill ${i}), Ctrl+C to stop`);try{for await(let l of Ve(n,{backfill:i,minLevel:s,...r?{sandboxId:r}:{},signal:c.signal,onReconnect:Bn}))if(a)console.log(JSON.stringify(l));else console.log(Gn(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 Ki(e){let[n,t]=te(e);if(!n){console.log(ve("agent",e));return}if(n==="list"||n==="ls"){await Hi(e);return}if(n==="get"){await Vi(t,e);return}throw Error(`Unknown agent subcommand: ${n}
|
|
404
404
|
|
|
405
405
|
${Z("agent")}`)}async function co(e){let{manifest:n,config:t}=await le({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),o=await q(b(e,"--base-url")??t.baseUrl),r=await new N({baseUrl:o.baseUrl,token:o.token}).getManifest(n.project,n.stage),s=n.resources.filter((i)=>i.kind==="agent").map((i)=>({name:i.name,config:i.config??{},agentId:r?.ids.agents[i.name]}));return{manifest:n,agents:s}}async function Hi(e){let{manifest:n,agents:t}=await co(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=lo(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 Vi(e,n){if(!e)throw Error(`Missing agent name.
|
|
406
406
|
|
|
@@ -449,4 +449,4 @@ export const myAgent = defineAgent({
|
|
|
449
449
|
// only reachable via internal endpoints or channel webhooks.
|
|
450
450
|
publicAccess: true,
|
|
451
451
|
});
|
|
452
|
-
`}function qi(){if("bun"in process.versions)return;if(typeof Ms.registerHooks==="function")return;throw Error(`broods needs Node ${De.engines.node.replace(">=","")} or newer, or Bun. This is Node ${process.version}.`)}function Zi(e,n){if(e==="status")throw Error("status was renamed to whoami. Run `broods whoami`.");if(I(n,"--env")||b(n,"--env")!==void 0)throw Error("--env was renamed to --stage. Pass --stage <name> instead.");h();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 Xi(){let e=h(),n=T(),[{createBroodsMcpServer:t},{serveStdio:o}]=await Promise.all([import("../chunk-
|
|
452
|
+
`}function qi(){if("bun"in process.versions)return;if(typeof Ms.registerHooks==="function")return;throw Error(`broods needs Node ${De.engines.node.replace(">=","")} or newer, or Bun. This is Node ${process.version}.`)}function Zi(e,n){if(e==="status")throw Error("status was renamed to whoami. Run `broods whoami`.");if(I(n,"--env")||b(n,"--env")!==void 0)throw Error("--env was renamed to --stage. Pass --stage <name> instead.");h();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 Xi(){let e=h(),n=T(),[{createBroodsMcpServer:t},{serveStdio:o}]=await Promise.all([import("../chunk-fb10617g.js"),import("../chunk-kjccsy1h.js")]),r=n?new N({baseUrl:n.baseUrl,token:n.token}):null,s=t({allowDestructive:process.env.BROODS_MCP_ALLOW_DESTRUCTIVE==="1"&&M("BROODS_MCP_ALLOW_DESTRUCTIVE"),cli:r,scope:{project:e.project,stage:e.stage}});o(()=>s),await new Promise((i)=>{process.stdin.on("close",i)})}Zs().catch((e)=>{At(e instanceof Error?e.message:String(e)),process.exit(1)});export{se,fe,D};
|
package/dist/index.d.ts
CHANGED
|
@@ -352,9 +352,9 @@ interface AgentSessionPruningConfig {
|
|
|
352
352
|
}
|
|
353
353
|
/**
|
|
354
354
|
* Compaction after a finished turn, on unless `enabled: false`. It runs once
|
|
355
|
-
* the turn's last model call
|
|
356
|
-
* 500000)
|
|
357
|
-
* this says.
|
|
355
|
+
* the turn's last model call read `maxContextLength` input tokens or more
|
|
356
|
+
* (default 500000), or after the provider refused a turn for context length.
|
|
357
|
+
* `/compact` works whatever this says.
|
|
358
358
|
*/
|
|
359
359
|
interface AgentSessionAutoCompactionConfig {
|
|
360
360
|
enabled?: boolean;
|
|
@@ -2378,7 +2378,7 @@ declare class BroodsAccountClient {
|
|
|
2378
2378
|
resumeSandbox(sandboxId: string, reservationKey: string): Promise<SandboxLifecycleResult>;
|
|
2379
2379
|
/** Terminate a persistent sandbox reservation and drop its live-instance row. Throws on 404/403/409. */
|
|
2380
2380
|
terminateSandbox(sandboxId: string, reservationKey: string): Promise<SandboxLifecycleResult>;
|
|
2381
|
-
/** Snapshot a persistent sandbox reservation into a reusable image (
|
|
2381
|
+
/** Snapshot a persistent sandbox reservation into a reusable image (`sandbox`, or `lambda`, which answers `building` until its image build lands). Throws on 404/403/409. */
|
|
2382
2382
|
snapshotSandbox(sandboxId: string, reservationKey: string, name: string): Promise<SandboxSnapshotResult>;
|
|
2383
2383
|
/** Mint a short-lived sealed ticket for an interactive PTY session on a persistent sandbox (`sandbox`/`lambda`/`cloudflare` providers). Throws on 404/403/409. */
|
|
2384
2384
|
openSandboxTerminal(sandboxId: string, reservationKey: string): Promise<SandboxTerminalTicket>;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{V,ge,Me,Pe,Ne,je,G,Ie,E,ye,F,J,xe,Y,z,qe,De,Le,Ue,Fe,Be,Ze,He,Ve,Ge,We,Ke,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,st,it,at,ct,lt,ut,dt,pt,mt,ht,ft,gt,yt,St,bt,vt,_t,ie,w,g}from"./chunk-
|
|
1
|
+
import{V,ge,Me,Pe,Ne,je,G,Ie,E,ye,F,J,xe,Y,z,qe,De,Le,Ue,Fe,Be,Ze,He,Ve,Ge,We,Ke,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,st,it,at,ct,lt,ut,dt,pt,mt,ht,ft,gt,yt,St,bt,vt,_t,ie,w,g}from"./chunk-hb3c3xt9.js";import{m,Ae,Z,R}from"./chunk-bb3jfhv3.js";export{m as BroodsAccountApiError,R as BroodsAccountClient,F as BroodsClient,xe as BroodsWebSocketClient,E as DEFAULT_CORE_BASE_URL,ye as IngressAcceptedError,Me as MAX_OBSERVABILITY_BACKFILL,xe as WebSocketClient,xe as WebsocketClient,De as defineAgent,Le as defineBroods,Ue as defineCron,ct as defineDiscordChannel,We as defineDiscordConnection,lt as defineGitHubChannel,Ke as defineGitHubConnection,ut as defineGoogleChatChannel,Je as defineGoogleChatConnection,Fe as defineHarness,dt as defineInstagramChannel,Ye as defineInstagramConnection,pt as defineLinearChannel,Xe as defineLinearConnection,mt as defineMatrixChannel,Qe as defineMatrixConnection,Be as defineMcp,ht as defineMessengerChannel,et as defineMessengerConnection,ft as definePancakeChannel,tt as definePancakeConnection,Ze as definePolicy,He as defineSandbox,Ve as defineSkill,gt as defineSlackChannel,nt as defineSlackConnection,yt as defineTeamsChannel,rt as defineTeamsConnection,St as defineTelegramChannel,ot as defineTelegramConnection,bt as defineTwilioChannel,st as defineTwilioConnection,vt as defineWhatsAppChannel,it as defineWhatsAppConnection,Ge as defineWorkspace,_t as defineZaloChannel,at as defineZaloConnection,qe as env,Ae as envPlaceholder,ie as isBroodsConfig,w as isConnectionDefinition,Pe as isLogLevel,Ne as isObservabilityClientMessage,g as isResource,je as isRootSpanKind,G as isSandboxLogId,Ie as isTraceId,J as normalizeHttpServiceUrl,ge as readSseStream,Z as resolveEnvCredential,V as resolveRunEvents,Y as toWebSocketBaseUrl,z as webSocketSubprotocols};
|
package/package.json
CHANGED
package/dist/chunk-agza3wkj.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
function V(e){if(e.events&&e.input!==void 0)throw Error("Run input accepts either `input` or `events`, not both");if(e.events&&e.events.length>0)return e.events;if(typeof e.input==="string")return[{role:"user",content:[{type:"text",text:e.input}]}];throw Error("Run input requires `input` (string) or a non-empty `events` array")}async function*ge(e){let n=e.getReader(),t=new TextDecoder,o="";try{while(!0){let{done:r,value:i}=await n.read();if(r)break;o+=t.decode(i,{stream:!0});let s=o.split(`
|
|
2
|
-
`);o=s.pop()??"";for(let a of s)if(a.startsWith("data: "))yield a.slice(6)}}finally{n.releaseLock()}}var Me=500,Ce=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,he=/^(?!0{32}$)[0-9a-f]{32}$/;function Pe(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function Ne(e){if(typeof e!=="object"||e===null)return!1;let n=e;if(n.type==="subscribe")return Re(n);if(n.type==="unsubscribe")return k(n.stream);if(n.type==="fetchTrace")return Ie(n.traceId);return!1}function je(e){return e==="task"||e==="cron"||e==="subtask"}function G(e){return typeof e==="string"&&Ce.test(e)}function Ie(e){return typeof e==="string"&&he.test(e)}function k(e){return e==="logs"||e==="traces"}function Re(e){let n=e.stream;if(!k(n))return!1;let t=e.backfill;if(t!==void 0&&(typeof t!=="number"||!Number.isSafeInteger(t)||t<0||t>500))return!1;if(e.liveOnly!==void 0&&typeof e.liveOnly!=="boolean")return!1;let o=e.minLevel;if(o!==void 0&&!Pe(o))return!1;let r=e.sandboxId;return r===void 0||n==="logs"&&G(r)}import{readFileSync as Se}from"node:fs";import{chmod as B,mkdir as be,writeFile as Ae}from"node:fs/promises";import{homedir as ke}from"node:os";import{dirname as D,join as ve}from"node:path";var y="broods",_="_generated",O=ve(ke(),".broods","config.json"),N="broods.app",P="dashboard",we="gateway";function T(e){let n=process.env.BROODS_TOKEN,t=e??process.env.BROODS_BASE_URL;if(n&&t)return{baseUrl:f(t),token:n,createdAt:new Date().toISOString()};let o=H();if(!o)return null;if(t)return o.logins[f(t)]??null;let r=process.env.BROODS_DASHBOARD_URL;if(r){let i=f(r);return Object.values(o.logins).find((s)=>s.dashboardUrl===i)??null}return o.logins[o.current]??null}async function W(e){let n=H()?.logins??{},t={current:e.baseUrl,logins:{...n,[e.baseUrl]:e}};await be(D(O),{recursive:!0,mode:448}),await B(D(O),448),await K(O,`${JSON.stringify(t,null,2)}
|
|
3
|
-
`)}async function K(e,n){await Ae(e,n,{encoding:"utf8",mode:384}),await B(e,384)}function v(){return process.env.BROODS_STAGE}function f(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function L(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${P}.`))return;let t=n.hostname.slice(P.length+1);if(t!==N&&!t.endsWith(`.${N}`))return;return n.hostname=`${we}.${t}`,f(n.origin)}catch{return}}function H(){try{let e=JSON.parse(Se(O,"utf8"));if(typeof e.current!=="string"||!e.logins)return null;return{current:e.current,logins:e.logins}}catch{return null}}import{existsSync as q,readFileSync as Z,statSync as Ee}from"node:fs";import{join as X,resolve as Q}from"node:path";var A=new Map,Te=new Set(Object.keys(process.env)),j=new Set;function h(e=process.cwd()){Oe(e);let n=T();return{dashboardUrl:process.env.BROODS_DASHBOARD_URL??n?.dashboardUrl,baseUrl:process.env.BROODS_BASE_URL??n?.baseUrl,token:n?.token,project:process.env.BROODS_PROJECT,stage:v()}}function U(){let e={};for(let[n,t]of Object.entries(process.env))if(typeof t==="string"&&!n.startsWith("BROODS_"))e[n]=t;return e}function M(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=Q(n);for(let r of[".env.local",".env"]){let i=X(o,r);if(!q(i))continue;let s=ee(Z(i,"utf8"));if(s[e]!==void 0)return s[e]!==t}return!0}function Oe(e){let n=Q(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=X(n,o);if(!q(r)){A.delete(r);continue}let i=Ee(r).mtimeMs,s=A.get(r);if(s&&s.mtimeMs===i)continue;A.set(r,{mtimeMs:i});for(let[a,p]of Object.entries(ee(Z(r,"utf8"))))if(t||!Te.has(a)||j.has(a))process.env[a]=p,j.add(a)}}function ee(e){let n={};for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;let r=o.startsWith("export ")?o.slice(7).trim():o,i=r.indexOf("=");if(i<=0)continue;let s=r.slice(0,i).trim();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(s))continue;n[s]=_e(r.slice(i+1).trim())}return n}function _e(e){if(e.startsWith('"')&&e.endsWith('"'))return e.slice(1,-1).replace(/\\n/g,`
|
|
4
|
-
`).replace(/\\"/g,'"');if(e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);let n=e.indexOf(" #");return n>=0?e.slice(0,n).trimEnd():e}var E="https://gateway.broods.app";class ye extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class F{baseUrl;apiKey;fetchImpl;constructor(e={}){h(),this.baseUrl=J(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||E),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||void 0,this.fetchImpl=e.fetch??fetch}channelWebhookUrl(e){return`${this.baseUrl}${e.webhookPath.startsWith("/")?"":"/"}${e.webhookPath}`}accountWebhookUrl(e,n){let t=[e,n].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${t.join("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(i)=>this.run({...i,agentName:o,agentId:r}),runAsync:(i)=>this.runAsync({...i,agentName:o,agentId:r}),continue:(i)=>this.continue({...i,agentId:r}),stream:(i)=>this.stream({...i,agentName:o,agentId:r})}}let t=e;if(!t.id)throw Error(`Agent ${t.name} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:t.id,run:(o)=>this.run(t,o),runAsync:(o)=>this.runAsync(t,o),continue:(o)=>this.continue(t,o),stream:(o)=>this.stream(t,o)}}async run(e,n){let t=[],o="",r=n?this.stream(e,n):this.stream(e);for await(let i of r)if(t.push(i),i.type==="text-delta")o+=i.text;return{text:o,events:t}}async*stream(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=ne(t,"cli"),r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`,i=await this.openStream(o,r);if(!i.ok)throw Error(`Run failed: ${i.status} ${await i.text()}`);if(i.status===202)throw new ye(te(await i.json(),o));if(!i.body)throw Error("Run response has no body");for await(let s of ge(i.body)){let a;try{a=JSON.parse(s)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${$e(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o={...ne(t,"async"),background:!0},r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(r,o,"Async run")}async continue(e,n){let t=n?e:null,o=n??e,r={agentId:t?t.id:e.agentId,eventId:o.eventId??`continue-${crypto.randomUUID()}`,conversationKey:o.conversationKey,continue:!0},i=t?this.scopedUrl(t):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(i,r,"Continue")}async getAsyncStatus(e){let n=this.resolveStatusUrl(e),t=await this.fetchJson(n,{method:"GET",headers:this.apiKeyHeaders()});if(t.status===404)return{status:"not_found"};if(!t.ok)throw Error(`Status check failed: ${t.status} ${await t.text()}`);return await t.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e);if(r.status==="awaiting_approval"||r.status==="awaiting_input"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await en(o,n.signal)}throw Error("Polling timeout")}scopedUrl(e){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/projects/${encodeURIComponent(e.projectSlug)}/stages/${encodeURIComponent(e.stageSlug)}/agents/${encodeURIComponent(e.endpointId)}`;return`${this.baseUrl}/v1/runs`}asyncAgentRun(e,n){return{...e,conversationKey:n,poll:()=>this.getAsyncStatus(e),wait:(t)=>this.waitForAsyncStatus(e,t)}}async postAcceptedRun(e,n,t){let o=await this.fetchJson(e,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(n)});if(o.status!==202)throw Error(`${t} failed: ${o.status} ${await ze(o,"202 JSON")}`);return this.asyncAgentRun(te(await o.json(),n),n.conversationKey)}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${E} by default; set host/baseUrl or BROODS_HOST/BROODS_BASE_URL to your own core service URL if your account uses a custom deployment. Cause: ${o instanceof Error?o.message:String(o)}`)}}apiKeyHeaders(){if(!this.apiKey)throw Error("BroodsClient requires apiKey or BROODS_API_KEY.");return{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}async fetchJson(e,n){let t=n.headers instanceof Headers||Array.isArray(n.headers)?Object.fromEntries(new Headers(n.headers).entries()):Object.fromEntries(Object.entries(n.headers??{}).map(([o,r])=>[o,typeof r==="string"?r:r.join(", ")]));if(!Object.keys(t).some((o)=>o.toLowerCase()==="content-type"))t["Content-Type"]="application/json";try{return await this.fetchImpl(e,{...n,headers:t})}catch(o){throw Error(`Cannot access the broods core service at ${e}. Cause: ${o instanceof Error?o.message:String(o)}`)}}resolveStatusUrl(e){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;return nn(this.baseUrl,e)}}function J(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return f(t)}function ne(e,n){let t=e.eventId??`${n}-${crypto.randomUUID()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:V(e),...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}}function $e(e){if(typeof e==="string")return e;if(!e||typeof e!=="object")return String(e);let n=e,t=n.data?.error?.message??n.message??n.responseBody??JSON.stringify(e),o=n.name?`${n.name}: `:"",r=n.statusCode?` (HTTP ${n.statusCode})`:"";return`${o}${t}${r}`}function te(e,n){if(!e||typeof e!=="object")throw Error("Async response must be an object");let t=e.statusUrl;if(typeof t!=="string"||t.length===0)throw Error("Async response missing statusUrl");let o=e.runId;if(typeof o!=="string"||o.length===0)throw Error("Async response missing runId");let r=typeof e.eventId==="string"?e.eventId:o,{status:i,requestedMode:s}=e;return{statusUrl:t,runId:o,eventId:r,agentId:n.agentId,...i==="accepted"||i==="queued"||i==="applied"||i==="processing"?{status:i}:{},...s==="reject"||s==="followup"||s==="collect"||s==="steer"?{requestedMode:s}:{}}}async function ze(e,n){if((e.headers.get("content-type")??"").toLowerCase().includes("text/event-stream"))return await e.body?.cancel().catch(()=>{}),`expected ${n}, but the server returned an SSE stream. This usually means the core deployment ignored the background flag and ran the request on the direct streaming runner.`;let o=await e.text();if(o.length<=2000)return o;return`${o.slice(0,2000)}... [truncated ${o.length-2000} chars]`}function en(e,n){return new Promise((t,o)=>{if(n?.aborted){o(Error("Async status polling aborted."));return}let r=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(r),o(Error("Async status polling aborted."))},{once:!0})})}function nn(e,n){return`${J(e)}/v1/runs/${encodeURIComponent(n)}`}var tn=2000,oe=0,R=1;class xe{baseUrl;apiKey;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(h(),this.baseUrl=ue(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||E),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||"",!this.apiKey)throw Error("BroodsWebSocketClient requires apiKey or BROODS_API_KEY.");this.WebSocketImpl=e.WebSocket,this.connectTimeoutMs=e.connectTimeoutMs??tn}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=on(e),i=ce(this.baseUrl),s=new t(o,z(this.apiKey)),a=!1,p=!1,d=setTimeout(()=>{if(!a)C(i)},this.connectTimeoutMs),x=(l=1000,b="client closed")=>{if(p)return;if(p=!0,clearTimeout(d),e.signal?.removeEventListener("abort",S),s.readyState===R||s.readyState===oe)s.close(l,b)},C=(l)=>{n.onError?.(l),x(1011,"websocket error")},me=()=>{n.onDone?.(),x(1000,"done")},S=()=>{if(s.readyState===R)s.send(JSON.stringify({type:"cancel"}));C(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",S,{once:!0}),s.onopen=()=>{if(a=!0,clearTimeout(d),e.signal?.aborted){S();return}s.send(JSON.stringify({type:"execute",agentId:r,...e.answers?{answers:e.answers}:{events:V(e)},sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},s.onmessage=(l)=>{if(typeof l.data!=="string")return;let b=se(l.data);if(!b)return;let I=ae(b,n);switch(n.onMessage?.(I),I.type){case"meta":n.onMeta?.(I);break;case"done":me();break;case"error":C(Error(re(I.error)));break}},s.onerror=()=>{C(i)},s.onclose=(l)=>{if(clearTimeout(d),e.signal?.removeEventListener("abort",S),p||l.code===1000)return;C(Error(l.reason||"WebSocket connection closed."))},{url:o,sendControl:function(l){if(s.readyState!==R)throw Error("WebSocket is not open");s.send(JSON.stringify({type:"control",...l}))},close:x}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o,z(this.apiKey)),i=!1,s=(a=1000,p="client closed")=>{if(i)return;if(i=!0,r.readyState===R||r.readyState===oe)r.close(a,p)};return r.onopen=()=>r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0})),r.onmessage=(a)=>{if(typeof a.data!=="string")return;let p=se(a.data);if(!p)return;let d=ae(p,n);if(n.onMessage?.(d),d.type==="done")n.onDone?.();if(d.type==="error")n.onError?.(Error(re(d.error)))},r.onerror=()=>n.onError?.(ce(this.baseUrl)),r.onclose=(a)=>{if(!i&&a.code!==1000)n.onError?.(Error(a.reason||"WebSocket connection closed."))},{url:o,sendControl:function(a){if(r.readyState!==R)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...a}))},close:s}}async*stream(e){let n=[],t=!1,o=null,r=null,i=()=>{r?.(),r=null},s=this.subscribe(e,{onMessage:function(a){n.push(a),i()},onDone:function(){t=!0,i()},onError:function(a){o=a,i()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{s.close()}}buildUrl(e){let n=rn(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t&&o?`/projects/${encodeURIComponent(t)}/stages/${encodeURIComponent(o)}`:"";return`${Y(this.baseUrl)}/v1${r}/agents/${encodeURIComponent(n)}/ws`}resolveWebSocket(){let e=this.WebSocketImpl??globalThis.WebSocket;if(!e)throw Error("WebSocket is not available. Pass a WebSocket implementation in BroodsWebSocketClient options.");return e}}function Y(e){let n=new URL(ue(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return f(n.toString())}function z(e){return["broods.v1",`broods.token.${e}`]}function re(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&typeof e.message==="string")return e.message;return e===void 0?"WebSocket stream error.":JSON.stringify(e)}function ue(e){let n=e.trim();if(/^wss?:\/\//.test(n))return f(n);return J(n)}function se(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function on(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function rn(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function ae(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function ce(e){return Error(`Cannot access the WebSocket service at ${e}.`)}var pe=Symbol.for("broods.resource"),de=Symbol.for("broods.config"),fe=Symbol.for("broods.connection"),le=/^[A-Z][A-Z0-9_]{0,63}$/,qe=new Proxy((e)=>{if(!le.test(e))throw Error("env name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return{__beeblastEnv:!0,name:e}},{get:function(e,n,t){if(typeof n==="string"&&le.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function De(e){let{name:n,description:t,...o}=e;return m("agent",n,t,o)}function Le(e){return{[de]:!0,config:e}}function Ue(e){let{name:n,description:t,...o}=e;return m("cron",n,t,o)}function Fe(e){return e}function Be(e){let{name:n,description:t,...o}=e;return m("mcp",n,t,o)}function Ze(e){let{name:n,description:t,...o}=e;return m("policy",n,t,o)}function He(e){let{name:n,description:t,...o}=e;return m("sandbox",n,t,o)}function Ve(e){let{name:n,description:t,...o}=e;return m("skill",n,t,o)}function Ge(e){let{name:n,description:t,...o}=e;return m("workspace",n,t,o)}function We(e){return u("discord",e)}function Ke(e){return u("github",e)}function Je(e){return u("gchat",e)}function Ye(e){return u("instagram",e)}function Xe(e){return u("linear",e)}function Qe(e){return u("matrix",e)}function et(e){return u("messenger",e)}function tt(e){return u("pancake",e)}function nt(e){return u("slack",e)}function rt(e){return u("teams",e)}function ot(e){return u("telegram",e)}function st(e){return u("twilio",e)}function it(e){return u("whatsapp",e)}function at(e){return u("zalo",e)}function ct(e){let{name:n,description:t,channelId:o,guildId:r,...i}=e;return c(n,t,o,r,i)}function lt(e){let{name:n,description:t,repo:o,...r}=e,[i,...s]=o.split("/");if(!i||s.length!==1||!s[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return c(n,t,o,i,r)}function ut(e){let{name:n,description:t,spaceName:o,...r}=e;return c(n,t,o,void 0,r)}function dt(e){let{name:n,description:t,igsid:o,...r}=e;return c(n,t,o,void 0,r)}function pt(e){let{name:n,description:t,team:o,...r}=e;return c(n,t,o,void 0,r)}function mt(e){let{name:n,description:t,channelId:o,...r}=e;return c(n,t,o,void 0,r)}function ht(e){let{name:n,description:t,psid:o,...r}=e;return c(n,t,o,void 0,r)}function ft(e){let{name:n,description:t,conversationId:o,...r}=e;return c(n,t,o,void 0,r)}function gt(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return c(n,t,o,r,i)}function yt(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return c(n,t,o,r,i)}function St(e){let{name:n,description:t,chatId:o,...r}=e;return c(n,t,o,void 0,r)}function bt(e){let{name:n,description:t,from:o,...r}=e;return c(n,t,o,void 0,r)}function vt(e){let{name:n,description:t,waId:o,...r}=e;return c(n,t,o,void 0,r)}function _t(e){let{name:n,description:t,chatId:o,...r}=e;return c(n,t,o,void 0,r)}function ie(e){return Boolean(e&&typeof e==="object"&&e[de])}function w(e){return Boolean(e&&typeof e==="object"&&e[fe])}function g(e){return Boolean(e&&typeof e==="object"&&e[pe])}function c(e,n,t,o,r){return m("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function u(e,n){let{partition:t,...o}=n;return{[fe]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function m(e,n,t,o){return{[pe]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}
|
|
5
|
-
export{V,ge,Me,Pe,Ne,je,G,Ie,y,_,O,T,W,K,v,f,L,h,U,M,E,ye,F,J,xe,Y,z,qe,De,Le,Ue,Fe,Be,Ze,He,Ve,Ge,We,Ke,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,st,it,at,ct,lt,ut,dt,pt,mt,ht,ft,gt,yt,St,bt,vt,_t,ie,w,g};
|