@tangle-network/sandbox-cli 0.9.1-develop.20260624145525.01545e5 → 0.9.2-develop.20260625093856.35d47c0
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/index.mjs +1 -1
- package/package.json +5 -5
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 ee,dirname as te,extname as ne,join as m,resolve as re}from"node:path";import{AuthError as h,NetworkError as g,NotFoundError as ie,QuotaError as _,Sandbox as v,ServerError as ae,StateError as oe,TimeoutError as se,ValidationError as ce,createConfidentialSandbox as le,generateAttestationNonce as ue,parseSSEStream as de}from"@tangle-network/sandbox";import*as fe from"node:os";import{homedir as pe,tmpdir as me}from"node:os";import{execFileSync as he,spawn as ge}from"node:child_process";import{HubClient as _e,HubSdkError as ve}from"@tangle-network/hub-sdk";import ye from"ora";import{CONTENT_COMPLETION_KEY as be,CONTENT_PROMPT_KEY as xe,CONTENT_TOOL_ARGS_KEY as Se,CONTENT_TOOL_NAME_KEY as Ce,CONTENT_TOOL_RESULT_KEY as we,TANGLE_SUBJECT_KEY as Te,asContentField as y,asContentString as Ee}from"@tangle-network/sdk-core/telemetry";import{createMcpServer as De}from"@tangle-network/sandbox/agent";import{readFile as Oe}from"node:fs/promises";import{fileURLToPath as ke}from"node:url";import Ae from"ws";import{supervise as je,workerFromBackend as Me}from"@tangle-network/agent-runtime/loops";import{createIntelligenceClient as Ne}from"@tangle-network/sandbox/intelligence";function Pe(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:ee(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:ee(e),content:t}}function Fe(e){let t=(e.skills??[]).map(Pe),n=(e.tools??[]).map(Pe),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 Ie(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 We(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await We(e):u(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw Error(`profile at "${e}" is not valid JSON`)}return Be(n,e),n}const Le=[`prompt`,`model`,`permissions`,`tools`,`mcp`,`connections`,`subagents`,`resources`,`hooks`,`modes`,`confidential`,`extensions`],Re=new Set([...Le,`name`,`description`,`version`,`tags`,`metadata`]),ze=[`files`,`tools`,`skills`,`agents`,`commands`];function Be(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=>Le.includes(e)),i=n.includes(`name`)&&n.every(e=>Re.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)`}.`);Ve(e,t)}function Ve(e,t){let n=e.resources;if(!n||typeof n!=`object`)return;for(let e of ze){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)Ue(e===`files`?He(n):n,t)}}let r=n.instructions;r!==void 0&&typeof r!=`string`&&Ue(r,t)}function He(e){return e&&typeof e==`object`?e.resource:e}function Ue(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 We(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function Ge(e){let t=e.profileSource?await Ie(e.profileSource):void 0,n=Fe(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const Ke=p.join(fe.homedir(),`.tangle`),b=p.join(Ke,`credentials.json`),qe=`tangle-sandbox-cli`,Je=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var Ye=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)}},Xe=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 ${Je}=1 to opt into a plaintext credentials.json with mode 0600.`),this.name=`KeychainUnavailableError`}};function Ze(e){let t=tt(e);if(t)return{value:t,source:`keychain`};let n=it(e);return n?{value:n,source:`file`}:{source:`none`}}function Qe(e,t){if(nt(e,t))return ot(e),`keychain`;if(!et())throw new Xe;return at(e,t),`file`}function $e(e){rt(e),ot(e)}function et(){let e=process.env[Je];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function tt(e){if(process.platform===`darwin`)try{return he(`security`,[`find-generic-password`,`-s`,qe,`-a`,ut(e),`-w`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}if(process.platform===`linux`)try{return he(`secret-tool`,[`lookup`,`service`,qe,`account`,ut(e)],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}}function nt(e,t){if(process.platform===`darwin`)try{return he(`security`,[`add-generic-password`,`-U`,`-s`,qe,`-a`,ut(e),`-w`,t],{stdio:[`ignore`,`ignore`,`ignore`]}),!0}catch{return!1}if(process.platform===`linux`)try{return he(`secret-tool`,[`store`,`--label=Tangle Sandbox CLI`,`service`,qe,`account`,ut(e)],{input:t,stdio:[`pipe`,`ignore`,`ignore`]}),!0}catch{return!1}return!1}function rt(e){if(process.platform===`darwin`){try{he(`security`,[`delete-generic-password`,`-s`,qe,`-a`,ut(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}return}if(process.platform===`linux`)try{he(`secret-tool`,[`clear`,`service`,qe,`account`,ut(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}}function it(e){return st()[e]}function at(e,t){let n=st();n[e]=t,ct(n)}function ot(e){let t;try{t=st()}catch(e){if(e instanceof Ye)return;throw e}e in t&&(delete t[e],ct(t))}function st(){let e;try{e=o.readFileSync(b,`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 Ye(b);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof Ye?e:new Ye(b,e instanceof Error?e:void 0)}}function ct(e){if(lt(),Object.keys(e).length===0){o.existsSync(b)&&o.unlinkSync(b);return}let t=`${b}.${process.pid}.tmp`;o.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),o.renameSync(t,b)}function lt(){if(!o.existsSync(Ke)){o.mkdirSync(Ke,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(o.statSync(Ke).mode&511)!=448&&o.chmodSync(Ke,448)}catch{}}function ut(e){return`profile:${e}`}const dt=p.join(fe.homedir(),`.tangle`),ft=p.join(dt,`credentials`),pt=p.join(dt,`config.json`),x=`default`;function mt(){o.existsSync(dt)||o.mkdirSync(dt,{mode:448,recursive:!0})}function ht(e,t){mt();let n=`${e}.${process.pid}.tmp`;o.writeFileSync(n,t,{mode:384}),o.renameSync(n,e)}function gt(){try{if(o.existsSync(ft)){let e=o.readFileSync(ft,`utf-8`).trim();return _t(e)?e:e.match(/api_key\s*=\s*(\S+)/)?.[1]}}catch{}}function _t(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function vt(){try{o.existsSync(ft)&&o.unlinkSync(ft)}catch{}}function S(){return Lt(It())}function C(e){let t=Rt(S(),e);ht(pt,`${JSON.stringify(t,null,2)}\n`)}function w(e){return zt(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||S().activeProfile||x)}function yt(e){C({activeProfile:zt(e)})}function bt(){return process.env.TANGLE_SANDBOX||S().currentSandbox||void 0}function xt(e){C({currentSandbox:e})}function St(){let e=S();delete e.currentSandbox,ht(pt,`${JSON.stringify(e,null,2)}\n`)}function Ct(){let e=S().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=fe.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=r(4).toString(`hex`),i=`${t?`${t}-`:`device-`}${n}`;return C({deviceId:i}),i}function wt(e){let t=e||bt();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 Tt(){let e=S(),t=w(),n=new Set([x,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(zt(e.activeProfile)),[...n].map(e=>{let n=Ze(e),r=e===x?gt():void 0,i=n.source===`none`?r?`legacy-file`:`none`:n.source;return{name:e,active:e===t,hasApiKey:n.source!==`none`||!!r,baseUrl:At(void 0,e),apiKeySource:i}}).sort((e,t)=>e.name.localeCompare(t.name))}function Et(e){let t=w(e);return{name:t,active:t===w(),apiKey:T(void 0,t),baseUrl:At(void 0,t),credentialSource:kt(void 0,t)}}function Dt(e,t){let n=zt(e),r=S(),i=Ft(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=Qe(n,t.apiKey),n===x&&vt()),C({profiles:Object.keys(l).length>0?l:{}}),u}function Ot(e){let t=w(e),n={...S().profiles??{}},r=n[t];if(r){let e={...r,apiKey:void 0};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}C({profiles:n}),$e(t),t===x&&vt()}function T(e,t){if(e)return e;let n=process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY;if(n)return n;let r=w(t),i=Ze(r);if(i.value)return i.value;if(r===x)return gt()}function kt(e,t){if(e)return`flag`;if(process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY)return`env`;let n=w(t),r=Ze(n);return r.source===`none`?n===x&>()?`legacy-file`:`none`:r.source}function At(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=w(t),i=S(),a=Ft(r,i);return a.baseUrl?a.baseUrl:r===x&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function jt(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function E(e){let t=w(e.profile),n=T(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===x?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:At(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...Mt(t)}}function Mt(e){let t=S(),n=Ft(w(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function Nt(e,t){Dt(w(t),{activeTeamId:e.id,activeTeamName:e.name})}function Pt(e){let t=w(e),n=S(),r={...n.profiles??{}},i={baseUrl:Ft(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],C({profiles:r})}function Ft(e,t=S()){let n=zt(e);return{...n===x?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[x]?.activeTeamId,activeTeamName:t.profiles?.[x]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function It(){try{if(o.existsSync(pt)){let e=o.readFileSync(pt,`utf-8`);return JSON.parse(e)}}catch{}return{}}function Lt(e){let t=!1,n={};e.apiKey&&(Qe(x,e.apiKey),vt(),t=!0);for(let[r,i]of Object.entries(e.profiles??{})){i.apiKey&&(Qe(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&&ht(pt,`${JSON.stringify(r,null,2)}\n`),r}function Rt(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 zt(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 D=null,O=null;function k(e){if(e)return D&&O&&O.apiKey===e.apiKey&&O.baseUrl===e.baseUrl&&O.timeout===e.timeout?D:(D=new v({apiKey:e.apiKey,baseUrl:e.baseUrl,timeoutMs:e.timeout}),O=e,D);if(D)return D;let t=E({});return D=new v({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),O=t,D}function Bt(){D=null,O=null}async function Vt(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 Ht(r,n)}function Ht(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(Ut(t,s))}function Ut(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 ee,dirname as te,extname as ne,join as m,resolve as re}from"node:path";import{AuthError as h,NetworkError as g,NotFoundError as ie,QuotaError as _,Sandbox as v,ServerError as ae,StateError as oe,TimeoutError as se,ValidationError as ce,createConfidentialSandbox as le,generateAttestationNonce as ue,parseSSEStream as de}from"@tangle-network/sandbox";import*as fe from"node:os";import{homedir as pe,tmpdir as me}from"node:os";import{execFileSync as he,spawn as ge}from"node:child_process";import{HubClient as _e,HubSdkError as ve}from"@tangle-network/hub-sdk";import ye from"ora";import{CONTENT_COMPLETION_KEY as be,CONTENT_PROMPT_KEY as xe,CONTENT_TOOL_ARGS_KEY as Se,CONTENT_TOOL_NAME_KEY as Ce,CONTENT_TOOL_RESULT_KEY as we,TANGLE_SUBJECT_KEY as Te,asContentField as y,asContentString as Ee}from"@tangle-network/agent-core/telemetry";import{createMcpServer as De}from"@tangle-network/sandbox/agent";import{readFile as Oe}from"node:fs/promises";import{fileURLToPath as ke}from"node:url";import Ae from"ws";import{supervise as je,workerFromBackend as Me}from"@tangle-network/agent-runtime/loops";import{createIntelligenceClient as Ne}from"@tangle-network/sandbox/intelligence";function Pe(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:ee(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:ee(e),content:t}}function Fe(e){let t=(e.skills??[]).map(Pe),n=(e.tools??[]).map(Pe),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 Ie(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 We(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await We(e):u(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw Error(`profile at "${e}" is not valid JSON`)}return Be(n,e),n}const Le=[`prompt`,`model`,`permissions`,`tools`,`mcp`,`connections`,`subagents`,`resources`,`hooks`,`modes`,`confidential`,`extensions`],Re=new Set([...Le,`name`,`description`,`version`,`tags`,`metadata`]),ze=[`files`,`tools`,`skills`,`agents`,`commands`];function Be(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=>Le.includes(e)),i=n.includes(`name`)&&n.every(e=>Re.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)`}.`);Ve(e,t)}function Ve(e,t){let n=e.resources;if(!n||typeof n!=`object`)return;for(let e of ze){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)Ue(e===`files`?He(n):n,t)}}let r=n.instructions;r!==void 0&&typeof r!=`string`&&Ue(r,t)}function He(e){return e&&typeof e==`object`?e.resource:e}function Ue(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 We(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function Ge(e){let t=e.profileSource?await Ie(e.profileSource):void 0,n=Fe(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const Ke=p.join(fe.homedir(),`.tangle`),b=p.join(Ke,`credentials.json`),qe=`tangle-sandbox-cli`,Je=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var Ye=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)}},Xe=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 ${Je}=1 to opt into a plaintext credentials.json with mode 0600.`),this.name=`KeychainUnavailableError`}};function Ze(e){let t=tt(e);if(t)return{value:t,source:`keychain`};let n=it(e);return n?{value:n,source:`file`}:{source:`none`}}function Qe(e,t){if(nt(e,t))return ot(e),`keychain`;if(!et())throw new Xe;return at(e,t),`file`}function $e(e){rt(e),ot(e)}function et(){let e=process.env[Je];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function tt(e){if(process.platform===`darwin`)try{return he(`security`,[`find-generic-password`,`-s`,qe,`-a`,ut(e),`-w`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}if(process.platform===`linux`)try{return he(`secret-tool`,[`lookup`,`service`,qe,`account`,ut(e)],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()}catch{return}}function nt(e,t){if(process.platform===`darwin`)try{return he(`security`,[`add-generic-password`,`-U`,`-s`,qe,`-a`,ut(e),`-w`,t],{stdio:[`ignore`,`ignore`,`ignore`]}),!0}catch{return!1}if(process.platform===`linux`)try{return he(`secret-tool`,[`store`,`--label=Tangle Sandbox CLI`,`service`,qe,`account`,ut(e)],{input:t,stdio:[`pipe`,`ignore`,`ignore`]}),!0}catch{return!1}return!1}function rt(e){if(process.platform===`darwin`){try{he(`security`,[`delete-generic-password`,`-s`,qe,`-a`,ut(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}return}if(process.platform===`linux`)try{he(`secret-tool`,[`clear`,`service`,qe,`account`,ut(e)],{stdio:[`ignore`,`ignore`,`ignore`]})}catch{}}function it(e){return st()[e]}function at(e,t){let n=st();n[e]=t,ct(n)}function ot(e){let t;try{t=st()}catch(e){if(e instanceof Ye)return;throw e}e in t&&(delete t[e],ct(t))}function st(){let e;try{e=o.readFileSync(b,`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 Ye(b);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof Ye?e:new Ye(b,e instanceof Error?e:void 0)}}function ct(e){if(lt(),Object.keys(e).length===0){o.existsSync(b)&&o.unlinkSync(b);return}let t=`${b}.${process.pid}.tmp`;o.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),o.renameSync(t,b)}function lt(){if(!o.existsSync(Ke)){o.mkdirSync(Ke,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(o.statSync(Ke).mode&511)!=448&&o.chmodSync(Ke,448)}catch{}}function ut(e){return`profile:${e}`}const dt=p.join(fe.homedir(),`.tangle`),ft=p.join(dt,`credentials`),pt=p.join(dt,`config.json`),x=`default`;function mt(){o.existsSync(dt)||o.mkdirSync(dt,{mode:448,recursive:!0})}function ht(e,t){mt();let n=`${e}.${process.pid}.tmp`;o.writeFileSync(n,t,{mode:384}),o.renameSync(n,e)}function gt(){try{if(o.existsSync(ft)){let e=o.readFileSync(ft,`utf-8`).trim();return _t(e)?e:e.match(/api_key\s*=\s*(\S+)/)?.[1]}}catch{}}function _t(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function vt(){try{o.existsSync(ft)&&o.unlinkSync(ft)}catch{}}function S(){return Lt(It())}function C(e){let t=Rt(S(),e);ht(pt,`${JSON.stringify(t,null,2)}\n`)}function w(e){return zt(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||S().activeProfile||x)}function yt(e){C({activeProfile:zt(e)})}function bt(){return process.env.TANGLE_SANDBOX||S().currentSandbox||void 0}function xt(e){C({currentSandbox:e})}function St(){let e=S();delete e.currentSandbox,ht(pt,`${JSON.stringify(e,null,2)}\n`)}function Ct(){let e=S().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=fe.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=r(4).toString(`hex`),i=`${t?`${t}-`:`device-`}${n}`;return C({deviceId:i}),i}function wt(e){let t=e||bt();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 Tt(){let e=S(),t=w(),n=new Set([x,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(zt(e.activeProfile)),[...n].map(e=>{let n=Ze(e),r=e===x?gt():void 0,i=n.source===`none`?r?`legacy-file`:`none`:n.source;return{name:e,active:e===t,hasApiKey:n.source!==`none`||!!r,baseUrl:At(void 0,e),apiKeySource:i}}).sort((e,t)=>e.name.localeCompare(t.name))}function Et(e){let t=w(e);return{name:t,active:t===w(),apiKey:T(void 0,t),baseUrl:At(void 0,t),credentialSource:kt(void 0,t)}}function Dt(e,t){let n=zt(e),r=S(),i=Ft(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=Qe(n,t.apiKey),n===x&&vt()),C({profiles:Object.keys(l).length>0?l:{}}),u}function Ot(e){let t=w(e),n={...S().profiles??{}},r=n[t];if(r){let e={...r,apiKey:void 0};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}C({profiles:n}),$e(t),t===x&&vt()}function T(e,t){if(e)return e;let n=process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY;if(n)return n;let r=w(t),i=Ze(r);if(i.value)return i.value;if(r===x)return gt()}function kt(e,t){if(e)return`flag`;if(process.env.TANGLE_API_KEY||process.env.SANDBOX_API_KEY)return`env`;let n=w(t),r=Ze(n);return r.source===`none`?n===x&>()?`legacy-file`:`none`:r.source}function At(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=w(t),i=S(),a=Ft(r,i);return a.baseUrl?a.baseUrl:r===x&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function jt(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function E(e){let t=w(e.profile),n=T(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===x?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:At(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...Mt(t)}}function Mt(e){let t=S(),n=Ft(w(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function Nt(e,t){Dt(w(t),{activeTeamId:e.id,activeTeamName:e.name})}function Pt(e){let t=w(e),n=S(),r={...n.profiles??{}},i={baseUrl:Ft(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],C({profiles:r})}function Ft(e,t=S()){let n=zt(e);return{...n===x?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[x]?.activeTeamId,activeTeamName:t.profiles?.[x]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function It(){try{if(o.existsSync(pt)){let e=o.readFileSync(pt,`utf-8`);return JSON.parse(e)}}catch{}return{}}function Lt(e){let t=!1,n={};e.apiKey&&(Qe(x,e.apiKey),vt(),t=!0);for(let[r,i]of Object.entries(e.profiles??{})){i.apiKey&&(Qe(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&&ht(pt,`${JSON.stringify(r,null,2)}\n`),r}function Rt(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 zt(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 D=null,O=null;function k(e){if(e)return D&&O&&O.apiKey===e.apiKey&&O.baseUrl===e.baseUrl&&O.timeout===e.timeout?D:(D=new v({apiKey:e.apiKey,baseUrl:e.baseUrl,timeoutMs:e.timeout}),O=e,D);if(D)return D;let t=E({});return D=new v({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),O=t,D}function Bt(){D=null,O=null}async function Vt(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 Ht(r,n)}function Ht(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(Ut(t,s))}function Ut(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 Wt(e,t){return[...t,e]}async function Gt(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:`${Ht(r,e.ref)}:${e.tail}`)}function Kt(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 qt(e){return e==null?a.dim(`-`):typeof e==`boolean`?e?a.green(`yes`):a.red(`no`):e instanceof Date?Yt(e):typeof e==`string`&&Jt(e)?Yt(new Date(e)):String(e)}function Jt(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function Yt(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 Xt(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 A(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=>qt(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=qt(r[e.key]);return e.key===`status`&&(i=Xt(String(r[e.key]))),i.padEnd(n[t])}).join(``);console.log(e)}}function j(e){console.log(JSON.stringify(e,null,2))}function M(e){console.log(a.green(`✓`),e)}function N(e){console.error(a.red(`✗`),e)}function Zt(e){console.log(a.yellow(`!`),e)}function P(e){console.log(a.blue(`→`),e)}const Qt=new Set;function F(e){let t=ye({text:e,color:`cyan`});return Qt.add(t),t}function $t(){for(let e of Qt)e.isSpinning&&e.stop();Qt.clear()}function I(e,t=0){let n=` `.repeat(t);for(let[t,r]of Object.entries(e))r!=null&&console.log(`${n}${a.dim(`${t}:`)} ${qt(r)}`)}function en(e){if(console.log(),console.log(a.bold(`Sandbox Details`)),console.log(a.dim(`─`.repeat(40))),I({ID:e.id,Name:e.name,Status:Xt(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}`;I({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&I({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&I({"API URL":e.connection.runtimeUrl})}console.log()}function L(e,t){$t(),t?j({error:e.message}):N(e.message),process.exit(1)}function R(e){j(e)}function z(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 B(e,t=!1){$t(),t&&(j(tn(e)),process.exit(ln(e)));let n=nn(e);console.error(a.red(`Error:`),n),process.exit(ln(e))}function tn(e){return e instanceof ve?{error:{code:e.code,message:e.message,...typeof e.status==`number`?{status:e.status}:{},...e.details===void 0?{}:{details:e.details}}}:cn(e)?{error:{code:e.code,message:e.message,status:e.status,...e.details===void 0?{}:{details:e.details}}}:{error:{message:nn(e)}}}function nn(e){if(e instanceof h)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 _)return`Quota exceeded. Upgrade your plan or wait for quota reset.`;if(e instanceof ce)return`Invalid input: ${e.message}`;if(e instanceof oe)return`Invalid state: ${e.message}`;if(e instanceof se)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 ae)return`${e.status?`HTTP ${e.status}`:`server error`}: ${e.message}`;if(e instanceof ve){let t=typeof e.status==`number`?` (HTTP ${e.status})`:``;return e.code===`HUB_CONNECTION_MISSING`?rn(e.code,t,e.message,e.details):e.code===`HUB_APPROVAL_REQUIRED`?on(e.code,t,e.message):e.code===`HUB_UNAUTHENTICATED`?sn(e.code,t,e.message):`${e.code}${t}: ${e.message}`}return cn(e)?e.code===`HUB_CONNECTION_MISSING`?rn(e.code,` (HTTP ${e.status})`,e.message,e.details):e.code===`HUB_APPROVAL_REQUIRED`?on(e.code,` (HTTP ${e.status})`,e.message):e.code===`HUB_UNAUTHENTICATED`?sn(e.code,` (HTTP ${e.status})`,e.message):`${e.code} (HTTP ${e.status}): ${e.message}`:e instanceof Error?e.message:String(e)}function rn(e,t,n,r){let i=an(r);return`${e}${t}: ${n}${i?`. Run: tangle hub connect ${i}`:``}`}function an(e){if(!e||typeof e!=`object`)return;let t=e.provider;return typeof t==`string`&&t.length>0?t:void 0}function on(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 sn(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, SANDBOX_API_KEY, or TANGLE_HUB_CAPABILITY_TOKEN (and pass --no-hub-key to skip auto-minting).`}function cn(e){if(!(e instanceof Error))return!1;let t=e;return typeof t.code==`string`&&t.code.startsWith(`HUB_`)&&typeof t.status==`number`}function ln(e){return e instanceof ce?2:1}function un(e,t){return n(`sha256`).update(`${e}${t}`).digest(`hex`).slice(0,32)}function dn(e){return`${e}:hub`}function fn(e){let{value:t}=Ze(dn(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 pn(e,t){try{Qe(dn(e),JSON.stringify(t))}catch{}}async function mn(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 hn=class{cache;fingerprint;constructor(e,t,n,r){this.profile=e,this.sandboxBaseUrl=t,this.sessionToken=n,this.deviceId=r,this.fingerprint=un(t,n);let i=fn(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 mn(this.sandboxBaseUrl,this.sessionToken,this.deviceId),sessionFingerprint:this.fingerprint};return this.cache=t,pn(this.profile,t),t}};function gn(e){if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function _n(e,t){if(e.baseUrl)return e.baseUrl;let n=jt(process.env.TANGLE_HUB_URL);if(n)return n;let r=fn(t);return r?r.platformUrl:`https://id.tangle.tools`}function vn(e,t){let n=w(),r=T(e.apiKey,n),i=kt(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/SANDBOX_API_KEY or TANGLE_HUB_CAPABILITY_TOKEN, not both`);if(i===`flag`&&r)return{kind:`static`,apiKey:r,baseUrl:_n(e,n)};if(i===`env`&&r)return{kind:`static`,apiKey:a??r,baseUrl:_n(e,n)};if(a)return{kind:`static`,apiKey:a,baseUrl:_n(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:_n(e,n)}:{kind:`managed`,profile:n,sandboxBaseUrl:At(void 0,n),sessionToken:r,deviceId:Ct(),baseUrlOverride:e.baseUrl}}async function V(e={}){let t=vn(e,e.hubKey===!1||gn(process.env.TANGLE_SKIP_HUB_KEY));if(t.kind===`static`)return new _e({baseUrl:t.baseUrl,apiKey:t.apiKey});let n=new hn(t.profile,t.sandboxBaseUrl,t.sessionToken,t.deviceId),r=await n.ensure();return new _e({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 yn(e){return e instanceof Date?e.toISOString():String(e)}function bn(e,t){return`Sandbox name is ambiguous: ${e}. Use a sandbox id instead.\n${t.map(e=>`- ${e.id} (status: ${e.status}, created: ${yn(e.createdAt)})`).join(`
|
|
4
4
|
`)}`}function xn(e){return e.activeTeamId?`team:${e.activeTeamId}`:void 0}async function H(e,t,n){let r=await e.get(n);if(r||n.startsWith(`sandbox-`)){if(!r)throw Error(`Sandbox not found: ${n}`);return r}let i=(await e.list({scope:xn(t)})).filter(e=>e.name?.toLowerCase()===n.toLowerCase());if(i.length===0)throw Error(`Sandbox not found: ${n}`);if(i.length>1)throw Error(bn(n,i));return i[0]}async function U(e,t){if(e.status!==`stopped`)return e;let n=t?.resumeTimeoutMs??12e4;P(`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 Sn=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function Cn(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.9.
|
|
3
|
+
"version": "0.9.2-develop.20260625093856.35d47c0",
|
|
4
4
|
"description": "CLI for Tangle Sandbox operations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
"hub-reference.md"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@tangle-network/agent-
|
|
19
|
-
"@tangle-network/agent-
|
|
18
|
+
"@tangle-network/agent-core": "^0.3.1",
|
|
19
|
+
"@tangle-network/agent-eval": "^0.100.0",
|
|
20
|
+
"@tangle-network/agent-runtime": "^0.77.0",
|
|
20
21
|
"chalk": "^5.4.1",
|
|
21
22
|
"commander": "12.1.0",
|
|
22
23
|
"dotenv": "17.2.3",
|
|
23
24
|
"ora": "^9.4.0",
|
|
24
25
|
"ws": "^8.20.0",
|
|
25
26
|
"@tangle-network/hub-sdk": "0.2.2",
|
|
26
|
-
"@tangle-network/sandbox": "0.9.
|
|
27
|
-
"@tangle-network/sdk-core": "0.1.8"
|
|
27
|
+
"@tangle-network/sandbox": "0.9.2-develop.20260625093856.35d47c0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "25.6.0",
|