@tangle-network/sandbox-cli 0.21.83 → 0.21.85
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 +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as e,findPackageJSON as t}from"node:module";import"dotenv/config";import{ALL_BACKEND_TYPES as n,AuthError as r,GPU_LEASE_PROVIDER_NAMES as i,NetworkError as a,NotFoundError as o,PublicTemplatePublishError as s,QuotaError as c,Sandbox as l,ServerError as u,StateError as d,TimeoutError as f,ValidationError as p,createAgentRunOutcomeTracker as m,createBatchResultAccumulator as h,createConfidentialSandbox as g,generateAttestationNonce as _,parseBackendType as ee,parseSSEStream as te,validateBatchRunRequest as v}from"@tangle-network/sandbox";import y from"chalk";import ne from"ora";import{Command as b}from"commander";import{createHash as re,randomBytes as ie,randomUUID as x}from"node:crypto";import{ProxySecretsSchema as S,agentInteractiveSessionRunRef as ae,agentProfileSchema as C,canonicalAgentProfileDigest as oe,canonicalCandidateDigest as se,modelProvider as ce,parseSeatSpec as le}from"@tangle-network/agent-interface";import*as w from"node:fs";import{chmodSync as ue,constants as de,existsSync as fe,mkdirSync as pe,readFileSync as T,renameSync as me,writeFileSync as he}from"node:fs";import*as E from"node:path";import{basename as ge,dirname as _e,extname as ve,isAbsolute as ye,join as D,relative as be,resolve as xe,sep as Se}from"node:path";import*as Ce from"node:os";import{homedir as O,tmpdir as we}from"node:os";import{execFile as Te,execFileSync as Ee,spawn as De}from"node:child_process";import{lockSync as Oe}from"proper-lockfile";import{HubClient as ke}from"@tangle-network/hub-sdk";import{createInterface as Ae}from"node:readline";import{Writable as je}from"node:stream";import{buffer as Me}from"node:stream/consumers";import{setTimeout as Ne}from"node:timers/promises";import{CONTENT_COMPLETION_KEY as Pe,CONTENT_PROMPT_KEY as Fe,CONTENT_TOOL_ARGS_KEY as Ie,CONTENT_TOOL_NAME_KEY as Le,CONTENT_TOOL_RESULT_KEY as Re,TANGLE_SUBJECT_KEY as ze,asContentField as k,asContentString as Be}from"@tangle-network/agent-core/telemetry";import{execCli as Ve,shellQuote as He}from"@tangle-network/sdk-cli-runner";import*as A from"node:fs/promises";import{mkdir as Ue,mkdtemp as We,open as Ge,readFile as Ke,realpath as qe,writeFile as Je}from"node:fs/promises";import{z as j}from"zod";import{listLocalModels as Ye,loadConfig as Xe}from"cli-bridge";import{createMcpServer as Ze}from"@tangle-network/sandbox/agent";import{ensureAgentPreview as Qe,publishAgentPreview as $e,resolveSelfSandbox as et}from"@tangle-network/sandbox/preview";import{fileURLToPath as tt}from"node:url";import{generatePrivateKey as nt,privateKeyToAccount as rt}from"viem/accounts";import{promisify as it}from"node:util";import{createPublicClient as at,createWalletClient as ot,decodeAbiParameters as st,decodeEventLog as ct,encodeAbiParameters as lt,getAddress as ut,http as dt,isAddress as ft,keccak256 as pt,parseAbi as mt,parseAbiItem as ht,parseAbiParameters as gt,stringToHex as _t,toHex as vt}from"viem";import{tempoModerato as yt}from"viem/chains";import{Actions as bt,withRelay as xt}from"viem/tempo";import St from"ws";import{createIntelligenceClient as Ct}from"@tangle-network/sandbox/intelligence";let wt=!1;function Tt(e){wt=e}function Et(...e){wt?console.error(...e):console.log(...e)}function Dt(e){return e==null?y.dim(`-`):typeof e==`boolean`?e?y.green(`yes`):y.red(`no`):e instanceof Date?kt(e):typeof e==`string`&&Ot(e)?kt(new Date(e)):String(e)}function Ot(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function kt(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 y.green(e);case`pending`:case`provisioning`:return y.yellow(e);case`stopped`:return y.gray(e);case`failed`:case`deleted`:return y.red(e);default:return e}}function M(e,t){let n=t.map(t=>{let n=t.header.length,r=Math.max(...e.map(e=>Dt(e[t.key]).length));return t.width??Math.max(n,r)+2}),r=e.map(e=>t.map(t=>t.key===`status`?At(String(e[t.key])):Dt(e[t.key])));Lt(t.map(e=>e.header),r,n)}function N(e){console.log(JSON.stringify(e,null,2))}function P(e){Et(y.green(`✓`),e)}function jt(e){console.error(y.red(`✗`),e)}function Mt(e){Et(y.yellow(`!`),e)}function F(e){Et(y.blue(`→`),e)}const Nt=new Set;function I(e){let t=ne({text:e,color:`cyan`,isSilent:wt});return Nt.add(t),t}function Pt(){for(let e of Nt)e.isSpinning&&e.stop();Nt.clear()}function L(e,t=0){let n=` `.repeat(t);for(let[t,r]of Object.entries(e))r!=null&&console.log(`${n}${y.dim(`${t}:`)} ${Dt(r)}`)}function Ft(e){let t=`${e.cpuCores} vCPU / ${e.memoryMB} MB / ${e.diskGB} GB`;return e.pool?`${t} (pool: ${e.pool})`:t}function It(e){if(console.log(),console.log(y.bold(`Sandbox Details`)),console.log(y.dim(`─`.repeat(40))),L({ID:e.id,Name:e.name,Status:At(e.status),Resources:e.resources?Ft(e.resources):void 0,Created:e.createdAt,Expires:e.expiresAt}),e.connection){if(console.log(),console.log(y.bold(`Connection`)),console.log(y.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}`;L({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&L({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&L({"API URL":e.connection.runtimeUrl})}console.log()}function Lt(e,t,n){if(t.length===0){console.log(y.dim(`No items found.`));return}let r=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)=>y.bold(e.padEnd(r[t]))).join(``));for(let e of t)console.log(e.map((e,t)=>String(e??``).padEnd(r[t])).join(``))}var R=class extends Error{constructor(e,t,n,r){super(t),this.code=e,this.cause=n,this.fix=r,this.name=`ActionableCliError`}};const Rt=new Set([`AUTH_EXPIRED`,`AUTH_WRONG_AUDIENCE`,`SEAT_NONE_DETECTED`,`SEAT_NOT_LOGGED_IN`,`SEAT_NOT_ENROLLED`,`HUB_NOT_CONNECTED`,`HUB_RECONNECT`,`HUB_APP_NOT_INSTALLED`,`HUB_APPROVAL_REQUIRED`]),zt=new Set([`GRAPH_INVALID`,`STEP_REF`,`PROFILE_INVALID`,`UNKNOWN_HARNESS`,`HUB_TOOL_UNKNOWN`,`TRIGGER_INVALID`,`WORKFLOW_INPUT_FILE_INVALID`,`VALIDATION_ERROR`]),Bt=new Set([`UNKNOWN_COMMAND`,`GRAPH_PARAM_MISSING`,`GRAPH_PARAM_UNKNOWN`,`SEAT_SYNTAX`,`HUB_PROVIDER_UNKNOWN`,`USAGE_INVALID`]),Vt=new Set([`SUBSCRIPTION_REQUIRED`,`MODEL_NOT_FOUND`,`MODEL_PROVIDER_MISMATCH`,`MCP_BLOCKED`,`CLOUD_SEAT_UNSUPPORTED`,`SCHEDULE_AUTHORITY`]);function Ht(e){return typeof e==`object`&&e?e:{}}function z(e){return typeof e==`string`&&e.length>0?e:void 0}function Ut(e){let t=z(e);return t&&/^[a-z0-9][a-z0-9_-]*$/i.test(t)?t:void 0}function Wt(e){let t,n=e;for(let e=0;n instanceof Error&&e<5;e++,n=n.cause){let e=n.message||(n instanceof AggregateError?n.errors.map(e=>e instanceof Error?e.message:String(e)).join(`; `):``),r=z(Ht(n).code);(e||r)&&(t=r?`${r}${e?`: ${e}`:``}`:e)}return t}function Gt(e){return e.code===`credential-refused`&&e.owner===`caller`&&e.providerCode===`subscription_required`?Ht(e.remediation):{}}function Kt(e){let t=Ht(e),n=Array.isArray(t.runtimeFailures)?t.runtimeFailures.map(Ht):[],i=n.find(e=>z(Gt(Ht(e.failure)).fix))??n[0],l=Ht(i?.failure??t.runtimeFailure),u=Gt(l),m=Ht(t.details),h=Ut(t.provider??m.provider??m.providerId),g=Ht(t.fix??m.fix),_=z(t.wireCode)??z(t.code)??`CLI_ERROR`,ee=z(t.message)??String(e),te=z(l.cause)??z(t.cause)??z(m.reason)??ee,v=`tangle --help`,y=typeof m.providerRetryable==`boolean`?m.providerRetryable:typeof t.retryable==`boolean`?t.retryable:null;if(e instanceof r||_===`HUB_UNAUTHENTICATED`||t.status===401)_=`AUTH_EXPIRED`,ee=`Authentication failed`,v=`tangle auth login`;else if([`HUB_CONNECTION_MISSING`,`HUB_CONNECTION_REVOKED`,`HUB_CONNECTION_UNHEALTHY`,`HUB_RECONNECT_REQUIRED`,`CONNECTION_REQUIRED`].includes(_))_=[`HUB_CONNECTION_MISSING`,`CONNECTION_REQUIRED`].includes(_)?`HUB_NOT_CONNECTED`:`HUB_RECONNECT`,v=h?`tangle hub connect ${h}`:`tangle hub connections --json`;else if(_===`HUB_APPROVAL_REQUIRED`){let e=Ut(Ht(m.approval).id);v=e?`tangle hub approvals approve ${e}`:`tangle hub approvals list --json`}else _===`HUB_PROVIDER_REJECTED`?(v=`tangle hub status --json`,m.providerRetryable===!1&&(te+=`. Change the request before retrying`)):_===`provider_quota_exhausted`||_===`SEAT_LIMIT`?(_=`SEAT_LIMIT`,v=`tangle auth status`,y=!0):e instanceof c?v=`tangle usage --json`:e instanceof a?(_=`NETWORK_UNAVAILABLE`,ee=`Network error: ${ee}`,te=Wt(e.cause)??`No response arrived`,v=`tangle auth status --json`,y=!0):e instanceof f?(_=`TIMEOUT`,v=`tangle sandbox list --json`,y=!0):e instanceof p?(_=`VALIDATION_ERROR`,ee=`Invalid input`):e instanceof o||e instanceof d?v=`tangle sandbox list --json`:_===`commander.unknownCommand`?(_=`UNKNOWN_COMMAND`,v=ee.includes(`'graph'`)?`npm install -g @tangle-network/sandbox-cli@latest`:`tangle --help`):_.startsWith(`commander.`)?_=`USAGE_INVALID`:(_===`ENOENT`||_===`EACCES`)&&(_=`INPUT_UNAVAILABLE`);e instanceof R&&(v=e.fix,y=!1),z(u.fix)&&(_=u.cause===`not_authenticated`?`SEAT_NOT_LOGGED_IN`:`SUBSCRIPTION_REQUIRED`),e instanceof s&&v===`tangle --help`&&(v=`tangle template publish --help`),v=z(u.fix)??z(g.command)??(_===`HUB_NOT_CONNECTED`?void 0:z(t.fixCommand))??v,Rt.has(_)&&v===`tangle --help`&&(v=`tangle auth login`);let ne=Ht(t.subject??m.subject??{node:i?.node??t.node,seat:t.seat??u.harness}),b=z(t.resumeAt??m.resumeAt??m.resetAt);return{code:_,subject:{...z(ne.node)?{node:String(ne.node)}:{},...z(ne.seat)?{seat:String(ne.seat)}:{}},what:ee,cause:te,fix:{command:v,...Array.isArray(g.alternatives)&&g.alternatives.every(e=>typeof e==`string`)?{alternatives:g.alternatives}:{},...g.edit===void 0?{}:{edit:g.edit},...z(g.url)?{url:String(g.url)}:{}},retryable:y,...b&&Number.isFinite(Date.parse(b))?{resumeAt:b}:{},...z(t.runId)?{runId:String(t.runId)}:{},...z(t.requestId)?{requestId:String(t.requestId)}:{},...typeof t.status==`number`?{status:t.status}:{},...z(l.code)&&z(l.owner)?{runtimeFailure:{code:String(l.code),owner:String(l.owner),cause:typeof l.cause==`string`?l.cause:te,...z(l.providerCode)?{providerCode:String(l.providerCode)}:{},...typeof l.providerStatus==`number`?{providerStatus:l.providerStatus}:{},...typeof l.retryAfterMs==`number`?{retryAfterMs:l.retryAfterMs}:{},...Object.keys(u).length?{remediation:u}:{}}}:{},...e instanceof s&&e.job?{job:e.job}:{}}}function qt(e){let t=[e.subject.node&&`node ${e.subject.node}`,e.subject.seat].filter(Boolean).join(` · `);return`✗ ${`${t?`${t}: `:``}${e.what}${e.status?` (HTTP ${e.status})`:``}`}${e.cause===e.what?``:` — ${e.cause}`}\n → run: ${e.fix.command}`+(e.runtimeFailure?`\n runtime: ${e.runtimeFailure.code} · ${e.runtimeFailure.owner}${e.runtimeFailure.providerCode?` · ${e.runtimeFailure.providerCode}`:``}${e.runtimeFailure.providerStatus===void 0?``:` · HTTP ${e.runtimeFailure.providerStatus}`}${e.runtimeFailure.retryAfterMs===void 0?``:` · retry-after ${e.runtimeFailure.retryAfterMs} ms`}`:``)+(e.fix.alternatives?.map(e=>`\n or: ${e}`).join(``)??``)+(e.resumeAt?`\n resumes ${e.resumeAt}${e.subject.seat?` on ${e.subject.seat}`:``}`:``)}function Jt(e){return qt(Kt(e))}function B(e,t=!1){Pt();let n=Kt(e);t?N({ok:!1,error:n}):console.error(y.red(qt(n)));let r=1;Rt.has(n.code)?r=77:zt.has(n.code)?r=65:Bt.has(n.code)?r=64:Vt.has(n.code)?r=78:[`SEAT_LIMIT`,`RATE_LIMITED`].includes(n.code)?r=75:[`HARNESS_NOT_INSTALLED`,`MCP_UNREACHABLE`,`NETWORK_UNAVAILABLE`].includes(n.code)?r=69:n.code===`RUN_STOPPED`&&(r=130),process.exit(r)}function Yt(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:ge(a)}}let t;try{t=T(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:ge(e),content:t}}function Xt(e){let t=(e.skills??[]).map(Yt),n=(e.tools??[]).map(Yt),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 Zt(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 $t(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await $t(e):T(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw new R(`PROFILE_INVALID`,`Profile '${e}' is invalid`,`Expected a JSON AgentProfile`,`tangle agent profile create --name my-agent --json`)}return Qt(n,e)}function Qt(e,t){let n=C.safeParse(e);if(!n.success)throw new R(`PROFILE_INVALID`,`Profile '${t}' is invalid`,n.error.issues.map(e=>`${e.path.join(`.`)||`(root)`}: ${e.message}`).join(`; `),`tangle agent profile create --name my-agent --json`);return e}async function $t(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function en(e){let t=e.profileSource?await Zt(e.profileSource):void 0,n=Xt(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const tn=E.join(Ce.homedir(),`.tangle`),nn=E.join(tn,`credentials.json`),rn=`tangle-sandbox-cli`,an=new Int32Array(new SharedArrayBuffer(4)),on=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var sn=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)}},cn=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 ${on}=1 to opt into a plaintext credentials.json with mode 0600.`),this.name=`KeychainUnavailableError`}},ln=class extends Error{constructor(e){super(`Credential storage preflight failed: ${e}`),this.name=`CredentialStorageProbeError`}},un=class extends Error{constructor(e){super(`Credential storage is busy. Wait a moment and retry.`),this.name=`CredentialsFileLockedError`,e&&(this.cause=e)}};function dn(e){let t=_n(e);if(t)return{value:t,source:`keychain`};let n=bn(e);return n?{value:n,source:`file`}:{source:`none`}}function fn(e,t){if(vn(e,t))return Sn(e),`keychain`;if(!hn())throw new cn;return xn(e,t),`file`}function pn(){let e=`credential-write-probe:${process.pid}:${x()}`,t=x();if(vn(e,t)){let n=_n(e);if(!yn(e))throw new ln(`the OS keychain accepted a test credential but the CLI could not remove it`);if(n!==t)throw new ln(`the OS keychain accepted a test credential but the CLI could not read it back`);return`keychain`}if(!hn())throw new cn;return En(e),`file`}function mn(e){yn(e),Sn(e)}function hn(){let e=process.env[on];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function gn(e,t){let n=process.platform;if(n!==`darwin`&&n!==`linux`)return;let r=n===`darwin`?`security`:`secret-tool`;try{return Ee(r,e[n],{encoding:`utf8`,input:t,stdio:[t===void 0?`ignore`:`pipe`,`pipe`,`ignore`],timeout:n===`linux`?1e4:void 0}).trim()}catch{return}}function _n(e){let t=On(e);return gn({darwin:[`find-generic-password`,`-s`,rn,`-a`,t,`-w`],linux:[`lookup`,`service`,rn,`account`,t]})}function vn(e,t){let n=On(e),r=[`add-generic-password`,`-U`,`-s`,rn,`-a`],i=[`store`,`--label=Tangle Sandbox CLI`,`service`];return gn({darwin:[...r,n,`-w`,t],linux:[...i,rn,`account`,n]},process.platform===`linux`?t:void 0)!==void 0}function yn(e){let t=On(e);return gn({darwin:[`delete-generic-password`,`-s`,rn,`-a`,t],linux:[`clear`,`service`,rn,`account`,t]})!==void 0}function bn(e){return wn()[e]}function xn(e,t){Cn(()=>{let n=wn();n[e]=t,Tn(n)})}function Sn(e){return Cn(()=>{let t;try{t=wn()}catch(e){if(e instanceof sn)return!1;throw e}return e in t?(delete t[e],Tn(t),bn(e)===void 0):!0})}function Cn(e){Dn();let t=Date.now()+2e3,n,r;for(;!n;)try{n=Oe(nn,{realpath:!1,stale:5e3})}catch(e){if(r=e instanceof Error?e:void 0,!e||typeof e!=`object`||!(`code`in e)||e.code!==`ELOCKED`)throw e;if(Date.now()>=t)throw new un(r);Atomics.wait(an,0,0,20)}try{return e()}finally{n()}}function wn(){let e;try{e=w.readFileSync(nn,`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 sn(nn);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof sn?e:new sn(nn,e instanceof Error?e:void 0)}}function Tn(e){if(Dn(),Object.keys(e).length===0){w.existsSync(nn)&&w.unlinkSync(nn);return}let t=`${nn}.${process.pid}.tmp`;w.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),w.renameSync(t,nn)}function En(e){let t=x(),n=!1,r;try{if(xn(e,t),n=!0,bn(e)!==t)throw new ln(`the credentials file did not return the value just written`)}catch(e){r=e}finally{if(n)try{!Sn(e)&&!r&&(r=new ln(`the credentials file accepted a test credential but the CLI could not remove it`))}catch(e){r??=e}}if(r)throw r}function Dn(){if(!w.existsSync(tn)){w.mkdirSync(tn,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(w.statSync(tn).mode&511)!=448&&w.chmodSync(tn,448)}catch{}}function On(e){return`profile:${e}`}const kn=E.join(Ce.homedir(),`.tangle`),An=E.join(kn,`config.json`),jn=`https://id.tangle.tools`,Mn=`https://solve.tangle.tools/api/solve`,Nn=`default`;function Pn(){return{tangleBaseUrl:process.env.TANGLE_BASE_URL,sandboxBaseUrl:process.env.SANDBOX_BASE_URL,hubUrl:process.env.TANGLE_HUB_URL}}function Fn(e,t){let n=Vn(t??(e===`solve`?`solve`:void 0));if(e===`solve`){if(n!==`solve`)throw Error(`The solve app cannot use profile '${n}'. Use the reserved 'solve' profile.`);return n}if(e===`sandbox`&&!t&&n===`solve`)return Nn;if(new Set([`solve`]).has(n))throw Error(`The ${e} app cannot use the reserved '${n}' profile. Use the '${e}' profile or choose a custom profile.`);return n}function In(){w.existsSync(kn)||w.mkdirSync(kn,{mode:448,recursive:!0})}function Ln(e,t){In();let n=`${e}.${process.pid}.tmp`;w.writeFileSync(n,t,{mode:384}),w.renameSync(n,e)}function Rn(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function zn(){try{if(w.existsSync(An))return JSON.parse(w.readFileSync(An,`utf-8`))}catch{}return{}}function Bn(e){let t=mr(zn(),e);Ln(An,`${JSON.stringify(t,null,2)}\n`)}function Vn(e){return hr(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||zn().activeProfile||Nn)}function Hn(e){Bn({activeProfile:hr(e)})}function Un(){return{token:process.env.TANGLE_LINE_TOKEN,baseUrl:process.env.TANGLE_HUB_URL}}function Wn(){return process.env.TANGLE_SANDBOX||zn().currentSandbox||void 0}function Gn(e){Bn({currentSandbox:e})}function Kn(){let e=zn();delete e.currentSandbox,Ln(An,`${JSON.stringify(e,null,2)}\n`)}function qn(){let e=zn().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=Ce.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=ie(4).toString(`hex`),r=`${t?`${t}-`:`device-`}${n}`;return Bn({deviceId:r}),r}function Jn(e){let t=e||Wn();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 Yn(){let e=zn(),t=Vn(),n=new Set([Nn,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(hr(e.activeProfile)),[...n].map(e=>{let n=dn(e).source;return{name:e,active:e===t,hasApiKey:n!==`none`,baseUrl:ir(void 0,e),apiKeySource:n}}).sort((e,t)=>e.name.localeCompare(t.name))}function Xn(e){let t=Vn(e);return{name:t,active:t===Vn(),baseUrl:ir(void 0,t),credentialSource:dn(t).source}}function Zn(e,t){let n=hr(e),r=zn(),i=pr(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=fn(n,t.apiKey)),Bn({profiles:Object.keys(l).length>0?l:{}}),u}function Qn(e){let t=Vn(e),n={...zn().profiles??{}},r=n[t];if(r){let e={...r};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}Bn({profiles:n}),mn(t)}function $n(){let e=process.env.TANGLE_API_KEY_FILE;if(e){let t=w.readFileSync(e,`utf8`).trim();if(!t.startsWith(`sk-tan-`))throw Error(`Invalid sandbox credential file`);return t}return process.env.TANGLE_API_KEY}function er(e,t){let n=Fn(`sandbox`,t);return e||$n()||dn(n).value}function tr(e,t){return e||(process.env.TANGLE_SOLVE_API_KEY?process.env.TANGLE_SOLVE_API_KEY:dn(Fn(`solve`,t)).value)}function nr(e,t){let n=Fn(`sandbox`,t);return e?`flag`:process.env.TANGLE_API_KEY_FILE||process.env.TANGLE_API_KEY?`env`:dn(n).source}function rr(e,t){return e?`flag`:process.env.TANGLE_SOLVE_API_KEY?`env`:dn(Fn(`solve`,t)).source}function ir(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=Vn(t),i=zn(),a=pr(r,i);return a.baseUrl?a.baseUrl:(r===Nn||r===`sandbox`)&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function ar(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function or(e){return e?.trim().replace(/\/+$/,``)||void 0}function sr(e){return or(e?.flag)??or(ar(or(process.env.TANGLE_HUB_URL)))??or(process.env.TANGLE_PLATFORM_URL)??or(e?.cachedPlatformUrl?.())??jn}function cr(e){let t=or(e)??or(process.env.TANGLE_SOLVE_API_URL);if(t&&t!==Mn)throw Error(`Solve credentials may only be sent to ${Mn}`);return Mn}function lr(e){let t=or(e);if(t&&t!==jn)throw Error(`Solve credentials may only be sent to ${jn}`);return jn}function V(e){let t=Fn(`sandbox`,e.profile),n=er(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===Nn?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:ir(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...ur(t)}}function ur(e){let t=zn(),n=pr(Vn(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function dr(e,t){Zn(Vn(t),{activeTeamId:e.id,activeTeamName:e.name})}function fr(e){let t=Vn(e),n=zn(),r={...n.profiles??{}},i={baseUrl:pr(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],Bn({profiles:r})}function pr(e,t=zn()){let n=hr(e);return{...n===Nn?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[Nn]?.activeTeamId,activeTeamName:t.profiles?.[Nn]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function mr(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 hr(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 gr=null,_r=null;function H(e){if(!e&&gr)return gr;let t=e??V({});return(!gr||!_r||_r.apiKey!==t.apiKey||_r.baseUrl!==t.baseUrl||_r.timeout!==t.timeout)&&(gr=new l({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),_r=t),gr}function vr(){gr=null,_r=null}function U(e){let t=V({apiKey:e.apiKey,baseUrl:e.baseUrl});return{context:t,client:H(t)}}async function yr(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 br(r,n)}function br(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(xr(t,s))}function xr(e,t){let n=t.map(e=>`- ${e.id} (provider: ${e.providerId}, account: ${e.accountDisplay??e.displayName})`).join(`
|
|
1
|
+
import{createRequire as e,findPackageJSON as t}from"node:module";import"dotenv/config";import{ALL_BACKEND_TYPES as n,AuthError as r,GPU_LEASE_PROVIDER_NAMES as i,NetworkError as a,NotFoundError as o,PublicTemplatePublishError as s,QuotaError as c,Sandbox as l,ServerError as u,StateError as d,TimeoutError as f,ValidationError as p,createAgentRunOutcomeTracker as m,createBatchResultAccumulator as h,createConfidentialSandbox as g,generateAttestationNonce as _,parseBackendType as ee,parseSSEStream as te,validateBatchRunRequest as v}from"@tangle-network/sandbox";import y from"chalk";import ne from"ora";import{Command as b}from"commander";import{createHash as re,randomBytes as ie,randomUUID as x}from"node:crypto";import{ProxySecretsSchema as S,agentInteractiveSessionRunRef as ae,agentProfileSchema as C,canonicalAgentProfileDigest as oe,canonicalCandidateDigest as se,modelProvider as ce,parseSeatSpec as le}from"@tangle-network/agent-interface";import*as w from"node:fs";import{chmodSync as ue,constants as de,existsSync as fe,mkdirSync as pe,readFileSync as T,renameSync as me,writeFileSync as he}from"node:fs";import*as E from"node:path";import{basename as ge,dirname as _e,extname as ve,isAbsolute as ye,join as D,relative as be,resolve as xe,sep as Se}from"node:path";import*as Ce from"node:os";import{homedir as O,tmpdir as we}from"node:os";import{execFile as Te,execFileSync as Ee,spawn as De}from"node:child_process";import{lockSync as Oe}from"proper-lockfile";import{HubClient as ke}from"@tangle-network/hub-sdk";import{createInterface as Ae}from"node:readline";import{Writable as je}from"node:stream";import{buffer as Me}from"node:stream/consumers";import{setTimeout as Ne}from"node:timers/promises";import{CONTENT_COMPLETION_KEY as Pe,CONTENT_PROMPT_KEY as Fe,CONTENT_TOOL_ARGS_KEY as Ie,CONTENT_TOOL_NAME_KEY as Le,CONTENT_TOOL_RESULT_KEY as Re,TANGLE_SUBJECT_KEY as ze,asContentField as k,asContentString as Be}from"@tangle-network/agent-core/telemetry";import{execCli as Ve,shellQuote as He}from"@tangle-network/sdk-cli-runner";import*as A from"node:fs/promises";import{mkdir as Ue,mkdtemp as We,open as Ge,readFile as Ke,realpath as qe,writeFile as Je}from"node:fs/promises";import{z as j}from"zod";import{listLocalModels as Ye,loadConfig as Xe}from"cli-bridge";import{createMcpServer as Ze}from"@tangle-network/sandbox/agent";import{ensureAgentPreview as Qe,publishAgentPreview as $e,resolveSelfSandbox as et}from"@tangle-network/sandbox/preview";import{fileURLToPath as tt}from"node:url";import{generatePrivateKey as nt,privateKeyToAccount as rt}from"viem/accounts";import{promisify as it}from"node:util";import{createPublicClient as at,createWalletClient as ot,decodeAbiParameters as st,decodeEventLog as ct,encodeAbiParameters as lt,getAddress as ut,http as dt,isAddress as ft,keccak256 as pt,parseAbi as mt,parseAbiItem as ht,parseAbiParameters as gt,stringToHex as _t,toHex as vt}from"viem";import{tempoModerato as yt}from"viem/chains";import{Actions as bt,withRelay as xt}from"viem/tempo";import St from"ws";import{createIntelligenceClient as Ct}from"@tangle-network/sandbox/intelligence";let wt=!1;function Tt(e){wt=e}function Et(...e){wt?console.error(...e):console.log(...e)}function Dt(e){return e==null?y.dim(`-`):typeof e==`boolean`?e?y.green(`yes`):y.red(`no`):e instanceof Date?kt(e):typeof e==`string`&&Ot(e)?kt(new Date(e)):String(e)}function Ot(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function kt(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 y.green(e);case`pending`:case`provisioning`:return y.yellow(e);case`stopped`:return y.gray(e);case`failed`:case`deleted`:return y.red(e);default:return e}}function M(e,t){let n=t.map(t=>{let n=t.header.length,r=Math.max(...e.map(e=>Dt(e[t.key]).length));return t.width??Math.max(n,r)+2}),r=e.map(e=>t.map(t=>t.key===`status`?At(String(e[t.key])):Dt(e[t.key])));Lt(t.map(e=>e.header),r,n)}function N(e){console.log(JSON.stringify(e,null,2))}function P(e){Et(y.green(`✓`),e)}function jt(e){console.error(y.red(`✗`),e)}function Mt(e){Et(y.yellow(`!`),e)}function F(e){Et(y.blue(`→`),e)}const Nt=new Set;function I(e){let t=ne({text:e,color:`cyan`,isSilent:wt});return Nt.add(t),t}function Pt(){for(let e of Nt)e.isSpinning&&e.stop();Nt.clear()}function L(e,t=0){let n=` `.repeat(t);for(let[t,r]of Object.entries(e))r!=null&&console.log(`${n}${y.dim(`${t}:`)} ${Dt(r)}`)}function Ft(e){let t=`${e.cpuCores} vCPU / ${e.memoryMB} MB / ${e.diskGB} GB`;return e.pool?`${t} (pool: ${e.pool})`:t}function It(e){if(console.log(),console.log(y.bold(`Sandbox Details`)),console.log(y.dim(`─`.repeat(40))),L({ID:e.id,Name:e.name,Status:At(e.status),Resources:e.resources?Ft(e.resources):void 0,Created:e.createdAt,Expires:e.expiresAt}),e.connection){if(console.log(),console.log(y.bold(`Connection`)),console.log(y.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}`;L({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&L({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&L({"API URL":e.connection.runtimeUrl})}console.log()}function Lt(e,t,n){if(t.length===0){console.log(y.dim(`No items found.`));return}let r=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)=>y.bold(e.padEnd(r[t]))).join(``));for(let e of t)console.log(e.map((e,t)=>String(e??``).padEnd(r[t])).join(``))}var R=class extends Error{constructor(e,t,n,r){super(t),this.code=e,this.cause=n,this.fix=r,this.name=`ActionableCliError`}};const Rt=new Set([`AUTH_EXPIRED`,`AUTH_WRONG_AUDIENCE`,`SEAT_NONE_DETECTED`,`SEAT_NOT_LOGGED_IN`,`SEAT_NOT_ENROLLED`,`HUB_NOT_CONNECTED`,`HUB_RECONNECT`,`HUB_APP_NOT_INSTALLED`,`HUB_APPROVAL_REQUIRED`]),zt=new Set([`GRAPH_INVALID`,`STEP_REF`,`PROFILE_INVALID`,`UNKNOWN_HARNESS`,`HUB_TOOL_UNKNOWN`,`TRIGGER_INVALID`,`WORKFLOW_INPUT_FILE_INVALID`,`VALIDATION_ERROR`]),Bt=new Set([`UNKNOWN_COMMAND`,`GRAPH_PARAM_MISSING`,`GRAPH_PARAM_UNKNOWN`,`SEAT_SYNTAX`,`HUB_PROVIDER_UNKNOWN`,`USAGE_INVALID`]),Vt=new Set([`SUBSCRIPTION_REQUIRED`,`MODEL_NOT_FOUND`,`MODEL_PROVIDER_MISMATCH`,`MCP_BLOCKED`,`CLOUD_SEAT_UNSUPPORTED`,`SCHEDULE_AUTHORITY`]);function Ht(e){return typeof e==`object`&&e?e:{}}function z(e){return typeof e==`string`&&e.length>0?e:void 0}function Ut(e){let t=z(e);return t&&/^[a-z0-9][a-z0-9_-]*$/i.test(t)?t:void 0}function Wt(e){let t,n=e;for(let e=0;n instanceof Error&&e<5;e++,n=n.cause){let e=n.message||(n instanceof AggregateError?n.errors.map(e=>e instanceof Error?e.message:String(e)).join(`; `):``),r=z(Ht(n).code);(e||r)&&(t=r?`${r}${e?`: ${e}`:``}`:e)}return t}function Gt(e){return e.code===`credential-refused`&&e.owner===`caller`&&e.providerCode===`subscription_required`?Ht(e.remediation):{}}function Kt(e){let t=Ht(e),n=Array.isArray(t.runtimeFailures)?t.runtimeFailures.map(Ht):[],i=n.find(e=>z(Gt(Ht(e.failure)).fix))??n[0],l=Ht(i?.failure??t.runtimeFailure),u=Gt(l),m=Ht(t.details),h=Ut(t.provider??m.provider??m.providerId),g=Ht(t.fix??m.fix),_=z(t.code)??`CLI_ERROR`,ee=z(t.message)??String(e),te=z(l.cause)??z(t.cause)??z(m.reason)??ee,v=`tangle --help`,y=typeof m.providerRetryable==`boolean`?m.providerRetryable:typeof t.retryable==`boolean`?t.retryable:null;if(e instanceof r||_===`HUB_UNAUTHENTICATED`||t.status===401)_=`AUTH_EXPIRED`,ee=`Authentication failed`,v=`tangle auth login`;else if([`HUB_CONNECTION_MISSING`,`HUB_CONNECTION_REVOKED`,`HUB_CONNECTION_UNHEALTHY`,`HUB_RECONNECT_REQUIRED`,`CONNECTION_REQUIRED`].includes(_))_=[`HUB_CONNECTION_MISSING`,`CONNECTION_REQUIRED`].includes(_)?`HUB_NOT_CONNECTED`:`HUB_RECONNECT`,v=h?`tangle hub connect ${h}`:`tangle hub connections --json`;else if(_===`HUB_APPROVAL_REQUIRED`){let e=Ut(Ht(m.approval).id);v=e?`tangle hub approvals approve ${e}`:`tangle hub approvals list --json`}else _===`HUB_PROVIDER_REJECTED`?(v=`tangle hub status --json`,m.providerRetryable===!1&&(te+=`. Change the request before retrying`)):_===`provider_quota_exhausted`||_===`SEAT_LIMIT`?(_=`SEAT_LIMIT`,v=`tangle auth status`,y=!0):e instanceof c?v=`tangle usage --json`:e instanceof a?(_=`NETWORK_UNAVAILABLE`,ee=`Network error: ${ee}`,te=Wt(e.cause)??`No response arrived`,v=`tangle auth status --json`,y=!0):e instanceof f?(_=`TIMEOUT`,v=`tangle sandbox list --json`,y=!0):e instanceof p?(_=`VALIDATION_ERROR`,ee=`Invalid input`):e instanceof o||e instanceof d?v=`tangle sandbox list --json`:_===`commander.unknownCommand`?(_=`UNKNOWN_COMMAND`,v=ee.includes(`'graph'`)?`npm install -g @tangle-network/sandbox-cli@latest`:`tangle --help`):_.startsWith(`commander.`)?_=`USAGE_INVALID`:(_===`ENOENT`||_===`EACCES`)&&(_=`INPUT_UNAVAILABLE`);e instanceof R&&(v=e.fix,y=!1),z(u.fix)&&(_=u.cause===`not_authenticated`?`SEAT_NOT_LOGGED_IN`:`SUBSCRIPTION_REQUIRED`),e instanceof s&&v===`tangle --help`&&(v=`tangle template publish --help`),v=z(u.fix)??z(g.command)??(_===`HUB_NOT_CONNECTED`?void 0:z(t.fixCommand))??v,Rt.has(_)&&v===`tangle --help`&&(v=`tangle auth login`);let ne=Ht(t.subject??m.subject??{node:i?.node??t.node,seat:t.seat??u.harness}),b=z(t.resumeAt??m.resumeAt??m.resetAt);return{code:_,subject:{...z(ne.node)?{node:String(ne.node)}:{},...z(ne.seat)?{seat:String(ne.seat)}:{}},what:ee,cause:te,fix:{command:v,...Array.isArray(g.alternatives)&&g.alternatives.every(e=>typeof e==`string`)?{alternatives:g.alternatives}:{},...g.edit===void 0?{}:{edit:g.edit},...z(g.url)?{url:String(g.url)}:{}},retryable:y,...b&&Number.isFinite(Date.parse(b))?{resumeAt:b}:{},...z(t.runId)?{runId:String(t.runId)}:{},...z(t.requestId)?{requestId:String(t.requestId)}:{},...typeof t.status==`number`?{status:t.status}:{},...z(l.code)&&z(l.owner)?{runtimeFailure:{code:String(l.code),owner:String(l.owner),cause:typeof l.cause==`string`?l.cause:te,...z(l.providerCode)?{providerCode:String(l.providerCode)}:{},...typeof l.providerStatus==`number`?{providerStatus:l.providerStatus}:{},...typeof l.retryAfterMs==`number`?{retryAfterMs:l.retryAfterMs}:{},...Object.keys(u).length?{remediation:u}:{}}}:{},...e instanceof s&&e.job?{job:e.job}:{}}}function qt(e){let t=[e.subject.node&&`node ${e.subject.node}`,e.subject.seat].filter(Boolean).join(` · `);return`✗ ${`${t?`${t}: `:``}${e.what}${e.status?` (HTTP ${e.status})`:``}`}${e.cause===e.what?``:` — ${e.cause}`}\n → run: ${e.fix.command}`+(e.runtimeFailure?`\n runtime: ${e.runtimeFailure.code} · ${e.runtimeFailure.owner}${e.runtimeFailure.providerCode?` · ${e.runtimeFailure.providerCode}`:``}${e.runtimeFailure.providerStatus===void 0?``:` · HTTP ${e.runtimeFailure.providerStatus}`}${e.runtimeFailure.retryAfterMs===void 0?``:` · retry-after ${e.runtimeFailure.retryAfterMs} ms`}`:``)+(e.fix.alternatives?.map(e=>`\n or: ${e}`).join(``)??``)+(e.resumeAt?`\n resumes ${e.resumeAt}${e.subject.seat?` on ${e.subject.seat}`:``}`:``)}function Jt(e){return qt(Kt(e))}function B(e,t=!1){Pt();let n=Kt(e);t?N({ok:!1,error:n}):console.error(y.red(qt(n)));let r=1;Rt.has(n.code)?r=77:zt.has(n.code)?r=65:Bt.has(n.code)?r=64:Vt.has(n.code)?r=78:[`SEAT_LIMIT`,`RATE_LIMITED`].includes(n.code)?r=75:[`HARNESS_NOT_INSTALLED`,`MCP_UNREACHABLE`,`NETWORK_UNAVAILABLE`].includes(n.code)?r=69:n.code===`RUN_STOPPED`&&(r=130),process.exit(r)}function Yt(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:ge(a)}}let t;try{t=T(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:ge(e),content:t}}function Xt(e){let t=(e.skills??[]).map(Yt),n=(e.tools??[]).map(Yt),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 Zt(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 $t(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await $t(e):T(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw new R(`PROFILE_INVALID`,`Profile '${e}' is invalid`,`Expected a JSON AgentProfile`,`tangle agent profile create --name my-agent --json`)}return Qt(n,e)}function Qt(e,t){let n=C.safeParse(e);if(!n.success)throw new R(`PROFILE_INVALID`,`Profile '${t}' is invalid`,n.error.issues.map(e=>`${e.path.join(`.`)||`(root)`}: ${e.message}`).join(`; `),`tangle agent profile create --name my-agent --json`);return e}async function $t(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function en(e){let t=e.profileSource?await Zt(e.profileSource):void 0,n=Xt(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const tn=E.join(Ce.homedir(),`.tangle`),nn=E.join(tn,`credentials.json`),rn=`tangle-sandbox-cli`,an=new Int32Array(new SharedArrayBuffer(4)),on=`TANGLE_ALLOW_PLAINTEXT_CREDENTIALS`;var sn=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)}},cn=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 ${on}=1 to opt into a plaintext credentials.json with mode 0600.`),this.name=`KeychainUnavailableError`}},ln=class extends Error{constructor(e){super(`Credential storage preflight failed: ${e}`),this.name=`CredentialStorageProbeError`}},un=class extends Error{constructor(e){super(`Credential storage is busy. Wait a moment and retry.`),this.name=`CredentialsFileLockedError`,e&&(this.cause=e)}};function dn(e){let t=_n(e);if(t)return{value:t,source:`keychain`};let n=bn(e);return n?{value:n,source:`file`}:{source:`none`}}function fn(e,t){if(vn(e,t))return Sn(e),`keychain`;if(!hn())throw new cn;return xn(e,t),`file`}function pn(){let e=`credential-write-probe:${process.pid}:${x()}`,t=x();if(vn(e,t)){let n=_n(e);if(!yn(e))throw new ln(`the OS keychain accepted a test credential but the CLI could not remove it`);if(n!==t)throw new ln(`the OS keychain accepted a test credential but the CLI could not read it back`);return`keychain`}if(!hn())throw new cn;return En(e),`file`}function mn(e){yn(e),Sn(e)}function hn(){let e=process.env[on];if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function gn(e,t){let n=process.platform;if(n!==`darwin`&&n!==`linux`)return;let r=n===`darwin`?`security`:`secret-tool`;try{return Ee(r,e[n],{encoding:`utf8`,input:t,stdio:[t===void 0?`ignore`:`pipe`,`pipe`,`ignore`],timeout:n===`linux`?1e4:void 0}).trim()}catch{return}}function _n(e){let t=On(e);return gn({darwin:[`find-generic-password`,`-s`,rn,`-a`,t,`-w`],linux:[`lookup`,`service`,rn,`account`,t]})}function vn(e,t){let n=On(e),r=[`add-generic-password`,`-U`,`-s`,rn,`-a`],i=[`store`,`--label=Tangle Sandbox CLI`,`service`];return gn({darwin:[...r,n,`-w`,t],linux:[...i,rn,`account`,n]},process.platform===`linux`?t:void 0)!==void 0}function yn(e){let t=On(e);return gn({darwin:[`delete-generic-password`,`-s`,rn,`-a`,t],linux:[`clear`,`service`,rn,`account`,t]})!==void 0}function bn(e){return wn()[e]}function xn(e,t){Cn(()=>{let n=wn();n[e]=t,Tn(n)})}function Sn(e){return Cn(()=>{let t;try{t=wn()}catch(e){if(e instanceof sn)return!1;throw e}return e in t?(delete t[e],Tn(t),bn(e)===void 0):!0})}function Cn(e){Dn();let t=Date.now()+2e3,n,r;for(;!n;)try{n=Oe(nn,{realpath:!1,stale:5e3})}catch(e){if(r=e instanceof Error?e:void 0,!e||typeof e!=`object`||!(`code`in e)||e.code!==`ELOCKED`)throw e;if(Date.now()>=t)throw new un(r);Atomics.wait(an,0,0,20)}try{return e()}finally{n()}}function wn(){let e;try{e=w.readFileSync(nn,`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 sn(nn);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof sn?e:new sn(nn,e instanceof Error?e:void 0)}}function Tn(e){if(Dn(),Object.keys(e).length===0){w.existsSync(nn)&&w.unlinkSync(nn);return}let t=`${nn}.${process.pid}.tmp`;w.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),w.renameSync(t,nn)}function En(e){let t=x(),n=!1,r;try{if(xn(e,t),n=!0,bn(e)!==t)throw new ln(`the credentials file did not return the value just written`)}catch(e){r=e}finally{if(n)try{!Sn(e)&&!r&&(r=new ln(`the credentials file accepted a test credential but the CLI could not remove it`))}catch(e){r??=e}}if(r)throw r}function Dn(){if(!w.existsSync(tn)){w.mkdirSync(tn,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(w.statSync(tn).mode&511)!=448&&w.chmodSync(tn,448)}catch{}}function On(e){return`profile:${e}`}const kn=E.join(Ce.homedir(),`.tangle`),An=E.join(kn,`config.json`),jn=`https://id.tangle.tools`,Mn=`https://solve.tangle.tools/api/solve`,Nn=`default`;function Pn(){return{tangleBaseUrl:process.env.TANGLE_BASE_URL,sandboxBaseUrl:process.env.SANDBOX_BASE_URL,hubUrl:process.env.TANGLE_HUB_URL}}function Fn(e,t){let n=Vn(t??(e===`solve`?`solve`:void 0));if(e===`solve`){if(n!==`solve`)throw Error(`The solve app cannot use profile '${n}'. Use the reserved 'solve' profile.`);return n}if(e===`sandbox`&&!t&&n===`solve`)return Nn;if(new Set([`solve`]).has(n))throw Error(`The ${e} app cannot use the reserved '${n}' profile. Use the '${e}' profile or choose a custom profile.`);return n}function In(){w.existsSync(kn)||w.mkdirSync(kn,{mode:448,recursive:!0})}function Ln(e,t){In();let n=`${e}.${process.pid}.tmp`;w.writeFileSync(n,t,{mode:384}),w.renameSync(n,e)}function Rn(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function zn(){try{if(w.existsSync(An))return JSON.parse(w.readFileSync(An,`utf-8`))}catch{}return{}}function Bn(e){let t=mr(zn(),e);Ln(An,`${JSON.stringify(t,null,2)}\n`)}function Vn(e){return hr(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||zn().activeProfile||Nn)}function Hn(e){Bn({activeProfile:hr(e)})}function Un(){return{token:process.env.TANGLE_LINE_TOKEN,baseUrl:process.env.TANGLE_HUB_URL}}function Wn(){return process.env.TANGLE_SANDBOX||zn().currentSandbox||void 0}function Gn(e){Bn({currentSandbox:e})}function Kn(){let e=zn();delete e.currentSandbox,Ln(An,`${JSON.stringify(e,null,2)}\n`)}function qn(){let e=zn().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=Ce.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=ie(4).toString(`hex`),r=`${t?`${t}-`:`device-`}${n}`;return Bn({deviceId:r}),r}function Jn(e){let t=e||Wn();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 Yn(){let e=zn(),t=Vn(),n=new Set([Nn,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(hr(e.activeProfile)),[...n].map(e=>{let n=dn(e).source;return{name:e,active:e===t,hasApiKey:n!==`none`,baseUrl:ir(void 0,e),apiKeySource:n}}).sort((e,t)=>e.name.localeCompare(t.name))}function Xn(e){let t=Vn(e);return{name:t,active:t===Vn(),baseUrl:ir(void 0,t),credentialSource:dn(t).source}}function Zn(e,t){let n=hr(e),r=zn(),i=pr(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=fn(n,t.apiKey)),Bn({profiles:Object.keys(l).length>0?l:{}}),u}function Qn(e){let t=Vn(e),n={...zn().profiles??{}},r=n[t];if(r){let e={...r};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}Bn({profiles:n}),mn(t)}function $n(){let e=process.env.TANGLE_API_KEY_FILE;if(e){let t=w.readFileSync(e,`utf8`).trim();if(!t.startsWith(`sk-tan-`))throw Error(`Invalid sandbox credential file`);return t}return process.env.TANGLE_API_KEY}function er(e,t){let n=Fn(`sandbox`,t);return e||$n()||dn(n).value}function tr(e,t){return e||(process.env.TANGLE_SOLVE_API_KEY?process.env.TANGLE_SOLVE_API_KEY:dn(Fn(`solve`,t)).value)}function nr(e,t){let n=Fn(`sandbox`,t);return e?`flag`:process.env.TANGLE_API_KEY_FILE||process.env.TANGLE_API_KEY?`env`:dn(n).source}function rr(e,t){return e?`flag`:process.env.TANGLE_SOLVE_API_KEY?`env`:dn(Fn(`solve`,t)).source}function ir(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=Vn(t),i=zn(),a=pr(r,i);return a.baseUrl?a.baseUrl:(r===Nn||r===`sandbox`)&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function ar(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function or(e){return e?.trim().replace(/\/+$/,``)||void 0}function sr(e){return or(e?.flag)??or(ar(or(process.env.TANGLE_HUB_URL)))??or(process.env.TANGLE_PLATFORM_URL)??or(e?.cachedPlatformUrl?.())??jn}function cr(e){let t=or(e)??or(process.env.TANGLE_SOLVE_API_URL);if(t&&t!==Mn)throw Error(`Solve credentials may only be sent to ${Mn}`);return Mn}function lr(e){let t=or(e);if(t&&t!==jn)throw Error(`Solve credentials may only be sent to ${jn}`);return jn}function V(e){let t=Fn(`sandbox`,e.profile),n=er(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===Nn?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:ir(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...ur(t)}}function ur(e){let t=zn(),n=pr(Vn(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function dr(e,t){Zn(Vn(t),{activeTeamId:e.id,activeTeamName:e.name})}function fr(e){let t=Vn(e),n=zn(),r={...n.profiles??{}},i={baseUrl:pr(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],Bn({profiles:r})}function pr(e,t=zn()){let n=hr(e);return{...n===Nn?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[Nn]?.activeTeamId,activeTeamName:t.profiles?.[Nn]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function mr(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 hr(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 gr=null,_r=null;function H(e){if(!e&&gr)return gr;let t=e??V({});return(!gr||!_r||_r.apiKey!==t.apiKey||_r.baseUrl!==t.baseUrl||_r.timeout!==t.timeout)&&(gr=new l({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),_r=t),gr}function vr(){gr=null,_r=null}function U(e){let t=V({apiKey:e.apiKey,baseUrl:e.baseUrl});return{context:t,client:H(t)}}async function yr(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 br(r,n)}function br(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(xr(t,s))}function xr(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 Sr(e,t){return[...t,e]}async function Cr(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:`${br(r,e.ref)}:${e.tail}`)}function wr(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 Tr(e,t){return re(`sha256`).update(`${e}\0${t}`).digest(`hex`).slice(0,32)}function Er(e){return`${e}:hub`}function Dr(e){let{value:t}=dn(Er(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 Or(e,t){try{fn(Er(e),JSON.stringify(t))}catch{}}async function kr(e,t,n,r){let i=`${e.replace(/\/+$/,``)}/auth/cli/hub-key`,a;try{a=await fetch(i,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${t}`},body:JSON.stringify({device_id:n}),signal:r})}catch(e){throw Error(`Could not reach ${i} to mint a platform key: ${e instanceof Error?e.message:String(e)}`)}let o=await a.text(),s;try{s=JSON.parse(o)}catch{s=null}if(!a.ok||!s?.success){let e=typeof s?.error?.message==`string`?s.error.message:`HTTP ${a.status}`;throw Error(`Platform key minting failed: ${e}. Your sandbox session may have expired — run \`tangle auth login\`.`)}let c=s.data;if(typeof c?.api_key!=`string`||typeof c?.expires_at!=`string`||typeof c?.platform_url!=`string`)throw Error(`Platform key minting returned an unexpected response shape.`);return{key:c.api_key,expiresAt:c.expires_at,platformUrl:c.platform_url}}var Ar=class{cache;fingerprint;constructor(e,t,n,r,i){this.profile=e,this.sandboxBaseUrl=t,this.sessionToken=n,this.deviceId=r,this.signal=i,this.fingerprint=Tr(t,n);let a=Dr(e);this.cache=a&&a.sessionFingerprint===this.fingerprint?a:null}isFresh(e){return e!==null&&Date.parse(e.expiresAt)-Date.now()>6e4}async ensure(e=!1){if(this.signal?.throwIfAborted(),!e&&this.isFresh(this.cache))return this.cache;let t={...await kr(this.sandboxBaseUrl,this.sessionToken,this.deviceId,this.signal),sessionFingerprint:this.fingerprint};return this.cache=t,Or(this.profile,t),t}};function jr(e){if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function Mr(e,t){return sr({flag:e.baseUrl,...e.useCachedPlatformUrl?{cachedPlatformUrl:()=>Dr(t)?.platformUrl}:{}})}function Nr(e,t){let n=Fn(`sandbox`,e.profile),r=er(e.apiKey,n),i=nr(e.apiKey,n),a=e.allowHubCapabilityToken&&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`);let o=i===`flag`&&r?r:a??r;if(!o)throw Error(`No API key found for profile '${n}'. Set TANGLE_API_KEY or run: tangle auth login${n===`default`?``:` --profile ${n}`}`);return(i===`flag`||i===`env`)&&r||a||o.startsWith(`sk-tan-`)||t?{kind:`static`,apiKey:o,baseUrl:Mr(e,n)}:{kind:`managed`,profile:n,sandboxBaseUrl:ir(e.sandboxBaseUrl,n),sessionToken:o,deviceId:qn(),baseUrlOverride:e.baseUrl}}async function Pr(e={}){let t=Nr(e,e.hubKey===!1||jr(process.env.TANGLE_SKIP_HUB_KEY));if(t.kind===`static`)return{token:t.apiKey,baseUrl:t.baseUrl,minted:!1};let n=new Ar(t.profile,t.sandboxBaseUrl,t.sessionToken,t.deviceId,e.signal),r=await n.ensure();return{token:r.key,baseUrl:t.baseUrlOverride??r.platformUrl,refresh:async()=>(await n.ensure(!0)).key,minted:!0}}async function Fr(e,t,n={}){let r=e=>{let r=new Headers(n.headers);return r.set(`Authorization`,`Bearer ${e}`),fetch(t,{...n,headers:r})},i=await r(e.token);return i.status!==401||!e.refresh?i:r(await e.refresh())}async function Ir(e={}){let t;try{t=await Pr(e)}catch(e){return{reachable:!1,reason:e instanceof Error?e.message:String(e),refused:!0}}try{let e=await Fr(t,`${t.baseUrl.replace(/\/+$/,``)}/v1/plans/current`);if(e.ok)return{reachable:!0,baseUrl:t.baseUrl};let n=e.status===401||e.status===403;return{reachable:!1,baseUrl:t.baseUrl,reason:n?`the platform refused this credential (HTTP ${e.status})`:`the platform answered HTTP ${e.status}`,refused:n}}catch(e){return{reachable:!1,baseUrl:t.baseUrl,reason:`could not reach ${t.baseUrl}: ${e instanceof Error?e.message:String(e)}`,refused:!1}}}async function Lr(e){let t=e.signal,n=t?(e,n)=>{let r=n?.signal??(e instanceof Request?e.signal:void 0);return fetch(e,{...n,signal:r?AbortSignal.any([r,t]):t})}:fetch.bind(globalThis),r=Nr(e,e.hubKey===!1||jr(process.env.TANGLE_SKIP_HUB_KEY));if(r.kind===`static`){let t=!e.apiKey&&process.env.TANGLE_API_KEY_FILE&&!process.env.TANGLE_HUB_CAPABILITY_TOKEN;return new ke({baseUrl:r.baseUrl,fetch:n,authHeaders:()=>({Authorization:`Bearer ${t?$n():r.apiKey}`})})}let i=new Ar(r.profile,r.sandboxBaseUrl,r.sessionToken,r.deviceId,e.signal),a=await i.ensure();return new ke({baseUrl:r.baseUrlOverride??a.platformUrl,authHeaders:async()=>({Authorization:`Bearer ${(await i.ensure()).key}`}),fetch:async(e,t)=>{let r=await n(e,t);if(r.status!==401)return r;let a=await i.ensure(!0),o=new Headers(t?.headers);return o.set(`Authorization`,`Bearer ${a.key}`),n(e,{...t,headers:o})}})}function Rr(e={}){return Lr(e)}function W(e={}){return Lr({...e,useCachedPlatformUrl:!0,allowHubCapabilityToken:!0})}function zr(e,t){return`Sandbox name is ambiguous: ${e}. Use a sandbox id instead.\n${t.map(e=>`- ${e.id} (status: ${e.status}, created: ${e.createdAt.toISOString()})`).join(`
|
|
4
4
|
`)}`}function Br(e){return e.activeTeamId?`team:${e.activeTeamId}`:void 0}async function G(e,t,n,r={}){if(!r.nameOnly){let t=await e.get(n);if(t)return t;if(Hr(n))throw Error(`Sandbox not found: ${n}`)}let i=(await e.list({scope:Br(t)})).filter(e=>e.name?.toLowerCase()===n.toLowerCase());if(i.length===0)throw Error(`Sandbox not found: ${n}`);if(i.length>1)throw Error(zr(n,i));return i[0]}const Vr=/^sandbox-(?:(?:(?:[a-z][a-z0-9-]*)-)?(?:[a-f0-9]{12}|[a-f0-9]{8}-[a-f0-9]{3})|l[0-9a-z]{1,8}-[0-9a-f]{8})(?:-branch-[a-z0-9]+-[0-9]+)*$/;function Hr(e){return Vr.test(e)}async function Ur(e,t,n,r={}){try{return(await(await G(e,t,n,{nameOnly:r.name})).delete()).outcome}catch(e){if(!(e instanceof Error&&e.message===`Sandbox not found: ${n}`)||r.name||!r.retryCleanup&&!Hr(n))throw e}let i=await e.fetch(`/v1/sandboxes/${encodeURIComponent(n)}`,{method:`DELETE`});if(i.ok){let e=await i.json().catch(()=>({}));return e.outcome===`destroyed`||e.outcome===`already_absent`?e.outcome:`unknown`}let a=(await i.text()).trim();throw Error(`Sandbox cleanup failed for ${n} (HTTP ${i.status})${a?`: ${a}`:``}`)}async function K(e,t){if(e.status!==`stopped`)return e;let n=t?.resumeTimeoutMs??12e4;F(`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 Wr=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function Gr(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.21.
|
|
3
|
+
"version": "0.21.85",
|
|
4
4
|
"description": "CLI for Tangle Sandbox operations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@tangle-network/agent-interface": "^5.10.13",
|
|
25
25
|
"@tangle-network/agent-runtime": "^3.0.1",
|
|
26
26
|
"@tangle-network/hub-sdk": "1.0.15",
|
|
27
|
-
"@tangle-network/sandbox": "^1.0.
|
|
27
|
+
"@tangle-network/sandbox": "^1.0.198",
|
|
28
28
|
"@tangle-network/sdk-cli-runner": "^0.3.6",
|
|
29
29
|
"chalk": "^5.6.2",
|
|
30
30
|
"cli-bridge": "https://github.com/drewstone/cli-bridge/archive/f0e7a3292f6f4293107c17d069b2a659a1cde720.tar.gz",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"author": "Tangle Network",
|
|
68
68
|
"license": "MIT",
|
|
69
69
|
"tangleRelease": {
|
|
70
|
-
"sourceSha": "
|
|
71
|
-
"mergedAt": "2026-11-
|
|
70
|
+
"sourceSha": "77c8906ad7fc437be7f7677d2ae0103e11227dba",
|
|
71
|
+
"mergedAt": "2026-11-02T15:56:21-08:00"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsdown",
|