broods 0.49.3 → 0.51.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 CHANGED
@@ -818,10 +818,14 @@ declare const WORKSPACE_STORAGE_PROVIDERS: readonly ["s3"];
818
818
  type WorkspaceStorageProvider = (typeof WORKSPACE_STORAGE_PROVIDERS)[number];
819
819
  type WorkspaceStorageAuth = {
820
820
  type: "managed";
821
- } | {
821
+ }
822
+ /**
823
+ * The role's trust policy requires the account's Broods-assigned
824
+ * sts:ExternalId (`storageTrust.ts`); a customer never sets one here.
825
+ */
826
+ | {
822
827
  type: "assumeRole";
823
828
  roleArn: string;
824
- externalId?: string;
825
829
  } | {
826
830
  type: "r2";
827
831
  /** `${NAME}` ref to the parent R2 token's access key id. */
@@ -1460,6 +1464,18 @@ interface RotateSecretResult {
1460
1464
  account: BroodsAccount;
1461
1465
  secret: string;
1462
1466
  }
1467
+ /**
1468
+ * Result of `GET /v1/account/storage-trust`: what a workspace's own AWS role
1469
+ * must trust. Broods assigns `externalId` per account and sends it on every
1470
+ * AssumeRole of an `assumeRole` workspace's role; it is never set in config.
1471
+ */
1472
+ interface StorageTrust {
1473
+ externalId: string;
1474
+ /** The Broods AWS principal to trust; absent on a deployment with no AWS. */
1475
+ principalArn?: string;
1476
+ /** A ready-to-paste trust policy JSON; absent on a deployment with no AWS. */
1477
+ trustPolicy?: string;
1478
+ }
1463
1479
  /** Result of `DELETE /v1/account`: the account and all account-scoped data are removed; `cleanup` reports per-resource deletion counts. */
1464
1480
  interface DeleteAccountResult {
1465
1481
  deleted: boolean;
@@ -1509,6 +1525,8 @@ declare class BroodsAccountClient {
1509
1525
  constructor(options?: BroodsAccountClientOptions);
1510
1526
  /** The account this secret belongs to. Its `accountId` is the first segment of channel webhook URLs. */
1511
1527
  getAccount(): Promise<BroodsAccount>;
1528
+ /** The external id and Broods principal this account's own storage roles must trust. */
1529
+ getStorageTrust(): Promise<StorageTrust>;
1512
1530
  /** Update account metadata (username/description). Returns null when the account is gone. Runtime config is managed through the agent endpoints. */
1513
1531
  updateAccount(patch: {
1514
1532
  username?: string;
@@ -1619,7 +1637,7 @@ declare class BroodsAccountClient {
1619
1637
  resumeSandbox(sandboxId: string, reservationKey: string): Promise<SandboxLifecycleResult>;
1620
1638
  /** Terminate a persistent sandbox reservation and drop its live-instance row. Throws on 404/403/409. */
1621
1639
  terminateSandbox(sandboxId: string, reservationKey: string): Promise<SandboxLifecycleResult>;
1622
- /** Snapshot a persistent sandbox reservation into an image any sandbox of that provider can pin with `snapshot` (`sandbox`, `daytona`, `e2b`, `vercel`, or `lambda`, which answers `building` until its image build lands). Throws on 404/403/409. */
1640
+ /** Snapshot a persistent sandbox reservation into an image any sandbox of that provider on the same stage can pin with `snapshot` (`sandbox`, `daytona`, `e2b`, `vercel`, or `lambda`, which answers `building` until its image build lands). The snapshot is locked to the stage of the sandbox it was taken from: pinning it on another stage throws a 400. Throws on 404/403/409. */
1623
1641
  snapshotSandbox(sandboxId: string, reservationKey: string, name: string): Promise<SandboxSnapshotResult>;
1624
1642
  /** Mint a short-lived sealed ticket for an interactive PTY session on a persistent sandbox (`sandbox`/`lambda`/`cloudflare` providers). Throws on 404/403/409. */
1625
1643
  openSandboxTerminal(sandboxId: string, reservationKey: string): Promise<SandboxTerminalTicket>;
@@ -1729,4 +1747,4 @@ declare class BroodsAccountClient {
1729
1747
  }
1730
1748
 
1731
1749
  export { BroodsAccountApiError, BroodsAccountClient, envPlaceholder, resolveEnvCredential };
1732
- export type { AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, AssumeRoleResult, AuditEvent, AuditPage, AuditPrincipalLink, AuditSink, AuditVerification, BroodsAccount, BroodsAccountClientOptions, ChannelRecordConfig, ConfigPatch, Connection, ConnectionCode, ConnectionStart, ConnectionStartResult, ConnectionType, CreateAgentResult, CreateMcpInput, DeleteAccountResult, McpOauthInput, McpRuntime, RotateSecretResult, SandboxLifecycleResult, SandboxSnapshotResult, SandboxTerminalTicket, SkillUploadInput, StageScope, UpdateAgentInput, UpdateMcpInput, WorkspaceFileEntry };
1750
+ export type { AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, AssumeRoleResult, AuditEvent, AuditPage, AuditPrincipalLink, AuditSink, AuditVerification, BroodsAccount, BroodsAccountClientOptions, ChannelRecordConfig, ConfigPatch, Connection, ConnectionCode, ConnectionStart, ConnectionStartResult, ConnectionType, CreateAgentResult, CreateMcpInput, DeleteAccountResult, McpOauthInput, McpRuntime, RotateSecretResult, SandboxLifecycleResult, SandboxSnapshotResult, SandboxTerminalTicket, SkillUploadInput, StageScope, StorageTrust, UpdateAgentInput, UpdateMcpInput, WorkspaceFileEntry };
package/dist/account.js CHANGED
@@ -1 +1 @@
1
- import{m,Ae,Z,R}from"./chunk-bb3jfhv3.js";export{m as BroodsAccountApiError,R as BroodsAccountClient,Ae as envPlaceholder,Z as resolveEnvCredential};
1
+ import{m,qe,Z,C}from"./chunk-njxsdp91.js";export{m as BroodsAccountApiError,C as BroodsAccountClient,qe as envPlaceholder,Z as resolveEnvCredential};
@@ -1 +1 @@
1
- import{j}from"./chunk-kx38nst5.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.",k=[{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 Lt(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 k)B(n,r,i,t.scope??{});x(n,r)}if(t.cli)q(n,t.cli);if(t.allowDestructive)O(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 A(r)}}function A(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 q(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 O(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 x(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 an image its provider's sandboxes can pin with `snapshot` (sandbox, lambda, daytona, e2b or vercel; 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 B(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:S,update:w,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(S){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 S(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 S(r,m)))}if(w)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 w(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{Lt as createBroodsMcpServer};
1
+ import{q}from"./chunk-ware5wzj.js";import{Z,C}from"./chunk-njxsdp91.js";import{e,o,a,l,s}from"./chunk-qxxrmem2.js";var R={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."),E="'********' keeps a stored secret and null deletes a field: never send a placeholder you did not read from a get.",k=[{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:E,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:E,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 Lt(t={}){let r=Z()?new C({}):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 q({name:"broods",version:"1"},{capabilities:{tools:{}}});if(r){for(let i of k)B(n,r,i,t.scope??{});j(n,r)}if(t.cli)O(n,t.cli);if(t.allowDestructive)x(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 A(r)}}function A(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 b(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 x(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 j(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 an image its provider's sandboxes can pin with `snapshot` (sandbox, lambda, daytona, e2b or vercel; 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 B(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:S,update:w,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:R},async({project:h,stage:m})=>await d(async()=>await f(r,b(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(S){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,...R}},async({body:m,project:T,stage:I})=>await d(async()=>await S(r,m,b(n,i,T,I))));else t.registerTool(`create-${n.singular}`,{description:u,inputSchema:{body:h}},async({body:m})=>await d(async()=>await S(r,m)))}if(w)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 w(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{Lt as createBroodsMcpServer};
@@ -0,0 +1 @@
1
+ import{x,i,H,j,re,oe,se,v,A,ie,me,fe,$e,Ce,Ee,ke,he,ge,Te,ze,Pe,q}from"./chunk-ware5wzj.js";var k=Symbol("swallowsErrorsAfterClose"),W=class{_readBuffer;_started=!1;_closed=!1;constructor(t=he.stdin,o=he.stdout,c){this._stdin=t,this._stdout=o,this._readBuffer=new Ee({maxBufferSize:c?.maxBufferSize})}onclose;onerror;onmessage;_ondata=(t)=>{try{this._readBuffer.append(t),this.processReadBuffer()}catch(o){this.onerror?.(o),this.close().catch(()=>{})}};_onerror=(t)=>{this.onerror?.(t)};_onstdouterror=(t)=>{if(this._closed)return;this.onerror?.(t),this.close().catch(()=>{})};_onstdinclose=()=>{this.close().catch(()=>{})};async start(){if(this._started)throw Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0;for(let t of this._stdout.listeners("error"))if(t[k])this._stdout.off("error",t);if(this._stdin.readableEnded||this._stdin.destroyed)setImmediate(this._onstdinclose);this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror),this._stdin.on("end",this._onstdinclose),this._stdin.on("close",this._onstdinclose),this._stdout.on("error",this._onstdouterror)}processReadBuffer(){while(!0)try{let t=this._readBuffer.readMessage();if(t===null)break;this.onmessage?.(t)}catch(t){this.onerror?.(t)}}async close(){if(this._closed)return;if(this._closed=!0,this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.off("end",this._onstdinclose),this._stdin.off("close",this._onstdinclose),this._onstdouterror[k]=!0,this._stdin.listenerCount("data")===0)this._stdin.pause();this._readBuffer.clear(),this.onclose?.()}send(t){if(this._closed)return Promise.reject(Error("StdioServerTransport is closed"));return new Promise((o,c)=>{let l=ke(t),r=!1,f=(_)=>{if(r)return;r=!0,this._stdout.off("error",f),this._stdout.off("drain",p),c(_)},p=()=>{if(r)return;r=!0,this._stdout.off("error",f),this._stdout.off("drain",p),o()};if(this._stdout.once("error",f),this._stdout.write(l)){if(r)return;r=!0,this._stdout.off("error",f),o()}else if(!r)this._stdout.once("drain",p)})}},D=3000,z=class{onclose;onerror;onmessage;_closed=!1;_pendingRequests=new Set;_drainWaiters=[];constructor(t,o,c){this._wire=t,this._onInstanceClose=o,this._outboundIntercept=c}async start(){}async send(t,o){if(ie(t)||me(t)){let{id:c}=t;if(c!==void 0)this._settle(c)}if(this._closed)return;if(this._outboundIntercept?.(t)==="handled")return;return this._wire.send(t,o)}setProtocolVersion=(t)=>{this._wire.setProtocolVersion?.(t)};deliver(t,o){if(this._closed)return;if(v(t))this._pendingRequests.add(t.id);else if(A(t)&&t.method==="notifications/cancelled"){let c=t.params?.requestId;if(c!==void 0)this._settle(c)}this.onmessage?.(t,o)}async whenRequestsAnswered(t){if(this._closed||this._pendingRequests.size===0)return!0;return await new Promise((o)=>{let c=()=>{clearTimeout(l),o(!0)},l=setTimeout(()=>{this._drainWaiters=this._drainWaiters.filter((r)=>r!==c),o(!1)},t);this._drainWaiters.push(c)})}async close(){if(this._closed)return;this._closed=!0,this._pendingRequests.clear(),this._releaseDrainWaiters();try{this._onInstanceClose()}finally{this.onclose?.()}}_settle(t){if(this._pendingRequests.delete(t),this._pendingRequests.size===0)this._releaseDrainWaiters()}_releaseDrainWaiters(){let t=this._drainWaiters;this._drainWaiters=[];for(let o of t)o()}};function J(t){let o=t.params;if(t.method==="initialize"&&!fe(o)){let f=o!==null&&typeof o==="object"&&typeof o.protocolVersion==="string"?o.protocolVersion:void 0;return{kind:"legacy",reason:"initialize",...f!==void 0&&{requestedVersion:f}}}if(!re(o))return{kind:"legacy",reason:"no-claim"};let c=j(o),l=(c===void 0?[]:se(c))[0];if(l!==void 0)return{kind:"invalid-envelope",issue:l};let r=oe(o);if(r===void 0||!x.includes(r))return{kind:"unsupported-revision",requested:r??"unknown"};return{kind:"modern",revision:r,classification:{era:"modern",revision:r}}}function F(t,o={}){let c=o.legacy??"serve",l=o.transport??new W,r={phase:"opening"},f,p=!1,_=()=>p||r.phase==="closed",d=(e)=>{try{o.onerror?.(e)}catch{}},m=(e,n,s,a)=>l.send({jsonrpc:"2.0",id:e,error:{code:n,message:s,...a!==void 0&&{data:a}}}).catch((u)=>d(h(u))),w=new Te(o.maxSubscriptions??ge),M=(e)=>{if(!A(e))return;let n=w.routeOutbound(e);if(n==="passthrough")return;for(let s of n)l.send({jsonrpc:"2.0",...s}).catch((a)=>d(h(a)));return"handled"},I=async(e)=>{if(v(e)&&e.method==="subscriptions/listen"){let n=j(e.params),s=re(e.params)?(n===void 0?[]:se(n))[0]:{key:"_meta",problem:"the per-request envelope is required on protocol revision 2026-07-28"},a=oe(e.params),u;if(s!==void 0)u={jsonrpc:"2.0",id:e.id,error:{code:-32602,message:`Invalid _meta envelope: ${s.key}: ${s.problem}`}};else if(a===void 0||!x.includes(a)){let y=new H({supported:[...x],requested:a??"unknown"});u={jsonrpc:"2.0",id:e.id,error:{code:y.code,message:y.message,data:y.data}}}else u=w.serve(e);return await l.send("error"in u?u:{jsonrpc:"2.0",method:u.method,params:u.params}).catch((y)=>d(h(y))),!0}if(A(e)&&e.method==="notifications/cancelled"){let n=e.params?.requestId;if(n!==void 0&&w.cancel(n))return!0}return!1},C=(e,n,s)=>{let a=$e({kind:"legacy",reason:n,...s!==void 0&&{requestedVersion:s}},x);if(a===void 0)return Promise.resolve();return d(Error(`Rejected 2025-era request on a modern-only stdio connection (${a.cell}): ${a.message}`)),m(e.id,a.code,a.message,a.data)},V=(e)=>{if(p||e===f)return;O()},R=async(e,n)=>{let s=await t({era:e}),a=s instanceof q?s.server:s;if(e==="modern")Ce(a,n),ze(a,x),w.setServerCapabilities(a.getCapabilities(),Pe(a));let u=new z(l,()=>V(u),e==="modern"?M:void 0);return await s.connect(u),{product:s,channel:u}},S=(e)=>e.product.close().catch((n)=>d(h(n))),T=async(e)=>{f=e.channel;try{if(!await e.channel.whenRequestsAnswered(D))d(Error(`Discarded the probe instance with requests still unanswered after ${D}ms; continuing with the fallback`));await e.product.close()}catch(n){d(h(n))}finally{f=void 0}},B=async(e)=>{if(r.phase==="closed")return;if(r.phase==="pinned"){if(r.era==="modern"&&v(e)&&e.method==="initialize"&&!fe(e.params)){await C(e,"initialize",e.params!==null&&typeof e.params==="object"&&typeof e.params.protocolVersion==="string"?e.params.protocolVersion:void 0);return}if(r.era==="modern"&&await I(e))return;if(_())return;r.instance.channel.deliver(e);return}if(!v(e)&&!A(e)){d(Error("Discarded a JSON-RPC response received before the connection negotiated an era"));return}let n=J(e);switch(n.kind){case"invalid-envelope":{let s=`Invalid _meta envelope for protocol revision 2026-07-28: ${n.issue.key}: ${n.issue.problem}`;if(v(e))await m(e.id,i.InvalidParams,s,{envelope:n.issue});else d(Error(`Discarded a notification with a malformed envelope: ${s}`));return}case"unsupported-revision":if(v(e)){let s=new H({supported:[...x],requested:n.requested});d(s),await m(e.id,s.code,s.message,s.data)}else d(Error(`Discarded a notification claiming unsupported protocol revision ${n.requested}`));return;case"modern":if(v(e)&&e.method==="server/discover"){if(r.phase==="probe"){r.instance.channel.deliver(e,{classification:n.classification});return}let s=await R("modern",n.revision);if(_()){await S(s);return}r={phase:"probe",instance:s},s.channel.deliver(e,{classification:n.classification});return}if(r.phase==="probe"){if(A(e)){r.instance.channel.deliver(e,{classification:n.classification});return}r={phase:"pinned",era:"modern",instance:r.instance}}else{let s=await R("modern",n.revision);if(_()){await S(s);return}r={phase:"pinned",era:"modern",instance:s}}if(await I(e))return;if(_())return;r.instance.channel.deliver(e,{classification:n.classification});return;case"legacy":{if(c==="reject"){if(v(e))await C(e,n.reason,n.requestedVersion);return}if(r.phase==="probe"){if(await T(r.instance),_())return;r={phase:"opening"}}let s=await R("legacy");if(_()){await S(s);return}r={phase:"pinned",era:"legacy",instance:s},r.instance.channel.deliver(e);return}}},E=[],b=!1,N=async()=>{if(b)return;b=!0;try{while(E.length>0){let e=E.shift();try{await B(e)}catch(n){if(v(e))await m(e.id,i.InternalError,"Internal server error");d(h(n))}}}finally{b=!1}},O=async()=>{if(p||r.phase==="closed")return;p=!0;let e=r;r={phase:"closed"};for(let n of w.teardownAll())await l.send(n).catch((s)=>d(h(s)));if(e.phase==="probe"||e.phase==="pinned")await e.instance.product.close().catch((n)=>d(h(n)));await l.close().catch((n)=>d(h(n)))};l.onmessage=(e)=>{E.push(e),N()},l.onerror=(e)=>{if(d(e),r.phase==="probe"||r.phase==="pinned")r.instance.channel.onerror?.(e)},l.onclose=()=>{if(p||r.phase==="closed")return;p=!0;let e=r;if(r={phase:"closed"},e.phase==="probe"||e.phase==="pinned")e.instance.product.close().catch((n)=>d(h(n)))};let P=l.start().catch((e)=>{throw d(h(e)),e});return P.catch(()=>{}),{close:async()=>{await P.catch(()=>{}),await O()}}}function h(t){return t instanceof Error?t:Error(String(t))}export{F as serveStdio};
@@ -0,0 +1,5 @@
1
+ function G(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*we(e){let n=e.getReader(),t=new TextDecoder,o="";try{while(!0){let{done:r,value:i}=await n.read();if(r)break;o+=t.decode(i,{stream:!0});let s=o.split(`
2
+ `);o=s.pop()??"";for(let a of s)if(a.startsWith("data: "))yield a.slice(6)}}finally{await n.cancel().catch(()=>{return}),n.releaseLock()}}var Le=500,Oe=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,Me=/^(?!0{32}$)[0-9a-f]{32}$/;function Ne(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function Ue(e){if(typeof e!=="object"||e===null)return!1;let n=e;if(n.type==="subscribe")return _e(n);if(n.type==="unsubscribe")return O(n.stream);if(n.type==="fetchTrace")return K(n.traceId);return!1}function Fe(e){return e==="task"||e==="cron"||e==="subtask"}function W(e){return typeof e==="string"&&Oe.test(e)}function K(e){return typeof e==="string"&&Me.test(e)}function O(e){return e==="logs"||e==="traces"}function _e(e){let n=e.stream;if(!O(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&&!Ne(o))return!1;let r=e.sandboxId;return r===void 0||n==="logs"&&W(r)}import{readFileSync as Pe}from"node:fs";import{chmod as j,mkdir as $e,writeFile as qe}from"node:fs/promises";import{homedir as ze}from"node:os";import{dirname as M,join as en}from"node:path";var S="broods",w="_generated",N=en(ze(),".broods","config.json"),L="broods.app",H="dashboard",nn="gateway";function P(e){let n=process.env.BROODS_TOKEN,t=e??process.env.BROODS_BASE_URL;if(n&&t)return{baseUrl:h(t),token:n,createdAt:new Date().toISOString()};let o=q();if(!o)return null;if(t)return o.logins[h(t)]??null;let r=process.env.BROODS_DASHBOARD_URL;if(r){let i=h(r);return Object.values(o.logins).find((s)=>s.dashboardUrl===i)??null}return o.logins[o.current]??null}async function J(e){let n=q()?.logins??{},t={current:e.baseUrl,logins:{...n,[e.baseUrl]:e}};await $e(M(N),{recursive:!0,mode:448}),await j(M(N),448),await Y(N,`${JSON.stringify(t,null,2)}
3
+ `)}async function Y(e,n){await qe(e,n,{encoding:"utf8",mode:384}),await j(e,384)}function _(){return process.env.BROODS_STAGE}function h(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function U(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${H}.`))return;let t=n.hostname.slice(H.length+1);if(t!==L&&!t.endsWith(`.${L}`))return;return n.hostname=`${nn}.${t}`,h(n.origin)}catch{return}}function q(){try{let e=JSON.parse(Pe(N,"utf8"));if(typeof e.current!=="string"||!e.logins)return null;return{current:e.current,logins:e.logins}}catch{return null}}import{existsSync as V,readFileSync as oe,statSync as tn}from"node:fs";import{join as re,resolve as ie}from"node:path";var E=new Map,on=new Set(Object.keys(process.env)),Z=new Set;function f(e=process.cwd()){rn(e);let n=P();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:_()}}function F(){let e={};for(let[n,t]of Object.entries(process.env))if(typeof t==="string"&&!n.startsWith("BROODS_"))e[n]=t;return e}function T(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=ie(n);for(let r of[".env.local",".env"]){let i=re(o,r);if(!V(i))continue;let s=X(oe(i,"utf8"));if(s[e]!==void 0)return s[e]!==t}return!0}function rn(e){let n=ie(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=re(n,o);if(!V(r)){E.delete(r);continue}let i=tn(r).mtimeMs,s=E.get(r);if(s&&s.mtimeMs===i)continue;E.set(r,{mtimeMs:i});for(let[a,c]of Object.entries(X(oe(r,"utf8"))))if(t||!on.has(a)||Z.has(a))process.env[a]=c,Z.add(a)}}function X(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]=sn(r.slice(i+1).trim())}return n}function sn(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 D=new TextEncoder,ae={name:"HMAC",hash:"SHA-256"};async function ce(e,n,t,o){let r=se(D.encode(JSON.stringify(t))),i=await crypto.subtle.sign(ae,await an(n,o),D.encode(r));return`${e}${r}.${se(new Uint8Array(i))}`}function se(e){let n="";for(let t of e)n+=String.fromCharCode(t);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function an(e,n){let t=await crypto.subtle.digest("SHA-256",D.encode(`${e}${n}`));return crypto.subtle.importKey("raw",t,ae,!1,["sign","verify"])}var cn="buat_",Q="bsig_",de="x-broods-user-token",ue="broods.user.";var ge=600000,ee=3600000,un="broods-user-token:",le=/^[A-Za-z0-9._@+=-]{1,128}$/,fe=100,gn=256,ln=60000;async function ye(e,n,t=Date.now()){if(!n.startsWith(Q))throw Error(`The user token signing secret must start with ${Q}. It is not the bsk_ runtime key.`);let o=pn(e,t);if(!o||e.expiresAt>t+ee)throw Error(`Invalid user token: userId must match ${le.source}, conversations must be at most ${fe} non-empty keys, and expiresAt must be in the next ${ee/60000} minutes.`);return await ce(cn,un,o,n)}function pn(e,n){if(!e||typeof e!=="object")return null;let{userId:t,conversations:o,expiresAt:r}=e;if(typeof t!=="string"||!le.test(t)||typeof r!=="number"||!Number.isFinite(r)||r<=n||r>n+ee+ln)return null;if(o===void 0)return{userId:t,expiresAt:r};if(!Array.isArray(o)||o.length>fe||!o.every((i)=>typeof i==="string"&&i.trim()===i&&i.length>0&&i.length<=gn))return null;return{userId:t,conversations:o,expiresAt:r}}var y="BROODS_USER_TOKEN_SECRET";async function Be(e){let n=e.secret??process.env[y];if(!n)throw Error(`signUserToken needs the stage's signing secret: pass secret or set ${y}. \`broods dev\` and \`broods deploy\` write it to .env.local; the dashboard's Runtime key tab rotates it.`);return await ye({userId:e.userId,...e.conversations?{conversations:e.conversations}:{},expiresAt:Date.now()+(e.ttlMs??ge)},n)}var I="https://gateway.broods.app";class Re extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class B{baseUrl;apiKey;userToken;fetchImpl;constructor(e={}){f(),this.baseUrl=te(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||I),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||void 0,this.userToken=e.userToken,this.fetchImpl=e.fetch??fetch}channelWebhookUrl(e){return`${this.baseUrl}${e.webhookPath.startsWith("/")?"":"/"}${e.webhookPath}`}accountWebhookUrl(e,n){let t=[e,n].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${t.join("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(i)=>this.run({...i,agentName:o,agentId:r}),runAsync:(i)=>this.runAsync({...i,agentName:o,agentId:r}),continue:(i)=>this.continue({...i,agentId:r}),stream:(i)=>this.stream({...i,agentName:o,agentId:r})}}let t=e;if(!t.id)throw Error(`Agent ${t.name} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:t.id,run:(o)=>this.run(t,o),runAsync:(o)=>this.runAsync(t,o),continue:(o)=>this.continue(t,o),stream:(o)=>this.stream(t,o)}}async run(e,n){let t=[],o="",r=n?this.stream(e,n):this.stream(e);for await(let i of r)if(t.push(i),i.type==="text-delta")o+=i.text;return{text:o,events:t}}async*stream(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=me(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 Re(Ce(await i.json(),o));if(!i.body)throw Error("Run response has no body");for await(let s of we(i.body)){let a;try{a=JSON.parse(s)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${dn(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o={...me(t,"async"),background:!0},r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(r,o,"Async run")}async continue(e,n){let t=n?e:null,o=n??e,r={agentId:t?t.id:e.agentId,eventId:o.eventId??`continue-${crypto.randomUUID()}`,conversationKey:o.conversationKey,continue:!0},i=t?this.scopedUrl(t):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(i,r,"Continue")}async getAsyncStatus(e){let n=this.resolveStatusUrl(e),t=await this.fetchJson(n,{method:"GET",headers:await this.apiKeyHeaders()});if(t.status===404)return{status:"not_found"};if(!t.ok)throw Error(`Status check failed: ${t.status} ${await t.text()}`);return await t.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e);if(r.status==="awaiting_approval"||r.status==="awaiting_input"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await yn(o,n.signal)}throw Error("Polling timeout")}scopedUrl(e){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/projects/${encodeURIComponent(e.projectSlug)}/stages/${encodeURIComponent(e.stageSlug)}/agents/${encodeURIComponent(e.endpointId)}`;return`${this.baseUrl}/v1/runs`}asyncAgentRun(e,n){return{...e,conversationKey:n,poll:()=>this.getAsyncStatus(e),wait:(t)=>this.waitForAsyncStatus(e,t)}}async postAcceptedRun(e,n,t){let o=await this.fetchJson(e,{method:"POST",headers:await this.apiKeyHeaders(),body:JSON.stringify(n)});if(o.status!==202)throw Error(`${t} failed: ${o.status} ${await fn(o,"202 JSON")}`);return this.asyncAgentRun(Ce(await o.json(),n),n.conversationKey)}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`,...await this.userTokenHeaders()});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${I} by default; set host/baseUrl or BROODS_HOST/BROODS_BASE_URL to your own core service URL if your account uses a custom deployment. Cause: ${o instanceof Error?o.message:String(o)}`)}}async apiKeyHeaders(){if(!this.apiKey)throw Error("BroodsClient requires apiKey or BROODS_API_KEY.");return{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,...await this.userTokenHeaders()}}async userTokenHeaders(){let e=typeof this.userToken==="function"?await this.userToken():this.userToken;return e?{[de]:e}:{}}async fetchJson(e,n){try{return await this.fetchImpl(e,n)}catch(t){throw Error(`Cannot access the broods core service at ${e}. Cause: ${t instanceof Error?t.message:String(t)}`)}}resolveStatusUrl(e){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;return mn(this.baseUrl,e)}}function te(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return h(t)}function me(e,n){let t=e.eventId??`${n}-${crypto.randomUUID()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:G(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 dn(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 Ce(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 fn(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 yn(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 mn(e,n){return`${te(e)}/v1/runs/${encodeURIComponent(n)}`}var Cn=2000,he=0,x=1;class je{baseUrl;apiKey;userToken;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(f(),this.baseUrl=ke(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||I),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||"",!this.apiKey)throw Error("BroodsWebSocketClient requires apiKey or BROODS_API_KEY.");this.userToken=e.userToken,this.WebSocketImpl=e.WebSocket,this.connectTimeoutMs=e.connectTimeoutMs??Cn}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=hn(e),i=xe(this.baseUrl),s=new t(o,z(this.apiKey,e.userToken??this.userToken)),a=!1,c=!1,d=setTimeout(()=>{if(!a)b(i)},this.connectTimeoutMs),m=(p=1000,A="client closed")=>{if(c)return;if(c=!0,clearTimeout(d),e.signal?.removeEventListener("abort",k),s.readyState===x||s.readyState===he)s.close(p,A)},b=(p)=>{n.onError?.(p),m(1011,"websocket error")},De=()=>{n.onDone?.(),m(1000,"done")},k=()=>{if(s.readyState===x)s.send(JSON.stringify({type:"cancel"}));b(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",k,{once:!0}),s.onopen=()=>{if(a=!0,clearTimeout(d),e.signal?.aborted){k();return}s.send(JSON.stringify({type:"execute",agentId:r,...e.answers?{answers:e.answers}:{events:G(e)},sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},s.onmessage=(p)=>{if(typeof p.data!=="string")return;let A=be(p.data);if(!A)return;let v=Ie(A,n);switch(n.onMessage?.(v),v.type){case"meta":n.onMeta?.(v);break;case"done":De();break;case"error":b(Error(Se(v.error)));break}},s.onerror=()=>{b(i)},s.onclose=(p)=>{if(clearTimeout(d),e.signal?.removeEventListener("abort",k),c||p.code===1000)return;b(Error(p.reason||"WebSocket connection closed."))},{url:o,sendControl:function(p){if(s.readyState!==x)throw Error("WebSocket is not open");s.send(JSON.stringify({type:"control",...p}))},close:m}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o,z(this.apiKey,e.userToken??this.userToken)),i=!1,s=(c=1000,d="client closed")=>{if(i)return;if(i=!0,e.signal?.removeEventListener("abort",a),r.readyState===x||r.readyState===he)r.close(c,d)},a=()=>{s(1000,"aborted"),n.onError?.(Error("WebSocket attach aborted."))};if(e.signal?.aborted)a();else e.signal?.addEventListener("abort",a,{once:!0});return r.onopen=()=>{if(i)return;r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0,userToken:void 0}))},r.onmessage=(c)=>{if(i||typeof c.data!=="string")return;let d=be(c.data);if(!d)return;let m=Ie(d,n);if(i)return;if(n.onMessage?.(m),i)return;if(m.type==="done")n.onDone?.();if(m.type==="error")n.onError?.(Error(Se(m.error)))},r.onerror=()=>{if(i)return;s(1011,"websocket error"),n.onError?.(xe(this.baseUrl))},r.onclose=(c)=>{if(e.signal?.removeEventListener("abort",a),!i&&c.code!==1000)n.onError?.(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl:function(c){if(r.readyState!==x)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...c}))},close:s}}async*stream(e){let n=[],t=!1,o=null,r=null,i=()=>{r?.(),r=null},s=this.subscribe(e,{onMessage:function(a){n.push(a),i()},onDone:function(){t=!0,i()},onError:function(a){o=a,i()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{s.close()}}buildUrl(e){let n=Sn(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t&&o?`/projects/${encodeURIComponent(t)}/stages/${encodeURIComponent(o)}`:"";return`${ne(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 ne(e){let n=new URL(ke(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return h(n.toString())}function z(e,n){return["broods.v1",`broods.token.${e}`,...n?[`${ue}${n}`]:[]]}function Se(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 ke(e){let n=e.trim();if(/^wss?:\/\//.test(n))return h(n);return te(n)}function be(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function hn(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function Sn(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function Ie(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function xe(e){return Error(`Cannot access the WebSocket service at ${e}.`)}var ve=Symbol.for("broods.resource"),Te=Symbol.for("broods.config"),Ee=Symbol.for("broods.connection"),Ae=/^[A-Z][A-Z0-9_]{0,63}$/,He=new Proxy((e)=>{if(!Ae.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"&&Ae.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function Ze(e){let{name:n,description:t,...o}=e;return C("agent",n,t,o)}function Ve(e){return{[Te]:!0,config:e}}function Ge(e){let{name:n,description:t,...o}=e;return C("cron",n,t,o)}function We(e){return e}function Ke(e){let{name:n,description:t,...o}=e;return C("mcp",n,t,o)}function Je(e){let{name:n,description:t,...o}=e;return C("policy",n,t,o)}function Ye(e){let{name:n,description:t,...o}=e;return C("sandbox",n,t,o)}function Xe(e){let{name:n,description:t,...o}=e;return C("skill",n,t,o)}function Qe(e){let{name:n,description:t,...o}=e;return C("workspace",n,t,o)}function et(e){return l("discord",e)}function tt(e){return l("github",e)}function nt(e){return l("gchat",e)}function rt(e){return l("instagram",e)}function ot(e){return l("linear",e)}function st(e){return l("matrix",e)}function it(e){return l("messenger",e)}function at(e){return l("pancake",e)}function ct(e){return l("slack",e)}function lt(e){return l("teams",e)}function ut(e){return l("telegram",e)}function dt(e){return l("twilio",e)}function pt(e){return l("whatsapp",e)}function mt(e){return l("zalo",e)}function ft(e){let{name:n,description:t,channelId:o,guildId:r,...i}=e;return u(n,t,o,r,i)}function ht(e){let{name:n,description:t,repo:o,...r}=e,[i,...s]=o.split("/");if(!i||s.length!==1||!s[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return u(n,t,o,i,r)}function gt(e){let{name:n,description:t,spaceName:o,...r}=e;return u(n,t,o,void 0,r)}function yt(e){let{name:n,description:t,igsid:o,...r}=e;return u(n,t,o,void 0,r)}function St(e){let{name:n,description:t,team:o,...r}=e;return u(n,t,o,void 0,r)}function bt(e){let{name:n,description:t,channelId:o,...r}=e;return u(n,t,o,void 0,r)}function vt(e){let{name:n,description:t,psid:o,...r}=e;return u(n,t,o,void 0,r)}function _t(e){let{name:n,description:t,conversationId:o,...r}=e;return u(n,t,o,void 0,r)}function wt(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return u(n,t,o,r,i)}function Rt(e){let{name:n,description:t,channelId:o,teamId:r,...i}=e;return u(n,t,o,r,i)}function $t(e){let{name:n,description:t,chatId:o,...r}=e;return u(n,t,o,void 0,r)}function Ct(e){let{name:n,description:t,from:o,...r}=e;return u(n,t,o,void 0,r)}function Et(e){let{name:n,description:t,waId:o,...r}=e;return u(n,t,o,void 0,r)}function kt(e){let{name:n,description:t,chatId:o,...r}=e;return u(n,t,o,void 0,r)}function pe(e){return Boolean(e&&typeof e==="object"&&e[Te])}function R(e){return Boolean(e&&typeof e==="object"&&e[Ee])}function g(e){return Boolean(e&&typeof e==="object"&&e[ve])}function u(e,n,t,o,r){return C("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function l(e,n){let{partition:t,...o}=n;return{[Ee]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function C(e,n,t,o){return{[ve]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}
5
+ export{G,we,Le,Ne,Ue,Fe,W,K,S,w,N,P,J,Y,_,h,U,f,F,T,X,Q,de,ee,y,Be,I,Re,B,te,je,ne,z,He,Ze,Ve,Ge,We,Ke,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,st,it,at,ct,lt,ut,dt,pt,mt,ft,ht,gt,yt,St,bt,vt,_t,wt,Rt,$t,Ct,Et,kt,pe,R,g};
@@ -0,0 +1,4 @@
1
+ import{F,z}from"./chunk-f19xvx4b.js";import{e,o,a,l,n,t,d,E,s,p,r}from"./chunk-qxxrmem2.js";import{ue,_e,L}from"./cli/index.js";import{spawn as re}from"node:child_process";import{statfsSync as ne}from"node:fs";import{availableParallelism as ie,homedir as se,hostname as ae,totalmem as ce}from"node:os";import{performance as j}from"node:perf_hooks";var P=["cursor_position","double_click","hold_key","key","left_click","left_click_drag","left_mouse_down","left_mouse_up","middle_click","mouse_move","right_click","screenshot","scroll","triple_click","type","wait","zoom"];var C={badFrame:{code:4400,reason:"Malformed frame"},expired:{code:4419,reason:"Credential expired"},occupied:{code:4423,reason:"Already connected from another daemon"},replaced:{code:4409,reason:"Replaced by a newer connection"},unauthorized:{code:4401,reason:"Unauthorized; run broods login"},unknownSandbox:{code:4404,reason:"No machine sandbox with that name in this account"}};var U="/v1/machines/ws",B=t({action:p(P),coordinate:n(o().int()).length(2).optional().describe("[x, y] in screenshot pixels for mouse actions."),start_coordinate:n(o().int()).length(2).optional().describe("[x, y] where a left_click_drag starts."),text:e().optional().describe("Text for type, the key chord for key and hold_key, or modifiers to hold during a click, drag or scroll."),scroll_direction: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.")}),G=B.extend({type:r("computer"),id:e()}),W=t({type:r("computer-result"),id:e(),text:e().optional(),image:t({data:e(),mediaType:e()}).optional(),app:e().optional(),error:e().optional()}),J=t({type:r("credential"),token:e().min(1)}),K=t({type:r("exec"),id:e(),code:e(),cwd:e().optional(),env:s(e(),e()).optional(),timeoutSeconds:o().positive(),outputLimitBytes:o().positive()}),X=t({type:r("hello"),sandbox:e().min(1),hostname:e().optional(),platform:e().optional(),computer:a().optional(),mcp:n(e()).optional(),instance:e().optional(),force:a().optional(),specs:t({vcpu:o().positive(),memoryMb:o().positive(),storageGb:o().positive().optional()}).optional().catch(void 0)}),Y=t({type:r("mcp-call"),id:e(),server:e(),tool:e(),args:s(e(),l())}),q=t({type:r("mcp-list"),id:e(),server:e()}),Z=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()}),V=t({type:r("ready"),sandboxId:e(),expiresInMs:o().optional()}),ee=t({type:r("result"),id:e(),exitCode:o().nullable(),stdout:e(),stderr:e(),durationMs:o(),timedOut:a(),truncated:a()}),te=E("type",[G,K,Y,q,V]),Fe=E("type",[W,J,X,Z,Q,ee]);function I(i){let c=new URL(U,i);return c.protocol=c.protocol==="https:"?"wss:":"ws:",c.toString()}function A(i){return oe(te,i)}function oe(i,c){if(typeof c!=="string")return null;try{let y=i.safeParse(JSON.parse(c));return y.success?y.data:null}catch{return null}}var le=new Set([C.occupied.code,C.replaced.code,C.unauthorized.code,C.unknownSandbox.code]),H=72,D=30000,O=1000;function pe(i,c,y){return new Promise((g)=>{let h=j.now(),f=new R(i.outputLimitBytes),w=new R(i.outputLimitBytes),b=!1,v=!1,x=(u,m)=>{if(v)return;if(v=!0,clearTimeout(T),y?.removeEventListener("abort",_),m)w.append(Buffer.from(`${m}
2
+ `));g({type:"result",id:i.id,exitCode:u,stdout:f.text(),stderr:w.text(),durationMs:Math.round(j.now()-h),timedOut:b,truncated:f.truncated||w.truncated})},M=re("bash",["-lc",i.code],{cwd:i.cwd??c,env:{...F(),...i.env},detached:!0,stdio:["ignore","pipe","pipe"]}),S=()=>{if(!M.pid)return;try{process.kill(-M.pid,"SIGKILL")}catch{M.kill("SIGKILL")}},T=setTimeout(()=>{b=!0,S()},i.timeoutSeconds*1000),_=()=>{S(),x(null,"stopped: the daemon closed its socket")};if(y?.addEventListener("abort",_,{once:!0}),M.stdout.on("data",(u)=>f.append(u)),M.stderr.on("data",(u)=>w.append(u)),M.on("error",(u)=>x(null,u.message)),M.on("close",(u)=>x(u)),y?.aborted)_()})}async function Oe(i){let c=_e(),y=crypto.randomUUID(),g=i.mcpFile?await fe(i.mcpFile,i.log):null,h=i.computer?await ye(i.log):null,f=O;try{while(!i.signal.aborted){let w=Date.now(),b;try{b=await i.credential()}catch(x){if(x instanceof L)throw x;i.log(`stage session unavailable (${x instanceof Error?x.message:String(x)}), retrying in ${Math.round(f/1000)}s`),await ue(f,i.signal),f=Math.min(f*2,D);continue}let v=await be(i,b,y,c,h,g);if(i.signal.aborted)return;if(le.has(v.code))throw Error(v.reason||`core closed the socket (${v.code})`);if(Date.now()-w>D)f=O;i.log(`disconnected (${v.reason||v.code}), reconnecting in ${Math.round(f/1000)}s`),await ue(f,i.signal),f=Math.min(f*2,D)}}finally{h?.stop(),await g?.stop()}}class R{#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
+ [output truncated]`:i}}function de(i){let c=[i.action];if(i.coordinate)c.push(`at ${i.coordinate.join(",")}`);if(i.text!==void 0)c.push(JSON.stringify(N(i.text)));if(i.region)c.push(`region ${i.region.join(",")}`);return c.join(" ")}function me(){let i=he();return{vcpu:ie(),memoryMb:Math.round(ce()/1048576),...i?{storageGb:i}:{}}}function he(){try{let i=ne(se());return Math.round(i.blocks*i.bsize/1073741824)}catch{return}}function N(i){let c=i.trim().split(`
4
+ `)[0]??"";return c.length>H?`${c.slice(0,H)}…`:c}async function ye(i){let{startDesktop:c}=await import("./chunk-5tnnqapc.js"),{display:y,driver:g,permissions:h}=await c(!1);if(i(`computer use on, ${y.width}x${y.height} screenshots`),!h.screenRecording||!h.accessibility)i(" screen recording or accessibility is missing, run `broods machine --doctor --request`");return g}async function fe(i,c){let{McpHost:y,readMcpServersFile:g}=await import("./chunk-vx04brkn.js"),h=new y(g(i),c);return c(`mcp servers from ${i}: ${h.names().join(", ")}`),h}async function ge(i,c,y){try{if(i.type==="mcp-list"){let h=await c.listTools(i.server);return y(` mcp ${i.server}: ${h.length} tools`),{type:"mcp-tools",id:i.id,tools:h}}y(` mcp ${i.server}.${i.tool}`);let g=await c.callTool(i.server,i.tool,i.args);return{type:"mcp-result",id:i.id,result:g}}catch(g){let h=g instanceof Error?g.message:String(g);return y(` mcp ${i.server}: ${h}`),{type:i.type==="mcp-call"?"mcp-result":"mcp-tools",id:i.id,error:h}}}function be(i,c,y,g,h,f){return new Promise((w)=>{let b=new g(I(i.baseUrl),z(c)),v=new AbortController,x=()=>b.close(1000,"daemon stopped"),M=(u)=>{if(b.readyState===b.OPEN)b.send(JSON.stringify(u))},S,T=(u)=>{if(clearTimeout(S),v.signal.aborted)return;S=setTimeout(()=>{i.credential().then((m)=>M({type:"credential",token:m}),(m)=>i.log(`credential refresh failed (${m instanceof Error?m.message:String(m)}), retrying`)).finally(()=>T(u))},Math.max((u-Date.now())/2,O))},_=(u,m)=>{i.signal.removeEventListener("abort",x),clearTimeout(S),v.abort(),w({code:u,reason:m})};i.signal.addEventListener("abort",x,{once:!0}),b.onopen=()=>M({type:"hello",sandbox:i.sandbox,hostname:ae(),platform:process.platform,computer:h!==null,mcp:f?.names(),instance:y,force:i.force,specs:me()}),b.onmessage=(u)=>{let m=A(u.data);if(m?.type==="ready"){if(S===void 0)i.log(`connected as ${i.sandbox} (${m.sandboxId})`);if(m.expiresInMs!==void 0)T(Date.now()+m.expiresInMs);return}if(m?.type==="computer"&&h){i.log(` ${de(m)}`),h.run(m).then((k)=>{if(k.error)i.log(` error: ${k.error}`);M(k)});return}if((m?.type==="mcp-call"||m?.type==="mcp-list")&&f){ge(m,f,i.log).then(M);return}if(m?.type!=="exec")return;i.log(`$ ${N(m.code)}`),pe(m,i.cwd,v.signal).then((k)=>{i.log(` exit ${k.exitCode??"none"} in ${k.durationMs}ms${k.timedOut?" (timed out)":""}`),M(k)})},b.onerror=()=>_(1006,"connection failed"),b.onclose=(u)=>_(u.code,u.reason)})}export{Oe as runMachineDaemon};
@@ -1 +1 @@
1
- import{S,de,pe,ke}from"./chunk-n890pdvc.js";var c=()=>{let a={string:{unit:"characters",verb:"to have"},file:{unit:"bytes",verb:"to have"},array:{unit:"items",verb:"to have"},set:{unit:"items",verb:"to have"},map:{unit:"entries",verb:"to have"}};function n(t){return a[t]??null}let d={regex:"input",email:"email address",url:"URL",emoji:"emoji",uuid:"UUID",uuidv4:"UUIDv4",uuidv6:"UUIDv6",nanoid:"nanoid",guid:"GUID",cuid:"cuid",cuid2:"cuid2",ulid:"ULID",xid:"XID",ksuid:"KSUID",datetime:"ISO datetime",date:"ISO date",time:"ISO time",duration:"ISO duration",ipv4:"IPv4 address",ipv6:"IPv6 address",mac:"MAC address",cidrv4:"IPv4 range",cidrv6:"IPv6 range",base64:"base64-encoded string",base64url:"base64url-encoded string",json_string:"JSON string",e164:"E.164 number",jwt:"JWT",template_literal:"input"},o={nan:"NaN"};return(t)=>{switch(t.code){case"invalid_type":{let e=o[t.expected]??t.expected,r=ke(t.input),l=o[r]??r;return`Invalid input: expected ${e}, received ${l}`}case"invalid_value":if(t.values.length===1)return`Invalid input: expected ${pe(t.values[0])}`;return`Invalid option: expected one of ${de(t.values,"|")}`;case"too_big":{let e=t.inclusive?"<=":"<",r=n(t.origin);if(r)return`Too big: expected ${t.origin??"value"} to have ${e}${t.maximum.toString()} ${r.unit??"elements"}`;return`Too big: expected ${t.origin??"value"} to be ${e}${t.maximum.toString()}`}case"too_small":{let e=t.inclusive?">=":">",r=n(t.origin);if(r)return`Too small: expected ${t.origin} to have ${e}${t.minimum.toString()} ${r.unit}`;return`Too small: expected ${t.origin} to be ${e}${t.minimum.toString()}`}case"invalid_format":{let e=t;if(e.format==="starts_with")return`Invalid string: must start with "${e.prefix}"`;if(e.format==="ends_with")return`Invalid string: must end with "${e.suffix}"`;if(e.format==="includes")return`Invalid string: must include "${e.includes}"`;if(e.format==="regex")return`Invalid string: must match pattern ${e.pattern}`;return`Invalid ${d[e.format]??t.format}`}case"not_multiple_of":return`Invalid number: must be a multiple of ${t.divisor}`;case"unrecognized_keys":return`Unrecognized key${t.keys.length>1?"s":""}: ${de(t.keys,", ")}`;case"invalid_key":return`Invalid key in ${t.origin}`;case"invalid_union":if(t.options&&Array.isArray(t.options)&&t.options.length>0)return`Invalid discriminator value. Expected ${t.options.map((r)=>`'${r}'`).join(" | ")}`;return"Invalid input";case"invalid_element":return`Invalid value in ${t.origin}`;default:return"Invalid input"}}};function i(){return{localeError:c()}}S(i());
1
+ import{b,ye,Se,xe}from"./chunk-qxxrmem2.js";var c=()=>{let a={string:{unit:"characters",verb:"to have"},file:{unit:"bytes",verb:"to have"},array:{unit:"items",verb:"to have"},set:{unit:"items",verb:"to have"},map:{unit:"entries",verb:"to have"}};function n(t){return a[t]??null}let d={regex:"input",email:"email address",url:"URL",emoji:"emoji",uuid:"UUID",uuidv4:"UUIDv4",uuidv6:"UUIDv6",nanoid:"nanoid",guid:"GUID",cuid:"cuid",cuid2:"cuid2",ulid:"ULID",xid:"XID",ksuid:"KSUID",datetime:"ISO datetime",date:"ISO date",time:"ISO time",duration:"ISO duration",ipv4:"IPv4 address",ipv6:"IPv6 address",mac:"MAC address",cidrv4:"IPv4 range",cidrv6:"IPv6 range",base64:"base64-encoded string",base64url:"base64url-encoded string",json_string:"JSON string",e164:"E.164 number",jwt:"JWT",template_literal:"input"},o={nan:"NaN"};return(t)=>{switch(t.code){case"invalid_type":{let e=o[t.expected]??t.expected,r=xe(t.input),l=o[r]??r;return`Invalid input: expected ${e}, received ${l}`}case"invalid_value":if(t.values.length===1)return`Invalid input: expected ${Se(t.values[0])}`;return`Invalid option: expected one of ${ye(t.values,"|")}`;case"too_big":{let e=t.inclusive?"<=":"<",r=n(t.origin);if(r)return`Too big: expected ${t.origin??"value"} to have ${e}${t.maximum.toString()} ${r.unit??"elements"}`;return`Too big: expected ${t.origin??"value"} to be ${e}${t.maximum.toString()}`}case"too_small":{let e=t.inclusive?">=":">",r=n(t.origin);if(r)return`Too small: expected ${t.origin} to have ${e}${t.minimum.toString()} ${r.unit}`;return`Too small: expected ${t.origin} to be ${e}${t.minimum.toString()}`}case"invalid_format":{let e=t;if(e.format==="starts_with")return`Invalid string: must start with "${e.prefix}"`;if(e.format==="ends_with")return`Invalid string: must end with "${e.suffix}"`;if(e.format==="includes")return`Invalid string: must include "${e.includes}"`;if(e.format==="regex")return`Invalid string: must match pattern ${e.pattern}`;return`Invalid ${d[e.format]??t.format}`}case"not_multiple_of":return`Invalid number: must be a multiple of ${t.divisor}`;case"unrecognized_keys":return`Unrecognized key${t.keys.length>1?"s":""}: ${ye(t.keys,", ")}`;case"invalid_key":return`Invalid key in ${t.origin}`;case"invalid_union":if(t.options&&Array.isArray(t.options)&&t.options.length>0)return`Invalid discriminator value. Expected ${t.options.map((r)=>`'${r}'`).join(" | ")}`;return"Invalid input";case"invalid_element":return`Invalid value in ${t.origin}`;default:return"Invalid input"}}};function i(){return{localeError:c()}}b(i());
@@ -0,0 +1,2 @@
1
+ var d=/^[A-Z][A-Z0-9_]*$/;class m extends Error{status;body;constructor(e,t,n,s){super(`${e} ${t} failed with ${n}: ${s}`);this.name="BroodsAccountApiError",this.status=n,this.body=s}}function qe(e){if(!d.test(e)||e.length>64)throw Error("envPlaceholder name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return`\${${e}}`}function Z(){return o("BROODS_SESSION_TOKEN")??o("BROODS_ACCOUNT_SECRET")}class C{baseUrl;bearerToken;fetchImpl;constructor(e={}){let t=e.baseUrl??o("BROODS_BASE_URL")??"https://gateway.broods.app",n=e.sessionToken??e.accountSecret??Z();if(!n)throw Error("BroodsAccountClient requires an accountSecret or sessionToken (or BROODS_ACCOUNT_SECRET / BROODS_SESSION_TOKEN).");let s=t.length;while(s>0&&t.charCodeAt(s-1)===47)s-=1;this.baseUrl=t.slice(0,s),this.bearerToken=n,this.fetchImpl=e.fetch??fetch}async getAccount(){let e=await this.request("GET","/v1/account");if(!e)throw new m("GET","/v1/account",404,"Account not found");return e.account}async getStorageTrust(){let e=await this.request("GET","/v1/account/storage-trust");if(!e)throw new m("GET","/v1/account/storage-trust",404,"Account not found");return e.storageTrust}async updateAccount(e){return(await this.request("PATCH","/v1/account",e))?.account??null}async assumeRole(e,t={}){let n=await this.request("POST","/v1/account/assume-role",{roleId:e,...t.ttlSeconds!==void 0?{ttlSeconds:t.ttlSeconds}:{}});if(!n)throw new m("POST","/v1/account/assume-role",404,"Role not found");return n}async rotateSecret(){let e=await this.request("POST","/v1/account/rotate-secret");if(!e)throw new m("POST","/v1/account/rotate-secret",404,"Account not found");return e}async deleteAccount(){return await this.request("DELETE","/v1/account")??{deleted:!1}}webhookUrl(e,t){let n=[e,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${n.join("/")}`}async listAgents(){return(await this.request("GET","/v1/agents"))?.agents??[]}async createAgent(e){let t=await this.request("POST","/v1/agents",e);if(!t)throw new m("POST","/v1/agents",404,"Not found");return t}async getAgent(e){return await this.request("GET",`/v1/agents/${encodeURIComponent(e)}`)}async updateAgent(e,t){return await this.request("PATCH",`/v1/agents/${encodeURIComponent(e)}`,t)}async deleteAgent(e){return(await this.request("DELETE",`/v1/agents/${encodeURIComponent(e)}`))?.deleted??!1}async listEnvVars(){return(await this.request("GET","/v1/env"))?.env??[]}async setEnvVar(e,t){await this.request("PUT",`/v1/env/${encodeURIComponent(e)}`,{value:t})}async deleteEnvVar(e){return(await this.request("DELETE",`/v1/env/${encodeURIComponent(e)}`))?.deleted??!1}async listConnections(){return(await this.request("GET","/v1/account/connections"))?.connections??[]}async getConnection(e){return await this.request("GET",`/v1/account/connections/${e}`)}async startConnection(e,t){let n=await this.request("POST",`/v1/account/connections/${e}/start`,t);if(!n)throw new m("POST",`/v1/account/connections/${e}/start`,404,"This deployment has no /v1/account/connections yet");return n}async connect(e,t){let n=await this.request("PUT",`/v1/account/connections/${e}`,t);if(!n)throw new m("PUT",`/v1/account/connections/${e}`,404,"This deployment has no /v1/account/connections yet");return n}async disconnect(e){return(await this.request("DELETE",`/v1/account/connections/${e}`))?.deleted??!1}async listCrons(){return(await this.request("GET","/v1/crons"))?.crons??[]}async createCron(e){let t=await this.request("POST","/v1/crons",e);if(!t)throw new m("POST","/v1/crons",404,"Not found");return t}async getCron(e){return await this.request("GET",`/v1/crons/${encodeURIComponent(e)}`)}async updateCron(e,t){return await this.request("PATCH",`/v1/crons/${encodeURIComponent(e)}`,t)}async deleteCron(e){return(await this.request("DELETE",`/v1/crons/${encodeURIComponent(e)}`))?.deleted??!1}async listCronRuns(e,t={}){let n=t.limit!==void 0?`?limit=${t.limit}`:"";return(await this.request("GET",`/v1/crons/${encodeURIComponent(e)}/runs${n}`))?.runs??[]}async listWorkspaces(){return(await this.request("GET","/v1/workspaces"))?.workspaces??[]}async createWorkspace(e){let t=await this.request("POST","/v1/workspaces",e);if(!t)throw new m("POST","/v1/workspaces",404,"Not found");return t}async getWorkspace(e){return await this.request("GET",`/v1/workspaces/${encodeURIComponent(e)}`)}async updateWorkspace(e,t){return await this.request("PATCH",`/v1/workspaces/${encodeURIComponent(e)}`,t)}async deleteWorkspace(e){return(await this.request("DELETE",`/v1/workspaces/${encodeURIComponent(e)}`))?.deleted??!1}async listWorkspaceFiles(e){return(await this.request("GET",`/v1/workspaces/${encodeURIComponent(e)}/files`))?.files??[]}async getWorkspaceFileUrl(e,t){let n=`?path=${encodeURIComponent(t)}`;return(await this.request("GET",`/v1/workspaces/${encodeURIComponent(e)}/files${n}`))?.url??null}async uploadWorkspaceFile(e,t){let n=`/v1/workspaces/${encodeURIComponent(e)}/files`,s=await this.request("POST",n,t);if(!s)throw new m("POST",n,404,"Workspace not found");return s.file}async renameWorkspaceFile(e,t,n){let s=`/v1/workspaces/${encodeURIComponent(e)}/files`,r=await this.request("PATCH",s,{path:t,newPath:n});if(!r)throw new m("PATCH",s,404,"Workspace not found");return r.renamed}async deleteWorkspaceFile(e,t){return(await this.request("DELETE",`/v1/workspaces/${encodeURIComponent(e)}/files`,{path:t}))?.deleted??0}async listSandboxes(){return(await this.request("GET","/v1/sandboxes"))?.sandboxes??[]}async createSandbox(e){let t=await this.request("POST","/v1/sandboxes",e);if(!t)throw new m("POST","/v1/sandboxes",404,"Not found");return t}async getSandbox(e){return await this.request("GET",`/v1/sandboxes/${encodeURIComponent(e)}`)}async updateSandbox(e,t){return await this.request("PATCH",`/v1/sandboxes/${encodeURIComponent(e)}`,t)}async deleteSandbox(e){return(await this.request("DELETE",`/v1/sandboxes/${encodeURIComponent(e)}`))?.deleted??!1}async suspendSandbox(e,t){return await this.sandboxAction(e,"suspend",{reservationKey:t})}async resumeSandbox(e,t){return await this.sandboxAction(e,"resume",{reservationKey:t})}async terminateSandbox(e,t){return await this.sandboxAction(e,"terminate",{reservationKey:t})}async snapshotSandbox(e,t,n){return await this.sandboxAction(e,"snapshot",{reservationKey:t,name:n})}async openSandboxTerminal(e,t){return await this.sandboxAction(e,"terminal",{reservationKey:t})}async listMcp(e){let t=`/v1/mcp${a(e)}`,n=await this.request("GET",t);if(!n)throw new m("GET",t,404,"Not found");return n.servers??[]}async createMcp(e,t){let n=`/v1/mcp${a(e)}`,s=await this.request("POST",n,t);if(!s)throw new m("POST",n,404,"Not found");return s}async uploadMcpBundle(e){let n=await this.request("POST","/v1/mcp/uploads");if(!n?.uploadUrl)throw new m("POST","/v1/mcp/uploads",502,"response omitted uploadUrl");let s=await this.fetchImpl(n.uploadUrl,{method:"POST",headers:{"Content-Type":"application/javascript"},body:e});if(!s.ok)throw new m("POST","/v1/mcp/uploads",s.status,await s.text());let{storageId:r}=await s.json();if(!r)throw new m("POST","/v1/mcp/uploads",502,"upload response omitted storageId");let c=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(e)),u=Array.from(new Uint8Array(c)).map((l)=>l.toString(16).padStart(2,"0")).join("");return{bundleStorageId:r,sha256:u}}async getMcp(e){return await this.request("GET",`/v1/mcp/${encodeURIComponent(e)}`)}async updateMcp(e,t){return await this.request("PATCH",`/v1/mcp/${encodeURIComponent(e)}`,t)}async deleteMcp(e){return(await this.request("DELETE",`/v1/mcp/${encodeURIComponent(e)}`))?.deleted??!1}async listPolicies(){return(await this.request("GET","/v1/policies"))?.policies??[]}async createPolicy(e){let t=await this.request("POST","/v1/policies",e);if(!t)throw new m("POST","/v1/policies",404,"Not found");return t}async getPolicy(e){return await this.request("GET",`/v1/policies/${encodeURIComponent(e)}`)}async updatePolicy(e,t){return await this.request("PATCH",`/v1/policies/${encodeURIComponent(e)}`,t)}async deletePolicy(e){return(await this.request("DELETE",`/v1/policies/${encodeURIComponent(e)}`))?.deleted??!1}async listRoles(){return(await this.request("GET","/v1/roles"))?.roles??[]}async createRole(e){let t=await this.request("POST","/v1/roles",e);if(!t)throw new m("POST","/v1/roles",404,"Not found");return t}async getRole(e){return await this.request("GET",`/v1/roles/${encodeURIComponent(e)}`)}async updateRole(e,t){return await this.request("PATCH",`/v1/roles/${encodeURIComponent(e)}`,t)}async deleteRole(e){return(await this.request("DELETE",`/v1/roles/${encodeURIComponent(e)}`))?.deleted??!1}audit={list:async(e={})=>{let t=await this.request("GET",`/v1/audit${i(e)}`);if(!t)throw new m("GET","/v1/audit",404,"Not found");return t},verify:async(e={})=>{let t=await this.request("GET",`/v1/audit/verify${i(e)}`);if(!t)throw new m("GET","/v1/audit/verify",404,"Not found");return t},getSink:async()=>await this.request("GET","/v1/audit/sink"),setSink:async(e)=>{let t=await this.request("PUT","/v1/audit/sink",e);if(!t)throw new m("PUT","/v1/audit/sink",404,"Not found");return t},deleteSink:async()=>(await this.request("DELETE","/v1/audit/sink"))?.deleted??!1};async listChannels(){return(await this.request("GET","/v1/channels"))?.channels??[]}async createChannel(e){let t=await this.request("POST","/v1/channels",e);if(!t)throw new m("POST","/v1/channels",404,"Not found");return t}async getChannel(e){return await this.request("GET",`/v1/channels/${encodeURIComponent(e)}`)}async updateChannel(e,t){return await this.request("PATCH",`/v1/channels/${encodeURIComponent(e)}`,t)}async deleteChannel(e){return(await this.request("DELETE",`/v1/channels/${encodeURIComponent(e)}`))?.deleted??!1}async listSkills(){return(await this.request("GET","/v1/skills"))?.skills??[]}async createSkill(e){let t=await this.request("POST","/v1/skills",e);if(!t)throw new m("POST","/v1/skills",404,"Not found");return t}async getSkill(e){return await this.request("GET",`/v1/skills/${encodeURIComponent(e)}`)}async uploadSkill(e,t){let n=`/v1/skills/${encodeURIComponent(e)}`,s=await this.request("PUT",n,t);if(!s)throw new m("PUT",n,404,"Skill not found");return s}async deleteSkill(e){return(await this.request("DELETE",`/v1/skills/${encodeURIComponent(e)}`))?.deleted??!1}async sandboxAction(e,t,n){let s=`/v1/sandboxes/${encodeURIComponent(e)}/${t}`,r=await this.request("POST",s,n);if(!r)throw new m("POST",s,404,"Sandbox not found");return r}async request(e,t,n){let s=await this.fetchImpl(`${this.baseUrl}${t}`,{method:e,headers:{Authorization:`Bearer ${this.bearerToken}`,...n!==void 0?{"Content-Type":"application/json"}:{}},...n!==void 0?{body:JSON.stringify(n)}:{}});if(s.status===404)return null;if(!s.ok)throw new m(e,t,s.status,await s.text());return await s.json()}}function o(e){return typeof process<"u"?process?.env?.[e]:void 0}function i(e){let t=new URLSearchParams;for(let[n,s]of Object.entries(e))if(s!==void 0)t.set(n,String(s));return t.size>0?`?${t.toString()}`:""}function a(e){return`?${new URLSearchParams({project:e.project,stage:e.stage}).toString()}`}
2
+ export{m,qe,Z,C};