@tangle-network/sandbox-cli 0.0.0-develop.20260601172150.3b0d399 → 0.0.0-develop.20260601195011.b9ed062

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.
Files changed (2) hide show
  1. package/dist/index.mjs +1 -1
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import{createRequire as e}from"node:module";import"dotenv/config";import{Command as t}from"commander";import n from"chalk";import{AuthError as r,NetworkError as i,NotFoundError as a,QuotaError as o,Sandbox as s,ServerError as c,StateError as l,TimeoutError as u,ValidationError as ee,createConfidentialSandbox as te,generateAttestationNonce as ne}from"@tangle-network/sandbox";import*as d from"node:fs";import{mkdirSync as re,readFileSync as ie,writeFileSync as ae}from"node:fs";import*as oe from"node:os";import{tmpdir as se}from"node:os";import*as f from"node:path";import{extname as ce,join as p,resolve as m}from"node:path";import{execFileSync as h,spawn as le}from"node:child_process";import{HubClient as ue,HubSdkError as de}from"@tangle-network/hub-sdk";import fe from"ora";import{randomBytes as pe}from"node:crypto";import{createMcpServer as me}from"@tangle-network/sandbox/agent";import{readFile as he}from"node:fs/promises";import ge from"ws";const g=f.join(oe.homedir(),`.tangle`),_=f.join(g,`credentials.json`),v=`tangle-sandbox-cli`,_e=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var ve=class extends Error{constructor(e,t){super(`Credentials file at ${e} is corrupted and cannot be parsed. Inspect or remove it manually before retrying — refusing to overwrite it automatically.`),this.filePath=e,this.name=`CredentialsFileCorruptedError`,t&&(this.cause=t)}},ye=class extends Error{constructor(){super(`Could not store credential in the OS keychain, and the plaintext fallback is not enabled. Install a keychain provider (macOS Keychain or libsecret/secret-tool on Linux), or set ${_e}=1 to opt into a plaintext credentials.json with mode 0600.`),this.name=`KeychainUnavailableError`}};function be(e){let t=we(e);if(t)return{value:t,source:`keychain`};let n=De(e);return n?{value:n,source:`file`}:{source:`none`}}function xe(e,t){if(Te(e,t))return ke(e),`keychain`;if(!Ce())throw new ye;return Oe(e,t),`file`}function Se(e){Ee(e),ke(e)}function Ce(){let e=process.env[_e];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function we(e){if(process.platform===`darwin`)try{return h(`security`,[`find-generic-password`,`-s`,v,`-a`,y(e),`-w`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}if(process.platform===`linux`)try{return h(`secret-tool`,[`lookup`,`service`,v,`account`,y(e)],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}}function Te(e,t){if(process.platform===`darwin`)try{return h(`security`,[`add-generic-password`,`-U`,`-s`,v,`-a`,y(e),`-w`,t],{stdio:[`ignore`,`ignore`,`ignore`]}),!0}catch{return!1}if(process.platform===`linux`)try{return h(`secret-tool`,[`store`,`--label=Tangle Sandbox CLI`,`service`,v,`account`,y(e)],{input:t,stdio:[`pipe`,`ignore`,`ignore`]}),!0}catch{return!1}return!1}function Ee(e){if(process.platform===`darwin`){try{h(`security`,[`delete-generic-password`,`-s`,v,`-a`,y(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}return}if(process.platform===`linux`)try{h(`secret-tool`,[`clear`,`service`,v,`account`,y(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}}function De(e){return Ae()[e]}function Oe(e,t){let n=Ae();n[e]=t,je(n)}function ke(e){let t;try{t=Ae()}catch(e){if(e instanceof ve)return;throw e}e in t&&(delete t[e],je(t))}function Ae(){let e;try{e=d.readFileSync(_,`utf8`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))throw new ve(_);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof ve?e:new ve(_,e instanceof Error?e:void 0)}}function je(e){if(Me(),Object.keys(e).length===0){d.existsSync(_)&&d.unlinkSync(_);return}let t=`${_}.${process.pid}.tmp`;d.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),d.renameSync(t,_)}function Me(){if(!d.existsSync(g)){d.mkdirSync(g,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(d.statSync(g).mode&511)!=448&&d.chmodSync(g,448)}catch{}}function y(e){return`profile:${e}`}const b=f.join(oe.homedir(),`.tangle`),x=f.join(b,`credentials`),S=f.join(b,`config.json`),C=`default`;function Ne(){d.existsSync(b)||d.mkdirSync(b,{mode:448,recursive:!0})}function Pe(e,t){Ne();let n=`${e}.${process.pid}.tmp`;d.writeFileSync(n,t,{mode:384}),d.renameSync(n,e)}function Fe(){try{if(d.existsSync(x)){let e=d.readFileSync(x,`utf-8`).trim();return Ie(e)?e:e.match(/api_key\s*=\s*(\S+)/)?.[1]}}catch{}}function Ie(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function Le(){try{d.existsSync(x)&&d.unlinkSync(x)}catch{}}function w(){return Ye(Je())}function T(e){let t=Xe(w(),e);Pe(S,`${JSON.stringify(t,null,2)}\n`)}function E(e){return A(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||w().activeProfile||C)}function Re(e){T({activeProfile:A(e)})}function ze(){let e=w(),t=E(),n=new Set([C,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(A(e.activeProfile)),[...n].map(e=>{let n=be(e),r=e===C?Fe():void 0,i=n.source===`none`?r?`legacy-file`:`none`:n.source;return{name:e,active:e===t,hasApiKey:n.source!==`none`||!!r,baseUrl:D(void 0,e),apiKeySource:i}}).sort((e,t)=>e.name.localeCompare(t.name))}function Be(e){let t=E(e);return{name:t,active:t===E(),apiKey:Ue(void 0,t),baseUrl:D(void 0,t),credentialSource:We(void 0,t)}}function Ve(e,t){let n=A(e),r=w(),i=k(n,r),a={},o=t.baseUrl??i.baseUrl;o&&(a.baseUrl=o);let s=t.activeTeamId??i.activeTeamId;s&&(a.activeTeamId=s);let c=t.activeTeamName??i.activeTeamName;c&&(a.activeTeamName=c);let l={...r.profiles??{}};a.baseUrl||a.activeTeamId||a.activeTeamName?l[n]=a:delete l[n];let u;return t.apiKey&&(u=xe(n,t.apiKey),n===C&&Le()),T({profiles:Object.keys(l).length>0?l:{}}),u}function He(e){let t=E(e),n={...w().profiles??{}},r=n[t];if(r){let e={...r,apiKey:void 0};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}T({profiles:n}),Se(t),t===C&&Le()}function Ue(e,t){if(e)return e;let n=process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY;if(n)return n;let r=E(t),i=be(r);if(i.value)return i.value;if(r===C)return Fe()}function We(e,t){if(e)return`flag`;if(process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY)return`env`;let n=E(t),r=be(n);return r.source===`none`?n===C&&Fe()?`legacy-file`:`none`:r.source}function D(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=E(t),i=w(),a=k(r,i);return a.baseUrl?a.baseUrl:r===C&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function O(e){let t=E(e.profile),n=Ue(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===C?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:D(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...Ge(t)}}function Ge(e){let t=w(),n=k(E(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function Ke(e,t){Ve(E(t),{activeTeamId:e.id,activeTeamName:e.name})}function qe(e){let t=E(e),n=w(),r={...n.profiles??{}},i={baseUrl:k(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],T({profiles:r})}function k(e,t=w()){let n=A(e);return{...n===C?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[C]?.activeTeamId,activeTeamName:t.profiles?.[C]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function Je(){try{if(d.existsSync(S)){let e=d.readFileSync(S,`utf-8`);return JSON.parse(e)}}catch{}return{}}function Ye(e){let t=!1,n={};e.apiKey&&(xe(C,e.apiKey),Le(),t=!0);for(let[r,i]of Object.entries(e.profiles??{})){i.apiKey&&(xe(r,i.apiKey),t=!0);let e={};i.baseUrl&&(e.baseUrl=i.baseUrl),i.activeTeamId&&(e.activeTeamId=i.activeTeamId),i.activeTeamName&&(e.activeTeamName=i.activeTeamName),Object.keys(e).length>0&&(n[r]=e)}let r={...e,apiKey:void 0,profiles:Object.keys(n).length>0?n:void 0};return t&&Pe(S,`${JSON.stringify(r,null,2)}\n`),r}function Xe(e,t){let n=t.profiles===void 0?{...e.profiles??{}}:Object.fromEntries(Object.entries(t.profiles).filter(([,e])=>!!(e.apiKey||e.baseUrl||e.activeTeamId||e.activeTeamName)));return{...e,...t,profiles:Object.keys(n).length>0?n:void 0}}function A(e){let t=e.trim().toLowerCase();if(!t)throw Error(`Profile name cannot be empty`);if(!/^[a-z0-9][a-z0-9._-]*$/.test(t))throw Error(`Profile names may only contain lowercase letters, numbers, dots, underscores, and hyphens`);return t}let j=null,M=null;function N(e){if(e)return j&&M&&M.apiKey===e.apiKey&&M.baseUrl===e.baseUrl?j:(j=new s({apiKey:e.apiKey,baseUrl:e.baseUrl,timeoutMs:e.timeout}),M=e,j);if(j)return j;let t=O({});return j=new s({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),M=t,j}function Ze(){j=null,M=null}function P(e){let t=Qe(e);console.error(n.red(`Error:`),t),process.exit(tt(e))}function Qe(e){if(e instanceof r)return`Authentication failed. Run 'tangle auth login' to authenticate.`;if(e instanceof a)return`Resource not found. Check the ID and try again.`;if(e instanceof o)return`Quota exceeded. Upgrade your plan or wait for quota reset.`;if(e instanceof ee)return`Invalid input: ${e.message}`;if(e instanceof l)return`Invalid state: ${e.message}`;if(e instanceof u)return`Request timed out. Try again or increase timeout with --timeout.`;if(e instanceof i)return`Network error. Check your connection and try again.`;if(e instanceof c)return`${e.status?`HTTP ${e.status}`:`server error`}: ${e.message}`;if(e instanceof de){let t=typeof e.status==`number`?` (HTTP ${e.status})`:``;return e.code===`HUB_CONNECTION_MISSING`?`${e.code}${t}: ${e.message}. Run: tangle hub connect github`:e.code===`HUB_APPROVAL_REQUIRED`?$e(e.code,t,e.message):`${e.code}${t}: ${e.message}`}return et(e)?e.code===`HUB_CONNECTION_MISSING`?`${e.code} (HTTP ${e.status}): ${e.message}. Run: tangle hub connect github`:e.code===`HUB_APPROVAL_REQUIRED`?$e(e.code,` (HTTP ${e.status})`,e.message):`${e.code} (HTTP ${e.status}): ${e.message}`:e instanceof Error?e.message:String(e)}function $e(e,t,n){return`${e}${t}: ${n}. Run the command again with --approve, or rerun with --json to inspect approval.id and then run: tangle hub resume <approval-id> --accept`}function et(e){if(!(e instanceof Error))return!1;let t=e;return typeof t.code==`string`&&t.code.startsWith(`HUB_`)&&typeof t.status==`number`}function tt(e){return e instanceof ee?2:1}function nt(e){return e==null?n.dim(`-`):typeof e==`boolean`?e?n.green(`yes`):n.red(`no`):e instanceof Date?it(e):typeof e==`string`&&rt(e)?it(new Date(e)):String(e)}function rt(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function it(e){let t=Date.now()-e.getTime();if(t<6e4)return`just now`;if(t<36e5)return`${Math.floor(t/6e4)} min ago`;if(t<864e5){let e=Math.floor(t/36e5);return`${e} hour${e>1?`s`:``} ago`}let n=Math.floor(t/864e5);return`${n} day${n>1?`s`:``} ago`}function at(e){switch(e){case`running`:return n.green(e);case`pending`:case`provisioning`:return n.yellow(e);case`stopped`:return n.gray(e);case`failed`:case`deleted`:return n.red(e);default:return e}}function F(e,t){if(e.length===0){console.log(n.dim(`No items found.`));return}let r=t.map(t=>{let n=t.header.length,r=Math.max(...e.map(e=>nt(e[t.key]).length));return t.width??Math.max(n,r)+2}),i=t.map((e,t)=>n.bold(e.header.padEnd(r[t]))).join(``);console.log(i);for(let n of e){let e=t.map((e,t)=>{let i=nt(n[e.key]);return e.key===`status`&&(i=at(String(n[e.key]))),i.padEnd(r[t])}).join(``);console.log(e)}}function I(e){console.log(JSON.stringify(e,null,2))}function L(e){console.log(n.green(`✓`),e)}function R(e){console.error(n.red(`✗`),e)}function ot(e){console.log(n.yellow(`!`),e)}function z(e){console.log(n.blue(`→`),e)}function B(e){return fe({text:e,color:`cyan`})}function V(e,t=0){let r=` `.repeat(t);for(let[t,i]of Object.entries(e))i!=null&&console.log(`${r}${n.dim(`${t}:`)} ${nt(i)}`)}function st(e){if(console.log(),console.log(n.bold(`Sandbox Details`)),console.log(n.dim(`─`.repeat(40))),V({ID:e.id,Name:e.name,Status:at(e.status),Created:e.createdAt,Expires:e.expiresAt}),e.connection){if(console.log(),console.log(n.bold(`Connection`)),console.log(n.dim(`─`.repeat(40))),e.connection.ssh){let{ssh:t}=e.connection,n=process.platform===`win32`?`NUL`:`/dev/null`,r=`ssh -o ProxyCommand="${t.proxyCommand}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=${n} -o GlobalKnownHostsFile=${n} -o LogLevel=ERROR -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -o TCPKeepAlive=yes ${t.username}@localhost -p ${t.port}`;V({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&V({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&V({"API URL":e.connection.runtimeUrl})}console.log()}function H(e,t){t?I({error:e.message}):R(e.message),process.exit(1)}function U(e){I(e)}function W(e,t){if(t.length===0){console.log(n.dim(`No items found.`));return}let r=e.map((e,n)=>{let r=Math.max(...t.map(e=>String(e[n]??``).length));return Math.max(e.length,r)+2});console.log(e.map((e,t)=>n.bold(e.padEnd(r[t]))).join(``));for(let e of t)console.log(e.map((e,t)=>String(e??``).padEnd(r[t])).join(``))}const G=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function ct(e,t,n){switch(e){case`anthropic`:return`// pnpm add @anthropic-ai/sdk @tangle-network/sandbox
1
+ import{createRequire as e}from"node:module";import"dotenv/config";import{Command as t}from"commander";import n from"chalk";import{AuthError as r,NetworkError as i,NotFoundError as a,QuotaError as o,Sandbox as s,ServerError as c,StateError as l,TimeoutError as u,ValidationError as ee,createConfidentialSandbox as te,generateAttestationNonce as ne}from"@tangle-network/sandbox";import*as d from"node:fs";import{mkdirSync as re,readFileSync as ie,writeFileSync as ae}from"node:fs";import*as oe from"node:os";import{tmpdir as se}from"node:os";import*as f from"node:path";import{extname as ce,join as p,resolve as m}from"node:path";import{execFileSync as h,spawn as le}from"node:child_process";import{HubClient as ue,HubSdkError as de}from"@tangle-network/hub-sdk";import fe from"ora";import{randomBytes as pe}from"node:crypto";import{createMcpServer as me}from"@tangle-network/sandbox/agent";import{readFile as he}from"node:fs/promises";import ge from"ws";const g=f.join(oe.homedir(),`.tangle`),_=f.join(g,`credentials.json`),v=`tangle-sandbox-cli`,_e=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var ve=class extends Error{constructor(e,t){super(`Credentials file at ${e} is corrupted and cannot be parsed. Inspect or remove it manually before retrying — refusing to overwrite it automatically.`),this.filePath=e,this.name=`CredentialsFileCorruptedError`,t&&(this.cause=t)}},ye=class extends Error{constructor(){super(`Could not store credential in the OS keychain, and the plaintext fallback is not enabled. Install a keychain provider (macOS Keychain or libsecret/secret-tool on Linux), or set ${_e}=1 to opt into a plaintext credentials.json with mode 0600.`),this.name=`KeychainUnavailableError`}};function be(e){let t=we(e);if(t)return{value:t,source:`keychain`};let n=De(e);return n?{value:n,source:`file`}:{source:`none`}}function xe(e,t){if(Te(e,t))return ke(e),`keychain`;if(!Ce())throw new ye;return Oe(e,t),`file`}function Se(e){Ee(e),ke(e)}function Ce(){let e=process.env[_e];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function we(e){if(process.platform===`darwin`)try{return h(`security`,[`find-generic-password`,`-s`,v,`-a`,y(e),`-w`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}if(process.platform===`linux`)try{return h(`secret-tool`,[`lookup`,`service`,v,`account`,y(e)],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}}function Te(e,t){if(process.platform===`darwin`)try{return h(`security`,[`add-generic-password`,`-U`,`-s`,v,`-a`,y(e),`-w`,t],{stdio:[`ignore`,`ignore`,`ignore`]}),!0}catch{return!1}if(process.platform===`linux`)try{return h(`secret-tool`,[`store`,`--label=Tangle Sandbox CLI`,`service`,v,`account`,y(e)],{input:t,stdio:[`pipe`,`ignore`,`ignore`]}),!0}catch{return!1}return!1}function Ee(e){if(process.platform===`darwin`){try{h(`security`,[`delete-generic-password`,`-s`,v,`-a`,y(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}return}if(process.platform===`linux`)try{h(`secret-tool`,[`clear`,`service`,v,`account`,y(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}}function De(e){return Ae()[e]}function Oe(e,t){let n=Ae();n[e]=t,je(n)}function ke(e){let t;try{t=Ae()}catch(e){if(e instanceof ve)return;throw e}e in t&&(delete t[e],je(t))}function Ae(){let e;try{e=d.readFileSync(_,`utf8`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))throw new ve(_);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof ve?e:new ve(_,e instanceof Error?e:void 0)}}function je(e){if(Me(),Object.keys(e).length===0){d.existsSync(_)&&d.unlinkSync(_);return}let t=`${_}.${process.pid}.tmp`;d.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),d.renameSync(t,_)}function Me(){if(!d.existsSync(g)){d.mkdirSync(g,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(d.statSync(g).mode&511)!=448&&d.chmodSync(g,448)}catch{}}function y(e){return`profile:${e}`}const b=f.join(oe.homedir(),`.tangle`),x=f.join(b,`credentials`),S=f.join(b,`config.json`),C=`default`;function Ne(){d.existsSync(b)||d.mkdirSync(b,{mode:448,recursive:!0})}function Pe(e,t){Ne();let n=`${e}.${process.pid}.tmp`;d.writeFileSync(n,t,{mode:384}),d.renameSync(n,e)}function Fe(){try{if(d.existsSync(x)){let e=d.readFileSync(x,`utf-8`).trim();return Ie(e)?e:e.match(/api_key\s*=\s*(\S+)/)?.[1]}}catch{}}function Ie(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function Le(){try{d.existsSync(x)&&d.unlinkSync(x)}catch{}}function w(){return Ye(Je())}function T(e){let t=Xe(w(),e);Pe(S,`${JSON.stringify(t,null,2)}\n`)}function E(e){return A(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||w().activeProfile||C)}function Re(e){T({activeProfile:A(e)})}function ze(){let e=w(),t=E(),n=new Set([C,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(A(e.activeProfile)),[...n].map(e=>{let n=be(e),r=e===C?Fe():void 0,i=n.source===`none`?r?`legacy-file`:`none`:n.source;return{name:e,active:e===t,hasApiKey:n.source!==`none`||!!r,baseUrl:D(void 0,e),apiKeySource:i}}).sort((e,t)=>e.name.localeCompare(t.name))}function Be(e){let t=E(e);return{name:t,active:t===E(),apiKey:Ue(void 0,t),baseUrl:D(void 0,t),credentialSource:We(void 0,t)}}function Ve(e,t){let n=A(e),r=w(),i=k(n,r),a={},o=t.baseUrl??i.baseUrl;o&&(a.baseUrl=o);let s=t.activeTeamId??i.activeTeamId;s&&(a.activeTeamId=s);let c=t.activeTeamName??i.activeTeamName;c&&(a.activeTeamName=c);let l={...r.profiles??{}};a.baseUrl||a.activeTeamId||a.activeTeamName?l[n]=a:delete l[n];let u;return t.apiKey&&(u=xe(n,t.apiKey),n===C&&Le()),T({profiles:Object.keys(l).length>0?l:{}}),u}function He(e){let t=E(e),n={...w().profiles??{}},r=n[t];if(r){let e={...r,apiKey:void 0};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}T({profiles:n}),Se(t),t===C&&Le()}function Ue(e,t){if(e)return e;let n=process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY;if(n)return n;let r=E(t),i=be(r);if(i.value)return i.value;if(r===C)return Fe()}function We(e,t){if(e)return`flag`;if(process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY)return`env`;let n=E(t),r=be(n);return r.source===`none`?n===C&&Fe()?`legacy-file`:`none`:r.source}function D(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=E(t),i=w(),a=k(r,i);return a.baseUrl?a.baseUrl:r===C&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function O(e){let t=E(e.profile),n=Ue(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===C?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:D(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...Ge(t)}}function Ge(e){let t=w(),n=k(E(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function Ke(e,t){Ve(E(t),{activeTeamId:e.id,activeTeamName:e.name})}function qe(e){let t=E(e),n=w(),r={...n.profiles??{}},i={baseUrl:k(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],T({profiles:r})}function k(e,t=w()){let n=A(e);return{...n===C?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[C]?.activeTeamId,activeTeamName:t.profiles?.[C]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function Je(){try{if(d.existsSync(S)){let e=d.readFileSync(S,`utf-8`);return JSON.parse(e)}}catch{}return{}}function Ye(e){let t=!1,n={};e.apiKey&&(xe(C,e.apiKey),Le(),t=!0);for(let[r,i]of Object.entries(e.profiles??{})){i.apiKey&&(xe(r,i.apiKey),t=!0);let e={};i.baseUrl&&(e.baseUrl=i.baseUrl),i.activeTeamId&&(e.activeTeamId=i.activeTeamId),i.activeTeamName&&(e.activeTeamName=i.activeTeamName),Object.keys(e).length>0&&(n[r]=e)}let r={...e,apiKey:void 0,profiles:Object.keys(n).length>0?n:void 0};return t&&Pe(S,`${JSON.stringify(r,null,2)}\n`),r}function Xe(e,t){let n=t.profiles===void 0?{...e.profiles??{}}:Object.fromEntries(Object.entries(t.profiles).filter(([,e])=>!!(e.apiKey||e.baseUrl||e.activeTeamId||e.activeTeamName)));return{...e,...t,profiles:Object.keys(n).length>0?n:void 0}}function A(e){let t=e.trim().toLowerCase();if(!t)throw Error(`Profile name cannot be empty`);if(!/^[a-z0-9][a-z0-9._-]*$/.test(t))throw Error(`Profile names may only contain lowercase letters, numbers, dots, underscores, and hyphens`);return t}let j=null,M=null;function N(e){if(e)return j&&M&&M.apiKey===e.apiKey&&M.baseUrl===e.baseUrl?j:(j=new s({apiKey:e.apiKey,baseUrl:e.baseUrl,timeoutMs:e.timeout}),M=e,j);if(j)return j;let t=O({});return j=new s({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),M=t,j}function Ze(){j=null,M=null}function P(e){let t=Qe(e);console.error(n.red(`Error:`),t),process.exit(tt(e))}function Qe(e){if(e instanceof r)return`Authentication failed. Run 'tangle auth login' to authenticate.`;if(e instanceof a)return`Resource not found. Check the ID and try again.`;if(e instanceof o)return`Quota exceeded. Upgrade your plan or wait for quota reset.`;if(e instanceof ee)return`Invalid input: ${e.message}`;if(e instanceof l)return`Invalid state: ${e.message}`;if(e instanceof u)return`Request timed out. Try again or increase timeout with --timeout.`;if(e instanceof i)return`Network error. Check your connection and try again.`;if(e instanceof c)return`${e.status?`HTTP ${e.status}`:`server error`}: ${e.message}`;if(e instanceof de){let t=typeof e.status==`number`?` (HTTP ${e.status})`:``;return e.code===`HUB_CONNECTION_MISSING`?`${e.code}${t}: ${e.message}. Run: tangle hub connect github`:e.code===`HUB_APPROVAL_REQUIRED`?$e(e.code,t,e.message):`${e.code}${t}: ${e.message}`}return et(e)?e.code===`HUB_CONNECTION_MISSING`?`${e.code} (HTTP ${e.status}): ${e.message}. Run: tangle hub connect github`:e.code===`HUB_APPROVAL_REQUIRED`?$e(e.code,` (HTTP ${e.status})`,e.message):`${e.code} (HTTP ${e.status}): ${e.message}`:e instanceof Error?e.message:String(e)}function $e(e,t,n){return`${e}${t}: ${n}. Run the command again with --auto-approve, or run: tangle hub resume <approval-id> --accept. See: tangle hub resume --help`}function et(e){if(!(e instanceof Error))return!1;let t=e;return typeof t.code==`string`&&t.code.startsWith(`HUB_`)&&typeof t.status==`number`}function tt(e){return e instanceof ee?2:1}function nt(e){return e==null?n.dim(`-`):typeof e==`boolean`?e?n.green(`yes`):n.red(`no`):e instanceof Date?it(e):typeof e==`string`&&rt(e)?it(new Date(e)):String(e)}function rt(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function it(e){let t=Date.now()-e.getTime();if(t<6e4)return`just now`;if(t<36e5)return`${Math.floor(t/6e4)} min ago`;if(t<864e5){let e=Math.floor(t/36e5);return`${e} hour${e>1?`s`:``} ago`}let n=Math.floor(t/864e5);return`${n} day${n>1?`s`:``} ago`}function at(e){switch(e){case`running`:return n.green(e);case`pending`:case`provisioning`:return n.yellow(e);case`stopped`:return n.gray(e);case`failed`:case`deleted`:return n.red(e);default:return e}}function F(e,t){if(e.length===0){console.log(n.dim(`No items found.`));return}let r=t.map(t=>{let n=t.header.length,r=Math.max(...e.map(e=>nt(e[t.key]).length));return t.width??Math.max(n,r)+2}),i=t.map((e,t)=>n.bold(e.header.padEnd(r[t]))).join(``);console.log(i);for(let n of e){let e=t.map((e,t)=>{let i=nt(n[e.key]);return e.key===`status`&&(i=at(String(n[e.key]))),i.padEnd(r[t])}).join(``);console.log(e)}}function I(e){console.log(JSON.stringify(e,null,2))}function L(e){console.log(n.green(`✓`),e)}function R(e){console.error(n.red(`✗`),e)}function ot(e){console.log(n.yellow(`!`),e)}function z(e){console.log(n.blue(`→`),e)}function B(e){return fe({text:e,color:`cyan`})}function V(e,t=0){let r=` `.repeat(t);for(let[t,i]of Object.entries(e))i!=null&&console.log(`${r}${n.dim(`${t}:`)} ${nt(i)}`)}function st(e){if(console.log(),console.log(n.bold(`Sandbox Details`)),console.log(n.dim(`─`.repeat(40))),V({ID:e.id,Name:e.name,Status:at(e.status),Created:e.createdAt,Expires:e.expiresAt}),e.connection){if(console.log(),console.log(n.bold(`Connection`)),console.log(n.dim(`─`.repeat(40))),e.connection.ssh){let{ssh:t}=e.connection,n=process.platform===`win32`?`NUL`:`/dev/null`,r=`ssh -o ProxyCommand="${t.proxyCommand}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=${n} -o GlobalKnownHostsFile=${n} -o LogLevel=ERROR -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -o TCPKeepAlive=yes ${t.username}@localhost -p ${t.port}`;V({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&V({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&V({"API URL":e.connection.runtimeUrl})}console.log()}function H(e,t){t?I({error:e.message}):R(e.message),process.exit(1)}function U(e){I(e)}function W(e,t){if(t.length===0){console.log(n.dim(`No items found.`));return}let r=e.map((e,n)=>{let r=Math.max(...t.map(e=>String(e[n]??``).length));return Math.max(e.length,r)+2});console.log(e.map((e,t)=>n.bold(e.padEnd(r[t]))).join(``));for(let e of t)console.log(e.map((e,t)=>String(e??``).padEnd(r[t])).join(``))}const G=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function ct(e,t,n){switch(e){case`anthropic`:return`// pnpm add @anthropic-ai/sdk @tangle-network/sandbox
2
2
  import Anthropic from "@anthropic-ai/sdk";
3
3
  import { Sandbox } from "@tangle-network/sandbox";
4
4
  import { anthropicTools } from "@tangle-network/sandbox/agent";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-cli",
3
- "version": "0.0.0-develop.20260601172150.3b0d399",
3
+ "version": "0.0.0-develop.20260601195011.b9ed062",
4
4
  "description": "CLI for Tangle Sandbox operations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,7 +20,7 @@
20
20
  "ora": "^9.4.0",
21
21
  "ws": "^8.20.0",
22
22
  "@tangle-network/hub-sdk": "0.2.0",
23
- "@tangle-network/sandbox": "0.0.0-develop.20260601172150.3b0d399"
23
+ "@tangle-network/sandbox": "0.0.0-develop.20260601195011.b9ed062"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/node": "25.6.0",