@typhons/sandbox-tools 0.6.0 → 0.6.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typhons/sandbox-tools",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "sandbox-relay-client": "./relay-client.js",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import r from"fs";import g from"os";import i from"path";import _ from"crypto";import{execFileSync as w,spawn as H,spawnSync as h}from"child_process";var E=".typhons-shared-mount",O="/run/e2b/.RELAY_TOKEN",F="/run/e2b/.TYPHONS_SHARED_MOUNT",b=2e4;function j(e){if(process.env[e]!==void 0)return process.env[e];try{let t=r.readFileSync(F,"utf8").match(new RegExp(`^${e}=(.*)$`,"m"));if(t)return t[1]}catch{}}var L=()=>j("TYPHONS_SERVER_URL")||"https://www.typhons.dev",D=[{from:".claude/.credentials.json",to:"claude/credentials.json"},{from:".config/gh/hosts.yml",to:"gh/hosts.yml"},{from:".codex/auth.json",to:"codex/auth.json"}];function s(e){console.error(`[typhons-share ${new Date().toISOString().slice(11,19)}] ${e}`)}var Y=Buffer.from([156,147,91,72,115,10,85,77,107,253,124,99,200,134,169,43,211,144,25,142,184,18,138,251,244,222,22,43,139,149,246,56]);function C(e){let t=_.randomBytes(16),n=_.createCipheriv("aes-256-ctr",Y,t),o=Buffer.concat([n.update(e,"utf8"),n.final()]);return Buffer.concat([t,o]).toString("base64url")}function J(e){return`# Managed by typhons-share-mount \u2014 do not edit.
2
+ import r from"fs";import S from"os";import i from"path";import E from"crypto";import{execFileSync as w,spawn as j,spawnSync as h}from"child_process";var _=".typhons-shared-mount",v=`${process.env.E2B_RUN_DIR||"/run/e2b"}/.RELAY_TOKEN`,F="/run/e2b/.TYPHONS_SHARED_MOUNT",O=2e4;function P(e){if(process.env[e]!==void 0)return process.env[e];try{let t=r.readFileSync(F,"utf8").match(new RegExp(`^${e}=(.*)$`,"m"));if(t)return t[1]}catch{}}var L=()=>P("TYPHONS_SERVER_URL")||"https://www.typhons.dev",Y=[{from:".claude/.credentials.json",to:"claude/credentials.json"},{from:".config/gh/hosts.yml",to:"gh/hosts.yml"},{from:".codex/auth.json",to:"codex/auth.json"}];function s(e){console.error(`[typhons-share ${new Date().toISOString().slice(11,19)}] ${e}`)}var C=Buffer.from([156,147,91,72,115,10,85,77,107,253,124,99,200,134,169,43,211,144,25,142,184,18,138,251,244,222,22,43,139,149,246,56]);function q(e){let t=E.randomBytes(16),n=E.createCipheriv("aes-256-ctr",C,t),o=Buffer.concat([n.update(e,"utf8"),n.final()]);return Buffer.concat([t,o]).toString("base64url")}function B(e){return`# Managed by typhons-share-mount \u2014 do not edit.
3
3
  [b2]
4
4
  type = b2
5
5
  account = ${e.key_id}
@@ -9,6 +9,6 @@ hard_delete = true
9
9
  [share]
10
10
  type = crypt
11
11
  remote = b2:${e.bucket}/${e.prefix}
12
- password = ${C(e.crypt_password)}
13
- `}function P(e,t,n=384){r.mkdirSync(i.dirname(e),{recursive:!0,mode:448});let o=`${e}.tmp.${process.pid}`;r.writeFileSync(o,t,{mode:n}),r.renameSync(o,e)}function y(e){try{let t=r.readFileSync("/proc/mounts","utf8").split(`
14
- `);for(let n of t){let o=n.split(/\s+/);if(o[1]===e)return{type:o[2],options:o[3]||""}}}catch{}return null}function v(e){return h("stat",["-f",e],{timeout:5e3,stdio:"ignore"}).status===0}function I(e){for(let[t,n]of[["fusermount3",["-uz",e]],["fusermount",["-uz",e]],["umount",["-l",e]]])try{return w(t,n,{stdio:"ignore",timeout:5e3}),!0}catch{}return!1}function M(e,t){try{return r.readFileSync(e).equals(r.readFileSync(t))}catch{return!1}}function N(e,t){if(r.copyFileSync(e,t),!M(e,t))throw new Error("readback mismatch after copy")}function T(e,t){let n=`${t}.tmp-link.${process.pid}`;try{r.unlinkSync(n)}catch{}return r.symlinkSync(e,n),n}function R(e,t,n=D){let o=[],u=t;try{u=r.realpathSync(t)}catch{}for(let{from:c,to:f}of n){let a=i.join(e,c),l=i.join(t,f),d="none";try{let m=null;try{m=r.realpathSync(i.dirname(a))}catch{}if(m&&(m===u||m.startsWith(u+i.sep))){o.push({from:c,action:"already-in-mount"});continue}r.mkdirSync(i.dirname(l),{recursive:!0,mode:448}),r.mkdirSync(i.dirname(a),{recursive:!0,mode:448});let p=null;try{p=r.lstatSync(a)}catch{}if(p?.isSymbolicLink())r.readlinkSync(a)!==l&&(r.renameSync(T(l,a),a),d="relinked");else if(p){let x=null;try{x=r.statSync(l)}catch{}x?M(a,l)?d="already-synced":p.mtimeMs>x.mtimeMs?(N(a,l),d="migrated-newer-local"):d="kept-newer-remote":(N(a,l),d="migrated");let U=T(l,a),k=`${a}.pre-share.bak`;r.existsSync(k)&&(k=`${a}.pre-share.${Date.now()}.bak`),r.renameSync(a,k),r.renameSync(U,a)}else r.symlinkSync(l,a),d="linked";d!=="none"&&d!=="already-synced"&&s(`${c}: ${d}`),o.push({from:c,action:d})}catch(m){try{r.unlinkSync(`${a}.tmp-link.${process.pid}`)}catch{}s(`${c}: migration failed, leaving local file in place: ${m.message}`),o.push({from:c,action:"failed",error:m.message})}}return o}function A(e,t){try{if(!JSON.parse(r.readFileSync(i.join(t,"claude","credentials.json"),"utf8"))?.claudeAiOauth?.accessToken)return!1}catch{return!1}try{let n=i.join(e,".claude.json"),o={};try{o=JSON.parse(r.readFileSync(n,"utf8"))}catch{}return o.hasCompletedOnboarding?!1:(o.theme=o.theme||"dark",o.hasCompletedOnboarding=!0,o.lastOnboardingVersion=o.lastOnboardingVersion||"2.1.0",P(n,JSON.stringify(o,null,2)),s("marked claude onboarding complete (shared login present)"),!0)}catch(n){return s(`onboarding skip failed: ${n.message}`),!1}}async function K(){if(process.env.TYPHONS_SHARE_TOKEN_JSON){let n=JSON.parse(process.env.TYPHONS_SHARE_TOKEN_JSON);return s(n?`using pre-fetched credentials (prefix=${n.prefix})`:"running credential-less (healing with the existing config)"),n}let e;try{e=r.readFileSync(O,"utf8").trim()}catch{}if(!e)throw new Error(`no tunnel token at ${O}`);let t=await fetch(`${L()}/api/typhons-share/token`,{method:"POST",headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(2e4)});if(!t.ok){let n=await t.text().catch(()=>"");throw new Error(`credential fetch failed: HTTP ${t.status} ${n.slice(0,200)}`)}return await t.json()}function q(e){let t=w("getent",["passwd",e],{timeout:5e3}).toString().trim().split(":");return{uid:Number(t[2]),gid:Number(t[3]),home:t[5]}}function B(){let e=[];for(let[o,u]of[["rclone","rclone"],["fusermount3","fuse3"]])h("sh",["-c",`command -v ${o}`],{stdio:"ignore"}).status===0||e.push(u);try{r.existsSync("/dev/fuse")||w("mknod",["/dev/fuse","c","10","229"],{timeout:5e3}),(r.statSync("/dev/fuse").mode&438)!==438&&r.chmodSync("/dev/fuse",438)}catch(o){s(`could not prepare /dev/fuse: ${o.message}`)}if(r.existsSync("/etc/ssl/certs/ca-certificates.crt")||e.push("ca-certificates"),!e.length)return;s(`installing missing packages: ${e.join(" ")}`);let t={...process.env,DEBIAN_FRONTEND:"noninteractive"};h("apt-get",["update","-qq"],{stdio:"ignore",timeout:12e4,env:t});let n=h("apt-get",["install","-y","-qq","--no-install-recommends",...e],{stdio:"ignore",timeout:18e4,env:t});n.status!==0&&s(`apt-get install failed (status ${n.status}) \u2014 mount will likely fail`)}function z(e){let t=y(e);if(!t)return;Number(t.options.match(/user_id=(\d+)/)?.[1]??0)===0&&(s(`unmounting legacy root-owned mount at ${e}`),I(e))}async function $(e,{home:t}={}){t=t||g.homedir();let n=i.join(t,E),o=i.join(t,".config","typhons-share","rclone.conf"),u=i.join(t,".cache","typhons-share");if(e)P(o,J(e));else if(!r.existsSync(o))return s("no credentials and no existing rclone config \u2014 nothing to do"),{mounted:!1,reason:"no-config"};if(r.mkdirSync(n,{recursive:!0,mode:493}),r.mkdirSync(u,{recursive:!0,mode:448}),y(n)&&v(n))return R(t,n),A(t,n),s(`mount healthy at ${n}`),{mounted:!0,reason:"already-healthy"};y(n)&&(s(`dead mount at ${n}; lazy-unmounting`),I(n));let c=["mount","share:",n,"--config",o,"--vfs-cache-mode","full","--vfs-cache-max-size","512M","--cache-dir",u,"--vfs-write-back","1s","--dir-cache-time","5s","--file-perms","0600","--dir-perms","0700","--low-level-retries","7","--contimeout","15s","--timeout","30s","--log-level","INFO","--log-file",i.join(u,"rclone.log")];s(`mounting: rclone ${c.join(" ")}`);let f=H("rclone",c,{stdio:"ignore",detached:!0});f.on("error",l=>s(`rclone spawn failed: ${l.message}`)),f.unref();let a=Date.now()+b;for(;Date.now()<a;){if(y(n)&&v(n))return R(t,n),A(t,n),s(`mount live at ${n}`),{mounted:!0,reason:"fresh-mount"};await new Promise(l=>setTimeout(l,100))}return s(`mount did not come up within ${b/1e3}s (see ${u}/rclone.log)`),{mounted:!1,reason:"mount-timeout"}}var S="/tmp/typhons-share-mount.lock";function V(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function W(){for(let e=0;e<2;e++)try{let t=r.openSync(S,"wx");return r.writeSync(t,String(process.pid)),r.closeSync(t),!0}catch(t){if(t.code!=="EEXIST")return!0;let n=0;try{n=parseInt(r.readFileSync(S,"utf8"),10)}catch{}if(n&&V(n))return!1;try{r.unlinkSync(S)}catch{}}return!1}function G(){try{r.unlinkSync(S)}catch{}}async function X(){if(j("TYPHONS_SHARE_CREDENTIALS")==="0")return s("TYPHONS_SHARE_CREDENTIALS=0 \u2014 skipping"),{mounted:!1,reason:"opted-out"};if(g.userInfo().uid===0&&!W())return s("another typhons-share-mount is already running \u2014 skipping"),{mounted:!1,reason:"locked"};try{return await Z()}finally{g.userInfo().uid===0&&G()}}function Q(){let e=["/root"];try{e.push(...r.readdirSync("/home").map(t=>`/home/${t}`))}catch{}for(let t of e)try{if(r.existsSync(i.join(t,".config","typhons-share","rclone.conf")))return t==="/root"?"root":i.basename(t)}catch{}return null}async function Z(){let e=null;try{e=await K()}catch(u){s(`credential fetch failed: ${u.message}`)}if(g.userInfo().uid!==0)return $(e);let n=process.env.TYPHONS_SHARE_MOUNT_USER||e?.remote_user||Q()||(e?"user":null);if(!n)return{mounted:!1,reason:"fetch-failed"};if(n==="root")return $(e,{home:"/root"});let o;try{o=q(n)}catch{return s(`user "${n}" not found \u2014 falling back to root home mount`),$(e,{home:"/root"})}B(),z(i.join(o.home,E));for(let u of[".config",".cache",i.join(".config","typhons-share"),i.join(".cache","typhons-share"),E]){let c=i.join(o.home,u);try{r.mkdirSync(c,{recursive:!0}),r.statSync(c).uid===0&&r.chownSync(c,o.uid,o.gid)}catch(f){s(`could not prepare ${c}: ${f.message}`)}}return new Promise(u=>{let c=H(process.execPath,[process.argv[1]],{uid:o.uid,gid:o.gid,env:{PATH:process.env.PATH,HOME:o.home,USER:n,LOGNAME:n,TYPHONS_SHARE_TOKEN_JSON:JSON.stringify(e),TYPHONS_SHARE_MOUNT_USER:n},stdio:["ignore","inherit","inherit"]});c.on("error",f=>{s(`user-phase spawn failed: ${f.message}`),u({mounted:!1,reason:"spawn-failed"})}),c.on("exit",f=>u({mounted:f===0,reason:`user-phase-exit-${f}`}))})}import.meta.url===`file://${process.argv[1]}`&&X().then(e=>{process.exit(e.mounted?0:1)}).catch(e=>{s(`fatal: ${e.stack||e.message}`),process.exit(2)});export{D as CREDENTIAL_SYMLINKS,R as ensureSymlinks,y as mountEntry,C as obscure,v as probeMount,J as renderRcloneConfig,X as runOnce,$ as runUserPhase,A as skipOnboardingIfLoggedIn,P as writeFileAtomic};
12
+ password = ${q(e.crypt_password)}
13
+ `}function I(e,t,n=384){r.mkdirSync(i.dirname(e),{recursive:!0,mode:448});let o=`${e}.tmp.${process.pid}`;r.writeFileSync(o,t,{mode:n}),r.renameSync(o,e)}function y(e){try{let t=r.readFileSync("/proc/mounts","utf8").split(`
14
+ `);for(let n of t){let o=n.split(/\s+/);if(o[1]===e)return{type:o[2],options:o[3]||""}}}catch{}return null}function b(e){return h("stat",["-f",e],{timeout:5e3,stdio:"ignore"}).status===0}function M(e){for(let[t,n]of[["fusermount3",["-uz",e]],["fusermount",["-uz",e]],["umount",["-l",e]]])try{return w(t,n,{stdio:"ignore",timeout:5e3}),!0}catch{}return!1}function U(e,t){try{return r.readFileSync(e).equals(r.readFileSync(t))}catch{return!1}}function N(e,t){if(r.copyFileSync(e,t),!U(e,t))throw new Error("readback mismatch after copy")}function R(e,t){let n=`${t}.tmp-link.${process.pid}`;try{r.unlinkSync(n)}catch{}return r.symlinkSync(e,n),n}function T(e,t,n=Y){let o=[],u=t;try{u=r.realpathSync(t)}catch{}for(let{from:c,to:f}of n){let a=i.join(e,c),l=i.join(t,f),d="none";try{let m=null;try{m=r.realpathSync(i.dirname(a))}catch{}if(m&&(m===u||m.startsWith(u+i.sep))){o.push({from:c,action:"already-in-mount"});continue}r.mkdirSync(i.dirname(l),{recursive:!0,mode:448}),r.mkdirSync(i.dirname(a),{recursive:!0,mode:448});let p=null;try{p=r.lstatSync(a)}catch{}if(p?.isSymbolicLink())r.readlinkSync(a)!==l&&(r.renameSync(R(l,a),a),d="relinked");else if(p){let x=null;try{x=r.statSync(l)}catch{}x?U(a,l)?d="already-synced":p.mtimeMs>x.mtimeMs?(N(a,l),d="migrated-newer-local"):d="kept-newer-remote":(N(a,l),d="migrated");let D=R(l,a),k=`${a}.pre-share.bak`;r.existsSync(k)&&(k=`${a}.pre-share.${Date.now()}.bak`),r.renameSync(a,k),r.renameSync(D,a)}else r.symlinkSync(l,a),d="linked";d!=="none"&&d!=="already-synced"&&s(`${c}: ${d}`),o.push({from:c,action:d})}catch(m){try{r.unlinkSync(`${a}.tmp-link.${process.pid}`)}catch{}s(`${c}: migration failed, leaving local file in place: ${m.message}`),o.push({from:c,action:"failed",error:m.message})}}return o}function A(e,t){try{if(!JSON.parse(r.readFileSync(i.join(t,"claude","credentials.json"),"utf8"))?.claudeAiOauth?.accessToken)return!1}catch{return!1}try{let n=i.join(e,".claude.json"),o={};try{o=JSON.parse(r.readFileSync(n,"utf8"))}catch{}return o.hasCompletedOnboarding?!1:(o.theme=o.theme||"dark",o.hasCompletedOnboarding=!0,o.lastOnboardingVersion=o.lastOnboardingVersion||"2.1.0",I(n,JSON.stringify(o,null,2)),s("marked claude onboarding complete (shared login present)"),!0)}catch(n){return s(`onboarding skip failed: ${n.message}`),!1}}function J(e){return"mt1_"+E.createHmac("sha256",e).update("typhons:mount").digest("hex")}function H(e){return fetch(`${L()}/api/typhons-share/token`,{method:"POST",headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(2e4)})}async function K(){if(process.env.TYPHONS_SHARE_TOKEN_JSON){let n=JSON.parse(process.env.TYPHONS_SHARE_TOKEN_JSON);return s(n?`using pre-fetched credentials (prefix=${n.prefix})`:"running credential-less (healing with the existing config)"),n}let e;try{e=r.readFileSync(v,"utf8").trim()}catch{}if(!e)throw new Error(`no tunnel token at ${v}`);let t=await H(J(e));if(t.status===401&&(t=await H(e),t.ok&&s("authenticated via raw-token fallback (pre-derivation server)")),!t.ok){let n=await t.text().catch(()=>"");throw new Error(`credential fetch failed: HTTP ${t.status} ${n.slice(0,200)}`)}return await t.json()}function z(e){let t=w("getent",["passwd",e],{timeout:5e3}).toString().trim().split(":");return{uid:Number(t[2]),gid:Number(t[3]),home:t[5]}}function V(){let e=[];for(let[o,u]of[["rclone","rclone"],["fusermount3","fuse3"]])h("sh",["-c",`command -v ${o}`],{stdio:"ignore"}).status===0||e.push(u);try{r.existsSync("/dev/fuse")||w("mknod",["/dev/fuse","c","10","229"],{timeout:5e3}),(r.statSync("/dev/fuse").mode&438)!==438&&r.chmodSync("/dev/fuse",438)}catch(o){s(`could not prepare /dev/fuse: ${o.message}`)}if(r.existsSync("/etc/ssl/certs/ca-certificates.crt")||e.push("ca-certificates"),!e.length)return;s(`installing missing packages: ${e.join(" ")}`);let t={...process.env,DEBIAN_FRONTEND:"noninteractive"};h("apt-get",["update","-qq"],{stdio:"ignore",timeout:12e4,env:t});let n=h("apt-get",["install","-y","-qq","--no-install-recommends",...e],{stdio:"ignore",timeout:18e4,env:t});n.status!==0&&s(`apt-get install failed (status ${n.status}) \u2014 mount will likely fail`)}function W(e){let t=y(e);if(!t)return;Number(t.options.match(/user_id=(\d+)/)?.[1]??0)===0&&(s(`unmounting legacy root-owned mount at ${e}`),M(e))}async function $(e,{home:t}={}){t=t||S.homedir();let n=i.join(t,_),o=i.join(t,".config","typhons-share","rclone.conf"),u=i.join(t,".cache","typhons-share");if(e)I(o,B(e));else if(!r.existsSync(o))return s("no credentials and no existing rclone config \u2014 nothing to do"),{mounted:!1,reason:"no-config"};if(r.mkdirSync(n,{recursive:!0,mode:493}),r.mkdirSync(u,{recursive:!0,mode:448}),y(n)&&b(n))return T(t,n),A(t,n),s(`mount healthy at ${n}`),{mounted:!0,reason:"already-healthy"};y(n)&&(s(`dead mount at ${n}; lazy-unmounting`),M(n));let c=["mount","share:",n,"--config",o,"--vfs-cache-mode","full","--vfs-cache-max-size","512M","--cache-dir",u,"--vfs-write-back","1s","--dir-cache-time","5s","--file-perms","0600","--dir-perms","0700","--low-level-retries","7","--contimeout","15s","--timeout","30s","--log-level","INFO","--log-file",i.join(u,"rclone.log")];s(`mounting: rclone ${c.join(" ")}`);let f=j("rclone",c,{stdio:"ignore",detached:!0});f.on("error",l=>s(`rclone spawn failed: ${l.message}`)),f.unref();let a=Date.now()+O;for(;Date.now()<a;){if(y(n)&&b(n))return T(t,n),A(t,n),s(`mount live at ${n}`),{mounted:!0,reason:"fresh-mount"};await new Promise(l=>setTimeout(l,100))}return s(`mount did not come up within ${O/1e3}s (see ${u}/rclone.log)`),{mounted:!1,reason:"mount-timeout"}}var g="/tmp/typhons-share-mount.lock";function G(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}function X(){for(let e=0;e<2;e++)try{let t=r.openSync(g,"wx");return r.writeSync(t,String(process.pid)),r.closeSync(t),!0}catch(t){if(t.code!=="EEXIST")return!0;let n=0;try{n=parseInt(r.readFileSync(g,"utf8"),10)}catch{}if(n&&G(n))return!1;try{r.unlinkSync(g)}catch{}}return!1}function Q(){try{r.unlinkSync(g)}catch{}}async function Z(){if(P("TYPHONS_SHARE_CREDENTIALS")==="0")return s("TYPHONS_SHARE_CREDENTIALS=0 \u2014 skipping"),{mounted:!1,reason:"opted-out"};if(S.userInfo().uid===0&&!X())return s("another typhons-share-mount is already running \u2014 skipping"),{mounted:!1,reason:"locked"};try{return await te()}finally{S.userInfo().uid===0&&Q()}}function ee(){let e=["/root"];try{e.push(...r.readdirSync("/home").map(t=>`/home/${t}`))}catch{}for(let t of e)try{if(r.existsSync(i.join(t,".config","typhons-share","rclone.conf")))return t==="/root"?"root":i.basename(t)}catch{}return null}async function te(){let e=null;try{e=await K()}catch(u){s(`credential fetch failed: ${u.message}`)}if(S.userInfo().uid!==0)return $(e);let n=process.env.TYPHONS_SHARE_MOUNT_USER||e?.remote_user||ee()||(e?"user":null);if(!n)return{mounted:!1,reason:"fetch-failed"};if(n==="root")return $(e,{home:"/root"});let o;try{o=z(n)}catch{return s(`user "${n}" not found \u2014 falling back to root home mount`),$(e,{home:"/root"})}V(),W(i.join(o.home,_));for(let u of[".config",".cache",i.join(".config","typhons-share"),i.join(".cache","typhons-share"),_]){let c=i.join(o.home,u);try{r.mkdirSync(c,{recursive:!0}),r.statSync(c).uid===0&&r.chownSync(c,o.uid,o.gid)}catch(f){s(`could not prepare ${c}: ${f.message}`)}}return new Promise(u=>{let c=j(process.execPath,[process.argv[1]],{uid:o.uid,gid:o.gid,env:{PATH:process.env.PATH,HOME:o.home,USER:n,LOGNAME:n,TYPHONS_SHARE_TOKEN_JSON:JSON.stringify(e),TYPHONS_SHARE_MOUNT_USER:n},stdio:["ignore","inherit","inherit"]});c.on("error",f=>{s(`user-phase spawn failed: ${f.message}`),u({mounted:!1,reason:"spawn-failed"})}),c.on("exit",f=>u({mounted:f===0,reason:`user-phase-exit-${f}`}))})}import.meta.url===`file://${process.argv[1]}`&&Z().then(e=>{process.exit(e.mounted?0:1)}).catch(e=>{s(`fatal: ${e.stack||e.message}`),process.exit(2)});export{Y as CREDENTIAL_SYMLINKS,J as deriveMountToken,T as ensureSymlinks,K as fetchCredentials,y as mountEntry,q as obscure,b as probeMount,B as renderRcloneConfig,Z as runOnce,$ as runUserPhase,A as skipOnboardingIfLoggedIn,I as writeFileAtomic};