broods 0.49.2 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/account.d.ts 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,4 +1,4 @@
1
- import{U,E}from"./chunk-6kgtx9kv.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 re}from"node:child_process";import{statfsSync as ne}from"node:fs";import{availableParallelism as ie,homedir as ae,hostname as ce,totalmem as le}from"node:os";import{performance as A}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"},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 P="/v1/machines/ws",B=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.")}),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=C("type",[G,K,Y,q,V]),xe=C("type",[W,J,X,Z,Q,ee]);function z(i){let c=new URL(P,i);return c.protocol=c.protocol==="https:"?"wss:":"ws:",c.toString()}function I(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 pe=new Set([_.occupied.code,_.replaced.code,_.unauthorized.code,_.unknownSandbox.code]),j=72,O=30000,R=1000;function de(i,c,y){return new Promise((g)=>{let h=A.now(),f=new L(i.outputLimitBytes),x=new L(i.outputLimitBytes),b=!1,v=!1,F=(u,m)=>{if(v)return;if(v=!0,clearTimeout(T),y?.removeEventListener("abort",S),m)x.append(Buffer.from(`${m}
2
- `));g({type:"result",id:i.id,exitCode:u,stdout:f.text(),stderr:x.text(),durationMs:Math.round(A.now()-h),timedOut:b,truncated:f.truncated||x.truncated})},M=re("bash",["-lc",i.code],{cwd:i.cwd??c,env:{...U(),...i.env},detached:!0,stdio:["ignore","pipe","pipe"]}),k=()=>{if(!M.pid)return;try{process.kill(-M.pid,"SIGKILL")}catch{M.kill("SIGKILL")}},T=setTimeout(()=>{b=!0,k()},i.timeoutSeconds*1000),S=()=>{k(),F(null,"stopped: the daemon closed its socket")};if(y?.addEventListener("abort",S,{once:!0}),M.stdout.on("data",(u)=>f.append(u)),M.stderr.on("data",(u)=>x.append(u)),M.on("error",(u)=>F(null,u.message)),M.on("close",(u)=>F(u)),y?.aborted)S()})}async function Oe(i){let c=fe(),y=crypto.randomUUID(),g=i.mcpFile?await ge(i.mcpFile,i.log):null,h=i.computer?await ye(i.log):null,f=R;try{while(!i.signal.aborted){let x=Date.now(),b;try{b=await i.credential()}catch(F){if(F instanceof D)throw F;i.log(`stage session unavailable (${F instanceof Error?F.message:String(F)}), retrying in ${Math.round(f/1000)}s`),await se(f,i.signal),f=Math.min(f*2,O);continue}let v=await Me(i,b,y,c,h,g);if(i.signal.aborted)return;if(pe.has(v.code))throw Error(v.reason||`core closed the socket (${v.code})`);if(Date.now()-x>O)f=R;i.log(`disconnected (${v.reason||v.code}), reconnecting in ${Math.round(f/1000)}s`),await se(f,i.signal),f=Math.min(f*2,O)}}finally{h?.stop(),await g?.stop()}}class L{#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 me(i){let c=[i.action];if(i.coordinate)c.push(`at ${i.coordinate.join(",")}`);if(i.text!==void 0)c.push(JSON.stringify(H(i.text)));if(i.region)c.push(`region ${i.region.join(",")}`);return c.join(" ")}function ue(){let i=he();return{vcpu:ie(),memoryMb:Math.round(le()/1048576),...i?{storageGb:i}:{}}}function he(){try{let i=ne(ae());return Math.round(i.blocks*i.bsize/1073741824)}catch{return}}function H(i){let c=i.trim().split(`
4
- `)[0]??"";return c.length>j?`${c.slice(0,j)}…`: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 ge(i,c){let{McpHost:y,readMcpServersFile:g}=await import("./chunk-ctt7r720.js"),h=new y(g(i),c);return c(`mcp servers from ${i}: ${h.names().join(", ")}`),h}async function be(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 Me(i,c,y,g,h,f){return new Promise((x)=>{let b=new g(z(i.baseUrl),E(c)),v=new AbortController,F=()=>b.close(1000,"daemon stopped"),M=(u)=>{if(b.readyState===b.OPEN)b.send(JSON.stringify(u))},k,T=(u)=>{if(clearTimeout(k),v.signal.aborted)return;k=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,R))},S=(u,m)=>{i.signal.removeEventListener("abort",F),clearTimeout(k),v.abort(),x({code:u,reason:m})};i.signal.addEventListener("abort",F,{once:!0}),b.onopen=()=>M({type:"hello",sandbox:i.sandbox,hostname:ce(),platform:process.platform,computer:h!==null,mcp:f?.names(),instance:y,force:i.force,specs:ue()}),b.onmessage=(u)=>{let m=I(u.data);if(m?.type==="ready"){if(k===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(` ${me(m)}`),h.run(m).then((w)=>{if(w.error)i.log(` error: ${w.error}`);M(w)});return}if((m?.type==="mcp-call"||m?.type==="mcp-list")&&f){be(m,f,i.log).then(M);return}if(m?.type!=="exec")return;i.log(`$ ${H(m.code)}`),de(m,i.cwd,v.signal).then((w)=>{i.log(` exit ${w.exitCode??"none"} in ${w.durationMs}ms${w.timedOut?" (timed out)":""}`),M(w)})},b.onerror=()=>S(1006,"connection failed"),b.onclose=(u)=>S(u.code,u.reason)})}export{Oe as runMachineDaemon};
1
+ import{F,z}from"./chunk-rv0n0evv.js";import{e,o,a,l,n,t,d,k,s,p,r}from"./chunk-463bn8qa.js";import{le,ve,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 E={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=k("type",[G,K,Y,q,V]),xe=k("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 pe=new Set([E.occupied.code,E.replaced.code,E.unauthorized.code,E.unknownSandbox.code]),H=72,D=30000,O=1000;function de(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",C),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"]}),_=()=>{if(!M.pid)return;try{process.kill(-M.pid,"SIGKILL")}catch{M.kill("SIGKILL")}},T=setTimeout(()=>{b=!0,_()},i.timeoutSeconds*1000),C=()=>{_(),x(null,"stopped: the daemon closed its socket")};if(y?.addEventListener("abort",C,{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)C()})}async function Oe(i){let c=ve(),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 le(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(pe.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 le(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 me(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 ue(){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-7ajf29ec.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))},_,T=(u)=>{if(clearTimeout(_),v.signal.aborted)return;_=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))},C=(u,m)=>{i.signal.removeEventListener("abort",x),clearTimeout(_),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:ue()}),b.onmessage=(u)=>{let m=A(u.data);if(m?.type==="ready"){if(_===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(` ${me(m)}`),h.run(m).then((S)=>{if(S.error)i.log(` error: ${S.error}`);M(S)});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)}`),de(m,i.cwd,v.signal).then((S)=>{i.log(` exit ${S.exitCode??"none"} in ${S.durationMs}ms${S.timedOut?" (timed out)":""}`),M(S)})},b.onerror=()=>C(1006,"connection failed"),b.onclose=(u)=>C(u.code,u.reason)})}export{Oe as runMachineDaemon};