@tangle-network/sandbox-cli 0.6.10 → 0.6.14

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 +7 -7
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{createHash as n,randomBytes as r,randomUUID as i}from"node:crypto";import a from"chalk";import*as o from"node:fs";import{chmodSync as s,existsSync as c,mkdirSync as l,readFileSync as u,renameSync as d,writeFileSync as f}from"node:fs";import*as p from"node:path";import{basename as m,dirname as ee,extname as te,join as h,resolve as ne}from"node:path";import{AuthError as re,NetworkError as g,NotFoundError as ie,QuotaError as ae,Sandbox as _,ServerError as oe,StateError as se,TimeoutError as ce,ValidationError as le,createBatchResultAccumulator as ue,createConfidentialSandbox as de,generateAttestationNonce as fe,parseBackendType as pe,parseSSEStream as me,validateBatchRunRequest as he}from"@tangle-network/sandbox";import*as ge from"node:os";import{homedir as _e,tmpdir as ve}from"node:os";import{execFileSync as ye,spawn as be}from"node:child_process";import{HubClient as xe,HubSdkError as Se}from"@tangle-network/hub-sdk";import Ce from"ora";import{CONTENT_COMPLETION_KEY as we,CONTENT_PROMPT_KEY as Te,CONTENT_TOOL_ARGS_KEY as Ee,CONTENT_TOOL_NAME_KEY as De,CONTENT_TOOL_RESULT_KEY as Oe,TANGLE_SUBJECT_KEY as ke,asContentField as v,asContentString as Ae}from"@tangle-network/agent-core/telemetry";import{createMcpServer as je}from"@tangle-network/sandbox/agent";import{readFile as Me}from"node:fs/promises";import{fileURLToPath as Ne}from"node:url";import Pe from"ws";import{supervise as Fe,workerFromBackend as Ie}from"@tangle-network/agent-runtime/loops";import{createIntelligenceClient as Le}from"@tangle-network/sandbox/intelligence";function Re(e){if(e.startsWith(`github:`)){let[t,n]=e.slice(7).split(`@`,2),r=t.split(`/`).filter(Boolean);if(r.length<3)throw Error(`invalid github ref "${e}": expected github:<owner>/<repo>/<path>[@<ref>]`);let i=`${r[0]}/${r[1]}`,a=r.slice(2).join(`/`);return{kind:`github`,repository:i,path:a,...n?{ref:n}:{},name:m(a)}}let t;try{t=u(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:m(e),content:t}}function ze(e){let t=(e.skills??[]).map(Re),n=(e.tools??[]).map(Re),r=t.length>0||n.length>0;if(!(!e.model&&!e.systemPrompt&&!r))return{...e.model?{model:{default:e.model}}:{},...e.systemPrompt?{prompt:{systemPrompt:e.systemPrompt}}:{},...r?{resources:{...t.length>0?{skills:t}:{},...n.length>0?{tools:n}:{}}}:{}}}async function Be(e){let t;if(e.startsWith(`github:`)){let[n,r]=e.slice(7).split(`@`,2),i=n.split(`/`).filter(Boolean);if(i.length<3)throw Error(`invalid --profile github ref "${e}": expected github:<owner>/<repo>/<path>[@<ref>]`);let a=r??`main`;t=await Je(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await Je(e):u(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw Error(`profile at "${e}" is not valid JSON`)}return We(n,e),n}const Ve=[`prompt`,`model`,`permissions`,`tools`,`mcp`,`connections`,`subagents`,`resources`,`hooks`,`modes`,`confidential`,`extensions`],He=new Set([...Ve,`name`,`description`,`version`,`tags`,`metadata`]),Ue=[`files`,`tools`,`skills`,`agents`,`commands`];function We(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`profile at "${t}" is not an object`);let n=Object.keys(e),r=n.some(e=>Ve.includes(e)),i=n.includes(`name`)&&n.every(e=>He.has(e));if(!r&&!i)throw Error(`"${t}" does not look like an agent profile: no recognized profile keys (model, prompt, resources, tools, connections, …). Got: ${n.slice(0,6).join(`, `)||`(empty object)`}.`);Ge(e,t)}function Ge(e,t){let n=e.resources;if(!n||typeof n!=`object`)return;for(let e of Ue){let r=n[e];if(r!==void 0){if(!Array.isArray(r))throw Error(`profile at "${t}" is malformed: resources.${e} must be an array`);for(let n of r)qe(e===`files`?Ke(n):n,t)}}let r=n.instructions;r!==void 0&&typeof r!=`string`&&qe(r,t)}function Ke(e){return e&&typeof e==`object`?e.resource:e}function qe(e,t){let n=e&&typeof e==`object`?e.kind:void 0;if(n!==`inline`&&n!==`github`)throw Error(`profile at "${t}" has an invalid resource ref kind ${JSON.stringify(n)}: expected "inline" or "github"`)}async function Je(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function Ye(e){let t=e.profileSource?await Be(e.profileSource):void 0,n=ze(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const Xe=p.join(ge.homedir(),`.tangle`),Ze=p.join(Xe,`credentials.json`),Qe=`tangle-sandbox-cli`,$e=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var et=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)}},tt=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 nt(e){let t=ot(e);if(t)return{value:t,source:`keychain`};let n=lt(e);return n?{value:n,source:`file`}:{source:`none`}}function rt(e,t){if(st(e,t))return dt(e),`keychain`;if(!at())throw new tt;return ut(e,t),`file`}function it(e){ct(e),dt(e)}function at(){let e=process.env[$e];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function ot(e){if(process.platform===`darwin`)try{return ye(`security`,[`find-generic-password`,`-s`,Qe,`-a`,ht(e),`-w`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}if(process.platform===`linux`)try{return ye(`secret-tool`,[`lookup`,`service`,Qe,`account`,ht(e)],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}}function st(e,t){if(process.platform===`darwin`)try{return ye(`security`,[`add-generic-password`,`-U`,`-s`,Qe,`-a`,ht(e),`-w`,t],{stdio:[`ignore`,`ignore`,`ignore`]}),!0}catch{return!1}if(process.platform===`linux`)try{return ye(`secret-tool`,[`store`,`--label=Tangle Sandbox CLI`,`service`,Qe,`account`,ht(e)],{input:t,stdio:[`pipe`,`ignore`,`ignore`]}),!0}catch{return!1}return!1}function ct(e){if(process.platform===`darwin`){try{ye(`security`,[`delete-generic-password`,`-s`,Qe,`-a`,ht(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}return}if(process.platform===`linux`)try{ye(`secret-tool`,[`clear`,`service`,Qe,`account`,ht(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}}function lt(e){return ft()[e]}function ut(e,t){let n=ft();n[e]=t,pt(n)}function dt(e){let t;try{t=ft()}catch(e){if(e instanceof et)return;throw e}e in t&&(delete t[e],pt(t))}function ft(){let e;try{e=o.readFileSync(Ze,`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 et(Ze);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof et?e:new et(Ze,e instanceof Error?e:void 0)}}function pt(e){if(mt(),Object.keys(e).length===0){o.existsSync(Ze)&&o.unlinkSync(Ze);return}let t=`${Ze}.${process.pid}.tmp`;o.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),o.renameSync(t,Ze)}function mt(){if(!o.existsSync(Xe)){o.mkdirSync(Xe,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(o.statSync(Xe).mode&511)!=448&&o.chmodSync(Xe,448)}catch{}}function ht(e){return`profile:${e}`}const gt=p.join(ge.homedir(),`.tangle`),_t=p.join(gt,`credentials`),vt=p.join(gt,`config.json`),y=`default`;function yt(){o.existsSync(gt)||o.mkdirSync(gt,{mode:448,recursive:!0})}function bt(e,t){yt();let n=`${e}.${process.pid}.tmp`;o.writeFileSync(n,t,{mode:384}),o.renameSync(n,e)}function xt(){try{if(o.existsSync(_t)){let e=o.readFileSync(_t,`utf-8`).trim();return St(e)?e:e.match(/api_key\s*=\s*(\S+)/)?.[1]}}catch{}}function St(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function Ct(){try{o.existsSync(_t)&&o.unlinkSync(_t)}catch{}}function b(){return Ut(Ht())}function x(e){let t=Wt(b(),e);bt(vt,`${JSON.stringify(t,null,2)}\n`)}function S(e){return Gt(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||b().activeProfile||y)}function wt(e){x({activeProfile:Gt(e)})}function Tt(){return process.env.TANGLE_SANDBOX||b().currentSandbox||void 0}function Et(e){x({currentSandbox:e})}function Dt(){let e=b();delete e.currentSandbox,bt(vt,`${JSON.stringify(e,null,2)}\n`)}function Ot(){let e=b().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=ge.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=r(4).toString(`hex`),i=`${t?`${t}-`:`device-`}${n}`;return x({deviceId:i}),i}function kt(e){let t=e||Tt();if(!t)throw Error("No sandbox specified. Pass it positionally, set a default with `tangle use <id>`, pass `--box <id>`, or set TANGLE_SANDBOX.");return t}function At(){let e=b(),t=S(),n=new Set([y,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(Gt(e.activeProfile)),[...n].map(e=>{let n=nt(e),r=e===y?xt():void 0,i=n.source===`none`?r?`legacy-file`:`none`:n.source;return{name:e,active:e===t,hasApiKey:n.source!==`none`||!!r,baseUrl:It(void 0,e),apiKeySource:i}}).sort((e,t)=>e.name.localeCompare(t.name))}function jt(e){let t=S(e);return{name:t,active:t===S(),apiKey:Pt(void 0,t),baseUrl:It(void 0,t),credentialSource:Ft(void 0,t)}}function Mt(e,t){let n=Gt(e),r=b(),i=Vt(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=rt(n,t.apiKey),n===y&&Ct()),x({profiles:Object.keys(l).length>0?l:{}}),u}function Nt(e){let t=S(e),n={...b().profiles??{}},r=n[t];if(r){let e={...r,apiKey:void 0};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}x({profiles:n}),it(t),t===y&&Ct()}function Pt(e,t){if(e)return e;let n=process.env.TANGLE_API_KEY;if(n)return n;let r=S(t),i=nt(r);if(i.value)return i.value;if(r===y)return xt()}function Ft(e,t){if(e)return`flag`;if(process.env.TANGLE_API_KEY)return`env`;let n=S(t),r=nt(n);return r.source===`none`?n===y&&xt()?`legacy-file`:`none`:r.source}function It(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=S(t),i=b(),a=Vt(r,i);return a.baseUrl?a.baseUrl:r===y&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function Lt(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function C(e){let t=S(e.profile),n=Pt(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===y?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:It(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...Rt(t)}}function Rt(e){let t=b(),n=Vt(S(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function zt(e,t){Mt(S(t),{activeTeamId:e.id,activeTeamName:e.name})}function Bt(e){let t=S(e),n=b(),r={...n.profiles??{}},i={baseUrl:Vt(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],x({profiles:r})}function Vt(e,t=b()){let n=Gt(e);return{...n===y?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[y]?.activeTeamId,activeTeamName:t.profiles?.[y]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function Ht(){try{if(o.existsSync(vt)){let e=o.readFileSync(vt,`utf-8`);return JSON.parse(e)}}catch{}return{}}function Ut(e){let t=!1,n={};e.apiKey&&(rt(y,e.apiKey),Ct(),t=!0);for(let[r,i]of Object.entries(e.profiles??{})){i.apiKey&&(rt(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&&bt(vt,`${JSON.stringify(r,null,2)}\n`),r}function Wt(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 Gt(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 w=null,Kt=null;function T(e){if(e)return w&&Kt&&Kt.apiKey===e.apiKey&&Kt.baseUrl===e.baseUrl&&Kt.timeout===e.timeout?w:(w=new _({apiKey:e.apiKey,baseUrl:e.baseUrl,timeoutMs:e.timeout}),Kt=e,w);if(w)return w;let t=C({});return w=new _({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),Kt=t,w}function qt(){w=null,Kt=null}async function Jt(e,t){let n=t.trim();if(n.length===0)throw Error(`Connection reference is empty.`);if(n.startsWith(`hubconn_`))return n;let{connections:r}=await e.connections.list();return Yt(r,n)}function Yt(e,t){let n=t.trim();if(n.length===0)throw Error(`Connection reference is empty.`);let r=e.find(e=>e.id===n);if(r)return r.id;let i=n.indexOf(`:`),a=(i===-1?n:n.slice(0,i)).trim().toLowerCase(),o=i===-1?null:n.slice(i+1).trim(),s=e.filter(e=>e.status!==`revoked`&&e.providerId.toLowerCase()===a);if(o&&o.length>0){let e=o.toLowerCase();s=s.filter(t=>(t.accountDisplay??``).toLowerCase()===e||t.displayName.toLowerCase()===e)}if(s.length===1)return s[0].id;throw s.length===0?Error(`No hub connection matches "${t}". List your connections with \`tangle hub connections\`.`):Error(Xt(t,s))}function Xt(e,t){let n=t.map(e=>`- ${e.id} (provider: ${e.providerId}, account: ${e.accountDisplay??e.displayName})`).join(`
1
+ import{createRequire as e}from"node:module";import"dotenv/config";import{Command as t}from"commander";import{createHash as n,randomBytes as r,randomUUID as i}from"node:crypto";import a from"chalk";import*as o from"node:fs";import{chmodSync as s,existsSync as c,mkdirSync as l,readFileSync as u,renameSync as d,writeFileSync as f}from"node:fs";import*as p from"node:path";import{basename as m,dirname as ee,extname as te,join as h,resolve as ne}from"node:path";import{AuthError as re,NetworkError as g,NotFoundError as ie,QuotaError as ae,Sandbox as _,ServerError as oe,StateError as se,TimeoutError as ce,ValidationError as le,createBatchResultAccumulator as ue,createConfidentialSandbox as de,generateAttestationNonce as fe,parseBackendType as pe,parseSSEStream as me,validateBatchRunRequest as he}from"@tangle-network/sandbox";import*as ge from"node:os";import{homedir as _e,tmpdir as ve}from"node:os";import{execFileSync as ye,spawn as be}from"node:child_process";import{HubClient as xe,HubSdkError as Se}from"@tangle-network/hub-sdk";import Ce from"ora";import{CONTENT_COMPLETION_KEY as we,CONTENT_PROMPT_KEY as Te,CONTENT_TOOL_ARGS_KEY as Ee,CONTENT_TOOL_NAME_KEY as De,CONTENT_TOOL_RESULT_KEY as Oe,TANGLE_SUBJECT_KEY as ke,asContentField as v,asContentString as Ae}from"@tangle-network/agent-core/telemetry";import{createMcpServer as je}from"@tangle-network/sandbox/agent";import{readFile as Me}from"node:fs/promises";import{fileURLToPath as Ne}from"node:url";import Pe from"ws";import{supervise as Fe,workerFromBackend as Ie}from"@tangle-network/agent-runtime/kernel";import{createIntelligenceClient as Le}from"@tangle-network/sandbox/intelligence";function Re(e){if(e.startsWith(`github:`)){let[t,n]=e.slice(7).split(`@`,2),r=t.split(`/`).filter(Boolean);if(r.length<3)throw Error(`invalid github ref "${e}": expected github:<owner>/<repo>/<path>[@<ref>]`);let i=`${r[0]}/${r[1]}`,a=r.slice(2).join(`/`);return{kind:`github`,repository:i,path:a,...n?{ref:n}:{},name:m(a)}}let t;try{t=u(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:m(e),content:t}}function ze(e){let t=(e.skills??[]).map(Re),n=(e.tools??[]).map(Re),r=t.length>0||n.length>0;if(!(!e.model&&!e.systemPrompt&&!r))return{...e.model?{model:{default:e.model}}:{},...e.systemPrompt?{prompt:{systemPrompt:e.systemPrompt}}:{},...r?{resources:{...t.length>0?{skills:t}:{},...n.length>0?{tools:n}:{}}}:{}}}async function Be(e){let t;if(e.startsWith(`github:`)){let[n,r]=e.slice(7).split(`@`,2),i=n.split(`/`).filter(Boolean);if(i.length<3)throw Error(`invalid --profile github ref "${e}": expected github:<owner>/<repo>/<path>[@<ref>]`);let a=r??`main`;t=await Je(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await Je(e):u(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw Error(`profile at "${e}" is not valid JSON`)}return We(n,e),n}const Ve=[`prompt`,`model`,`permissions`,`tools`,`mcp`,`connections`,`subagents`,`resources`,`hooks`,`modes`,`confidential`,`extensions`],He=new Set([...Ve,`name`,`description`,`version`,`tags`,`metadata`]),Ue=[`files`,`tools`,`skills`,`agents`,`commands`];function We(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`profile at "${t}" is not an object`);let n=Object.keys(e),r=n.some(e=>Ve.includes(e)),i=n.includes(`name`)&&n.every(e=>He.has(e));if(!r&&!i)throw Error(`"${t}" does not look like an agent profile: no recognized profile keys (model, prompt, resources, tools, connections, …). Got: ${n.slice(0,6).join(`, `)||`(empty object)`}.`);Ge(e,t)}function Ge(e,t){let n=e.resources;if(!n||typeof n!=`object`)return;for(let e of Ue){let r=n[e];if(r!==void 0){if(!Array.isArray(r))throw Error(`profile at "${t}" is malformed: resources.${e} must be an array`);for(let n of r)qe(e===`files`?Ke(n):n,t)}}let r=n.instructions;r!==void 0&&typeof r!=`string`&&qe(r,t)}function Ke(e){return e&&typeof e==`object`?e.resource:e}function qe(e,t){let n=e&&typeof e==`object`?e.kind:void 0;if(n!==`inline`&&n!==`github`)throw Error(`profile at "${t}" has an invalid resource ref kind ${JSON.stringify(n)}: expected "inline" or "github"`)}async function Je(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function Ye(e){let t=e.profileSource?await Be(e.profileSource):void 0,n=ze(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const Xe=p.join(ge.homedir(),`.tangle`),Ze=p.join(Xe,`credentials.json`),Qe=`tangle-sandbox-cli`,$e=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var et=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)}},tt=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 nt(e){let t=ot(e);if(t)return{value:t,source:`keychain`};let n=lt(e);return n?{value:n,source:`file`}:{source:`none`}}function rt(e,t){if(st(e,t))return dt(e),`keychain`;if(!at())throw new tt;return ut(e,t),`file`}function it(e){ct(e),dt(e)}function at(){let e=process.env[$e];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function ot(e){if(process.platform===`darwin`)try{return ye(`security`,[`find-generic-password`,`-s`,Qe,`-a`,ht(e),`-w`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}if(process.platform===`linux`)try{return ye(`secret-tool`,[`lookup`,`service`,Qe,`account`,ht(e)],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}}function st(e,t){if(process.platform===`darwin`)try{return ye(`security`,[`add-generic-password`,`-U`,`-s`,Qe,`-a`,ht(e),`-w`,t],{stdio:[`ignore`,`ignore`,`ignore`]}),!0}catch{return!1}if(process.platform===`linux`)try{return ye(`secret-tool`,[`store`,`--label=Tangle Sandbox CLI`,`service`,Qe,`account`,ht(e)],{input:t,stdio:[`pipe`,`ignore`,`ignore`]}),!0}catch{return!1}return!1}function ct(e){if(process.platform===`darwin`){try{ye(`security`,[`delete-generic-password`,`-s`,Qe,`-a`,ht(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}return}if(process.platform===`linux`)try{ye(`secret-tool`,[`clear`,`service`,Qe,`account`,ht(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}}function lt(e){return ft()[e]}function ut(e,t){let n=ft();n[e]=t,pt(n)}function dt(e){let t;try{t=ft()}catch(e){if(e instanceof et)return;throw e}e in t&&(delete t[e],pt(t))}function ft(){let e;try{e=o.readFileSync(Ze,`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 et(Ze);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof et?e:new et(Ze,e instanceof Error?e:void 0)}}function pt(e){if(mt(),Object.keys(e).length===0){o.existsSync(Ze)&&o.unlinkSync(Ze);return}let t=`${Ze}.${process.pid}.tmp`;o.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),o.renameSync(t,Ze)}function mt(){if(!o.existsSync(Xe)){o.mkdirSync(Xe,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(o.statSync(Xe).mode&511)!=448&&o.chmodSync(Xe,448)}catch{}}function ht(e){return`profile:${e}`}const gt=p.join(ge.homedir(),`.tangle`),_t=p.join(gt,`credentials`),vt=p.join(gt,`config.json`),y=`default`;function yt(){o.existsSync(gt)||o.mkdirSync(gt,{mode:448,recursive:!0})}function bt(e,t){yt();let n=`${e}.${process.pid}.tmp`;o.writeFileSync(n,t,{mode:384}),o.renameSync(n,e)}function xt(){try{if(o.existsSync(_t)){let e=o.readFileSync(_t,`utf-8`).trim();return St(e)?e:e.match(/api_key\s*=\s*(\S+)/)?.[1]}}catch{}}function St(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function Ct(){try{o.existsSync(_t)&&o.unlinkSync(_t)}catch{}}function b(){return Ut(Ht())}function x(e){let t=Wt(b(),e);bt(vt,`${JSON.stringify(t,null,2)}\n`)}function S(e){return Gt(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||b().activeProfile||y)}function wt(e){x({activeProfile:Gt(e)})}function Tt(){return process.env.TANGLE_SANDBOX||b().currentSandbox||void 0}function Et(e){x({currentSandbox:e})}function Dt(){let e=b();delete e.currentSandbox,bt(vt,`${JSON.stringify(e,null,2)}\n`)}function Ot(){let e=b().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=ge.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=r(4).toString(`hex`),i=`${t?`${t}-`:`device-`}${n}`;return x({deviceId:i}),i}function kt(e){let t=e||Tt();if(!t)throw Error("No sandbox specified. Pass it positionally, set a default with `tangle use <id>`, pass `--box <id>`, or set TANGLE_SANDBOX.");return t}function At(){let e=b(),t=S(),n=new Set([y,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(Gt(e.activeProfile)),[...n].map(e=>{let n=nt(e),r=e===y?xt():void 0,i=n.source===`none`?r?`legacy-file`:`none`:n.source;return{name:e,active:e===t,hasApiKey:n.source!==`none`||!!r,baseUrl:It(void 0,e),apiKeySource:i}}).sort((e,t)=>e.name.localeCompare(t.name))}function jt(e){let t=S(e);return{name:t,active:t===S(),apiKey:Pt(void 0,t),baseUrl:It(void 0,t),credentialSource:Ft(void 0,t)}}function Mt(e,t){let n=Gt(e),r=b(),i=Vt(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=rt(n,t.apiKey),n===y&&Ct()),x({profiles:Object.keys(l).length>0?l:{}}),u}function Nt(e){let t=S(e),n={...b().profiles??{}},r=n[t];if(r){let e={...r,apiKey:void 0};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}x({profiles:n}),it(t),t===y&&Ct()}function Pt(e,t){if(e)return e;let n=process.env.TANGLE_API_KEY;if(n)return n;let r=S(t),i=nt(r);if(i.value)return i.value;if(r===y)return xt()}function Ft(e,t){if(e)return`flag`;if(process.env.TANGLE_API_KEY)return`env`;let n=S(t),r=nt(n);return r.source===`none`?n===y&&xt()?`legacy-file`:`none`:r.source}function It(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=S(t),i=b(),a=Vt(r,i);return a.baseUrl?a.baseUrl:r===y&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function Lt(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function C(e){let t=S(e.profile),n=Pt(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===y?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:It(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...Rt(t)}}function Rt(e){let t=b(),n=Vt(S(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function zt(e,t){Mt(S(t),{activeTeamId:e.id,activeTeamName:e.name})}function Bt(e){let t=S(e),n=b(),r={...n.profiles??{}},i={baseUrl:Vt(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],x({profiles:r})}function Vt(e,t=b()){let n=Gt(e);return{...n===y?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[y]?.activeTeamId,activeTeamName:t.profiles?.[y]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function Ht(){try{if(o.existsSync(vt)){let e=o.readFileSync(vt,`utf-8`);return JSON.parse(e)}}catch{}return{}}function Ut(e){let t=!1,n={};e.apiKey&&(rt(y,e.apiKey),Ct(),t=!0);for(let[r,i]of Object.entries(e.profiles??{})){i.apiKey&&(rt(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&&bt(vt,`${JSON.stringify(r,null,2)}\n`),r}function Wt(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 Gt(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 w=null,Kt=null;function T(e){if(e)return w&&Kt&&Kt.apiKey===e.apiKey&&Kt.baseUrl===e.baseUrl&&Kt.timeout===e.timeout?w:(w=new _({apiKey:e.apiKey,baseUrl:e.baseUrl,timeoutMs:e.timeout}),Kt=e,w);if(w)return w;let t=C({});return w=new _({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),Kt=t,w}function qt(){w=null,Kt=null}async function Jt(e,t){let n=t.trim();if(n.length===0)throw Error(`Connection reference is empty.`);if(n.startsWith(`hubconn_`))return n;let{connections:r}=await e.connections.list();return Yt(r,n)}function Yt(e,t){let n=t.trim();if(n.length===0)throw Error(`Connection reference is empty.`);let r=e.find(e=>e.id===n);if(r)return r.id;let i=n.indexOf(`:`),a=(i===-1?n:n.slice(0,i)).trim().toLowerCase(),o=i===-1?null:n.slice(i+1).trim(),s=e.filter(e=>e.status!==`revoked`&&e.providerId.toLowerCase()===a);if(o&&o.length>0){let e=o.toLowerCase();s=s.filter(t=>(t.accountDisplay??``).toLowerCase()===e||t.displayName.toLowerCase()===e)}if(s.length===1)return s[0].id;throw s.length===0?Error(`No hub connection matches "${t}". List your connections with \`tangle hub connections\`.`):Error(Xt(t,s))}function Xt(e,t){let n=t.map(e=>`- ${e.id} (provider: ${e.providerId}, account: ${e.accountDisplay??e.displayName})`).join(`
2
2
  `);return`Hub connection reference is ambiguous: "${e}" matches ${t.length} connections. Use a connection id or provider:account instead.
3
3
  `+n}function Zt(e,t){return[...t,e]}async function Qt(e,t){let n=e.map(e=>{let t=e.trim(),n=t.indexOf(`:`);return n===-1?{raw:e,ref:null,tail:null}:{raw:e,ref:t.slice(0,n).trim(),tail:t.slice(n+1)}});if(!n.some(e=>e.ref!==null&&e.ref!==`*`&&!e.ref.startsWith(`hubconn_`)))return[...e];let{connections:r}=await(await t()).connections.list();return n.map(e=>e.ref===null||e.ref===`*`||e.ref.startsWith(`hubconn_`)?e.raw:`${Yt(r,e.ref)}:${e.tail}`)}function $t(e){let t=new Map,n=[];for(let r of e){let e=r.trim(),i=e.indexOf(`:`);if(i===-1)throw Error(`Invalid --connection "${r}": expected <connectionId>:<capability>[,<capability>]. List connection ids with \`tangle hub connections\` and capability paths with \`tangle hub tools search <keyword>\`.`);let a=e.slice(0,i).trim();if(a.length===0)throw Error(`Invalid --connection "${r}": connection id is empty. Use <connectionId>:<capability> — list ids with \`tangle hub connections\`.`);let o=e.slice(i+1).split(`,`).map(e=>e.trim()).filter(e=>e.length>0);if(o.length===0)throw Error(`Invalid --connection "${r}": grant at least one capability, e.g. ${a}:gmail.messages.list. Discover paths with \`tangle hub tools search <keyword>\`.`);if(o.includes(`*`)&&o.length>1)throw Error(`Invalid --connection "${r}": "*" grants all capabilities and can't be combined with specific paths. Use <connectionId>:* alone, or list explicit paths.`);if(a===`*`&&!(o.length===1&&o[0]===`*`))throw Error(`Invalid --connection "${r}": a "*" connection is only valid as "*:*" (all connections, all capabilities). Name a connection id for specific paths.`);let s=t.get(a);s===void 0&&(s=new Set,t.set(a,s),n.push(a));for(let e of o)s.add(e)}return n.map(e=>{let n=t.get(e),r=n?[...n]:[];if(r.includes(`*`)&&r.length>1)throw Error(`Invalid --connection for "${e}": "*" can't be combined with specific capability paths across repeated --connection flags.`);return{connectionId:e,capabilities:r}})}function en(e){return e==null?a.dim(`-`):typeof e==`boolean`?e?a.green(`yes`):a.red(`no`):e instanceof Date?nn(e):typeof e==`string`&&tn(e)?nn(new Date(e)):String(e)}function tn(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function nn(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 rn(e){switch(e){case`running`:return a.green(e);case`pending`:case`provisioning`:return a.yellow(e);case`stopped`:return a.gray(e);case`failed`:case`deleted`:return a.red(e);default:return e}}function E(e,t){if(e.length===0){console.log(a.dim(`No items found.`));return}let n=t.map(t=>{let n=t.header.length,r=Math.max(...e.map(e=>en(e[t.key]).length));return t.width??Math.max(n,r)+2}),r=t.map((e,t)=>a.bold(e.header.padEnd(n[t]))).join(``);console.log(r);for(let r of e){let e=t.map((e,t)=>{let i=en(r[e.key]);return e.key===`status`&&(i=rn(String(r[e.key]))),i.padEnd(n[t])}).join(``);console.log(e)}}function D(e){console.log(JSON.stringify(e,null,2))}function O(e){console.log(a.green(`✓`),e)}function k(e){console.error(a.red(`✗`),e)}function A(e){console.log(a.yellow(`!`),e)}function j(e){console.log(a.blue(`→`),e)}const an=new Set;function M(e){let t=Ce({text:e,color:`cyan`});return an.add(t),t}function on(){for(let e of an)e.isSpinning&&e.stop();an.clear()}function N(e,t=0){let n=` `.repeat(t);for(let[t,r]of Object.entries(e))r!=null&&console.log(`${n}${a.dim(`${t}:`)} ${en(r)}`)}function sn(e){if(console.log(),console.log(a.bold(`Sandbox Details`)),console.log(a.dim(`─`.repeat(40))),N({ID:e.id,Name:e.name,Status:rn(e.status),Created:e.createdAt,Expires:e.expiresAt}),e.connection){if(console.log(),console.log(a.bold(`Connection`)),console.log(a.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}`;N({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&N({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&N({"API URL":e.connection.runtimeUrl})}console.log()}function P(e,t){on(),t?D({error:e.message}):k(e.message),process.exit(1)}function F(e){D(e)}function I(e,t){if(t.length===0){console.log(a.dim(`No items found.`));return}let n=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)=>a.bold(e.padEnd(n[t]))).join(``));for(let e of t)console.log(e.map((e,t)=>String(e??``).padEnd(n[t])).join(``))}function L(e,t=!1){on(),t&&(D(cn(e)),process.exit(hn(e)));let n=ln(e);console.error(a.red(`Error:`),n),process.exit(hn(e))}function cn(e){return e instanceof Se?{error:{code:e.code,message:e.message,...typeof e.status==`number`?{status:e.status}:{},...e.details===void 0?{}:{details:e.details}}}:mn(e)?{error:{code:e.code,message:e.message,status:e.status,...e.details===void 0?{}:{details:e.details}}}:{error:{message:ln(e)}}}function ln(e){if(e instanceof re)return`Authentication failed. Run 'tangle auth login' to authenticate.`;if(e instanceof ie)return`Resource not found. Check the ID and try again.`;if(e instanceof ae)return`Quota exceeded. Upgrade your plan or wait for quota reset.`;if(e instanceof le)return`Invalid input: ${e.message}`;if(e instanceof se)return`Invalid state: ${e.message}`;if(e instanceof ce)return`Request timed out after ${e.timeoutMs} ms. Retry, or re-run with a longer --timeout <ms> on commands that accept it (e.g. create, resume).`;if(e instanceof g)return`Network error. Check your connection and try again.`;if(e instanceof oe)return`${e.status?`HTTP ${e.status}`:`server error`}: ${e.message}`;if(e instanceof Se){let t=typeof e.status==`number`?` (HTTP ${e.status})`:``;return e.code===`HUB_CONNECTION_MISSING`?un(e.code,t,e.message,e.details):e.code===`HUB_APPROVAL_REQUIRED`?fn(e.code,t,e.message):e.code===`HUB_UNAUTHENTICATED`?pn(e.code,t,e.message):`${e.code}${t}: ${e.message}`}return mn(e)?e.code===`HUB_CONNECTION_MISSING`?un(e.code,` (HTTP ${e.status})`,e.message,e.details):e.code===`HUB_APPROVAL_REQUIRED`?fn(e.code,` (HTTP ${e.status})`,e.message):e.code===`HUB_UNAUTHENTICATED`?pn(e.code,` (HTTP ${e.status})`,e.message):`${e.code} (HTTP ${e.status}): ${e.message}`:e instanceof Error?e.message:String(e)}function un(e,t,n,r){let i=dn(r);return`${e}${t}: ${n}${i?`. Run: tangle hub connect ${i}`:``}`}function dn(e){if(!e||typeof e!=`object`)return;let t=e.provider;return typeof t==`string`&&t.length>0?t:void 0}function fn(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 pn(e,t,n){return`${e}${t}: ${n}. The CLI auto-mints a short-lived Hub key from your login session, so this usually means that session has expired — run 'tangle auth login' to re-authenticate. To use a credential directly instead, set TANGLE_API_KEY or TANGLE_HUB_CAPABILITY_TOKEN (and pass --no-hub-key to skip auto-minting).`}function mn(e){if(!(e instanceof Error))return!1;let t=e;return typeof t.code==`string`&&t.code.startsWith(`HUB_`)&&typeof t.status==`number`}function hn(e){return e instanceof le?2:1}function gn(e,t){return n(`sha256`).update(`${e}\0${t}`).digest(`hex`).slice(0,32)}function _n(e){return`${e}:hub`}function vn(e){let{value:t}=nt(_n(e));if(!t)return null;try{let e=JSON.parse(t);if(typeof e.key==`string`&&typeof e.expiresAt==`string`&&typeof e.platformUrl==`string`&&typeof e.sessionFingerprint==`string`)return{key:e.key,expiresAt:e.expiresAt,platformUrl:e.platformUrl,sessionFingerprint:e.sessionFingerprint}}catch{}return null}function yn(e,t){try{rt(_n(e),JSON.stringify(t))}catch{}}async function bn(e,t,n){let r=`${e.replace(/\/+$/,``)}/auth/cli/hub-key`,i;try{i=await fetch(r,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`},body:JSON.stringify({device_id:n})})}catch(e){throw Error(`Could not reach ${r} to mint a Hub key: ${e instanceof Error?e.message:String(e)}`)}let a=await i.text(),o;try{o=JSON.parse(a)}catch{o=null}if(!i.ok||!o?.success){let e=typeof o?.error?.message==`string`?o.error.message:`HTTP ${i.status}`;throw Error(`Hub key minting failed: ${e}. Your sandbox session may have expired — run \`tangle auth login\`.`)}let s=o.data;if(typeof s?.api_key!=`string`||typeof s?.expires_at!=`string`||typeof s?.platform_url!=`string`)throw Error(`Hub key minting returned an unexpected response shape.`);return{key:s.api_key,expiresAt:s.expires_at,platformUrl:s.platform_url}}var xn=class{cache;fingerprint;constructor(e,t,n,r){this.profile=e,this.sandboxBaseUrl=t,this.sessionToken=n,this.deviceId=r,this.fingerprint=gn(t,n);let i=vn(e);this.cache=i&&i.sessionFingerprint===this.fingerprint?i:null}isFresh(e){return e!==null&&Date.parse(e.expiresAt)-Date.now()>6e4}async ensure(e=!1){if(!e&&this.isFresh(this.cache))return this.cache;let t={...await bn(this.sandboxBaseUrl,this.sessionToken,this.deviceId),sessionFingerprint:this.fingerprint};return this.cache=t,yn(this.profile,t),t}};function Sn(e){if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function Cn(e,t){if(e.baseUrl)return e.baseUrl;let n=Lt(process.env.TANGLE_HUB_URL);if(n)return n;let r=vn(t);return r?r.platformUrl:`https://id.tangle.tools`}function wn(e,t){let n=S(),r=Pt(e.apiKey,n),i=Ft(e.apiKey,n),a=process.env.TANGLE_HUB_CAPABILITY_TOKEN?.trim()||void 0;if(a&&i===`env`)throw Error(`Set exactly one of TANGLE_API_KEY or TANGLE_HUB_CAPABILITY_TOKEN, not both`);if(i===`flag`&&r)return{kind:`static`,apiKey:r,baseUrl:Cn(e,n)};if(i===`env`&&r)return{kind:`static`,apiKey:a??r,baseUrl:Cn(e,n)};if(a)return{kind:`static`,apiKey:a,baseUrl:Cn(e,n)};if(!r)throw Error(`No API key found for profile '${n}'. Set TANGLE_API_KEY or run: tangle auth login${n===`default`?``:` --profile ${n}`}`);return t?{kind:`static`,apiKey:r,baseUrl:Cn(e,n)}:{kind:`managed`,profile:n,sandboxBaseUrl:It(void 0,n),sessionToken:r,deviceId:Ot(),baseUrlOverride:e.baseUrl}}async function R(e={}){let t=wn(e,e.hubKey===!1||Sn(process.env.TANGLE_SKIP_HUB_KEY));if(t.kind===`static`)return new xe({baseUrl:t.baseUrl,apiKey:t.apiKey});let n=new xn(t.profile,t.sandboxBaseUrl,t.sessionToken,t.deviceId),r=await n.ensure();return new xe({baseUrl:t.baseUrlOverride??r.platformUrl,authHeaders:async()=>({Authorization:`Bearer ${(await n.ensure()).key}`}),fetch:async(e,t)=>{let r=await fetch(e,t);if(r.status!==401)return r;let i=await n.ensure(!0),a=new Headers(t?.headers);return a.set(`Authorization`,`Bearer ${i.key}`),fetch(e,{...t,headers:a})}})}function Tn(e){return e instanceof Date?e.toISOString():String(e)}function En(e,t){return`Sandbox name is ambiguous: ${e}. Use a sandbox id instead.\n${t.map(e=>`- ${e.id} (status: ${e.status}, created: ${Tn(e.createdAt)})`).join(`
4
4
  `)}`}function Dn(e){return e.activeTeamId?`team:${e.activeTeamId}`:void 0}async function z(e,t,n,r={}){if(!r.nameOnly){let t=await e.get(n);if(t)return t;if(kn(n))throw Error(`Sandbox not found: ${n}`)}let i=(await e.list({scope:Dn(t)})).filter(e=>e.name?.toLowerCase()===n.toLowerCase());if(i.length===0)throw Error(`Sandbox not found: ${n}`);if(i.length>1)throw Error(En(n,i));return i[0]}const On=/^sandbox-(?:(?:[a-z][a-z0-9-]*)-)?(?:[a-f0-9]{12}|[a-f0-9]{8}-[a-f0-9]{3})(?:-branch-[a-z0-9]+-[0-9]+)*$/;function kn(e){return On.test(e)}async function An(e,t,n,r={}){try{await(await z(e,t,n,{nameOnly:r.name})).delete();return}catch(e){if(!(e instanceof Error&&e.message===`Sandbox not found: ${n}`)||r.name||!r.retryCleanup&&!kn(n))throw e}let i=await e.fetch(`/v1/sandboxes/${encodeURIComponent(n)}`,{method:`DELETE`});if(i.ok)return;let a=(await i.text()).trim();throw Error(`Sandbox cleanup failed for ${n} (HTTP ${i.status})${a?`: ${a}`:``}`)}async function B(e,t){if(e.status!==`stopped`)return e;let n=t?.resumeTimeoutMs??12e4;j(`Sandbox ${e.id} is stopped. Resuming...`);try{await e.resume({timeoutMs:n}),await e.waitFor(`running`,{timeoutMs:n})}catch(t){let r=t instanceof Error?t.message:String(t);throw Error(`Failed to resume sandbox ${e.id}: ${r}. Run \`tangle sandbox resume ${e.id} --timeout ${n}\` and retry.`)}return e}const jn=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function Mn(e,t,n){switch(e){case`anthropic`:return`// pnpm add @anthropic-ai/sdk @tangle-network/sandbox
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-cli",
3
- "version": "0.6.10",
3
+ "version": "0.6.14",
4
4
  "description": "CLI for Tangle Sandbox operations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -15,17 +15,17 @@
15
15
  "hub-reference.md"
16
16
  ],
17
17
  "dependencies": {
18
- "@tangle-network/agent-core": "0.5.0",
19
- "@tangle-network/agent-eval": "0.133.3",
20
- "@tangle-network/agent-interface": "0.43.1",
21
- "@tangle-network/agent-runtime": "0.107.5",
18
+ "@tangle-network/agent-core": "0.5.2",
19
+ "@tangle-network/agent-eval": "0.143.0",
20
+ "@tangle-network/agent-interface": "0.45.0",
21
+ "@tangle-network/agent-runtime": "0.128.0",
22
22
  "chalk": "^5.4.1",
23
23
  "commander": "12.1.0",
24
24
  "dotenv": "17.2.3",
25
25
  "ora": "^9.4.0",
26
26
  "ws": "^8.20.0",
27
- "@tangle-network/hub-sdk": "0.6.1",
28
- "@tangle-network/sandbox": "0.19.1"
27
+ "@tangle-network/sandbox": "0.19.3",
28
+ "@tangle-network/hub-sdk": "0.7.2"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "25.6.0",