@tangle-network/sandbox-cli 0.22.133 → 0.22.134

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +38 -30
  2. package/package.json +3 -3
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,p as c,r as l,s as u,t as d,u as f}from"./output-BqCeTtw4.mjs";import{i as p,n as m,r as h,t as g}from"./credential-store-Bpw_4ZTQ.mjs";import{createRequire as _,findPackageJSON as v}from"node:module";import"dotenv/config";import{ALL_BACKEND_TYPES as y,AuthError as b,InteractiveSessionNotRunningError as x,NetworkError as S,NotFoundError as C,PublicTemplatePublishError as w,QuotaError as T,SANDBOX_RUNTIMES as ee,Sandbox as E,SandboxError as D,ServerError as O,StateError as k,TimeoutError as A,ValidationError as te,createAgentRunOutcomeTracker as ne,createConfidentialSandbox as re,generateAttestationNonce as ie,parseBackendType as ae,parseSSEStream as oe,validateBatchRunRequest as se}from"@tangle-network/sandbox";import j from"chalk";import*as ce from"node:path";import{basename as le,dirname as ue,extname as de,isAbsolute as fe,join as M,posix as pe,relative as me,resolve as he,sep as ge}from"node:path";import{Command as N,Option as _e}from"commander";import{createHash as ve,randomBytes as ye,randomUUID as be}from"node:crypto";import{ProxySecretsSchema as xe,REASONING_EFFORTS as Se,agentCandidateArtifactRefSchema as Ce,agentCandidateWorkspaceSnapshotEvidenceSchema as we,agentInteractiveSessionRunRef as Te,agentProfileSchema as Ee,canonicalAgentProfileDigest as De,canonicalCandidateDigest as P,modelProvider as Oe,parseSeatSpec as ke,validateAgentProfileSecurity as Ae}from"@tangle-network/agent-interface";import*as je from"node:fs";import{chmodSync as Me,constants as Ne,existsSync as Pe,mkdirSync as Fe,readFileSync as Ie,realpathSync as Le,renameSync as Re,writeFileSync as ze}from"node:fs";import*as Be from"node:os";import{homedir as F,tmpdir as Ve}from"node:os";import{execFile as He,execFileSync as Ue,spawn as We}from"node:child_process";import{HubClient as Ge,graphMcpPolicySchema as Ke,graphMcpPolicySchema as qe,graphProfileSecurity as Je,resolveConnectionReferenceFrom as Ye,resolveConnectionReferenceFrom as Xe}from"@tangle-network/hub-sdk";import{createInterface as Ze}from"node:readline";import{Writable as Qe}from"node:stream";import{buffer as $e}from"node:stream/consumers";import{setTimeout as et}from"node:timers/promises";import{CONTENT_COMPLETION_KEY as tt,CONTENT_PROMPT_KEY as nt,CONTENT_TOOL_ARGS_KEY as rt,CONTENT_TOOL_NAME_KEY as it,CONTENT_TOOL_RESULT_KEY as at,TANGLE_SUBJECT_KEY as ot,asContentField as st,asContentString as ct}from"@tangle-network/agent-core/telemetry";import{z as I}from"zod";import{execCli as lt,shellQuote as ut}from"@tangle-network/sdk-cli-runner";import{lstat as dt,mkdir as ft,mkdtemp as pt,open as mt,readFile as L,realpath as R,rm as ht,writeFile as z}from"node:fs/promises";import{promisify as gt,stripVTControlCharacters as _t}from"node:util";import{gunzipSync as vt}from"node:zlib";import{fileURLToPath as yt,pathToFileURL as bt}from"node:url";import{ensureAgentPreview as xt,publishAgentPreview as St,resolveSelfSandbox as Ct}from"@tangle-network/sandbox/preview";import{createIntelligenceClient as wt}from"@tangle-network/sandbox/intelligence";import Tt from"node:http";import Et from"node:https";var B=class extends Error{constructor(e,t,n,r){super(t),this.code=e,this.cause=n,this.fix=r,this.name=`ActionableCliError`}};const Dt=new Set([`AUTH_EXPIRED`,`SANDBOX_CREDENTIAL_REFUSED`,`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`]),Ot=new Set([`GRAPH_INVALID`,`STEP_REF`,`PROFILE_INVALID`,`UNKNOWN_HARNESS`,`HUB_TOOL_UNKNOWN`,`TRIGGER_INVALID`,`WORKFLOW_INPUT_FILE_INVALID`,`VALIDATION_ERROR`]),kt=new Set([`UNKNOWN_COMMAND`,`GRAPH_PARAM_MISSING`,`GRAPH_PARAM_UNKNOWN`,`SEAT_SYNTAX`,`HUB_PROVIDER_UNKNOWN`,`USAGE_INVALID`]),At=new Set([`SUBSCRIPTION_REQUIRED`,`MODEL_NOT_FOUND`,`MODEL_PROVIDER_MISMATCH`,`MCP_BLOCKED`,`CLOUD_SEAT_UNSUPPORTED`,`SCHEDULE_AUTHORITY`]);function jt(e){return typeof e==`object`&&e?e:{}}function V(e){return typeof e==`string`&&e.length>0?e:void 0}function Mt(e){let t=V(e);return t&&/^[a-z0-9][a-z0-9_-]*$/i.test(t)?t:void 0}function Nt(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=V(jt(n).code);(e||r)&&(t=r?`${r}${e?`: ${e}`:``}`:e)}return t}function Pt(e){return e.code===`credential-refused`&&e.owner===`caller`&&e.providerCode===`subscription_required`?jt(e.remediation):{}}function Ft(e){let t=jt(e),n=Array.isArray(t.runtimeFailures)?t.runtimeFailures.map(jt):[],r=n.find(e=>V(Pt(jt(e.failure)).fix))??n[0],i=jt(r?.failure??t.runtimeFailure),a=Pt(i),o=jt(t.details),s=Mt(t.provider??o.provider??o.providerId),c=jt(t.fix??o.fix),l=V(t.code)??`CLI_ERROR`,u=V(t.message)??String(e),d=V(i.cause)??V(t.cause)??V(o.reason)??u,f=`tangle --help`,p=typeof o.providerRetryable==`boolean`?o.providerRetryable:typeof t.retryable==`boolean`?t.retryable:null;if(e instanceof b||l===`HUB_UNAUTHENTICATED`||t.status===401)l=`AUTH_EXPIRED`,u=`Authentication failed`,f=`tangle auth login`;else if(t.status===403&&u.startsWith(`Sandbox runtime creden`))l=`SANDBOX_CREDENTIAL_REFUSED`,u=`This sandbox's own TANGLE_API_KEY may call Hub endpoints only`,f=`export TANGLE_API_KEY=<owner or workspace sk-tan- key> (or pass --api-key), or run outside the sandbox`;else if([`HUB_CONNECTION_MISSING`,`HUB_CONNECTION_REVOKED`,`HUB_CONNECTION_UNHEALTHY`,`HUB_RECONNECT_REQUIRED`,`CONNECTION_REQUIRED`].includes(l))l=[`HUB_CONNECTION_MISSING`,`CONNECTION_REQUIRED`].includes(l)?`HUB_NOT_CONNECTED`:`HUB_RECONNECT`,f=s?`tangle hub connect ${s}`:`tangle hub connections --json`;else if(l===`HUB_APPROVAL_REQUIRED`){let e=Mt(jt(o.approval).id);f=e?`tangle hub approvals approve ${e}`:`tangle hub approvals list --json`}else l===`HUB_PROVIDER_REJECTED`?(f=`tangle hub status --json`,o.providerRetryable===!1&&(d+=`. Change the request before retrying`)):l===`provider_quota_exhausted`||l===`SEAT_LIMIT`?(l=`SEAT_LIMIT`,f=`tangle auth status`,p=!0):e instanceof T?f=`tangle usage --json`:e instanceof S?(l=`NETWORK_UNAVAILABLE`,u=`Network error: ${u}`,d=Nt(e.cause)??`No response arrived`,f=`tangle auth status --json`):e instanceof A?(l=`TIMEOUT`,f=`tangle sandbox list --json`):e instanceof te?(l=`VALIDATION_ERROR`,u=`Invalid input`):e instanceof C||e instanceof k?f=`tangle sandbox list --json`:l===`commander.unknownCommand`?(l=`UNKNOWN_COMMAND`,f=u.includes(`'graph'`)?`npm install -g @tangle-network/sandbox-cli@latest`:`tangle --help`):l.startsWith(`commander.`)?l=`USAGE_INVALID`:(l===`ENOENT`||l===`EACCES`)&&(l=`INPUT_UNAVAILABLE`);e instanceof B&&(f=e.fix,p=!1),V(a.fix)&&(l=a.cause===`not_authenticated`?`SEAT_NOT_LOGGED_IN`:`SUBSCRIPTION_REQUIRED`),e instanceof w&&f===`tangle --help`&&(f=`tangle template publish --help`),f=V(a.fix)??V(c.command)??(l===`HUB_NOT_CONNECTED`?void 0:V(t.fixCommand))??f,Dt.has(l)&&f===`tangle --help`&&(f=`tangle auth login`);let m=jt(t.subject??o.subject??{node:r?.node??t.node,seat:t.seat??a.harness}),h=e instanceof S||e instanceof Error&&`batchCustody`in e?t.batchCustody:void 0;h&&(d=`Batch acceptance: ${h.acceptance}; retirement receipt ${h.cleanup?.mode===`release`&&h.cleanup.isComplete?`proved`:`unproved`}.`,p=!1,f=`tangle batch run --help`);let g=V(t.resumeAt??o.resumeAt??o.resetAt);return{code:l,...h?{batchCustody:h}:{},catalogCode:V(t.catalogCode),message:V(t.nextStep)&&V(t.message),nextStep:V(t.nextStep),subject:{...V(m.node)?{node:String(m.node)}:{},...V(m.seat)?{seat:String(m.seat)}:{}},what:u,cause:d,fix:{command:f,...Array.isArray(c.alternatives)&&c.alternatives.every(e=>typeof e==`string`)?{alternatives:c.alternatives}:{},...c.edit===void 0?{}:{edit:c.edit},...V(c.url)?{url:String(c.url)}:{}},retryable:p,...g&&Number.isFinite(Date.parse(g))?{resumeAt:g}:{},...V(t.runId)?{runId:String(t.runId)}:{},...V(t.requestId)?{requestId:String(t.requestId)}:{},...typeof t.status==`number`?{status:t.status}:{},...V(i.code)&&V(i.owner)?{runtimeFailure:{code:String(i.code),owner:String(i.owner),cause:typeof i.cause==`string`?i.cause:d,...V(i.providerCode)?{providerCode:String(i.providerCode)}:{},...typeof i.providerStatus==`number`?{providerStatus:i.providerStatus}:{},...typeof i.retryAfterMs==`number`?{retryAfterMs:i.retryAfterMs}:{},...Object.keys(a).length?{remediation:a}:{}}}:{},...e instanceof w&&e.job?{job:e.job}:{}}}function It(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}`}${e.nextStep?`\n → next: ${e.nextStep}`:``}\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 Lt(e){return It(Ft(e))}function H(t,r=!1){n();let i=Ft(t);r?e({ok:!1,error:i}):console.error(j.red(It(i)));let a=1;Dt.has(i.code)?a=77:Ot.has(i.code)?a=65:kt.has(i.code)?a=64:At.has(i.code)?a=78:[`SEAT_LIMIT`,`RATE_LIMITED`].includes(i.code)?a=75:[`HARNESS_NOT_INSTALLED`,`MCP_UNREACHABLE`,`NETWORK_UNAVAILABLE`].includes(i.code)?a=69:i.code===`RUN_STOPPED`&&(a=130),process.exit(a)}function Rt(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:le(a)}}let t;try{t=Ie(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:le(e),content:t}}function zt(e){let t=(e.skills??[]).map(Rt),n=(e.tools??[]).map(Rt),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 Bt(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 Ht(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await Ht(e):Ie(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw new B(`PROFILE_INVALID`,`Profile '${e}' is invalid`,`Expected a JSON AgentProfile`,`tangle agent profile create --name my-agent --json`)}return Vt(n,e)}function Vt(e,t){let n=Ee.safeParse(e);if(!n.success)throw new B(`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 Ht(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function Ut(e){let t=e.profileSource?await Bt(e.profileSource):void 0,n=zt(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const Wt=ce.join(Be.homedir(),`.tangle`),Gt=ce.join(Wt,`config.json`),Kt=`https://id.tangle.tools`,qt=`https://solve.tangle.tools/api/solve`,Jt=`default`;function Yt(){return{tangleBaseUrl:process.env.TANGLE_BASE_URL,sandboxBaseUrl:process.env.SANDBOX_BASE_URL,hubUrl:process.env.TANGLE_HUB_URL}}function Xt(e,t){let n=nn(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 Jt;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 Zt(){je.existsSync(Wt)||je.mkdirSync(Wt,{mode:448,recursive:!0})}function Qt(e,t){Zt();let n=`${e}.${process.pid}.tmp`;je.writeFileSync(n,t,{mode:384}),je.renameSync(n,e)}function $t(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function en(){try{if(je.existsSync(Gt))return JSON.parse(je.readFileSync(Gt,`utf-8`))}catch{}return{}}function tn(e){let t=An(en(),e);Qt(Gt,`${JSON.stringify(t,null,2)}\n`)}function nn(e){return jn(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||en().activeProfile||Jt)}function rn(e){tn({activeProfile:jn(e)})}function an(){return{token:process.env.TANGLE_LINE_TOKEN,baseUrl:process.env.TANGLE_HUB_URL}}function on(){return process.env.TANGLE_SANDBOX||en().currentSandbox||void 0}function sn(e){tn({currentSandbox:e})}function cn(){let e=en();delete e.currentSandbox,Qt(Gt,`${JSON.stringify(e,null,2)}\n`)}function ln(){let e=en().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=Be.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=ye(4).toString(`hex`),r=`${t?`${t}-`:`device-`}${n}`;return tn({deviceId:r}),r}function un(e){let t=e||on();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 dn(){let e=en(),t=nn(),n=new Set([Jt,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(jn(e.activeProfile)),[...n].map(e=>{let n=h(e).source;return{name:e,active:e===t,hasApiKey:n!==`none`,baseUrl:bn(void 0,e),apiKeySource:n}}).sort((e,t)=>e.name.localeCompare(t.name))}function fn(e){let t=nn(e);return{name:t,active:t===nn(),baseUrl:bn(void 0,t),credentialSource:h(t).source}}function pn(e,t){let n=jn(e),r=en(),i=kn(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=p(n,t.apiKey)),tn({profiles:Object.keys(l).length>0?l:{}}),u}function mn(e){let t=nn(e),n={...en().profiles??{}},r=n[t];if(r){let e={...r};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}tn({profiles:n}),m(t)}function hn(){let e=process.env.TANGLE_API_KEY_FILE;if(e){let t=je.readFileSync(e,`utf8`).trim();if(!t.startsWith(`sk-tan-`))throw Error(`Invalid sandbox credential file`);return t}return process.env.TANGLE_API_KEY}function gn(e,t){let n=Xt(`sandbox`,t);return e||hn()||h(n).value}function _n(e,t){return e||(process.env.TANGLE_SOLVE_API_KEY?process.env.TANGLE_SOLVE_API_KEY:h(Xt(`solve`,t)).value)}function vn(e,t){let n=Xt(`sandbox`,t);return e?`flag`:process.env.TANGLE_API_KEY_FILE||process.env.TANGLE_API_KEY?`env`:h(n).source}function yn(e,t){return e?`flag`:process.env.TANGLE_SOLVE_API_KEY?`env`:h(Xt(`solve`,t)).source}function bn(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=nn(t),i=en(),a=kn(r,i);return a.baseUrl?a.baseUrl:(r===Jt||r===`sandbox`)&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function xn(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function Sn(e){return e?.trim().replace(/\/+$/,``)||void 0}function Cn(e){return Sn(e?.flag)??Sn(xn(Sn(process.env.TANGLE_HUB_URL)))??Sn(process.env.TANGLE_PLATFORM_URL)??Sn(e?.cachedPlatformUrl?.())??Kt}function wn(e){let t=Sn(e)??Sn(process.env.TANGLE_SOLVE_API_URL);if(t&&t!==qt)throw Error(`Solve credentials may only be sent to ${qt}`);return qt}function Tn(e){let t=Sn(e);if(t&&t!==Kt)throw Error(`Solve credentials may only be sent to ${Kt}`);return Kt}function U(e){let t=Xt(`sandbox`,e.profile),n=gn(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===Jt?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:bn(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...En(t)}}function En(e){let t=en(),n=kn(nn(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function Dn(e,t){pn(nn(t),{activeTeamId:e.id,activeTeamName:e.name})}function On(e){let t=nn(e),n=en(),r={...n.profiles??{}},i={baseUrl:kn(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],tn({profiles:r})}function kn(e,t=en()){let n=jn(e);return{...n===Jt?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[Jt]?.activeTeamId,activeTeamName:t.profiles?.[Jt]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function An(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 jn(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 Mn=null,Nn=null;function W(e){if(!e&&Mn)return Mn;let t=e??U({});return(!Mn||!Nn||Nn.apiKey!==t.apiKey||Nn.baseUrl!==t.baseUrl||Nn.timeout!==t.timeout)&&(Mn=new E({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),Nn=t),Mn}function Pn(){Mn=null,Nn=null}function G(e){let t=U({apiKey:e.apiKey,baseUrl:e.baseUrl});return{context:t,client:W(t)}}async function Fn(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 Ye(r,n)}function In(e,t){return[...t,e]}async function Ln(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:`${Xe(r,e.ref)}:${e.tail}`)}function Rn(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 zn(e,t){return ve(`sha256`).update(`${e}\0${t}`).digest(`hex`).slice(0,32)}function Bn(e){return`${e}:hub`}function Vn(e){let{value:t}=h(Bn(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 Hn(e,t){try{p(Bn(e),JSON.stringify(t))}catch{}}async function Un(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 Wn=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=zn(t,n);let a=Vn(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 Un(this.sandboxBaseUrl,this.sessionToken,this.deviceId,this.signal),sessionFingerprint:this.fingerprint};return this.cache=t,Hn(this.profile,t),t}};function Gn(e){if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function Kn(e,t){return Cn({flag:e.baseUrl,...e.useCachedPlatformUrl?{cachedPlatformUrl:()=>Vn(t)?.platformUrl}:{}})}function qn(e,t){let n=Xt(`sandbox`,e.profile),r=gn(e.apiKey,n),i=vn(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:Kn(e,n)}:{kind:`managed`,profile:n,sandboxBaseUrl:bn(e.sandboxBaseUrl,n),sessionToken:o,deviceId:ln(),baseUrlOverride:e.baseUrl}}async function Jn(e={}){let t=qn(e,e.hubKey===!1||Gn(process.env.TANGLE_SKIP_HUB_KEY));if(t.kind===`static`)return{token:t.apiKey,baseUrl:t.baseUrl,minted:!1};let n=new Wn(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 Yn(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 Xn(e={}){let t;try{t=await Jn(e)}catch(e){return{reachable:!1,reason:e instanceof Error?e.message:String(e),refused:!0}}try{let e=await Yn(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 Zn(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=qn(e,e.hubKey===!1||Gn(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 Ge({baseUrl:r.baseUrl,fetch:n,authHeaders:()=>({Authorization:`Bearer ${t?hn():r.apiKey}`})})}let i=new Wn(r.profile,r.sandboxBaseUrl,r.sessionToken,r.deviceId,e.signal),a=await i.ensure();return new Ge({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 Qn(e={}){return Zn(e)}function K(e={}){return Zn({...e,useCachedPlatformUrl:!0,allowHubCapabilityToken:!0})}function $n(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(`
2
- `)}`}function er(e){return e.activeTeamId?`team:${e.activeTeamId}`:void 0}async function q(e,t,n,r={}){if(!r.nameOnly){let t=await e.get(n);if(t)return t;if(nr(n))throw Error(`Sandbox not found: ${n}`)}let i=(await e.list({scope:er(t)})).filter(e=>e.name?.toLowerCase()===n.toLowerCase());if(i.length===0)throw Error(`Sandbox not found: ${n}`);if(i.length>1)throw Error($n(n,i));return i[0]}const tr=/^sandbox-(?:(?:(?:[a-z][a-z0-9-]*)-)?(?:[a-v0-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 nr(e){return tr.test(e)}async function rr(e,t,n,r={}){let i=n;try{i=(await q(e,t,n,{nameOnly:r.name})).id}catch(e){if(!(e instanceof Error&&e.message===`Sandbox not found: ${n}`)||r.name||!r.retryCleanup&&!nr(n))throw e}let a=await e.delete(i,{until:r.until}).catch(e=>{throw e instanceof D&&e.method&&e.endpoint&&(e.message=`${e.method} ${e.endpoint}: ${e.message}`),e});if(r.until===`removed`&&a.removal!==`complete`)throw Error(`Sandbox removal is unconfirmed for ${i}: ${a.removal??`unknown`}`);return a.outcome}async function J(e,t){if(e.status!==`stopped`)return e;let n=t?.resumeTimeoutMs??12e4;l(`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 ir=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function ar(e,t,n){switch(e){case`anthropic`:return`// pnpm add @anthropic-ai/sdk @tangle-network/sandbox
1
+ import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,p as c,r as l,s as u,t as d,u as f}from"./output-BqCeTtw4.mjs";import{i as p,n as m,r as h,t as g}from"./credential-store-Bpw_4ZTQ.mjs";import{createRequire as _,findPackageJSON as v}from"node:module";import"dotenv/config";import{ALL_BACKEND_TYPES as y,AuthError as b,InteractiveSessionNotRunningError as x,NetworkError as S,NotFoundError as C,PublicTemplatePublishError as w,QuotaError as T,SANDBOX_RUNTIMES as ee,Sandbox as E,SandboxError as D,ServerError as O,StateError as k,TimeoutError as A,ValidationError as te,createAgentRunOutcomeTracker as ne,createConfidentialSandbox as re,generateAttestationNonce as ie,parseBackendType as ae,parseSSEStream as oe,validateBatchRunRequest as se}from"@tangle-network/sandbox";import j from"chalk";import*as ce from"node:path";import{basename as le,dirname as ue,extname as de,isAbsolute as fe,join as M,posix as pe,relative as me,resolve as he,sep as ge}from"node:path";import{Command as N,Option as _e}from"commander";import{createHash as ve,randomBytes as ye,randomUUID as be}from"node:crypto";import{ProxySecretsSchema as xe,REASONING_EFFORTS as Se,agentCandidateArtifactRefSchema as Ce,agentCandidateWorkspaceSnapshotEvidenceSchema as we,agentInteractiveSessionRunRef as Te,agentProfileSchema as Ee,canonicalAgentProfileDigest as De,canonicalCandidateDigest as P,modelProvider as Oe,parseSeatSpec as ke,validateAgentProfileSecurity as Ae}from"@tangle-network/agent-interface";import*as je from"node:fs";import{chmodSync as Me,constants as Ne,existsSync as Pe,mkdirSync as Fe,readFileSync as Ie,realpathSync as Le,renameSync as Re,writeFileSync as ze}from"node:fs";import*as Be from"node:os";import{homedir as F,tmpdir as Ve}from"node:os";import{execFile as He,execFileSync as Ue,spawn as We}from"node:child_process";import{HubClient as Ge,graphMcpPolicySchema as Ke,graphMcpPolicySchema as qe,graphProfileSecurity as Je,resolveConnectionReferenceFrom as Ye,resolveConnectionReferenceFrom as Xe}from"@tangle-network/hub-sdk";import{createInterface as Ze}from"node:readline";import{Writable as Qe}from"node:stream";import{buffer as $e}from"node:stream/consumers";import{setTimeout as et}from"node:timers/promises";import{CONTENT_COMPLETION_KEY as tt,CONTENT_PROMPT_KEY as nt,CONTENT_TOOL_ARGS_KEY as rt,CONTENT_TOOL_NAME_KEY as it,CONTENT_TOOL_RESULT_KEY as at,TANGLE_SUBJECT_KEY as ot,asContentField as st,asContentString as ct}from"@tangle-network/agent-core/telemetry";import{z as I}from"zod";import{execCli as lt,shellQuote as ut}from"@tangle-network/sdk-cli-runner";import{lstat as dt,mkdir as ft,mkdtemp as pt,open as mt,readFile as L,realpath as R,rm as ht,writeFile as z}from"node:fs/promises";import{promisify as gt,stripVTControlCharacters as _t}from"node:util";import{gunzipSync as vt}from"node:zlib";import{fileURLToPath as yt,pathToFileURL as bt}from"node:url";import{ensureAgentPreview as xt,publishAgentPreview as St,resolveSelfSandbox as Ct}from"@tangle-network/sandbox/preview";import{createIntelligenceClient as wt}from"@tangle-network/sandbox/intelligence";var B=class extends Error{constructor(e,t,n,r){super(t),this.code=e,this.cause=n,this.fix=r,this.name=`ActionableCliError`}};const Tt=new Set([`AUTH_EXPIRED`,`SANDBOX_CREDENTIAL_REFUSED`,`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`]),Et=new Set([`GRAPH_INVALID`,`STEP_REF`,`PROFILE_INVALID`,`UNKNOWN_HARNESS`,`HUB_TOOL_UNKNOWN`,`TRIGGER_INVALID`,`WORKFLOW_INPUT_FILE_INVALID`,`VALIDATION_ERROR`]),Dt=new Set([`UNKNOWN_COMMAND`,`GRAPH_PARAM_MISSING`,`GRAPH_PARAM_UNKNOWN`,`SEAT_SYNTAX`,`HUB_PROVIDER_UNKNOWN`,`USAGE_INVALID`]),Ot=new Set([`SUBSCRIPTION_REQUIRED`,`MODEL_NOT_FOUND`,`MODEL_PROVIDER_MISMATCH`,`MCP_BLOCKED`,`CLOUD_SEAT_UNSUPPORTED`,`SCHEDULE_AUTHORITY`]);function kt(e){return typeof e==`object`&&e?e:{}}function V(e){return typeof e==`string`&&e.length>0?e:void 0}function At(e){let t=V(e);return t&&/^[a-z0-9][a-z0-9_-]*$/i.test(t)?t:void 0}function jt(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=V(kt(n).code);(e||r)&&(t=r?`${r}${e?`: ${e}`:``}`:e)}return t}function Mt(e){return e.code===`credential-refused`&&e.owner===`caller`&&e.providerCode===`subscription_required`?kt(e.remediation):{}}function Nt(e){let t=kt(e),n=Array.isArray(t.runtimeFailures)?t.runtimeFailures.map(kt):[],r=n.find(e=>V(Mt(kt(e.failure)).fix))??n[0],i=kt(r?.failure??t.runtimeFailure),a=Mt(i),o=kt(t.details),s=At(t.provider??o.provider??o.providerId),c=kt(t.fix??o.fix),l=V(t.code)??`CLI_ERROR`,u=V(t.message)??String(e),d=V(i.cause)??V(t.cause)??V(o.reason)??u,f=`tangle --help`,p=typeof o.providerRetryable==`boolean`?o.providerRetryable:typeof t.retryable==`boolean`?t.retryable:null;if(e instanceof b||l===`HUB_UNAUTHENTICATED`||t.status===401)l=`AUTH_EXPIRED`,u=`Authentication failed`,f=`tangle auth login`;else if(t.status===403&&u.startsWith(`Sandbox runtime creden`))l=`SANDBOX_CREDENTIAL_REFUSED`,u=`This sandbox's own TANGLE_API_KEY may call Hub endpoints only`,f=`export TANGLE_API_KEY=<owner or workspace sk-tan- key> (or pass --api-key), or run outside the sandbox`;else if([`HUB_CONNECTION_MISSING`,`HUB_CONNECTION_REVOKED`,`HUB_CONNECTION_UNHEALTHY`,`HUB_RECONNECT_REQUIRED`,`CONNECTION_REQUIRED`].includes(l))l=[`HUB_CONNECTION_MISSING`,`CONNECTION_REQUIRED`].includes(l)?`HUB_NOT_CONNECTED`:`HUB_RECONNECT`,f=s?`tangle hub connect ${s}`:`tangle hub connections --json`;else if(l===`HUB_APPROVAL_REQUIRED`){let e=At(kt(o.approval).id);f=e?`tangle hub approvals approve ${e}`:`tangle hub approvals list --json`}else l===`HUB_PROVIDER_REJECTED`?(f=`tangle hub status --json`,o.providerRetryable===!1&&(d+=`. Change the request before retrying`)):l===`provider_quota_exhausted`||l===`SEAT_LIMIT`?(l=`SEAT_LIMIT`,f=`tangle auth status`,p=!0):e instanceof T?f=`tangle usage --json`:e instanceof S?(l=`NETWORK_UNAVAILABLE`,u=`Network error: ${u}`,d=jt(e.cause)??`No response arrived`,f=`tangle auth status --json`):e instanceof A?(l=`TIMEOUT`,f=`tangle sandbox list --json`):e instanceof te?(l=`VALIDATION_ERROR`,u=`Invalid input`):e instanceof C||e instanceof k?f=`tangle sandbox list --json`:l===`commander.unknownCommand`?(l=`UNKNOWN_COMMAND`,f=u.includes(`'graph'`)?`npm install -g @tangle-network/sandbox-cli@latest`:`tangle --help`):l.startsWith(`commander.`)?l=`USAGE_INVALID`:(l===`ENOENT`||l===`EACCES`)&&(l=`INPUT_UNAVAILABLE`);e instanceof B&&(f=e.fix,p=!1),V(a.fix)&&(l=a.cause===`not_authenticated`?`SEAT_NOT_LOGGED_IN`:`SUBSCRIPTION_REQUIRED`),e instanceof w&&f===`tangle --help`&&(f=`tangle template publish --help`),f=V(a.fix)??V(c.command)??(l===`HUB_NOT_CONNECTED`?void 0:V(t.fixCommand))??f,Tt.has(l)&&f===`tangle --help`&&(f=`tangle auth login`);let m=kt(t.subject??o.subject??{node:r?.node??t.node,seat:t.seat??a.harness}),h=e instanceof S||e instanceof Error&&`batchCustody`in e?t.batchCustody:void 0;h&&(d=`Batch acceptance: ${h.acceptance}; retirement receipt ${h.cleanup?.mode===`release`&&h.cleanup.isComplete?`proved`:`unproved`}.`,p=!1,f=`tangle batch run --help`);let g=V(t.resumeAt??o.resumeAt??o.resetAt);return{code:l,...h?{batchCustody:h}:{},catalogCode:V(t.catalogCode),message:V(t.nextStep)&&V(t.message),nextStep:V(t.nextStep),subject:{...V(m.node)?{node:String(m.node)}:{},...V(m.seat)?{seat:String(m.seat)}:{}},what:u,cause:d,fix:{command:f,...Array.isArray(c.alternatives)&&c.alternatives.every(e=>typeof e==`string`)?{alternatives:c.alternatives}:{},...c.edit===void 0?{}:{edit:c.edit},...V(c.url)?{url:String(c.url)}:{}},retryable:p,...g&&Number.isFinite(Date.parse(g))?{resumeAt:g}:{},...V(t.runId)?{runId:String(t.runId)}:{},...V(t.requestId)?{requestId:String(t.requestId)}:{},...typeof t.status==`number`?{status:t.status}:{},...V(i.code)&&V(i.owner)?{runtimeFailure:{code:String(i.code),owner:String(i.owner),cause:typeof i.cause==`string`?i.cause:d,...V(i.providerCode)?{providerCode:String(i.providerCode)}:{},...typeof i.providerStatus==`number`?{providerStatus:i.providerStatus}:{},...typeof i.retryAfterMs==`number`?{retryAfterMs:i.retryAfterMs}:{},...Object.keys(a).length?{remediation:a}:{}}}:{},...e instanceof w&&e.job?{job:e.job}:{}}}function Pt(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}`}${e.nextStep?`\n → next: ${e.nextStep}`:``}\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 Ft(e){return Pt(Nt(e))}function H(t,r=!1){n();let i=Nt(t);r?e({ok:!1,error:i}):console.error(j.red(Pt(i)));let a=1;Tt.has(i.code)?a=77:Et.has(i.code)?a=65:Dt.has(i.code)?a=64:Ot.has(i.code)?a=78:[`SEAT_LIMIT`,`RATE_LIMITED`].includes(i.code)?a=75:[`HARNESS_NOT_INSTALLED`,`MCP_UNREACHABLE`,`NETWORK_UNAVAILABLE`].includes(i.code)?a=69:i.code===`RUN_STOPPED`&&(a=130),process.exit(a)}function It(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:le(a)}}let t;try{t=Ie(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:le(e),content:t}}function Lt(e){let t=(e.skills??[]).map(It),n=(e.tools??[]).map(It),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 Rt(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 Bt(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await Bt(e):Ie(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw new B(`PROFILE_INVALID`,`Profile '${e}' is invalid`,`Expected a JSON AgentProfile`,`tangle agent profile create --name my-agent --json`)}return zt(n,e)}function zt(e,t){let n=Ee.safeParse(e);if(!n.success)throw new B(`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 Bt(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function Vt(e){let t=e.profileSource?await Rt(e.profileSource):void 0,n=Lt(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const Ht=ce.join(Be.homedir(),`.tangle`),Ut=ce.join(Ht,`config.json`),Wt=`https://id.tangle.tools`,Gt=`https://solve.tangle.tools/api/solve`,Kt=`default`;function qt(){return{tangleBaseUrl:process.env.TANGLE_BASE_URL,sandboxBaseUrl:process.env.SANDBOX_BASE_URL,hubUrl:process.env.TANGLE_HUB_URL}}function Jt(e,t){let n=en(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 Kt;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 Yt(){je.existsSync(Ht)||je.mkdirSync(Ht,{mode:448,recursive:!0})}function Xt(e,t){Yt();let n=`${e}.${process.pid}.tmp`;je.writeFileSync(n,t,{mode:384}),je.renameSync(n,e)}function Zt(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function Qt(){try{if(je.existsSync(Ut))return JSON.parse(je.readFileSync(Ut,`utf-8`))}catch{}return{}}function $t(e){let t=On(Qt(),e);Xt(Ut,`${JSON.stringify(t,null,2)}\n`)}function en(e){return kn(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||Qt().activeProfile||Kt)}function tn(e){$t({activeProfile:kn(e)})}function nn(){return{token:process.env.TANGLE_LINE_TOKEN,baseUrl:process.env.TANGLE_HUB_URL}}function rn(){return process.env.TANGLE_SANDBOX||Qt().currentSandbox||void 0}function an(e){$t({currentSandbox:e})}function on(){let e=Qt();delete e.currentSandbox,Xt(Ut,`${JSON.stringify(e,null,2)}\n`)}function sn(){let e=Qt().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=Be.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=ye(4).toString(`hex`),r=`${t?`${t}-`:`device-`}${n}`;return $t({deviceId:r}),r}function cn(e){let t=e||rn();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 ln(){let e=Qt(),t=en(),n=new Set([Kt,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(kn(e.activeProfile)),[...n].map(e=>{let n=h(e).source;return{name:e,active:e===t,hasApiKey:n!==`none`,baseUrl:vn(void 0,e),apiKeySource:n}}).sort((e,t)=>e.name.localeCompare(t.name))}function un(e){let t=en(e);return{name:t,active:t===en(),baseUrl:vn(void 0,t),credentialSource:h(t).source}}function dn(e,t){let n=kn(e),r=Qt(),i=Dn(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=p(n,t.apiKey)),$t({profiles:Object.keys(l).length>0?l:{}}),u}function fn(e){let t=en(e),n={...Qt().profiles??{}},r=n[t];if(r){let e={...r};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}$t({profiles:n}),m(t)}function pn(){let e=process.env.TANGLE_API_KEY_FILE;if(e){let t=je.readFileSync(e,`utf8`).trim();if(!t.startsWith(`sk-tan-`))throw Error(`Invalid sandbox credential file`);return t}return process.env.TANGLE_API_KEY}function mn(e,t){let n=Jt(`sandbox`,t);return e||pn()||h(n).value}function hn(e,t){return e||(process.env.TANGLE_SOLVE_API_KEY?process.env.TANGLE_SOLVE_API_KEY:h(Jt(`solve`,t)).value)}function gn(e,t){let n=Jt(`sandbox`,t);return e?`flag`:process.env.TANGLE_API_KEY_FILE||process.env.TANGLE_API_KEY?`env`:h(n).source}function _n(e,t){return e?`flag`:process.env.TANGLE_SOLVE_API_KEY?`env`:h(Jt(`solve`,t)).source}function vn(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=en(t),i=Qt(),a=Dn(r,i);return a.baseUrl?a.baseUrl:(r===Kt||r===`sandbox`)&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function yn(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function bn(e){return e?.trim().replace(/\/+$/,``)||void 0}function xn(e){return bn(e?.flag)??bn(yn(bn(process.env.TANGLE_HUB_URL)))??bn(process.env.TANGLE_PLATFORM_URL)??bn(e?.cachedPlatformUrl?.())??Wt}function Sn(e){let t=bn(e)??bn(process.env.TANGLE_SOLVE_API_URL);if(t&&t!==Gt)throw Error(`Solve credentials may only be sent to ${Gt}`);return Gt}function Cn(e){let t=bn(e);if(t&&t!==Wt)throw Error(`Solve credentials may only be sent to ${Wt}`);return Wt}function U(e){let t=Jt(`sandbox`,e.profile),n=mn(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===Kt?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:vn(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...wn(t)}}function wn(e){let t=Qt(),n=Dn(en(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function Tn(e,t){dn(en(t),{activeTeamId:e.id,activeTeamName:e.name})}function En(e){let t=en(e),n=Qt(),r={...n.profiles??{}},i={baseUrl:Dn(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],$t({profiles:r})}function Dn(e,t=Qt()){let n=kn(e);return{...n===Kt?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[Kt]?.activeTeamId,activeTeamName:t.profiles?.[Kt]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function On(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 kn(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 An=null,jn=null;function W(e){if(!e&&An)return An;let t=e??U({});return(!An||!jn||jn.apiKey!==t.apiKey||jn.baseUrl!==t.baseUrl||jn.timeout!==t.timeout)&&(An=new E({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),jn=t),An}function Mn(){An=null,jn=null}function G(e){let t=U({apiKey:e.apiKey,baseUrl:e.baseUrl});return{context:t,client:W(t)}}async function Nn(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 Ye(r,n)}function Pn(e,t){return[...t,e]}async function Fn(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:`${Xe(r,e.ref)}:${e.tail}`)}function In(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 Ln(e,t){return ve(`sha256`).update(`${e}\0${t}`).digest(`hex`).slice(0,32)}function Rn(e){return`${e}:hub`}function zn(e){let{value:t}=h(Rn(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 Bn(e,t){try{p(Rn(e),JSON.stringify(t))}catch{}}async function Vn(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 Hn=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=Ln(t,n);let a=zn(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 Vn(this.sandboxBaseUrl,this.sessionToken,this.deviceId,this.signal),sessionFingerprint:this.fingerprint};return this.cache=t,Bn(this.profile,t),t}};function Un(e){if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function Wn(e,t){return xn({flag:e.baseUrl,...e.useCachedPlatformUrl?{cachedPlatformUrl:()=>zn(t)?.platformUrl}:{}})}function Gn(e,t){let n=Jt(`sandbox`,e.profile),r=mn(e.apiKey,n),i=gn(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:Wn(e,n)}:{kind:`managed`,profile:n,sandboxBaseUrl:vn(e.sandboxBaseUrl,n),sessionToken:o,deviceId:sn(),baseUrlOverride:e.baseUrl}}async function Kn(e={}){let t=Gn(e,e.hubKey===!1||Un(process.env.TANGLE_SKIP_HUB_KEY));if(t.kind===`static`)return{token:t.apiKey,baseUrl:t.baseUrl,minted:!1};let n=new Hn(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 qn(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 Jn(e={}){let t;try{t=await Kn(e)}catch(e){return{reachable:!1,reason:e instanceof Error?e.message:String(e),refused:!0}}try{let e=await qn(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 Yn(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=Gn(e,e.hubKey===!1||Un(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 Ge({baseUrl:r.baseUrl,fetch:n,authHeaders:()=>({Authorization:`Bearer ${t?pn():r.apiKey}`})})}let i=new Hn(r.profile,r.sandboxBaseUrl,r.sessionToken,r.deviceId,e.signal),a=await i.ensure();return new Ge({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 Xn(e={}){return Yn(e)}function K(e={}){return Yn({...e,useCachedPlatformUrl:!0,allowHubCapabilityToken:!0})}function Zn(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(`
2
+ `)}`}function Qn(e){return e.activeTeamId?`team:${e.activeTeamId}`:void 0}async function q(e,t,n,r={}){if(!r.nameOnly){let t=await e.get(n);if(t)return t;if(er(n))throw Error(`Sandbox not found: ${n}`)}let i=(await e.list({scope:Qn(t)})).filter(e=>e.name?.toLowerCase()===n.toLowerCase());if(i.length===0)throw Error(`Sandbox not found: ${n}`);if(i.length>1)throw Error(Zn(n,i));return i[0]}const $n=/^sandbox-(?:(?:(?:[a-z][a-z0-9-]*)-)?(?:[a-v0-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 er(e){return $n.test(e)}async function tr(e,t,n,r={}){let i=n;try{i=(await q(e,t,n,{nameOnly:r.name})).id}catch(e){if(!(e instanceof Error&&e.message===`Sandbox not found: ${n}`)||r.name||!r.retryCleanup&&!er(n))throw e}let a=await e.delete(i,{until:r.until}).catch(e=>{throw e instanceof D&&e.method&&e.endpoint&&(e.message=`${e.method} ${e.endpoint}: ${e.message}`),e});if(r.until===`removed`&&a.removal!==`complete`)throw Error(`Sandbox removal is unconfirmed for ${i}: ${a.removal??`unknown`}`);return a.outcome}async function J(e,t){if(e.status!==`stopped`)return e;let n=t?.resumeTimeoutMs??12e4;l(`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 nr=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function rr(e,t,n){switch(e){case`anthropic`:return`// pnpm add @anthropic-ai/sdk @tangle-network/sandbox
3
3
  import Anthropic from "@anthropic-ai/sdk";
4
4
  import { Sandbox } from "@tangle-network/sandbox";
5
5
  import { anthropicTools } from "@tangle-network/sandbox/agent";
@@ -119,39 +119,39 @@ await connect(new StdioServerTransport());`;case`claude-desktop`:return`// Add t
119
119
  }
120
120
  }
121
121
  }
122
- }`}}function or(e){return{anthropic:`Anthropic Messages API (Claude)`,openai:`OpenAI Chat Completions (function calling)`,"vercel-ai":`Vercel AI SDK (generateText / streamText)`,mastra:`Mastra agent framework`,"mcp-local":`Local MCP server bridge (stdio)`,"claude-desktop":`Claude Desktop config (uses local MCP)`,cursor:`Cursor config (uses local MCP)`,zed:`Zed config (uses local MCP)`}[e]}function sr(){return new N(`connect`).description(`Print a copy-paste SDK integration snippet for one of: ${ir.join(`, `)} (to stream a local agent's telemetry to Intelligence, see 'tangle connect')`).argument(`<framework>`,ir.join(` | `)).option(`-i, --sandbox <id>`,`Sandbox ID to embed in the snippet`,`<SANDBOX_ID>`).option(`-s, --session <id>`,`Session ID to embed in the snippet`,`default`).action((e,t)=>{ir.includes(e)||(console.error(j.red(`unknown framework: ${e}`),`\nsupported: ${ir.join(`, `)}`),process.exit(2));let n=e;process.stdout.write(j.cyan(`# ${or(n)}\n\n`)),process.stdout.write(`${ar(n,t.sandbox,t.session)}\n`)})}async function cr(e,t=!1,n){n?.throwIfAborted();let r=t?new Qe({write(e,t,n){n()}}):process.stderr,i=Ze({input:process.stdin,signal:n,output:r,...t?{terminal:!0}:{}});n&&i.once(`SIGINT`,()=>{process.emit(`SIGINT`),i.close()}),t&&process.stderr.write(e);try{return await new Promise(n=>{i.once(`close`,()=>n(void 0)),i.question(t?``:e,e=>{n(e.trim()),i.close()})})}finally{i.close(),t&&process.stderr.write(`
123
- `)}}async function lr(e){let t=await cr(e,!0);if(t===void 0)throw Error(`No answer on stdin.`);return t}async function ur(e,t){let n=await cr(e);if(n===void 0)throw process.stderr.write(`
124
- `),Error(t?`No answer on stdin. Pass ${t} to skip the confirmation.`:`No answer on stdin.`);return[`y`,`yes`].includes(n.toLowerCase())}async function dr(e,t,n){let r=await cr(`${e}${t?` [${t}]`:``}: `,!1,n);if(r===void 0)throw Error(`No answer on stdin.`);return r||t||``}async function fr(e,t=`secret`){if(process.stdin.isTTY)throw Error(e?`${e} reads ${t} from stdin, but stdin is a terminal; pipe it in`:`Cannot read ${t} from stdin when stdin is a TTY`);return(await $e(process.stdin)).toString(`utf8`).replace(/\r?\n$/,``)}function pr(){let t=new N(`profile`).description(`Create, inspect, and validate portable agent profiles`);return t.command(`create [output]`).description(`Create a profile — interactively (a wizard), or fully via flags`).option(`--name <name>`,`Profile name (when set, skips the wizard)`).option(`--description <text>`,`Profile description`).option(`--model <model>`,`Model (provider/model)`).option(`--system-prompt <text>`,`System prompt`).option(`--skills <ref...>`,`Skill refs: local path or github:<owner>/<repo>/<path>[@<ref>]`).option(`--tools <ref...>`,`Tool refs: local path or github:<owner>/<repo>/<path>[@<ref>]`).option(`--harness <name>`,`Harness hint shown in the run command`).action(async(t,n)=>{let r=n.name,i=n.description,a=n.harness,o=n.model,s=n.systemPrompt,c=n.skills??[],u=n.tools??[];if(!r&&process.stdin.isTTY&&(r=await dr(`Profile name`,`my-agent`),i=await dr(`Description (optional)`)||void 0,a=await dr(`Harness`,`claude-code`)||void 0,o=await dr(`Model (optional, provider/model)`)||void 0,s=await dr(`System prompt (optional)`)||void 0,c=await mr(`Skill ref (local path or github:..., blank to finish)`),u=await mr(`Tool ref (blank to finish)`)),!r)throw Error(process.stdin.isTTY?`Profile name is required.`:"`agent profile create` needs at least --name in a non-interactive shell (no TTY to prompt). Pass --name <name> (and optionally --model/--skills/--tools/--system-prompt).");let d=zt({model:o,systemPrompt:s,skills:c,tools:u}),f=Vt({...r?{name:r}:{},...i?{description:i}:{},...d??{},...a?{harness:a}:{}},`new profile`);if(n.json){e(f);return}let p=t??`agent-profile.json`;ze(p,`${JSON.stringify(f,null,2)}\n`),l(`Wrote ${p}`),l(`Run it: tangle agent prompt <box> --profile ${p}${a?` --harness ${a}`:``}`)}),t.command(`show <source>`).description(`Load and print a profile (local path, https URL, or github:owner/repo/path[@ref])`).action(async t=>{try{e(await Bt(t))}catch(e){H(e,!0)}}),t.command(`validate <source>`).description(`Validate a profile against the canonical AgentProfile schema`).action(async(t,n)=>{let r=await Bt(t),i=typeof r.name==`string`?r.name:`(unnamed)`;n.json?e({ok:!0,name:i}):l(`Profile valid: "${i}"`)}),t}async function mr(e){let t=[];for(;;){let n=await dr(e);if(!n)break;t.push(n)}return t}function hr(e){return(process.env.TANGLE_SANDBOX_WEB_URL?.trim()||e).replace(/\/+$/,``)}function gr(e,t){if(process.exitCode=1,e.status===`blocked_on_approval`){console.error(j.yellow(`⚠ Blocked on a hub approval.`));let t=e.approval?.approvalId;console.error(t?`Approve it: tangle hub approvals approve ${t}`:"Approve the pending request (`tangle hub approvals`), then re-run.");return}if(e.status===`awaiting_question`){console.error(j.yellow(`⚠ Agent is awaiting an answer to a question.`)),console.error(`Re-run with --interactive to answer it, or answer programmatically via box.session(<id>).answer(<questionId>, { ... }).`);return}if(e.status===`awaiting_interaction`){console.error(j.yellow(`⚠ Agent is awaiting a response.`)),console.error(`Open an interactive session, or answer the canonical interaction through the Sandbox SDK.`);return}if(e.status===`awaiting_plan_decision`){console.error(j.yellow(`⚠ Agent is awaiting a plan decision.`)),console.error(`Approve or reject the pending plan before continuing.`);return}console.error(j.red(`✗ ${e.error&&e.error.length>0?e.error:t}`))}function _r(e){let t=e.part;if(t?.type===`text`)return t.text??t.content??void 0}function vr(e){return e.finalText??e.response??e.output??e.content??e.text??void 0}function yr(e){if(!e.result.success){gr(e.result,`Agent run failed`);return}let t=Date.now()-e.startedAt,n=e.tokenUsage,r=[`${t}ms`,n?.inputTokens===void 0?void 0:`${n.inputTokens} in`,n?.outputTokens===void 0?void 0:`${n.outputTokens} out`].filter(e=>!!e);console.log(j.green(`✓ Done`),j.dim(`(${r.join(`, `)})`))}async function br(e,t,n=!0){let r=``,i,a=ne(),o=e=>{if(e.startsWith(r)){let t=e.slice(r.length);t&&n&&process.stdout.write(t)}else n&&process.stdout.write(e);r=e};try{for await(let t of e)switch(a.observe(t),t.type){case`token`:{let e=t.data?.value;typeof e==`string`&&(n&&process.stdout.write(e),r+=e);break}case`message.part.updated`:{let e=_r(t.data);typeof e==`string`&&e.length>0&&o(e);break}case`raw`:break;case`result`:i=t.data;break}}catch(e){a.observe({type:`error`,data:{message:e instanceof Error?e.message:String(e)}})}if(r.length===0&&i){let e=vr(i);typeof e==`string`&&e.length>0&&(n&&process.stdout.write(e),r=e)}return{outcome:{result:a.finish(),startedAt:t,tokenUsage:i?.tokenUsage},resultData:i,printed:r.length,...r.length>0?{response:r}:{}}}function xr(e){let t=Rn(e??[]);if(t.length!==0)return{profile:{connections:t}}}function Sr(e,t,n,r,i,a){let o={...r??{},harness:n,...i?{model:{...r?.model??{},default:i}}:{}},s={profile:o,requestedProfileDigest:De(o),initialPrompt:a};return{...s,run:Te({provider:`tangle-sandbox`,environmentId:e,sessionId:t,executionId:`interactive-execution-${t}`},s)}}async function Cr(e){let t=Rn(e.connection??[]);if(t.length===0)throw Error(`--allow-writes needs at least one --connection to grant writes for.`);if(t.some(e=>e.connectionId===`*`))throw Error("--allow-writes needs explicit --connection ids; the `*:*` wildcard can't be bulk-granted. Grant per connection, e.g. --connection conn_x:* --allow-writes.");let n=await K({hubKey:e.hubKey});for(let r of t){let t=await n.permissions.allowWrites(r.connectionId);e.json||l(`Allowed ${t.writeActions} write action${t.writeActions===1?``:`s`} for connection ${r.connectionId} (${t.granted} newly granted).`)}e.json||l(`Revert anytime: ${t.map(e=>`tangle hub permissions revert-writes --connection ${e.connectionId}`).join(` · `)}`)}async function wr(e){!e.connection||e.connection.length===0||(e.connection=await Ln(e.connection,()=>K({hubKey:e.hubKey})))}const Tr=15e3;async function Er(e){let t=process.stdin,n=process.stdout,r=null,i=!1,a=!1,o=!1,s=!1,c,u=0,d,f,p=new Promise(e=>{f=e}),m=()=>{try{t.setRawMode(!1)}catch{}t.pause()},h=()=>{i||(i=!0,clearTimeout(d),m(),t.off(`data`,w),process.off(`SIGWINCH`,_),process.off(`SIGINT`,g),process.off(`SIGTERM`,g),process.off(`exit`,m),f())},g=e=>{s=!0,Promise.resolve(r?.close()).finally(()=>{h(),process.exit(e===`SIGTERM`?143:130)})},_=()=>{r?.isOpen&&!o&&r.resize(n.columns||80,n.rows||24)},v=[],y=e=>{if(e.length!==0){try{if(!o&&r?.isOpen)return r.write(e)}catch{}v.push(e),C()}},b=()=>{clearTimeout(d);let e=r?.authorityLifetimeMs;e!==void 0&&(d=setTimeout(()=>void C(),Math.max(Tr,e*.8)))},S=async e=>{for(let t=1;;t++)try{return await e.reconnect({cols:n.columns||80,rows:n.rows||24})}catch(e){if(t>=3||e instanceof x)throw e;await new Promise(e=>setTimeout(e,500*2**t))}},C=async()=>{let e=r;if(!(o||i||a||!e)){o=!0,clearTimeout(d);try{await e.close(),r=await S(e);for(let e of v.splice(0))r.write(e)}catch(t){i||(c=t instanceof x?`the session ended`:`could not reattach: ${t.message}`),o=!1,r!==e&&await r?.close(),h();return}if(o=!1,i){await r.close();return}_(),b()}},w=e=>{if(!r)return;let t=e.indexOf(29);if(t===-1){y(e);return}y(e.subarray(0,t)),s=!0,r.close().finally(h)};if(r=await e.attach({cols:n.columns||80,rows:n.rows||24,handlers:{onData:e=>{n.write(Buffer.from(e.buffer,e.byteOffset,e.byteLength))},onExit:e=>{a=!0;let t=e.exitCode===void 0?``:` (code ${e.exitCode})`;n.write(`\r\n[interactive session exited${t}]\r\n`),r?.close().finally(h)},onError:e=>{n.write(`\r\n[terminal stream error: ${e.message}]\r\n`)},onClose:()=>{if(o||i)return;let e=Date.now();s||a?h():e-u<Tr?(c=`the connection keeps closing`,h()):(u=e,C())}}}),b(),t.setRawMode(!0),t.resume(),t.on(`data`,w),process.on(`SIGWINCH`,_),process.on(`SIGINT`,g),process.on(`SIGTERM`,g),process.on(`exit`,m),await p,console.log(),a){l(`Interactive session ended.`);return}l(`Detached — ${c??`the session keeps running`}.`)}function Dr(){let t=new N(`agent`).description(`Interact with AI agent`);return t.command(`prompt <idOrMessage> [message]`).description("Send a single prompt to the agent. With one arg it's the prompt and the box comes from `tangle use` / --box / TANGLE_SANDBOX; with two it's <id> <message>.").option(`--box <id>`,`Target sandbox (overrides the active one)`).option(`--session <id>`,`Continue existing session`).option(`--model <model>`,`Model to use`).option(`-t, --timeout <ms>`,`Timeout in milliseconds`,`300000`).option(`--stream`,`Stream response in real-time`).option(`--interactive`,`Spawn the harness's interactive TUI in the sandbox, inject this prompt, and print a link to watch + drive the live session in the browser (omit for the default headless run)`).option(`--harness <name>`,`Harness that executes this run (claude-code, codex, kimi-code, opencode, pi, amp, hermes). Defaults to the sandbox's configured backend. The box ships all harnesses, so this is a per-run choice.`).option(`--profile <source>`,`Agent profile to run: a local JSON path, an https URL, or github:<owner>/<repo>/<path>[@<ref>]`).option(`--skills <ref...>`,`Attach skills (repeatable): a local file path, or github:<owner>/<repo>/<path>[@<ref>] to pull from a repo`).option(`--tools <ref...>`,`Attach tools (repeatable): a local file path, or github:<owner>/<repo>/<path>[@<ref>]`).option(`--system-prompt <text>`,`Override the agent's system prompt for this run`).option(`--connection <spec>`,"Grant a hub connection to the agent as MCP tools (repeatable). The connection is a connection id or a provider name. Modes: <connection>:<cap1>,<cap2> (least privilege, recommended), <connection>:* (all of one connection), or *:* (all connections). List connections with `tangle hub connections`; paths with `tangle hub tools search <keyword>`.",In,[]).option(`--allow-writes`,"Pre-approve every WRITE action of each granted --connection so the agent can write unattended (reads are already allowed; destructive actions still prompt). Revert with `tangle hub permissions revert-writes`.").option(`--no-hub-key`,`Do not auto-mint a platform Hub key for --allow-writes; use the stored credential as-is`).action(async(t,n,r)=>{let i=n===void 0?t:n,a=n===void 0?un(r.box):t,{context:o,client:c}=G(r),u=await Ut({profileSource:r.profile,systemPrompt:r.systemPrompt,skills:r.skills,tools:r.tools});await wr(r);let d=xr(r.connection);r.allowWrites&&await Cr(r);let p=u||d?{...u,...d?.profile}:void 0,m=r.harness,h=p||m||r.model?{...m?{type:m}:{},...p?{profile:p}:{},...r.model?{model:{model:r.model}}:{}}:void 0,g=await q(c,o,a);if(g=await J(g),r.interactive){let t=r.session??`int-${be()}`,n=m??(await g.backend.status()).type,a=Sr(g.id,t,n,p,r.model,i),c=g.session(t).interactive(),u=f(`Starting interactive ${n} session...`);u.start();let d;try{d=await c.start(a)}finally{u.stop()}let h=d.ref.preparationReceipt.harness,_=d.state===`running`?d.streamUrl:void 0,v=`${hr(o.baseUrl)}/dashboard/sandbox/${encodeURIComponent(g.id)}?interactive=${encodeURIComponent(d.ref.run.sessionId)}`;if(r.json){e({state:d.state,sessionId:d.ref.run.sessionId,harness:h,..._?{streamUrl:_}:{},webUrl:v});return}if(l(`Interactive ${h} session ${d.state}.`),console.log(),d.state===`running`&&(s({"Watch & drive":v}),console.log()),d.state===`exited`){l(`The initial prompt completed with reason: ${d.reason}.`);return}l(`Open the link to watch the agent and type to take over.`),process.stdin.isTTY===!0&&process.stdout.isTTY===!0&&(console.log(),l(`Attaching to the live session — press Ctrl-] to detach.`),await Er(c));return}if(r.stream){r.json||(l(`Streaming response...`),console.log());let t=Date.now(),n=await br(g.streamPrompt(i,{sessionId:r.session,timeoutMs:Number.parseInt(r.timeout,10),...h?{backend:h}:{}}),t,!r.json);r.json?(e({...n.outcome.result,...n.response?{response:n.response}:{},...n.outcome.tokenUsage?{tokenUsage:n.outcome.tokenUsage}:{},durationMs:Date.now()-t}),n.outcome.result.success||(process.exitCode=1)):(n.printed>0&&console.log(),yr(n.outcome))}else{let t=f(`Processing prompt...`);t.start();let n=await g.prompt(i,{sessionId:r.session,timeoutMs:Number.parseInt(r.timeout,10),...h?{backend:h}:{}});t.stop(),r.json?(e(n),n.success===!1&&(process.exitCode=1)):n.success===!1?gr(n,`Agent prompt failed`):(console.log(n.response),console.log(),s({Duration:`${n.durationMs}ms`,"Input Tokens":n.usage?.inputTokens,"Output Tokens":n.usage?.outputTokens}))}}),t.addCommand(sr()),t.addCommand(pr()),t}async function Or(e){let t=e.timeoutMs??1e4,n=e.baseUrl.replace(/\/$/,``),r=`${n}/v1/account/me`;try{let n=await fetch(r,{headers:{Accept:`application/json`,Authorization:`Bearer ${e.apiKey}`},signal:AbortSignal.timeout(t)});if(!n.ok){let e=await Ar(n);throw n.status===401||n.status===403?new b(e||`Invalid API key`):n.status>=500?new O(e||`Sandbox API returned an unexpected error`,{status:n.status}):Error(e||`Credential validation failed with status ${n.status}`)}let i=await n.json();if(!i.success||!i.data)throw Error(`Sandbox API returned an invalid account response`);return{customerId:i.data.customer_id,billingOwnerId:typeof i.data.billing_owner_id==`string`?i.data.billing_owner_id:void 0,apiKeyId:typeof i.data.api_key_id==`string`||i.data.api_key_id===null?i.data.api_key_id:void 0,billingDelegationAuthorized:typeof i.data.billing_delegation_authorized==`boolean`?i.data.billing_delegation_authorized:void 0,email:i.data.email,name:i.data.name,tier:i.data.tier,createdAt:i.data.created_at}}catch(e){throw e instanceof b||e instanceof O||e instanceof A?e:e instanceof Error&&e.name===`AbortError`?new A(`Timed out validating credentials against ${n}`,{timeoutMs:t}):e instanceof Error&&!(e instanceof TypeError)?e:new S(`Failed to reach ${n}`,{cause:kr(e)})}}function kr(e){return e instanceof Error?e:void 0}async function Ar(e){let t=await e.text();if(t)try{let e=JSON.parse(t);return e.error?.message??e.message??t}catch{return t}}function jr(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}function Mr(e){if(!Pr(e.hostHeader))return{kind:`host-mismatch`};let t;try{t=new URL(e.requestUrl??`/`,`http://127.0.0.1`)}catch{return{kind:`not-found`}}if(t.pathname!==`/callback`)return{kind:`not-found`};if(t.searchParams.get(`state`)!==e.expectedState)return{kind:`state-mismatch`};let n=t.searchParams.get(`error`);if(n)return{kind:`error`,reason:n};let r=t.searchParams.get(`grant_token`);return r?{kind:`ok`,token:r}:{kind:`missing-token`}}async function Nr(e){e.signal?.throwIfAborted();let t=e.timeoutMs??12e4,n=e.baseUrl.replace(/\/$/,``),r=await import(`node:http`),i=ye(32).toString(`hex`),a=null,o=null,s=new Promise((e,t)=>{a=e,o=t}),c=r.createServer((e,t)=>{try{let n=Mr({hostHeader:e.headers.host,requestUrl:e.url,expectedState:i});switch(n.kind){case`host-mismatch`:t.writeHead(421,{"content-type":`text/plain; charset=utf-8`}),t.end(`Misdirected request`);return;case`not-found`:t.writeHead(404,{"content-type":`text/plain; charset=utf-8`}),t.end(`Not found`);return;case`state-mismatch`:t.writeHead(400,{"content-type":`text/html; charset=utf-8`}),t.end(Rr(`State mismatch — refusing login`)),o?.(Error(`Browser login state mismatch — refusing potentially hijacked callback`));return;case`error`:t.writeHead(400,{"content-type":`text/html; charset=utf-8`}),t.end(Rr(n.reason)),o?.(Error(`Browser login failed: ${n.reason}`));return;case`missing-token`:t.writeHead(400,{"content-type":`text/html; charset=utf-8`}),t.end(Rr(null)),o?.(Error(`Browser login did not return a grant token`));return;case`ok`:t.writeHead(200,{"content-type":`text/html; charset=utf-8`}),t.end(Rr(null)),a?.(n.token);return}}catch(e){o?.(e instanceof Error?e:Error(`Browser login callback failed`))}});await new Promise((e,t)=>{c.once(`error`,t),c.listen(0,`127.0.0.1`,()=>e())});try{let r=c.address();if(!r||typeof r==`string`)throw Error(`Failed to bind local callback server`);let a=new URL(`http://127.0.0.1:${r.port}/callback`);a.searchParams.set(`state`,i);let o=new URL(`${n}/auth/cli/login`);o.searchParams.set(`callback_url`,a.toString()),e.provider&&o.searchParams.set(`provider`,e.provider);let l=await Lr(o.toString());e.onLoginUrl?.({loginUrl:o.toString(),browserOpened:l});let u=await Ir({baseUrl:n,grantToken:await Fr(s,t,e.signal),timeoutMs:t,signal:e.signal});return{apiKey:u.apiKey,email:u.email,name:u.name,tier:u.tier}}finally{e.signal?.aborted&&c.closeAllConnections(),await new Promise((e,t)=>{c.close(n=>{if(n){t(n);return}e()})}).catch(()=>void 0)}}function Pr(e){if(!e)return!1;let t=e.toLowerCase().match(/^(\[[^\]]+\]|[^:]+)(?::\d+)?$/);if(!t)return!1;let n=t[1];return n===`127.0.0.1`||n===`localhost`||n===`[::1]`}async function Fr(e,t,n){let r=new AbortController;try{return await Promise.race([e,et(t,void 0,{signal:AbortSignal.any([r.signal,...n?[n]:[]])}).then(()=>{throw new A(`Timed out waiting for browser login to complete`,{timeoutMs:t})})])}finally{r.abort()}}async function Ir(e){let t=await fetch(`${e.baseUrl}/auth/cli/exchange`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`},body:JSON.stringify({grant_token:e.grantToken}),signal:AbortSignal.any([AbortSignal.timeout(e.timeoutMs),...e.signal?[e.signal]:[]])}).catch(t=>{throw new S(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),n=await t.json().catch(()=>null);if(!t.ok||!n?.success||!n.data?.api_key)throw Error(n?.error?.message||`Failed to exchange browser login grant`);return{apiKey:n.data.api_key,email:n.data.email,name:n.data.name,tier:n.data.tier}}async function Lr(e){let{spawn:t}=await import(`node:child_process`),n=process.platform===`darwin`?[`open`,e]:process.platform===`win32`?[`cmd`,`/c`,`start`,``,e]:[`xdg-open`,e];return await new Promise(e=>{let r=t(n[0],n.slice(1),{detached:!0,stdio:`ignore`});r.once(`error`,()=>e(!1)),r.once(`spawn`,()=>{r.unref(),e(!0)})})}function Rr(e){return`<!doctype html>
122
+ }`}}function ir(e){return{anthropic:`Anthropic Messages API (Claude)`,openai:`OpenAI Chat Completions (function calling)`,"vercel-ai":`Vercel AI SDK (generateText / streamText)`,mastra:`Mastra agent framework`,"mcp-local":`Local MCP server bridge (stdio)`,"claude-desktop":`Claude Desktop config (uses local MCP)`,cursor:`Cursor config (uses local MCP)`,zed:`Zed config (uses local MCP)`}[e]}function ar(){return new N(`connect`).description(`Print a copy-paste SDK integration snippet for one of: ${nr.join(`, `)} (to stream a local agent's telemetry to Intelligence, see 'tangle connect')`).argument(`<framework>`,nr.join(` | `)).option(`-i, --sandbox <id>`,`Sandbox ID to embed in the snippet`,`<SANDBOX_ID>`).option(`-s, --session <id>`,`Session ID to embed in the snippet`,`default`).action((e,t)=>{nr.includes(e)||(console.error(j.red(`unknown framework: ${e}`),`\nsupported: ${nr.join(`, `)}`),process.exit(2));let n=e;process.stdout.write(j.cyan(`# ${ir(n)}\n\n`)),process.stdout.write(`${rr(n,t.sandbox,t.session)}\n`)})}async function or(e,t=!1,n){n?.throwIfAborted();let r=t?new Qe({write(e,t,n){n()}}):process.stderr,i=Ze({input:process.stdin,signal:n,output:r,...t?{terminal:!0}:{}});n&&i.once(`SIGINT`,()=>{process.emit(`SIGINT`),i.close()}),t&&process.stderr.write(e);try{return await new Promise(n=>{i.once(`close`,()=>n(void 0)),i.question(t?``:e,e=>{n(e.trim()),i.close()})})}finally{i.close(),t&&process.stderr.write(`
123
+ `)}}async function sr(e){let t=await or(e,!0);if(t===void 0)throw Error(`No answer on stdin.`);return t}async function cr(e,t){let n=await or(e);if(n===void 0)throw process.stderr.write(`
124
+ `),Error(t?`No answer on stdin. Pass ${t} to skip the confirmation.`:`No answer on stdin.`);return[`y`,`yes`].includes(n.toLowerCase())}async function lr(e,t,n){let r=await or(`${e}${t?` [${t}]`:``}: `,!1,n);if(r===void 0)throw Error(`No answer on stdin.`);return r||t||``}async function ur(e,t=`secret`){if(process.stdin.isTTY)throw Error(e?`${e} reads ${t} from stdin, but stdin is a terminal; pipe it in`:`Cannot read ${t} from stdin when stdin is a TTY`);return(await $e(process.stdin)).toString(`utf8`).replace(/\r?\n$/,``)}function dr(){let t=new N(`profile`).description(`Create, inspect, and validate portable agent profiles`);return t.command(`create [output]`).description(`Create a profile — interactively (a wizard), or fully via flags`).option(`--name <name>`,`Profile name (when set, skips the wizard)`).option(`--description <text>`,`Profile description`).option(`--model <model>`,`Model (provider/model)`).option(`--system-prompt <text>`,`System prompt`).option(`--skills <ref...>`,`Skill refs: local path or github:<owner>/<repo>/<path>[@<ref>]`).option(`--tools <ref...>`,`Tool refs: local path or github:<owner>/<repo>/<path>[@<ref>]`).option(`--harness <name>`,`Harness hint shown in the run command`).action(async(t,n)=>{let r=n.name,i=n.description,a=n.harness,o=n.model,s=n.systemPrompt,c=n.skills??[],u=n.tools??[];if(!r&&process.stdin.isTTY&&(r=await lr(`Profile name`,`my-agent`),i=await lr(`Description (optional)`)||void 0,a=await lr(`Harness`,`claude-code`)||void 0,o=await lr(`Model (optional, provider/model)`)||void 0,s=await lr(`System prompt (optional)`)||void 0,c=await fr(`Skill ref (local path or github:..., blank to finish)`),u=await fr(`Tool ref (blank to finish)`)),!r)throw Error(process.stdin.isTTY?`Profile name is required.`:"`agent profile create` needs at least --name in a non-interactive shell (no TTY to prompt). Pass --name <name> (and optionally --model/--skills/--tools/--system-prompt).");let d=Lt({model:o,systemPrompt:s,skills:c,tools:u}),f=zt({...r?{name:r}:{},...i?{description:i}:{},...d??{},...a?{harness:a}:{}},`new profile`);if(n.json){e(f);return}let p=t??`agent-profile.json`;ze(p,`${JSON.stringify(f,null,2)}\n`),l(`Wrote ${p}`),l(`Run it: tangle agent prompt <box> --profile ${p}${a?` --harness ${a}`:``}`)}),t.command(`show <source>`).description(`Load and print a profile (local path, https URL, or github:owner/repo/path[@ref])`).action(async t=>{try{e(await Rt(t))}catch(e){H(e,!0)}}),t.command(`validate <source>`).description(`Validate a profile against the canonical AgentProfile schema`).action(async(t,n)=>{let r=await Rt(t),i=typeof r.name==`string`?r.name:`(unnamed)`;n.json?e({ok:!0,name:i}):l(`Profile valid: "${i}"`)}),t}async function fr(e){let t=[];for(;;){let n=await lr(e);if(!n)break;t.push(n)}return t}function pr(e){return(process.env.TANGLE_SANDBOX_WEB_URL?.trim()||e).replace(/\/+$/,``)}function mr(e,t){if(process.exitCode=1,e.status===`blocked_on_approval`){console.error(j.yellow(`⚠ Blocked on a hub approval.`));let t=e.approval?.approvalId;console.error(t?`Approve it: tangle hub approvals approve ${t}`:"Approve the pending request (`tangle hub approvals`), then re-run.");return}if(e.status===`awaiting_question`){console.error(j.yellow(`⚠ Agent is awaiting an answer to a question.`)),console.error(`Re-run with --interactive to answer it, or answer programmatically via box.session(<id>).answer(<questionId>, { ... }).`);return}if(e.status===`awaiting_interaction`){console.error(j.yellow(`⚠ Agent is awaiting a response.`)),console.error(`Open an interactive session, or answer the canonical interaction through the Sandbox SDK.`);return}if(e.status===`awaiting_plan_decision`){console.error(j.yellow(`⚠ Agent is awaiting a plan decision.`)),console.error(`Approve or reject the pending plan before continuing.`);return}console.error(j.red(`✗ ${e.error&&e.error.length>0?e.error:t}`))}function hr(e){let t=e.part;if(t?.type===`text`)return t.text??t.content??void 0}function gr(e){return e.finalText??e.response??e.output??e.content??e.text??void 0}function _r(e){if(!e.result.success){mr(e.result,`Agent run failed`);return}let t=Date.now()-e.startedAt,n=e.tokenUsage,r=[`${t}ms`,n?.inputTokens===void 0?void 0:`${n.inputTokens} in`,n?.outputTokens===void 0?void 0:`${n.outputTokens} out`].filter(e=>!!e);console.log(j.green(`✓ Done`),j.dim(`(${r.join(`, `)})`))}async function vr(e,t,n=!0){let r=``,i,a=ne(),o=e=>{if(e.startsWith(r)){let t=e.slice(r.length);t&&n&&process.stdout.write(t)}else n&&process.stdout.write(e);r=e};try{for await(let t of e)switch(a.observe(t),t.type){case`token`:{let e=t.data?.value;typeof e==`string`&&(n&&process.stdout.write(e),r+=e);break}case`message.part.updated`:{let e=hr(t.data);typeof e==`string`&&e.length>0&&o(e);break}case`raw`:break;case`result`:i=t.data;break}}catch(e){a.observe({type:`error`,data:{message:e instanceof Error?e.message:String(e)}})}if(r.length===0&&i){let e=gr(i);typeof e==`string`&&e.length>0&&(n&&process.stdout.write(e),r=e)}return{outcome:{result:a.finish(),startedAt:t,tokenUsage:i?.tokenUsage},resultData:i,printed:r.length,...r.length>0?{response:r}:{}}}function yr(e){let t=In(e??[]);if(t.length!==0)return{profile:{connections:t}}}function br(e,t,n,r,i,a){let o={...r??{},harness:n,...i?{model:{...r?.model??{},default:i}}:{}},s={profile:o,requestedProfileDigest:De(o),initialPrompt:a};return{...s,run:Te({provider:`tangle-sandbox`,environmentId:e,sessionId:t,executionId:`interactive-execution-${t}`},s)}}async function xr(e){let t=In(e.connection??[]);if(t.length===0)throw Error(`--allow-writes needs at least one --connection to grant writes for.`);if(t.some(e=>e.connectionId===`*`))throw Error("--allow-writes needs explicit --connection ids; the `*:*` wildcard can't be bulk-granted. Grant per connection, e.g. --connection conn_x:* --allow-writes.");let n=await K({hubKey:e.hubKey});for(let r of t){let t=await n.permissions.allowWrites(r.connectionId);e.json||l(`Allowed ${t.writeActions} write action${t.writeActions===1?``:`s`} for connection ${r.connectionId} (${t.granted} newly granted).`)}e.json||l(`Revert anytime: ${t.map(e=>`tangle hub permissions revert-writes --connection ${e.connectionId}`).join(` · `)}`)}async function Sr(e){!e.connection||e.connection.length===0||(e.connection=await Fn(e.connection,()=>K({hubKey:e.hubKey})))}const Cr=15e3;async function wr(e){let t=process.stdin,n=process.stdout,r=null,i=!1,a=!1,o=!1,s=!1,c,u=0,d,f,p=new Promise(e=>{f=e}),m=()=>{try{t.setRawMode(!1)}catch{}t.pause()},h=()=>{i||(i=!0,clearTimeout(d),m(),t.off(`data`,w),process.off(`SIGWINCH`,_),process.off(`SIGINT`,g),process.off(`SIGTERM`,g),process.off(`exit`,m),f())},g=e=>{s=!0,Promise.resolve(r?.close()).finally(()=>{h(),process.exit(e===`SIGTERM`?143:130)})},_=()=>{r?.isOpen&&!o&&r.resize(n.columns||80,n.rows||24)},v=[],y=e=>{if(e.length!==0){try{if(!o&&r?.isOpen)return r.write(e)}catch{}v.push(e),C()}},b=()=>{clearTimeout(d);let e=r?.authorityLifetimeMs;e!==void 0&&(d=setTimeout(()=>void C(),Math.max(Cr,e*.8)))},S=async e=>{for(let t=1;;t++)try{return await e.reconnect({cols:n.columns||80,rows:n.rows||24})}catch(e){if(t>=3||e instanceof x)throw e;await new Promise(e=>setTimeout(e,500*2**t))}},C=async()=>{let e=r;if(!(o||i||a||!e)){o=!0,clearTimeout(d);try{await e.close(),r=await S(e);for(let e of v.splice(0))r.write(e)}catch(t){i||(c=t instanceof x?`the session ended`:`could not reattach: ${t.message}`),o=!1,r!==e&&await r?.close(),h();return}if(o=!1,i){await r.close();return}_(),b()}},w=e=>{if(!r)return;let t=e.indexOf(29);if(t===-1){y(e);return}y(e.subarray(0,t)),s=!0,r.close().finally(h)};if(r=await e.attach({cols:n.columns||80,rows:n.rows||24,handlers:{onData:e=>{n.write(Buffer.from(e.buffer,e.byteOffset,e.byteLength))},onExit:e=>{a=!0;let t=e.exitCode===void 0?``:` (code ${e.exitCode})`;n.write(`\r\n[interactive session exited${t}]\r\n`),r?.close().finally(h)},onError:e=>{n.write(`\r\n[terminal stream error: ${e.message}]\r\n`)},onClose:()=>{if(o||i)return;let e=Date.now();s||a?h():e-u<Cr?(c=`the connection keeps closing`,h()):(u=e,C())}}}),b(),t.setRawMode(!0),t.resume(),t.on(`data`,w),process.on(`SIGWINCH`,_),process.on(`SIGINT`,g),process.on(`SIGTERM`,g),process.on(`exit`,m),await p,console.log(),a){l(`Interactive session ended.`);return}l(`Detached — ${c??`the session keeps running`}.`)}function Tr(){let t=new N(`agent`).description(`Interact with AI agent`);return t.command(`prompt <idOrMessage> [message]`).description("Send a single prompt to the agent. With one arg it's the prompt and the box comes from `tangle use` / --box / TANGLE_SANDBOX; with two it's <id> <message>.").option(`--box <id>`,`Target sandbox (overrides the active one)`).option(`--session <id>`,`Continue existing session`).option(`--model <model>`,`Model to use`).option(`-t, --timeout <ms>`,`Timeout in milliseconds`,`300000`).option(`--stream`,`Stream response in real-time`).option(`--interactive`,`Spawn the harness's interactive TUI in the sandbox, inject this prompt, and print a link to watch + drive the live session in the browser (omit for the default headless run)`).option(`--harness <name>`,`Harness that executes this run (claude-code, codex, kimi-code, opencode, pi, amp, hermes). Defaults to the sandbox's configured backend. The box ships all harnesses, so this is a per-run choice.`).option(`--profile <source>`,`Agent profile to run: a local JSON path, an https URL, or github:<owner>/<repo>/<path>[@<ref>]`).option(`--skills <ref...>`,`Attach skills (repeatable): a local file path, or github:<owner>/<repo>/<path>[@<ref>] to pull from a repo`).option(`--tools <ref...>`,`Attach tools (repeatable): a local file path, or github:<owner>/<repo>/<path>[@<ref>]`).option(`--system-prompt <text>`,`Override the agent's system prompt for this run`).option(`--connection <spec>`,"Grant a hub connection to the agent as MCP tools (repeatable). The connection is a connection id or a provider name. Modes: <connection>:<cap1>,<cap2> (least privilege, recommended), <connection>:* (all of one connection), or *:* (all connections). List connections with `tangle hub connections`; paths with `tangle hub tools search <keyword>`.",Pn,[]).option(`--allow-writes`,"Pre-approve every WRITE action of each granted --connection so the agent can write unattended (reads are already allowed; destructive actions still prompt). Revert with `tangle hub permissions revert-writes`.").option(`--no-hub-key`,`Do not auto-mint a platform Hub key for --allow-writes; use the stored credential as-is`).action(async(t,n,r)=>{let i=n===void 0?t:n,a=n===void 0?cn(r.box):t,{context:o,client:c}=G(r),u=await Vt({profileSource:r.profile,systemPrompt:r.systemPrompt,skills:r.skills,tools:r.tools});await Sr(r);let d=yr(r.connection);r.allowWrites&&await xr(r);let p=u||d?{...u,...d?.profile}:void 0,m=r.harness,h=p||m||r.model?{...m?{type:m}:{},...p?{profile:p}:{},...r.model?{model:{model:r.model}}:{}}:void 0,g=await q(c,o,a);if(g=await J(g),r.interactive){let t=r.session??`int-${be()}`,n=m??(await g.backend.status()).type,a=br(g.id,t,n,p,r.model,i),c=g.session(t).interactive(),u=f(`Starting interactive ${n} session...`);u.start();let d;try{d=await c.start(a)}finally{u.stop()}let h=d.ref.preparationReceipt.harness,_=d.state===`running`?d.streamUrl:void 0,v=`${pr(o.baseUrl)}/dashboard/sandbox/${encodeURIComponent(g.id)}?interactive=${encodeURIComponent(d.ref.run.sessionId)}`;if(r.json){e({state:d.state,sessionId:d.ref.run.sessionId,harness:h,..._?{streamUrl:_}:{},webUrl:v});return}if(l(`Interactive ${h} session ${d.state}.`),console.log(),d.state===`running`&&(s({"Watch & drive":v}),console.log()),d.state===`exited`){l(`The initial prompt completed with reason: ${d.reason}.`);return}l(`Open the link to watch the agent and type to take over.`),process.stdin.isTTY===!0&&process.stdout.isTTY===!0&&(console.log(),l(`Attaching to the live session — press Ctrl-] to detach.`),await wr(c));return}if(r.stream){r.json||(l(`Streaming response...`),console.log());let t=Date.now(),n=await vr(g.streamPrompt(i,{sessionId:r.session,timeoutMs:Number.parseInt(r.timeout,10),...h?{backend:h}:{}}),t,!r.json);r.json?(e({...n.outcome.result,...n.response?{response:n.response}:{},...n.outcome.tokenUsage?{tokenUsage:n.outcome.tokenUsage}:{},durationMs:Date.now()-t}),n.outcome.result.success||(process.exitCode=1)):(n.printed>0&&console.log(),_r(n.outcome))}else{let t=f(`Processing prompt...`);t.start();let n=await g.prompt(i,{sessionId:r.session,timeoutMs:Number.parseInt(r.timeout,10),...h?{backend:h}:{}});t.stop(),r.json?(e(n),n.success===!1&&(process.exitCode=1)):n.success===!1?mr(n,`Agent prompt failed`):(console.log(n.response),console.log(),s({Duration:`${n.durationMs}ms`,"Input Tokens":n.usage?.inputTokens,"Output Tokens":n.usage?.outputTokens}))}}),t.addCommand(ar()),t.addCommand(dr()),t}async function Er(e){let t=e.timeoutMs??1e4,n=e.baseUrl.replace(/\/$/,``),r=`${n}/v1/account/me`;try{let n=await fetch(r,{headers:{Accept:`application/json`,Authorization:`Bearer ${e.apiKey}`},signal:AbortSignal.timeout(t)});if(!n.ok){let e=await Or(n);throw n.status===401||n.status===403?new b(e||`Invalid API key`):n.status>=500?new O(e||`Sandbox API returned an unexpected error`,{status:n.status}):Error(e||`Credential validation failed with status ${n.status}`)}let i=await n.json();if(!i.success||!i.data)throw Error(`Sandbox API returned an invalid account response`);return{customerId:i.data.customer_id,billingOwnerId:typeof i.data.billing_owner_id==`string`?i.data.billing_owner_id:void 0,apiKeyId:typeof i.data.api_key_id==`string`||i.data.api_key_id===null?i.data.api_key_id:void 0,billingDelegationAuthorized:typeof i.data.billing_delegation_authorized==`boolean`?i.data.billing_delegation_authorized:void 0,email:i.data.email,name:i.data.name,tier:i.data.tier,createdAt:i.data.created_at}}catch(e){throw e instanceof b||e instanceof O||e instanceof A?e:e instanceof Error&&e.name===`AbortError`?new A(`Timed out validating credentials against ${n}`,{timeoutMs:t}):e instanceof Error&&!(e instanceof TypeError)?e:new S(`Failed to reach ${n}`,{cause:Dr(e)})}}function Dr(e){return e instanceof Error?e:void 0}async function Or(e){let t=await e.text();if(t)try{let e=JSON.parse(t);return e.error?.message??e.message??t}catch{return t}}function kr(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}function Ar(e){if(!Mr(e.hostHeader))return{kind:`host-mismatch`};let t;try{t=new URL(e.requestUrl??`/`,`http://127.0.0.1`)}catch{return{kind:`not-found`}}if(t.pathname!==`/callback`)return{kind:`not-found`};if(t.searchParams.get(`state`)!==e.expectedState)return{kind:`state-mismatch`};let n=t.searchParams.get(`error`);if(n)return{kind:`error`,reason:n};let r=t.searchParams.get(`grant_token`);return r?{kind:`ok`,token:r}:{kind:`missing-token`}}async function jr(e){e.signal?.throwIfAborted();let t=e.timeoutMs??12e4,n=e.baseUrl.replace(/\/$/,``),r=await import(`node:http`),i=ye(32).toString(`hex`),a=null,o=null,s=new Promise((e,t)=>{a=e,o=t}),c=r.createServer((e,t)=>{try{let n=Ar({hostHeader:e.headers.host,requestUrl:e.url,expectedState:i});switch(n.kind){case`host-mismatch`:t.writeHead(421,{"content-type":`text/plain; charset=utf-8`}),t.end(`Misdirected request`);return;case`not-found`:t.writeHead(404,{"content-type":`text/plain; charset=utf-8`}),t.end(`Not found`);return;case`state-mismatch`:t.writeHead(400,{"content-type":`text/html; charset=utf-8`}),t.end(Ir(`State mismatch — refusing login`)),o?.(Error(`Browser login state mismatch — refusing potentially hijacked callback`));return;case`error`:t.writeHead(400,{"content-type":`text/html; charset=utf-8`}),t.end(Ir(n.reason)),o?.(Error(`Browser login failed: ${n.reason}`));return;case`missing-token`:t.writeHead(400,{"content-type":`text/html; charset=utf-8`}),t.end(Ir(null)),o?.(Error(`Browser login did not return a grant token`));return;case`ok`:t.writeHead(200,{"content-type":`text/html; charset=utf-8`}),t.end(Ir(null)),a?.(n.token);return}}catch(e){o?.(e instanceof Error?e:Error(`Browser login callback failed`))}});await new Promise((e,t)=>{c.once(`error`,t),c.listen(0,`127.0.0.1`,()=>e())});try{let r=c.address();if(!r||typeof r==`string`)throw Error(`Failed to bind local callback server`);let a=new URL(`http://127.0.0.1:${r.port}/callback`);a.searchParams.set(`state`,i);let o=new URL(`${n}/auth/cli/login`);o.searchParams.set(`callback_url`,a.toString()),e.provider&&o.searchParams.set(`provider`,e.provider);let l=await Fr(o.toString());e.onLoginUrl?.({loginUrl:o.toString(),browserOpened:l});let u=await Pr({baseUrl:n,grantToken:await Nr(s,t,e.signal),timeoutMs:t,signal:e.signal});return{apiKey:u.apiKey,email:u.email,name:u.name,tier:u.tier}}finally{e.signal?.aborted&&c.closeAllConnections(),await new Promise((e,t)=>{c.close(n=>{if(n){t(n);return}e()})}).catch(()=>void 0)}}function Mr(e){if(!e)return!1;let t=e.toLowerCase().match(/^(\[[^\]]+\]|[^:]+)(?::\d+)?$/);if(!t)return!1;let n=t[1];return n===`127.0.0.1`||n===`localhost`||n===`[::1]`}async function Nr(e,t,n){let r=new AbortController;try{return await Promise.race([e,et(t,void 0,{signal:AbortSignal.any([r.signal,...n?[n]:[]])}).then(()=>{throw new A(`Timed out waiting for browser login to complete`,{timeoutMs:t})})])}finally{r.abort()}}async function Pr(e){let t=await fetch(`${e.baseUrl}/auth/cli/exchange`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`},body:JSON.stringify({grant_token:e.grantToken}),signal:AbortSignal.any([AbortSignal.timeout(e.timeoutMs),...e.signal?[e.signal]:[]])}).catch(t=>{throw new S(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),n=await t.json().catch(()=>null);if(!t.ok||!n?.success||!n.data?.api_key)throw Error(n?.error?.message||`Failed to exchange browser login grant`);return{apiKey:n.data.api_key,email:n.data.email,name:n.data.name,tier:n.data.tier}}async function Fr(e){let{spawn:t}=await import(`node:child_process`),n=process.platform===`darwin`?[`open`,e]:process.platform===`win32`?[`cmd`,`/c`,`start`,``,e]:[`xdg-open`,e];return await new Promise(e=>{let r=t(n[0],n.slice(1),{detached:!0,stdio:`ignore`});r.once(`error`,()=>e(!1)),r.once(`spawn`,()=>{r.unref(),e(!0)})})}function Ir(e){return`<!doctype html>
125
125
  <html lang="en">
126
126
  <head>
127
127
  <meta charset="utf-8" />
128
128
  <title>Sandbox CLI Login</title>
129
129
  </head>
130
130
  <body>
131
- <p>${e?`Sandbox CLI login failed: ${jr(e)}`:`Sandbox CLI login complete. You can close this window.`}</p>
131
+ <p>${e?`Sandbox CLI login failed: ${kr(e)}`:`Sandbox CLI login complete. You can close this window.`}</p>
132
132
  </body>
133
- </html>`}const zr=15*6e4,Br=`sandbox`;function Vr(e){return Number.isFinite(e)&&e>0?e:zr}async function Hr(e){let t=e.timeoutMs??zr,n=Date.now(),r=await Ur({baseUrl:e.baseUrl,app:e.app??Br,timeoutMs:t,provider:e.provider});for(e.onInstructions?.({userCode:r.user_code,verificationUrl:r.verification_uri,verificationUrlComplete:r.verification_uri_complete,expiresIn:r.expires_in,intervalSeconds:r.interval});;){if(Date.now()-n>t)throw new A(`Timed out waiting for device authorization to complete`,{timeoutMs:t});let i=await Wr({baseUrl:e.baseUrl,app:e.app??Br,deviceCode:r.device_code,timeoutMs:t});if(i.status===`approved`)return i.data;let a=i.intervalSeconds*1e3;await new Promise(e=>setTimeout(e,a))}}async function Ur(e){let t=Vr(e.timeoutMs),n=e.app!==Br,r=await fetch(`${Gr(e.baseUrl)}${n?`/cross-site/device/start`:`/auth/cli/device/start`}`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`},body:JSON.stringify(n?{app:e.app,...e.provider?{provider:e.provider}:{}}:e.provider?{provider:e.provider}:{}),signal:AbortSignal.timeout(t)}).catch(t=>{throw new S(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success||!i.data?.device_code)throw Error(i?.error?.message||`Failed to start device login`);return i.data}async function Wr(e){let t=Vr(e.timeoutMs),n=e.app!==Br,r=await fetch(`${Gr(e.baseUrl)}${n?`/cross-site/device/poll`:`/auth/cli/device/poll`}`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`},body:JSON.stringify(n?{app:e.app,device_code:e.deviceCode}:{device_code:e.deviceCode}),signal:AbortSignal.timeout(t)}).catch(t=>{throw new S(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),i=await r.json().catch(()=>null);if(r.status===428&&i?.error?.code===`AUTHORIZATION_PENDING`)return{status:`pending`,intervalSeconds:typeof i.data?.interval==`number`&&i.data.interval>0?i.data.interval:5};if(!r.ok||!i?.success||!i.data?.api_key||!i.data.email)throw Error(i?.error?.message||`Failed to complete device authorization`);return{status:`approved`,data:{apiKey:i.data.api_key,email:i.data.email,name:i.data.name,tier:i.data.tier}}}function Gr(e){return e.replace(/\/$/,``)}async function Kr(e){let t=e.apiKey,n=ei(e.app??`sandbox`),i=ti(n,e.profile),a=$r(e.provider),o=n===`solve`?Tn(e.baseUrl):bn(e.baseUrl,i),c=e.browser!==!1,u=(t,a)=>{Xr({profile:i,apiKey:t,baseUrl:e.baseUrl?o:void 0,activate:n===`sandbox`}),Pn(),r(`Authenticated`),s({Profile:i,Email:a.email,Tier:a.tier,"Base URL":o}),l(Zr)};if(t&&!$t(t)){d(`Invalid API key format. Keys should start with 'sk_' or 'sk-tan-'.`),process.exit(1);return}if(g(),!t){let t=c&&n===`sandbox`,r=f(t?`Starting browser login...`:`Starting device login...`);r.start();let i;try{i=t?await Nr({baseUrl:o,provider:a,signal:e.signal,onLoginUrl:({loginUrl:e,browserOpened:t})=>{r.stop(),l(t?`Browser login opened.`:`Open this URL to continue browser login:`),console.log(e)}}):await Hr({baseUrl:o,app:n,provider:a,onInstructions:({userCode:e,verificationUrl:t,verificationUrlComplete:i})=>{r.stop(),l(`Complete login in a browser on any device:`),s({"Verification URL":t,"Verification URL (prefilled)":i,"Device Code":e}),n===`solve`&&c&&Lr(i)}})}finally{r.stop()}u(i.apiKey,i);return}let p=f(`Validating credentials...`);p.start();let m=await Or({apiKey:t,baseUrl:o});p.stop(),u(t,m)}function qr(){let t=new N(`auth`).description(`Manage authentication`);return t.command(`login`).description(`Authenticate with browser login, device code, or an API key`).option(`--no-browser`,`Use device-code login instead of opening a browser`).option(`--profile <name>`,`Profile name`).option(`--provider <provider>`,`Identity provider (github, google, microsoft)`).option(`--app <app>`,`Product to authorize (sandbox or solve)`,`sandbox`).action(Kr),t.command(`logout`).description(`Remove stored credentials`).option(`--profile <name>`,`Profile name`).option(`--app <app>`,`Product credentials to remove (sandbox or solve)`,`sandbox`).action(e=>{let t=ti(ei(e.app),e.profile);mn(t),Pn(),r(`Logged out successfully.`),l(`Credentials removed for profile '${t}'.`)}),t.command(`status`).description(`Show current authentication status`).option(`--profile <name>`,`Profile name`).option(`--app <app>`,`Product credentials to check (sandbox or solve)`,`sandbox`).action(async t=>{let n=ei(t.app),i=ti(n,t.profile),a=n===`solve`?_n(t.apiKey,i):gn(t.apiKey,i),o=n===`solve`?Tn(t.baseUrl):bn(t.baseUrl,i),u=n===`solve`?yn(t.apiKey,i):vn(t.apiKey,i);if(!a){if(t.json){e({authenticated:!1,reason:`missing_credentials`,profile:i,baseUrl:o,credentialSource:null});return}d(`Not authenticated`),l(`Run 'tangle auth login --profile ${i}' to authenticate.`),process.exit(1)}let p=t.json?null:f(`Checking credentials...`);p?.start();try{let d=await Or({apiKey:a,baseUrl:o}),f=n===`solve`?null:await Xn({...t.apiKey===void 0?{}:{apiKey:t.apiKey},...t.profile===void 0?{}:{profile:t.profile},sandboxBaseUrl:o});p?.stop();let m=f!==null&&!f.reachable&&f.refused,h=!m,g=f!==null&&!f.reachable&&!f.refused;if(t.json){e({authenticated:h,profile:i,baseUrl:o,credentialSource:u,account:d,...f?{sandbox:{authenticated:!0},platform:f}:{}}),h||process.exit(1);return}m?c(`Authenticated for sandbox only`):g?c(`Authenticated — the platform is unreachable right now`):r(`Authenticated`),s({Profile:i,Credentials:`configured`,"Base URL":o,Source:Yr(u),Email:d.email,Tier:d.tier,...f?{Platform:f.reachable?`reachable (${f.baseUrl})`:`UNREACHABLE — ${f.reason}`}:{}}),g&&l(`Platform commands (keys, workflows, hub) will not work until the platform answers again. The stored credential is not the cause and does not need replacing.`),h||(l("Platform commands (keys, workflows, hub) will not work until this resolves. Set TANGLE_API_KEY to a key you minted in the console, or run `tangle auth login` again."),process.exit(1))}catch(n){p?.stop(),t.json&&(e({authenticated:!1,profile:i,baseUrl:o,credentialSource:u,error:n instanceof Error?n.message:String(n)}),process.exit(1)),n instanceof b?d(`Stored credentials are invalid.`):c(`Stored credentials found, but validation could not complete.`),s({Profile:i,Credentials:`configured`,"Base URL":o,Source:Yr(u),Error:n instanceof Error?n.message:String(n)}),process.exit(1)}}),t.addCommand(Jr()),t}function Jr(){let t=new N(`profiles`).description(`Manage CLI profiles`);return t.command(`list`).description(`List configured profiles`).action(t=>{let n=dn();if(t.json){e(n);return}if(n.length===0){l(`No profiles found.`);return}i([`Profile`,`Active`,`Base URL`,`Credentials`,`Source`],n.map(e=>[e.name,e.active?`yes`:`no`,e.baseUrl,e.hasApiKey?`configured`:`none`,e.apiKeySource]))}),t.command(`use <name>`).description(`Set the active profile`).action(e=>{rn(e);let t=fn(e);r(`Active profile set to '${t.name}'.`),s({"Base URL":t.baseUrl,Credentials:t.credentialSource===`none`?`missing`:`configured`})}),t.command(`current`).description(`Show the active profile`).action(t=>{let n=fn();if(t.json){e({name:n.name,active:n.active,baseUrl:n.baseUrl,credentialSource:n.credentialSource});return}s({Profile:n.name,"Base URL":n.baseUrl,Credentials:n.credentialSource===`none`?`missing`:`configured`,Source:Yr(n.credentialSource)})}),t}function Yr(e){switch(e){case`flag`:return`command flag`;case`env`:return`environment`;case`keychain`:return`OS keychain`;case`file`:return`credentials file`;default:return`unknown`}}function Xr(e){let t=pn(e.profile,{apiKey:e.apiKey,...e.baseUrl?{baseUrl:e.baseUrl}:{}});e.activate!==!1&&rn(e.profile),tn(e.baseUrl&&e.profile===`default`?{baseUrl:e.baseUrl}:{}),Zr=Qr(e.profile,t)}let Zr=`Credentials updated.`;function Qr(e,t){return t===`keychain`?e===`default`?`API key saved to the OS keychain for the default profile`:`API key saved to the OS keychain for profile '${e}'`:t===`file`?e===`default`?`API key saved to ~/.tangle/credentials.json for the default profile`:`API key saved to ~/.tangle/credentials.json for profile '${e}'`:`Profile '${e}' updated.`}function $r(e){if(e===void 0||e===`github`||e===`google`||e===`microsoft`)return e;throw Error(`--provider must be one of: github, google, microsoft`)}function ei(e){if(e===void 0||e===`sandbox`||e===`solve`)return e??`sandbox`;throw Error(`--app must be one of: sandbox, solve`)}function ti(e,t){return Xt(e,t)}function ni(){let n=new N(`backend`).description(`Manage sandbox AI agent backend`);return n.command(`status <sandboxId-or-name>`).description(`Get backend agent status`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching backend status...`);a.start();let o=await(await q(i,r,t)).backend.status();a.stop(),n.json?e(o):(l(`Backend Type: ${o.type}`),l(`Status: ${o.status}`),o.version&&l(`Version: ${o.version}`),o.error&&l(`Error: ${o.error}`),o.capabilities&&l(`Capabilities: ${JSON.stringify(o.capabilities)}`))}),n.command(`configure <sandboxId-or-name>`).description(`Update backend configuration`).option(`--model <model>`,`Model id (e.g. provider/model)`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=f(`Updating backend config...`);o.start();let s=await q(a,i,t),c=n.model?{model:n.model}:{};await s.backend.updateConfig(c),o.stop(),r(`Backend configuration updated`),n.json&&e(c)}),n.command(`mcp-status <sandboxId-or-name>`).description(`Get status of MCP servers`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching MCP status...`);o.start();let s=await(await q(a,i,n)).backend.getMcpStatus();if(o.stop(),r.json)e(s);else{let e=Object.entries(s);e.length===0?l(`No MCP servers configured`):t(e.map(([e,t])=>{let n=t;return{name:e,status:n.status,error:n.error??``}}),[{key:`name`,header:`Name`,width:24},{key:`status`,header:`Status`,width:12},{key:`error`,header:`Error`,width:40}])}}),n.command(`restart <sandboxId-or-name>`).description(`Restart the backend agent`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Restarting backend...`);a.start(),await(await q(i,n,e)).backend.restart(),a.stop(),r(`Backend restarted`)}),n}function ri(e){let t=e.indexOf(`=`);if(t<=0)throw Error(`Invalid --task "${e}": expected format id=message (e.g. t1=summarize README)`);let n=e.slice(0,t).trim(),r=e.slice(t+1).trim();if(!n||!r)throw Error(`Invalid --task "${e}": id and message must be non-empty`);return{id:n,message:r}}function ii(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`--tasks file is not valid JSON: ${e.message}`)}let n=Array.isArray(t)?t:t?.tasks;if(!Array.isArray(n))throw Error(`--tasks file must contain an array or an object with a "tasks" array`);return n.map((e,t)=>{if(!e||typeof e!=`object`)throw Error(`--tasks[${t}] must be an object`);let n=e,r=typeof n.id==`string`?n.id.trim():``,i=typeof n.message==`string`?n.message:``;if(!r)throw Error(`--tasks[${t}].id must be a non-empty string`);if(!i.trim())throw Error(`--tasks[${t}].message must be a non-empty string`);let a={id:r,message:i};if(n.context!==void 0&&(typeof n.context!=`object`||n.context===null||Array.isArray(n.context)))throw Error(`--tasks[${t}].context must be a JSON object`);if(n.context!==void 0&&(a.context=n.context),n.timeoutMs!==void 0&&(!Number.isInteger(n.timeoutMs)||n.timeoutMs<=0))throw Error(`--tasks[${t}].timeoutMs must be a positive integer`);return n.timeoutMs!==void 0&&(a.timeoutMs=n.timeoutMs),a})}function ai(e){let t=e.readFile??(e=>Ie(e,`utf8`)),n=[];e.file&&n.push(...ii(t(e.file)));for(let t of e.inline??[])n.push(ri(t));if(n.length===0)throw Error(`No tasks provided. Use --tasks <file> and/or --task id=message.`);let r=new Set;for(let e of n){if(r.has(e.id))throw Error(`Duplicate task id: ${e.id}`);r.add(e.id)}return n}const oi=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function si(e){let t=e.trim(),n=t.indexOf(`/`);if(n<=0||n===t.length-1)throw Error(`--model must be in the form provider/model (got "${e}")`);return{provider:t.slice(0,n),model:t.slice(n+1)}}function ci(e){let t=e.indexOf(`=`);if(t<=0||t===e.length-1)throw Error(`Invalid --backend "${e}": expected format id=type (e.g. primary=opencode)`);let n=e.slice(0,t).trim(),r=e.slice(t+1).trim();if(!oi.test(n))throw Error(`Invalid backend id "${n}": use 1-128 letters, numbers, dots, underscores, or hyphens, starting with a letter or number`);if(!r||r.includes(`=`))throw Error(`Invalid --backend "${e}": type must be a non-empty backend name`);return{id:n,type:r}}function li(e,t){if(!e||e.length===0)throw Error(`No backends provided. Use --backend id=type or --request <file>.`);let n=e.map(ci),r=new Set;for(let e of n){if(r.has(e.id))throw Error(`Duplicate backend id: ${e.id}`);r.add(e.id)}if(t&&n.length!==1)throw Error(`--model requires exactly one backend; use a profile to configure models for multiple backends`);return t&&(n[0]={...n[0],model:si(t)}),n}function ui(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`--request file is not valid JSON: ${e.message}`)}try{return se(t)}catch(e){throw Error(`--request file is not a valid batch request: ${e.message}`)}}function di(e,t,n){return n?`${e} [${t}]`:e}function fi(e){let t=new Map;for(let n of e)t.set(n.taskId,(t.get(n.taskId)??0)+1);return new Set([...t.entries()].filter(([,e])=>e>1).map(([e])=>e))}function pi(){let t=new N(`batch`).description(`Run multiple agent tasks in parallel across sandboxes`);return t.command(`run`).description(`Execute a batch of tasks. Provide tasks via --tasks <file.json> and/or repeated --task id=message flags.`).option(`--tasks <file>`,`Path to a JSON file with an array of tasks (or {tasks: [...]})`).option(`--request <file>`,`Path to a complete batch request JSON file`).option(`--task <id=message>`,`Inline task, id=message. Repeatable.`,(e,t=[])=>[...t,e],[]).option(`--stream`,`Stream per-task events as they arrive`).option(`-t, --timeout <ms>`,`Per-task timeout in milliseconds`,`300000`).option(`--persistent`,`Keep sandboxes alive after completion`,!1).option(`--reuse-key <key>`,`Stable workspace identity required by --persistent`).option(`--replay-only`,`Rejoin existing keyed work; refuse missing custody`).option(`--idempotency-key <key>`,`Retry identity; keyed runs continue after disconnect`).option(`--backend <id=type>`,`Backend identity and type. Required and repeatable without --request.`,(e,t=[])=>[...t,e],[]).option(`--model <provider/model>`,`Model override when exactly one backend is selected`).action(async(t,n)=>{let r=new AbortController,i=!1,a=()=>{i||(i=!0,l(`Cancel requested — stopping stream...`),r.abort())};process.on(`SIGINT`,a),process.on(`SIGTERM`,a);try{let i;if(t.request){let e=[`tasks`,`task`,`backend`,`model`,`timeout`,`persistent`,`reuseKey`].filter(e=>n.getOptionValueSource(e)===`cli`);if(e.length>0){let t={reuseKey:`reuse-key`};throw Error(`--request cannot be combined with ${e.map(e=>`--${t[e]??e}`).join(`, `)}`)}i=ui(Ie(t.request,`utf8`))}else{let e=ai({file:t.tasks,inline:t.task}),n=li(t.backend,t.model),r=Number(t.timeout);if(!Number.isInteger(r)||r<=0)throw Error(`--timeout must be a positive integer number of milliseconds`);let a=!!t.persistent;if(a&&!t.reuseKey)throw Error(`--persistent requires --reuse-key`);if(!a&&t.reuseKey)throw Error(`--reuse-key requires --persistent`);i=se({tasks:e,timeoutMs:r,backends:n,...a?{persistent:!0,reuseKey:t.reuseKey}:{persistent:!1}})}let{tasks:a,backends:o}=i,{client:c}=G(t),u={signal:r.signal,replayOnly:!!t.replayOnly,...t.idempotencyKey?{idempotencyKey:t.idempotencyKey}:{}},d;if(t.stream){let e=t.json?console.error:console.log;l(`Streaming batch of ${a.length} task(s)...`),e();let n=c.streamBatch(i,u),r=o.length>1;for(;;){let t=await n.next();if(t.done){d=t.value;break}let i=t.value;switch(i.type){case`batch.started`:{let e=i.data;l(`Batch started (${e.taskCount} tasks, ${e.backendCount} backends)`);break}case`task.started`:{let t=i.data;e(j.dim(`→ ${di(t.taskId,t.backendId,r)} started`));break}case`task.retry`:{let t=i.data;e(j.yellow(`↻ ${di(t.taskId,t.backendId,r)} retry ${t.attempt}: ${t.error}`));break}case`task.completed`:{let t=i.data;e(j.green(`✓ ${di(t.taskId,t.backendId,r)} completed in ${t.durationMs}ms`+(t.retries?` (${t.retries} retries)`:``)));break}case`task.failed`:{let t=i.data;e(j.red(`✗ ${di(t.taskId,t.backendId,r)} failed: ${t.error}`));break}}}e()}else l(`Running batch of ${a.length} task(s)...`),d=await c.runBatch(i,u),t.json||console.log();if(t.json)e(d);else if(s({"Total tasks":d.totalTasks,"Total backends":d.totalBackends,"Total executions":d.totalExecutions,Succeeded:d.totalSuccess,Failed:d.totalFailure,"Total retries":d.totalRetries,"Success rate":`${d.successRate.toFixed(1)}%`}),!t.stream&&d.results.length>0){let e=fi(d.results);console.log(),console.log(j.bold(`Task Results`)),console.log(j.dim(`─`.repeat(40)));for(let t of d.results){let n=t.success?j.green(`✓`):j.red(`✗`),r=t.success?t.usage.inputTokens+t.usage.outputTokens:0,i=r>0?` • ${r} tokens`:``;console.log(`${n} ${di(t.taskId,t.backendId,e.has(t.taskId))} ${j.dim(`(${t.durationMs}ms, ${t.retries} retries${i})`)}`),t.success||console.log(j.red(` ${t.error}`))}}d.totalFailure>0&&(process.exitCode=1)}catch(n){let r=n instanceof Error&&`batchCustody`in n?n.batchCustody:void 0;if(r?.acceptance===`accepted`&&!(r.cleanup?.mode===`release`&&r.cleanup.isComplete)&&l(`Batch accepted; retirement receipt unproved.`),i){console.log(),l(`Batch cancelled.`),t.json&&n instanceof Error&&`batchCustody`in n&&e({ok:!1,batchCustody:n.batchCustody}),process.exitCode=130;return}H(n,t.json)}finally{process.off(`SIGINT`,a),process.off(`SIGTERM`,a)}}),t}function mi(){let n=new N(`branch`).description(`Branch a running sandbox into copy-on-write children`);return n.command(`create <sandbox-id-or-name>`).description(`Branch a running sandbox into N copy-on-write children`).option(`--count <n>`,`Number of children to create`,`1`).option(`--idempotency-key <key>`,`Retry identity: the same key and count replays the first fan-out and creates no second one`).action(async(n,i)=>{let a=Number.parseInt(i.count,10);if(!Number.isInteger(a)||a<1)throw Error(`--count must be an integer >= 1 (got ${i.count})`);let{context:o,client:s}=G(i),u=f(`Branching into ${a} child(ren)...`);u.start();let d=await q(s,o,n),p=await d.fork(a,{...i.idempotencyKey?{idempotencyKey:i.idempotencyKey}:{}}),m=p.children;u.stop(),i.json?e({children:m.map(e=>({sandboxId:e.id})),requestedCount:p.requestedCount,materializedCount:p.materializedCount,complete:p.complete,...p.idempotency?{idempotency:p.idempotency}:{}}):(p.complete?r(`Branched ${m.length} child(ren) from ${d.id}`):c(`Branched ${p.materializedCount} of ${p.requestedCount} requested child(ren) from ${d.id}`),p.idempotency?.outcome===`replayed`&&l(`Replayed an earlier fan-out under this key; created none.`),t(m.map(e=>({sandboxId:e.id})),[{key:`sandboxId`,header:`Child Sandbox`,width:28}]))}),n}const hi=[`codex`,`claude-code`,`nanoclaw`,`kimi-code`,`opencode`,`pi`,`openclaw`,`hermes`],gi=`https://intelligence.tangle.tools/v1/otlp`,_i=[`codex`,`claude-code`],vi=[`codex`,`claude-code`,`nanoclaw`],yi=[`SessionStart`,`UserPromptSubmit`,`PreToolUse`,`PostToolUse`,`Stop`],bi={codex:{kind:`native`,surface:`codex`,label:`Codex`,buildFiles:Pi},"claude-code":{kind:`native`,surface:`claude-code`,label:`Claude Code`,buildFiles:Fi},nanoclaw:{kind:`native`,surface:`nanoclaw`,label:`NanoClaw`,buildFiles:Fi},"kimi-code":{kind:`manual`,surface:`kimi-code`,label:`Kimi Code`,reason:`Kimi Code loads hooks through an explicit config file, so use standard OTLP env wiring until the native config adapter is verified.`},opencode:{kind:`manual`,surface:`opencode`,label:`OpenCode`,reason:`OpenCode hooks run as plugins; use standard OTLP env wiring until the native plugin adapter is verified.`},pi:{kind:`manual`,surface:`pi`,label:`Pi`,reason:`Pi hooks run through TypeScript extensions; use standard OTLP env wiring until the native extension adapter is verified.`},openclaw:{kind:`manual`,surface:`openclaw`,label:`OpenClaw`,reason:`OpenClaw project hooks require user opt-in; use standard OTLP env wiring until the hook toggle and adapter are verified.`},hermes:{kind:`manual`,surface:`hermes`,label:`Hermes`,reason:`Hermes project plugins require explicit enablement; use standard OTLP env wiring until the plugin adapter is verified.`}};function xi(e){let t=e.split(`,`).map(e=>e.trim()).filter(Boolean).flatMap(e=>Ni(e));return t.length===0?[..._i]:Ji(t)}function Si(e){return Object.hasOwn(bi,e)}function Ci(e=process.cwd()){return le(he(e))||`agent-workspace`}function wi(){return M(F(),`.tangle`,`intelligence.json`)}function Ti(e=wi()){if(!Pe(e))return null;let t=Gi(e),n=Yi(t,`apiKey`),r=Yi(t,`endpoint`),i=Yi(t,`serviceName`),a=Yi(t,`environment`);if(!n||!r||!i||!a)throw Error(`${e} is missing apiKey, endpoint, serviceName, or environment`);return{apiKey:n,endpoint:r,serviceName:i,environment:a}}async function Ei(e){let t=he(e.workspace),n=wi(),r=xi(e.selection),i=[],a=[],o=[],s={apiKey:e.apiKey,endpoint:Mi(e.endpoint),serviceName:e.serviceName,environment:e.environment};e.dryRun||Hi(n,s),o.push(n);for(let n of r){let r=bi[n];if(r.kind===`manual`){a.push({agent:r.surface,label:r.label,reason:r.reason});continue}i.push(r.surface);let s=t=>Di(e.hookCommand,r.surface,t);for(let n of r.buildFiles(s)){let r=M(t,n.relPath);if(e.dryRun){o.push(r);continue}Wi(r,JSON.parse(n.content),n.mode),o.push(r)}}return!e.smoke||e.dryRun?{configPath:n,written:o,agents:r,nativeAgents:i,manual:a}:{configPath:n,written:o,agents:r,nativeAgents:i,manual:a,smokeTraceId:await ki({agent:i[0]??r[0]??`codex`,event:`install.smoke`,endpoint:s.endpoint,apiKey:s.apiKey,serviceName:s.serviceName,environment:s.environment,sessionId:`install-smoke-${Date.now()}`,payload:{source:`tangle intelligence connect`}})}}function Di(e,t,n){return`${e.trim()} --agent ${t} --event ${n} --non-blocking`}function Oi(e){let t=BigInt(Date.now())*1000000n,n=Zi(16),r=Zi(8),i=e.sessionId??Ii(e.payload),a={"service.name":e.serviceName,"deployment.environment":e.environment,"tangle.agent.surface":e.agent,"tangle.agent.hook.event":e.event,"tangle.agent.hook.source":`local-hook`,...Li(e.payload)};return i&&(a[`session.id`]=i,a[`gen_ai.conversation.id`]=i,a[`tangle.sessionId`]=i),{body:{resourceSpans:[{resource:{attributes:[Qi(`service.name`,e.serviceName),Qi(`deployment.environment`,e.environment),Qi(`tangle.agent.surface`,e.agent)]},scopeSpans:[{scope:{name:`tangle.intelligence.agent-hook`,version:`1.0.0`},spans:[{traceId:n,spanId:r,name:`agent.${e.agent}.${e.event}`,kind:1,startTimeUnixNano:t.toString(),endTimeUnixNano:(t+1000000n).toString(),attributes:Object.entries(a).map(([e,t])=>Qi(e,t)),status:{code:1}}]}]}]},traceId:n}}async function ki(e){let{body:t,traceId:n}=Oi(e),r=await fetch(`${Mi(e.endpoint)}/v1/traces`,{method:`POST`,headers:{Authorization:`Bearer ${e.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(t)});if(!r.ok){let e=await r.text().catch(()=>``);throw Error(`OTLP smoke ingest failed: ${r.status}${e?` ${e}`:``}`)}return n}function Ai(e){return Mi(e).replace(/\/v1\/otlp$/,``).replace(/\/+$/,``)}async function ji(e){let t=`${Ai(e.endpoint)}/v1/onboarding/status`,n=await fetch(t,{headers:{Authorization:`Bearer ${e.apiKey}`},signal:e.timeoutMs&&e.timeoutMs>0?AbortSignal.timeout(e.timeoutMs):void 0});if(!n.ok){let e=await n.text().catch(()=>``);throw Error(`onboarding status request failed: ${n.status}${e?` ${e}`:``}`)}let r=await n.json();return{tracesSeen:!!r.tracesSeen,contentSeen:!!r.contentSeen,lastSeenAt:typeof r.lastSeenAt==`string`?r.lastSeenAt:null,windowDays:typeof r.windowDays==`number`?r.windowDays:7,byAgent:r.byAgent&&typeof r.byAgent==`object`?r.byAgent:{}}}function Mi(e){let t=e.trim().replace(/\/+$/,``);return t.endsWith(`/v1/traces`)?t.slice(0,-10):t.endsWith(`/v1/logs`)?t.slice(0,-8):t}function Ni(e){switch(e){case`local`:case`both`:return[..._i];case`all`:return[...vi];case`claude`:return[`claude-code`];case`kimi`:return[`kimi-code`];default:if(Si(e))return[e];throw Error(`agent must be one of: local, all, both, ${hi.join(`, `)}`)}}function Pi(e){let t=Object.fromEntries(yi.map(t=>[t,[{command:e(t),timeoutMs:3e3,blocking:!1,matcher:`*`}]]));return[{relPath:`.codex/hooks.json`,content:JSON.stringify({hooks:t},null,2)}]}function Fi(e){let t=Object.fromEntries(yi.map(t=>[t,[{matcher:`*`,hooks:[{type:`command`,command:e(t),timeout:3}]}]]));return[{relPath:`.claude/settings.json`,content:JSON.stringify({hooks:t},null,2)}]}function Ii(e){return zi(e,[`session.id`,`sessionId`,`session_id`,`conversationId`,`conversation_id`,`threadId`,`thread_id`,`transcriptId`,`transcript_id`])||process.env.TANGLE_SESSION_ID||process.env.CODEX_THREAD_ID||process.env.CLAUDE_SESSION_ID||process.env.OPENCODE_SESSION_ID}function Li(e){let t={},n=Ri(e,[`tool.name`,`toolName`,`tool_name`,`tool`]),r=Ri(e,[`command`,`cmd`,`shell_command`,`shellCommand`]),i=Ri(e,[`tool.input`,`toolInput`,`tool_input`,`input`,`arguments`,`args`]),a=Ri(e,[`tool.output`,`toolOutput`,`tool_output`,`output`,`result`]),o=Ri(e,[`tool.exit_code`,`exitCode`,`exit_code`,`status`]),s=Ri(e,[`tool.error.message`,`errorMessage`,`error_message`,`error`]);return n&&(t[`tool.name`]=n),r&&(t[`process.command`]=r),i&&(t[`tool.input.summary`]=i),a&&(t[`tool.output.summary`]=a),o&&(t[`tool.exit_code`]=o),s&&(t[`tool.error.message`]=s),t}function Ri(e,t){let n=Bi(e,t);if(n===void 0)return null;if(typeof n==`string`)return Vi(n);if(typeof n==`number`||typeof n==`boolean`||typeof n==`bigint`)return String(n);try{return Vi(JSON.stringify(n))}catch{return null}}function zi(e,t){let n=Bi(e,t);return typeof n==`string`&&n.length>0?n:void 0}function Bi(e,t){if(typeof e!=`object`||!e)return;let n=[e],r=new Set;for(;n.length;){let e=n.pop();if(typeof e!=`object`||!e||r.has(e))continue;r.add(e);let i=e;for(let e of t){let t=i[e];if(t!=null&&t!==``)return t}for(let e of Object.values(i))typeof e==`object`&&e&&n.push(e)}}function Vi(e){return e.length>4096?`${e.slice(0,4093)}...`:e}function Hi(e,t){Ui(e,`${JSON.stringify(t,null,2)}\n`)}function Ui(e,t){Fe(ue(e),{mode:448,recursive:!0});let n=`${e}.${process.pid}.tmp`;ze(n,t,{mode:384}),Re(n,e)}function Wi(e,t,n){Fe(ue(e),{recursive:!0});let r=Ki(Gi(e),t);ze(e,`${JSON.stringify(r,null,2)}\n`,{mode:n??420})}function Gi(e){if(!Pe(e))return{};let t=JSON.parse(Ie(e,`utf8`));if(!Xi(t))throw Error(`${e} must contain a JSON object`);return t}function Ki(e,t){let n={...e};for(let[e,r]of Object.entries(t)){let t=n[e];Xi(t)&&Xi(r)?n[e]=Ki(t,r):Array.isArray(t)&&Array.isArray(r)?n[e]=qi([...t,...r]):n[e]=r}return n}function qi(e){let t=new Set,n=[];for(let r of e){let e=JSON.stringify(r);t.has(e)||(t.add(e),n.push(r))}return n}function Ji(e){return[...new Set(e)]}function Yi(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function Xi(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&(Object.getPrototypeOf(e)===Object.prototype||Object.getPrototypeOf(e)===null)}function Zi(e){return ye(e).toString(`hex`)}function Qi(e,t){return{key:e,value:{stringValue:t}}}const $i=`tangle.opencode-exporter`,ea=16384;function ta(e){return e.length<=ea?e:`${e.slice(0,ea-1)}…`}function na(e,t){return{key:e,value:{stringValue:t}}}function ra(e){if(!e||typeof e!=`object`)return null;let t=e,n=st(t.type);return n?{type:n,properties:t.properties&&typeof t.properties==`object`?t.properties:void 0}:null}function ia(e,t){let n=[na(`event.name`,e),na(`gen_ai.system`,`opencode`),na(`service.name`,`opencode`)];return t&&(n.push(na(`session.id`,t)),n.push(na(`gen_ai.conversation.id`,t))),n}function aa(e){if(!e)return null;let t=e.part,n=e.info;return st(t?.sessionID)??st(n?.sessionID)??st(e.sessionID)??null}function oa(e,t){let n=st(e.role)??st(e.info?.role);if(n)return n.toLowerCase();let r=st(e.messageID),i=t?.(r)??null;return i?i.toLowerCase():null}function sa(e,t,n){let r=[],i=aa(e.properties),a=(n,r)=>({timeUnixNano:t,severityNumber:9,severityText:`INFO`,...n===null?{}:{body:{stringValue:ta(n)}},attributes:[...ia(e.type,i),...r]});if(e.type===`message.part.updated`){let t=e.properties?.part;if(!t)return r;let i=st(t.type);if(i===`text`||i===`reasoning`){let e=st(t.text);if(e){let i=oa(t,n)===`user`?nt:tt;r.push(a(e,[na(i,ta(e))]))}return r}if(i===`tool`){let e=st(t.tool),n=t.state,i=ct(n?.input),o=ct(n?.output),s=st(n?.error)??(typeof n?.error==`object`&&n?.error!==null?ct(n.error):null);if(e||i){let t=[];e&&t.push(na(it,e)),i&&t.push(na(rt,ta(i))),r.push(a(null,t))}let c=o??s;if(c){let t=[na(at,ta(c))];e&&t.push(na(it,e)),r.push(a(c,t))}return r}return r}if(e.type===`session.next.text.delta`||e.type===`session.next.text.ended`){let t=e.properties??{},n=st(t.text)??(e.type===`session.next.text.delta`?st(t.delta):null);return n&&r.push(a(n,[na(tt,ta(n))])),r}return r}function ca(e=process.env.OTEL_RESOURCE_ATTRIBUTES){if(!e)return null;for(let t of e.split(`,`)){let e=t.indexOf(`=`);if(e===-1||t.slice(0,e).trim()!==ot)continue;let n=t.slice(e+1).trim();if(n.length>0)return n}return null}function la(e,t){if(e.length===0)return null;let n=[na(`service.name`,`opencode`),na(`gen_ai.system`,`opencode`),na(`telemetry.sdk.name`,$i)];return t&&t.trim().length>0&&n.push(na(ot,t.trim())),{resourceLogs:[{resource:{attributes:n},scopeLogs:[{scope:{name:$i,version:`1.0.0`},logRecords:e}]}]}}function ua(e){return(e??process.env.OPENCODE_BASE_URL??`http://127.0.0.1:4096`).replace(/\/+$/,``)}async function da(e){let t=Mi(e.endpoint),n=await(e.fetchImpl??fetch)(`${t}/v1/logs`,{method:`POST`,headers:{Authorization:`Bearer ${e.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(e.request),signal:e.timeoutMs&&e.timeoutMs>0?AbortSignal.timeout(e.timeoutMs):void 0});if(!n.ok){let e=await n.text().catch(()=>``);throw Error(`OpenCode OTLP logs ingest failed: ${n.status}${e?` ${e}`:``}`)}}var fa=class extends Error{partial;constructor(e,t){let n=e instanceof Error?e.message:String(e);super(n),this.name=`OpencodeExporterError`,this.partial=t,e instanceof Error&&(this.cause=e)}};function pa(){return(BigInt(Date.now())*1000000n).toString()}async function ma(e){let t=ua(e.opencodeBaseUrl),n=e.nowUnixNano??pa,r=e.fetchImpl??fetch,i=e.subjectKey===void 0?ca():e.subjectKey,a=await r(`${t}/event`,{headers:{Accept:`text/event-stream`},signal:e.signal});if(!a.ok){let e=await a.text().catch(()=>``);throw Error(`OpenCode event subscribe failed: ${a.status} at ${t}/event${e?` ${e}`:``}. Is OpenCode running with 'opencode serve'?`)}if(!a.body)throw Error(`OpenCode event stream at ${t}/event returned no body — cannot subscribe`);let o={eventsSeen:0,contentEventsExported:0,recordsExported:0},s=new Map,c=e=>e?s.get(e)??null:null;try{for await(let t of oe(a.body,{signal:e.signal})){o.eventsSeen++;let a=ra(t.data);if(!a)continue;if(a.type===`message.updated`){let e=a.properties?.info,t=st(e?.id),n=st(e?.role);t&&n&&s.set(t,n);continue}let l=sa(a,n(),c),u=la(l,i);u&&(await da({endpoint:e.endpoint,apiKey:e.apiKey,request:u,timeoutMs:e.postTimeoutMs,fetchImpl:r}),o.contentEventsExported++,o.recordsExported+=l.length,e.onExport?.({eventType:a.type,records:l.length}))}}catch(e){if(e instanceof Error&&(e.name===`AbortError`||e.message.toLowerCase().includes(`abort`)))return o;throw new fa(e,o)}return o}function ha(e,t){let n=Number(e);if(!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}const ga=[`claude-code`,`codex`,`opencode`,`openclaw`,`hermes`,`nanoclaw`],_a={"claude-code":`Claude Code`,codex:`Codex`,opencode:`OpenCode`,openclaw:`OpenClaw`,hermes:`Hermes`,nanoclaw:`NanoClaw`};function va(e){return ga.includes(e)}function ya(e){return Pe(e)?Ie(e,`utf8`):``}function ba(e,t){Fe(ue(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;ze(n,t,{mode:384}),Me(n,384),Re(n,e)}const xa=`# >>> tangle intelligence (claude-code) >>>`,Sa=`# <<< tangle intelligence (claude-code) <<<`,Ca={full:[{key:`OTEL_LOG_USER_PROMPTS`,comment:`the user/task prompt text`},{key:`OTEL_LOG_TOOL_DETAILS`,comment:`tool arguments`},{key:`OTEL_LOG_TOOL_CONTENT`,comment:`full tool input+output bodies`},{key:`OTEL_LOG_RAW_API_BODIES`,comment:`full prompt+completion JSON (richest)`}],prompts:[{key:`OTEL_LOG_USER_PROMPTS`,comment:`the user/task prompt text`},{key:`OTEL_LOG_TOOL_DETAILS`,comment:`tool arguments`}],metadata:[]};function wa(e,t){return t===`env`?e:/\s/.test(e)?`"${e}"`:e}function Ta(e,t){let n=t===`shell`?`export `:t===`dockerfile`?`ENV `:``,r=[];for(let i of e){if(i.kind===`blank`){t===`shell`&&r.push(``);continue}if(i.kind===`comment`){t===`shell`&&r.push(`# ${i.text}`);continue}let e=t===`shell`&&i.comment?` # ${i.comment}`:``;r.push(`${n}${i.key}=${wa(i.value,t)}${e}`)}return r.join(`
134
- `)}function Ea(e){let t=Mi(e.endpoint),n=e.apiKey??"${TANGLE_API_KEY}",r=e.content??`full`,i=e.format??`shell`,a=[{kind:`comment`,text:`Enable + point Claude Code at Tangle (JSON protocol — matches our adapter)`},{kind:`set`,key:`CLAUDE_CODE_ENABLE_TELEMETRY`,value:`1`},{kind:`set`,key:`OTEL_EXPORTER_OTLP_PROTOCOL`,value:`http/json`},{kind:`set`,key:`OTEL_EXPORTER_OTLP_ENDPOINT`,value:t},{kind:`set`,key:`OTEL_EXPORTER_OTLP_HEADERS`,value:`Authorization=Bearer ${n}`}];e.projectKey?a.push({kind:`blank`},{kind:`comment`,text:`Groups your runs into a project so Tangle can roll up + automate per-project:`},{kind:`set`,key:`OTEL_RESOURCE_ATTRIBUTES`,value:`tangle.subject.key=${e.projectKey}`}):a.push({kind:`blank`},{kind:`comment`,text:`Label this project so Tangle rolls up + automates per-project (pick your own):`},{kind:`comment`,text:` export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=<your project>`}),a.push({kind:`blank`},{kind:`comment`,text:`CONTENT rides LOG EVENTS, so the logs exporter is MANDATORY.`},{kind:`set`,key:`OTEL_LOGS_EXPORTER`,value:`otlp`,comment:`required for prompt/completion/tool content`},{kind:`set`,key:`OTEL_METRICS_EXPORTER`,value:`otlp`,comment:`tokens / cost`},{kind:`set`,key:`OTEL_TRACES_EXPORTER`,value:`otlp`,comment:`spans (beta)`},{kind:`blank`});let o=Ca[r];if(o.length===0)a.push({kind:`comment`,text:`Content gates intentionally OFF (metadata-only: tokens, durations, tool names — no prompt/completion/tool bodies).`});else{a.push({kind:`comment`,text:`THE CONTENT GATES (all default OFF):`});for(let e of o)a.push({kind:`set`,key:e.key,value:`1`,comment:e.comment})}return Ta(a,i)}function Da(e){return[xa,Ea(e),Sa].join(`
135
- `)}function Oa(e,t){let n=e.indexOf(xa);if(n!==-1){let r=e.indexOf(Sa,n);if(r===-1)throw Error(`shell rc has a '${xa}' marker without its closing '${Sa}' — fix it by hand and re-run`);let i=r+43,a=`${e.slice(0,n)}${t}${e.slice(i)}`;return{contents:a,changed:a!==e}}return{contents:`${e.length===0?``:ka(e)}${t}\n`,changed:!0}}function ka(e){return e.endsWith(`
133
+ </html>`}const Lr=15*6e4,Rr=`sandbox`;function zr(e){return Number.isFinite(e)&&e>0?e:Lr}async function Br(e){let t=e.timeoutMs??Lr,n=Date.now(),r=await Vr({baseUrl:e.baseUrl,app:e.app??Rr,timeoutMs:t,provider:e.provider});for(e.onInstructions?.({userCode:r.user_code,verificationUrl:r.verification_uri,verificationUrlComplete:r.verification_uri_complete,expiresIn:r.expires_in,intervalSeconds:r.interval});;){if(Date.now()-n>t)throw new A(`Timed out waiting for device authorization to complete`,{timeoutMs:t});let i=await Hr({baseUrl:e.baseUrl,app:e.app??Rr,deviceCode:r.device_code,timeoutMs:t});if(i.status===`approved`)return i.data;let a=i.intervalSeconds*1e3;await new Promise(e=>setTimeout(e,a))}}async function Vr(e){let t=zr(e.timeoutMs),n=e.app!==Rr,r=await fetch(`${Ur(e.baseUrl)}${n?`/cross-site/device/start`:`/auth/cli/device/start`}`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`},body:JSON.stringify(n?{app:e.app,...e.provider?{provider:e.provider}:{}}:e.provider?{provider:e.provider}:{}),signal:AbortSignal.timeout(t)}).catch(t=>{throw new S(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),i=await r.json().catch(()=>null);if(!r.ok||!i?.success||!i.data?.device_code)throw Error(i?.error?.message||`Failed to start device login`);return i.data}async function Hr(e){let t=zr(e.timeoutMs),n=e.app!==Rr,r=await fetch(`${Ur(e.baseUrl)}${n?`/cross-site/device/poll`:`/auth/cli/device/poll`}`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`},body:JSON.stringify(n?{app:e.app,device_code:e.deviceCode}:{device_code:e.deviceCode}),signal:AbortSignal.timeout(t)}).catch(t=>{throw new S(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),i=await r.json().catch(()=>null);if(r.status===428&&i?.error?.code===`AUTHORIZATION_PENDING`)return{status:`pending`,intervalSeconds:typeof i.data?.interval==`number`&&i.data.interval>0?i.data.interval:5};if(!r.ok||!i?.success||!i.data?.api_key||!i.data.email)throw Error(i?.error?.message||`Failed to complete device authorization`);return{status:`approved`,data:{apiKey:i.data.api_key,email:i.data.email,name:i.data.name,tier:i.data.tier}}}function Ur(e){return e.replace(/\/$/,``)}async function Wr(e){let t=e.apiKey,n=Qr(e.app??`sandbox`),i=$r(n,e.profile),a=Zr(e.provider),o=n===`solve`?Cn(e.baseUrl):vn(e.baseUrl,i),c=e.browser!==!1,u=(t,a)=>{Jr({profile:i,apiKey:t,baseUrl:e.baseUrl?o:void 0,activate:n===`sandbox`}),Mn(),r(`Authenticated`),s({Profile:i,Email:a.email,Tier:a.tier,"Base URL":o}),l(Yr)};if(t&&!Zt(t)){d(`Invalid API key format. Keys should start with 'sk_' or 'sk-tan-'.`),process.exit(1);return}if(g(),!t){let t=c&&n===`sandbox`,r=f(t?`Starting browser login...`:`Starting device login...`);r.start();let i;try{i=t?await jr({baseUrl:o,provider:a,signal:e.signal,onLoginUrl:({loginUrl:e,browserOpened:t})=>{r.stop(),l(t?`Browser login opened.`:`Open this URL to continue browser login:`),console.log(e)}}):await Br({baseUrl:o,app:n,provider:a,onInstructions:({userCode:e,verificationUrl:t,verificationUrlComplete:i})=>{r.stop(),l(`Complete login in a browser on any device:`),s({"Verification URL":t,"Verification URL (prefilled)":i,"Device Code":e}),n===`solve`&&c&&Fr(i)}})}finally{r.stop()}u(i.apiKey,i);return}let p=f(`Validating credentials...`);p.start();let m=await Er({apiKey:t,baseUrl:o});p.stop(),u(t,m)}function Gr(){let t=new N(`auth`).description(`Manage authentication`);return t.command(`login`).description(`Authenticate with browser login, device code, or an API key`).option(`--no-browser`,`Use device-code login instead of opening a browser`).option(`--profile <name>`,`Profile name`).option(`--provider <provider>`,`Identity provider (github, google, microsoft)`).option(`--app <app>`,`Product to authorize (sandbox or solve)`,`sandbox`).action(Wr),t.command(`logout`).description(`Remove stored credentials`).option(`--profile <name>`,`Profile name`).option(`--app <app>`,`Product credentials to remove (sandbox or solve)`,`sandbox`).action(e=>{let t=$r(Qr(e.app),e.profile);fn(t),Mn(),r(`Logged out successfully.`),l(`Credentials removed for profile '${t}'.`)}),t.command(`status`).description(`Show current authentication status`).option(`--profile <name>`,`Profile name`).option(`--app <app>`,`Product credentials to check (sandbox or solve)`,`sandbox`).action(async t=>{let n=Qr(t.app),i=$r(n,t.profile),a=n===`solve`?hn(t.apiKey,i):mn(t.apiKey,i),o=n===`solve`?Cn(t.baseUrl):vn(t.baseUrl,i),u=n===`solve`?_n(t.apiKey,i):gn(t.apiKey,i);if(!a){if(t.json){e({authenticated:!1,reason:`missing_credentials`,profile:i,baseUrl:o,credentialSource:null});return}d(`Not authenticated`),l(`Run 'tangle auth login --profile ${i}' to authenticate.`),process.exit(1)}let p=t.json?null:f(`Checking credentials...`);p?.start();try{let d=await Er({apiKey:a,baseUrl:o}),f=n===`solve`?null:await Jn({...t.apiKey===void 0?{}:{apiKey:t.apiKey},...t.profile===void 0?{}:{profile:t.profile},sandboxBaseUrl:o});p?.stop();let m=f!==null&&!f.reachable&&f.refused,h=!m,g=f!==null&&!f.reachable&&!f.refused;if(t.json){e({authenticated:h,profile:i,baseUrl:o,credentialSource:u,account:d,...f?{sandbox:{authenticated:!0},platform:f}:{}}),h||process.exit(1);return}m?c(`Authenticated for sandbox only`):g?c(`Authenticated — the platform is unreachable right now`):r(`Authenticated`),s({Profile:i,Credentials:`configured`,"Base URL":o,Source:qr(u),Email:d.email,Tier:d.tier,...f?{Platform:f.reachable?`reachable (${f.baseUrl})`:`UNREACHABLE — ${f.reason}`}:{}}),g&&l(`Platform commands (keys, workflows, hub) will not work until the platform answers again. The stored credential is not the cause and does not need replacing.`),h||(l("Platform commands (keys, workflows, hub) will not work until this resolves. Set TANGLE_API_KEY to a key you minted in the console, or run `tangle auth login` again."),process.exit(1))}catch(n){p?.stop(),t.json&&(e({authenticated:!1,profile:i,baseUrl:o,credentialSource:u,error:n instanceof Error?n.message:String(n)}),process.exit(1)),n instanceof b?d(`Stored credentials are invalid.`):c(`Stored credentials found, but validation could not complete.`),s({Profile:i,Credentials:`configured`,"Base URL":o,Source:qr(u),Error:n instanceof Error?n.message:String(n)}),process.exit(1)}}),t.addCommand(Kr()),t}function Kr(){let t=new N(`profiles`).description(`Manage CLI profiles`);return t.command(`list`).description(`List configured profiles`).action(t=>{let n=ln();if(t.json){e(n);return}if(n.length===0){l(`No profiles found.`);return}i([`Profile`,`Active`,`Base URL`,`Credentials`,`Source`],n.map(e=>[e.name,e.active?`yes`:`no`,e.baseUrl,e.hasApiKey?`configured`:`none`,e.apiKeySource]))}),t.command(`use <name>`).description(`Set the active profile`).action(e=>{tn(e);let t=un(e);r(`Active profile set to '${t.name}'.`),s({"Base URL":t.baseUrl,Credentials:t.credentialSource===`none`?`missing`:`configured`})}),t.command(`current`).description(`Show the active profile`).action(t=>{let n=un();if(t.json){e({name:n.name,active:n.active,baseUrl:n.baseUrl,credentialSource:n.credentialSource});return}s({Profile:n.name,"Base URL":n.baseUrl,Credentials:n.credentialSource===`none`?`missing`:`configured`,Source:qr(n.credentialSource)})}),t}function qr(e){switch(e){case`flag`:return`command flag`;case`env`:return`environment`;case`keychain`:return`OS keychain`;case`file`:return`credentials file`;default:return`unknown`}}function Jr(e){let t=dn(e.profile,{apiKey:e.apiKey,...e.baseUrl?{baseUrl:e.baseUrl}:{}});e.activate!==!1&&tn(e.profile),$t(e.baseUrl&&e.profile===`default`?{baseUrl:e.baseUrl}:{}),Yr=Xr(e.profile,t)}let Yr=`Credentials updated.`;function Xr(e,t){return t===`keychain`?e===`default`?`API key saved to the OS keychain for the default profile`:`API key saved to the OS keychain for profile '${e}'`:t===`file`?e===`default`?`API key saved to ~/.tangle/credentials.json for the default profile`:`API key saved to ~/.tangle/credentials.json for profile '${e}'`:`Profile '${e}' updated.`}function Zr(e){if(e===void 0||e===`github`||e===`google`||e===`microsoft`)return e;throw Error(`--provider must be one of: github, google, microsoft`)}function Qr(e){if(e===void 0||e===`sandbox`||e===`solve`)return e??`sandbox`;throw Error(`--app must be one of: sandbox, solve`)}function $r(e,t){return Jt(e,t)}function ei(){let n=new N(`backend`).description(`Manage sandbox AI agent backend`);return n.command(`status <sandboxId-or-name>`).description(`Get backend agent status`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching backend status...`);a.start();let o=await(await q(i,r,t)).backend.status();a.stop(),n.json?e(o):(l(`Backend Type: ${o.type}`),l(`Status: ${o.status}`),o.version&&l(`Version: ${o.version}`),o.error&&l(`Error: ${o.error}`),o.capabilities&&l(`Capabilities: ${JSON.stringify(o.capabilities)}`))}),n.command(`configure <sandboxId-or-name>`).description(`Update backend configuration`).option(`--model <model>`,`Model id (e.g. provider/model)`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=f(`Updating backend config...`);o.start();let s=await q(a,i,t),c=n.model?{model:n.model}:{};await s.backend.updateConfig(c),o.stop(),r(`Backend configuration updated`),n.json&&e(c)}),n.command(`mcp-status <sandboxId-or-name>`).description(`Get status of MCP servers`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching MCP status...`);o.start();let s=await(await q(a,i,n)).backend.getMcpStatus();if(o.stop(),r.json)e(s);else{let e=Object.entries(s);e.length===0?l(`No MCP servers configured`):t(e.map(([e,t])=>{let n=t;return{name:e,status:n.status,error:n.error??``}}),[{key:`name`,header:`Name`,width:24},{key:`status`,header:`Status`,width:12},{key:`error`,header:`Error`,width:40}])}}),n.command(`restart <sandboxId-or-name>`).description(`Restart the backend agent`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Restarting backend...`);a.start(),await(await q(i,n,e)).backend.restart(),a.stop(),r(`Backend restarted`)}),n}function ti(e){let t=e.indexOf(`=`);if(t<=0)throw Error(`Invalid --task "${e}": expected format id=message (e.g. t1=summarize README)`);let n=e.slice(0,t).trim(),r=e.slice(t+1).trim();if(!n||!r)throw Error(`Invalid --task "${e}": id and message must be non-empty`);return{id:n,message:r}}function ni(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`--tasks file is not valid JSON: ${e.message}`)}let n=Array.isArray(t)?t:t?.tasks;if(!Array.isArray(n))throw Error(`--tasks file must contain an array or an object with a "tasks" array`);return n.map((e,t)=>{if(!e||typeof e!=`object`)throw Error(`--tasks[${t}] must be an object`);let n=e,r=typeof n.id==`string`?n.id.trim():``,i=typeof n.message==`string`?n.message:``;if(!r)throw Error(`--tasks[${t}].id must be a non-empty string`);if(!i.trim())throw Error(`--tasks[${t}].message must be a non-empty string`);let a={id:r,message:i};if(n.context!==void 0&&(typeof n.context!=`object`||n.context===null||Array.isArray(n.context)))throw Error(`--tasks[${t}].context must be a JSON object`);if(n.context!==void 0&&(a.context=n.context),n.timeoutMs!==void 0&&(!Number.isInteger(n.timeoutMs)||n.timeoutMs<=0))throw Error(`--tasks[${t}].timeoutMs must be a positive integer`);return n.timeoutMs!==void 0&&(a.timeoutMs=n.timeoutMs),a})}function ri(e){let t=e.readFile??(e=>Ie(e,`utf8`)),n=[];e.file&&n.push(...ni(t(e.file)));for(let t of e.inline??[])n.push(ti(t));if(n.length===0)throw Error(`No tasks provided. Use --tasks <file> and/or --task id=message.`);let r=new Set;for(let e of n){if(r.has(e.id))throw Error(`Duplicate task id: ${e.id}`);r.add(e.id)}return n}const ii=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function ai(e){let t=e.trim(),n=t.indexOf(`/`);if(n<=0||n===t.length-1)throw Error(`--model must be in the form provider/model (got "${e}")`);return{provider:t.slice(0,n),model:t.slice(n+1)}}function oi(e){let t=e.indexOf(`=`);if(t<=0||t===e.length-1)throw Error(`Invalid --backend "${e}": expected format id=type (e.g. primary=opencode)`);let n=e.slice(0,t).trim(),r=e.slice(t+1).trim();if(!ii.test(n))throw Error(`Invalid backend id "${n}": use 1-128 letters, numbers, dots, underscores, or hyphens, starting with a letter or number`);if(!r||r.includes(`=`))throw Error(`Invalid --backend "${e}": type must be a non-empty backend name`);return{id:n,type:r}}function si(e,t){if(!e||e.length===0)throw Error(`No backends provided. Use --backend id=type or --request <file>.`);let n=e.map(oi),r=new Set;for(let e of n){if(r.has(e.id))throw Error(`Duplicate backend id: ${e.id}`);r.add(e.id)}if(t&&n.length!==1)throw Error(`--model requires exactly one backend; use a profile to configure models for multiple backends`);return t&&(n[0]={...n[0],model:ai(t)}),n}function ci(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`--request file is not valid JSON: ${e.message}`)}try{return se(t)}catch(e){throw Error(`--request file is not a valid batch request: ${e.message}`)}}function li(e,t,n){return n?`${e} [${t}]`:e}function ui(e){let t=new Map;for(let n of e)t.set(n.taskId,(t.get(n.taskId)??0)+1);return new Set([...t.entries()].filter(([,e])=>e>1).map(([e])=>e))}function di(){let t=new N(`batch`).description(`Run multiple agent tasks in parallel across sandboxes`);return t.command(`run`).description(`Execute a batch of tasks. Provide tasks via --tasks <file.json> and/or repeated --task id=message flags.`).option(`--tasks <file>`,`Path to a JSON file with an array of tasks (or {tasks: [...]})`).option(`--request <file>`,`Path to a complete batch request JSON file`).option(`--task <id=message>`,`Inline task, id=message. Repeatable.`,(e,t=[])=>[...t,e],[]).option(`--stream`,`Stream per-task events as they arrive`).option(`-t, --timeout <ms>`,`Per-task timeout in milliseconds`,`300000`).option(`--persistent`,`Keep sandboxes alive after completion`,!1).option(`--reuse-key <key>`,`Stable workspace identity required by --persistent`).option(`--replay-only`,`Rejoin existing keyed work; refuse missing custody`).option(`--idempotency-key <key>`,`Retry identity; keyed runs continue after disconnect`).option(`--backend <id=type>`,`Backend identity and type. Required and repeatable without --request.`,(e,t=[])=>[...t,e],[]).option(`--model <provider/model>`,`Model override when exactly one backend is selected`).action(async(t,n)=>{let r=new AbortController,i=!1,a=()=>{i||(i=!0,l(`Cancel requested — stopping stream...`),r.abort())};process.on(`SIGINT`,a),process.on(`SIGTERM`,a);try{let i;if(t.request){let e=[`tasks`,`task`,`backend`,`model`,`timeout`,`persistent`,`reuseKey`].filter(e=>n.getOptionValueSource(e)===`cli`);if(e.length>0){let t={reuseKey:`reuse-key`};throw Error(`--request cannot be combined with ${e.map(e=>`--${t[e]??e}`).join(`, `)}`)}i=ci(Ie(t.request,`utf8`))}else{let e=ri({file:t.tasks,inline:t.task}),n=si(t.backend,t.model),r=Number(t.timeout);if(!Number.isInteger(r)||r<=0)throw Error(`--timeout must be a positive integer number of milliseconds`);let a=!!t.persistent;if(a&&!t.reuseKey)throw Error(`--persistent requires --reuse-key`);if(!a&&t.reuseKey)throw Error(`--reuse-key requires --persistent`);i=se({tasks:e,timeoutMs:r,backends:n,...a?{persistent:!0,reuseKey:t.reuseKey}:{persistent:!1}})}let{tasks:a,backends:o}=i,{client:c}=G(t),u={signal:r.signal,replayOnly:!!t.replayOnly,...t.idempotencyKey?{idempotencyKey:t.idempotencyKey}:{}},d;if(t.stream){let e=t.json?console.error:console.log;l(`Streaming batch of ${a.length} task(s)...`),e();let n=c.streamBatch(i,u),r=o.length>1;for(;;){let t=await n.next();if(t.done){d=t.value;break}let i=t.value;switch(i.type){case`batch.started`:{let e=i.data;l(`Batch started (${e.taskCount} tasks, ${e.backendCount} backends)`);break}case`task.started`:{let t=i.data;e(j.dim(`→ ${li(t.taskId,t.backendId,r)} started`));break}case`task.retry`:{let t=i.data;e(j.yellow(`↻ ${li(t.taskId,t.backendId,r)} retry ${t.attempt}: ${t.error}`));break}case`task.completed`:{let t=i.data;e(j.green(`✓ ${li(t.taskId,t.backendId,r)} completed in ${t.durationMs}ms`+(t.retries?` (${t.retries} retries)`:``)));break}case`task.failed`:{let t=i.data;e(j.red(`✗ ${li(t.taskId,t.backendId,r)} failed: ${t.error}`));break}}}e()}else l(`Running batch of ${a.length} task(s)...`),d=await c.runBatch(i,u),t.json||console.log();if(t.json)e(d);else if(s({"Total tasks":d.totalTasks,"Total backends":d.totalBackends,"Total executions":d.totalExecutions,Succeeded:d.totalSuccess,Failed:d.totalFailure,"Total retries":d.totalRetries,"Success rate":`${d.successRate.toFixed(1)}%`}),!t.stream&&d.results.length>0){let e=ui(d.results);console.log(),console.log(j.bold(`Task Results`)),console.log(j.dim(`─`.repeat(40)));for(let t of d.results){let n=t.success?j.green(`✓`):j.red(`✗`),r=t.success?t.usage.inputTokens+t.usage.outputTokens:0,i=r>0?` • ${r} tokens`:``;console.log(`${n} ${li(t.taskId,t.backendId,e.has(t.taskId))} ${j.dim(`(${t.durationMs}ms, ${t.retries} retries${i})`)}`),t.success||console.log(j.red(` ${t.error}`))}}d.totalFailure>0&&(process.exitCode=1)}catch(n){let r=n instanceof Error&&`batchCustody`in n?n.batchCustody:void 0;if(r?.acceptance===`accepted`&&!(r.cleanup?.mode===`release`&&r.cleanup.isComplete)&&l(`Batch accepted; retirement receipt unproved.`),i){console.log(),l(`Batch cancelled.`),t.json&&n instanceof Error&&`batchCustody`in n&&e({ok:!1,batchCustody:n.batchCustody}),process.exitCode=130;return}H(n,t.json)}finally{process.off(`SIGINT`,a),process.off(`SIGTERM`,a)}}),t}function fi(){let n=new N(`branch`).description(`Branch a running sandbox into copy-on-write children`);return n.command(`create <sandbox-id-or-name>`).description(`Branch a running sandbox into N copy-on-write children`).option(`--count <n>`,`Number of children to create`,`1`).option(`--idempotency-key <key>`,`Retry identity: the same key and count replays the first fan-out and creates no second one`).action(async(n,i)=>{let a=Number.parseInt(i.count,10);if(!Number.isInteger(a)||a<1)throw Error(`--count must be an integer >= 1 (got ${i.count})`);let{context:o,client:s}=G(i),u=f(`Branching into ${a} child(ren)...`);u.start();let d=await q(s,o,n),p=await d.fork(a,{...i.idempotencyKey?{idempotencyKey:i.idempotencyKey}:{}}),m=p.children;u.stop(),i.json?e({children:m.map(e=>({sandboxId:e.id})),requestedCount:p.requestedCount,materializedCount:p.materializedCount,complete:p.complete,...p.idempotency?{idempotency:p.idempotency}:{}}):(p.complete?r(`Branched ${m.length} child(ren) from ${d.id}`):c(`Branched ${p.materializedCount} of ${p.requestedCount} requested child(ren) from ${d.id}`),p.idempotency?.outcome===`replayed`&&l(`Replayed an earlier fan-out under this key; created none.`),t(m.map(e=>({sandboxId:e.id})),[{key:`sandboxId`,header:`Child Sandbox`,width:28}]))}),n}const pi=[`codex`,`claude-code`,`nanoclaw`,`kimi-code`,`opencode`,`pi`,`openclaw`,`hermes`],mi=`https://intelligence.tangle.tools/v1/otlp`,hi=[`codex`,`claude-code`],gi=[`codex`,`claude-code`,`nanoclaw`],_i=[`SessionStart`,`UserPromptSubmit`,`PreToolUse`,`PostToolUse`,`Stop`],vi={codex:{kind:`native`,surface:`codex`,label:`Codex`,buildFiles:Mi},"claude-code":{kind:`native`,surface:`claude-code`,label:`Claude Code`,buildFiles:Ni},nanoclaw:{kind:`native`,surface:`nanoclaw`,label:`NanoClaw`,buildFiles:Ni},"kimi-code":{kind:`manual`,surface:`kimi-code`,label:`Kimi Code`,reason:`Kimi Code loads hooks through an explicit config file, so use standard OTLP env wiring until the native config adapter is verified.`},opencode:{kind:`manual`,surface:`opencode`,label:`OpenCode`,reason:`OpenCode hooks run as plugins; use standard OTLP env wiring until the native plugin adapter is verified.`},pi:{kind:`manual`,surface:`pi`,label:`Pi`,reason:`Pi hooks run through TypeScript extensions; use standard OTLP env wiring until the native extension adapter is verified.`},openclaw:{kind:`manual`,surface:`openclaw`,label:`OpenClaw`,reason:`OpenClaw project hooks require user opt-in; use standard OTLP env wiring until the hook toggle and adapter are verified.`},hermes:{kind:`manual`,surface:`hermes`,label:`Hermes`,reason:`Hermes project plugins require explicit enablement; use standard OTLP env wiring until the plugin adapter is verified.`}};function yi(e){let t=e.split(`,`).map(e=>e.trim()).filter(Boolean).flatMap(e=>ji(e));return t.length===0?[...hi]:Ki(t)}function bi(e){return Object.hasOwn(vi,e)}function xi(e=process.cwd()){return le(he(e))||`agent-workspace`}function Si(){return M(F(),`.tangle`,`intelligence.json`)}function Ci(e=Si()){if(!Pe(e))return null;let t=Ui(e),n=qi(t,`apiKey`),r=qi(t,`endpoint`),i=qi(t,`serviceName`),a=qi(t,`environment`);if(!n||!r||!i||!a)throw Error(`${e} is missing apiKey, endpoint, serviceName, or environment`);return{apiKey:n,endpoint:r,serviceName:i,environment:a}}async function wi(e){let t=he(e.workspace),n=Si(),r=yi(e.selection),i=[],a=[],o=[],s={apiKey:e.apiKey,endpoint:Ai(e.endpoint),serviceName:e.serviceName,environment:e.environment};e.dryRun||Bi(n,s),o.push(n);for(let n of r){let r=vi[n];if(r.kind===`manual`){a.push({agent:r.surface,label:r.label,reason:r.reason});continue}i.push(r.surface);let s=t=>Ti(e.hookCommand,r.surface,t);for(let n of r.buildFiles(s)){let r=M(t,n.relPath);if(e.dryRun){o.push(r);continue}Hi(r,JSON.parse(n.content),n.mode),o.push(r)}}return!e.smoke||e.dryRun?{configPath:n,written:o,agents:r,nativeAgents:i,manual:a}:{configPath:n,written:o,agents:r,nativeAgents:i,manual:a,smokeTraceId:await Di({agent:i[0]??r[0]??`codex`,event:`install.smoke`,endpoint:s.endpoint,apiKey:s.apiKey,serviceName:s.serviceName,environment:s.environment,sessionId:`install-smoke-${Date.now()}`,payload:{source:`tangle intelligence connect`}})}}function Ti(e,t,n){return`${e.trim()} --agent ${t} --event ${n} --non-blocking`}function Ei(e){let t=BigInt(Date.now())*1000000n,n=Yi(16),r=Yi(8),i=e.sessionId??Pi(e.payload),a={"service.name":e.serviceName,"deployment.environment":e.environment,"tangle.agent.surface":e.agent,"tangle.agent.hook.event":e.event,"tangle.agent.hook.source":`local-hook`,...Fi(e.payload)};return i&&(a[`session.id`]=i,a[`gen_ai.conversation.id`]=i,a[`tangle.sessionId`]=i),{body:{resourceSpans:[{resource:{attributes:[Xi(`service.name`,e.serviceName),Xi(`deployment.environment`,e.environment),Xi(`tangle.agent.surface`,e.agent)]},scopeSpans:[{scope:{name:`tangle.intelligence.agent-hook`,version:`1.0.0`},spans:[{traceId:n,spanId:r,name:`agent.${e.agent}.${e.event}`,kind:1,startTimeUnixNano:t.toString(),endTimeUnixNano:(t+1000000n).toString(),attributes:Object.entries(a).map(([e,t])=>Xi(e,t)),status:{code:1}}]}]}]},traceId:n}}async function Di(e){let{body:t,traceId:n}=Ei(e),r=await fetch(`${Ai(e.endpoint)}/v1/traces`,{method:`POST`,headers:{Authorization:`Bearer ${e.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(t)});if(!r.ok){let e=await r.text().catch(()=>``);throw Error(`OTLP smoke ingest failed: ${r.status}${e?` ${e}`:``}`)}return n}function Oi(e){return Ai(e).replace(/\/v1\/otlp$/,``).replace(/\/+$/,``)}async function ki(e){let t=`${Oi(e.endpoint)}/v1/onboarding/status`,n=await fetch(t,{headers:{Authorization:`Bearer ${e.apiKey}`},signal:e.timeoutMs&&e.timeoutMs>0?AbortSignal.timeout(e.timeoutMs):void 0});if(!n.ok){let e=await n.text().catch(()=>``);throw Error(`onboarding status request failed: ${n.status}${e?` ${e}`:``}`)}let r=await n.json();return{tracesSeen:!!r.tracesSeen,contentSeen:!!r.contentSeen,lastSeenAt:typeof r.lastSeenAt==`string`?r.lastSeenAt:null,windowDays:typeof r.windowDays==`number`?r.windowDays:7,byAgent:r.byAgent&&typeof r.byAgent==`object`?r.byAgent:{}}}function Ai(e){let t=e.trim().replace(/\/+$/,``);return t.endsWith(`/v1/traces`)?t.slice(0,-10):t.endsWith(`/v1/logs`)?t.slice(0,-8):t}function ji(e){switch(e){case`local`:case`both`:return[...hi];case`all`:return[...gi];case`claude`:return[`claude-code`];case`kimi`:return[`kimi-code`];default:if(bi(e))return[e];throw Error(`agent must be one of: local, all, both, ${pi.join(`, `)}`)}}function Mi(e){let t=Object.fromEntries(_i.map(t=>[t,[{command:e(t),timeoutMs:3e3,blocking:!1,matcher:`*`}]]));return[{relPath:`.codex/hooks.json`,content:JSON.stringify({hooks:t},null,2)}]}function Ni(e){let t=Object.fromEntries(_i.map(t=>[t,[{matcher:`*`,hooks:[{type:`command`,command:e(t),timeout:3}]}]]));return[{relPath:`.claude/settings.json`,content:JSON.stringify({hooks:t},null,2)}]}function Pi(e){return Li(e,[`session.id`,`sessionId`,`session_id`,`conversationId`,`conversation_id`,`threadId`,`thread_id`,`transcriptId`,`transcript_id`])||process.env.TANGLE_SESSION_ID||process.env.CODEX_THREAD_ID||process.env.CLAUDE_SESSION_ID||process.env.OPENCODE_SESSION_ID}function Fi(e){let t={},n=Ii(e,[`tool.name`,`toolName`,`tool_name`,`tool`]),r=Ii(e,[`command`,`cmd`,`shell_command`,`shellCommand`]),i=Ii(e,[`tool.input`,`toolInput`,`tool_input`,`input`,`arguments`,`args`]),a=Ii(e,[`tool.output`,`toolOutput`,`tool_output`,`output`,`result`]),o=Ii(e,[`tool.exit_code`,`exitCode`,`exit_code`,`status`]),s=Ii(e,[`tool.error.message`,`errorMessage`,`error_message`,`error`]);return n&&(t[`tool.name`]=n),r&&(t[`process.command`]=r),i&&(t[`tool.input.summary`]=i),a&&(t[`tool.output.summary`]=a),o&&(t[`tool.exit_code`]=o),s&&(t[`tool.error.message`]=s),t}function Ii(e,t){let n=Ri(e,t);if(n===void 0)return null;if(typeof n==`string`)return zi(n);if(typeof n==`number`||typeof n==`boolean`||typeof n==`bigint`)return String(n);try{return zi(JSON.stringify(n))}catch{return null}}function Li(e,t){let n=Ri(e,t);return typeof n==`string`&&n.length>0?n:void 0}function Ri(e,t){if(typeof e!=`object`||!e)return;let n=[e],r=new Set;for(;n.length;){let e=n.pop();if(typeof e!=`object`||!e||r.has(e))continue;r.add(e);let i=e;for(let e of t){let t=i[e];if(t!=null&&t!==``)return t}for(let e of Object.values(i))typeof e==`object`&&e&&n.push(e)}}function zi(e){return e.length>4096?`${e.slice(0,4093)}...`:e}function Bi(e,t){Vi(e,`${JSON.stringify(t,null,2)}\n`)}function Vi(e,t){Fe(ue(e),{mode:448,recursive:!0});let n=`${e}.${process.pid}.tmp`;ze(n,t,{mode:384}),Re(n,e)}function Hi(e,t,n){Fe(ue(e),{recursive:!0});let r=Wi(Ui(e),t);ze(e,`${JSON.stringify(r,null,2)}\n`,{mode:n??420})}function Ui(e){if(!Pe(e))return{};let t=JSON.parse(Ie(e,`utf8`));if(!Ji(t))throw Error(`${e} must contain a JSON object`);return t}function Wi(e,t){let n={...e};for(let[e,r]of Object.entries(t)){let t=n[e];Ji(t)&&Ji(r)?n[e]=Wi(t,r):Array.isArray(t)&&Array.isArray(r)?n[e]=Gi([...t,...r]):n[e]=r}return n}function Gi(e){let t=new Set,n=[];for(let r of e){let e=JSON.stringify(r);t.has(e)||(t.add(e),n.push(r))}return n}function Ki(e){return[...new Set(e)]}function qi(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function Ji(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&(Object.getPrototypeOf(e)===Object.prototype||Object.getPrototypeOf(e)===null)}function Yi(e){return ye(e).toString(`hex`)}function Xi(e,t){return{key:e,value:{stringValue:t}}}const Zi=`tangle.opencode-exporter`,Qi=16384;function $i(e){return e.length<=Qi?e:`${e.slice(0,Qi-1)}…`}function ea(e,t){return{key:e,value:{stringValue:t}}}function ta(e){if(!e||typeof e!=`object`)return null;let t=e,n=st(t.type);return n?{type:n,properties:t.properties&&typeof t.properties==`object`?t.properties:void 0}:null}function na(e,t){let n=[ea(`event.name`,e),ea(`gen_ai.system`,`opencode`),ea(`service.name`,`opencode`)];return t&&(n.push(ea(`session.id`,t)),n.push(ea(`gen_ai.conversation.id`,t))),n}function ra(e){if(!e)return null;let t=e.part,n=e.info;return st(t?.sessionID)??st(n?.sessionID)??st(e.sessionID)??null}function ia(e,t){let n=st(e.role)??st(e.info?.role);if(n)return n.toLowerCase();let r=st(e.messageID),i=t?.(r)??null;return i?i.toLowerCase():null}function aa(e,t,n){let r=[],i=ra(e.properties),a=(n,r)=>({timeUnixNano:t,severityNumber:9,severityText:`INFO`,...n===null?{}:{body:{stringValue:$i(n)}},attributes:[...na(e.type,i),...r]});if(e.type===`message.part.updated`){let t=e.properties?.part;if(!t)return r;let i=st(t.type);if(i===`text`||i===`reasoning`){let e=st(t.text);if(e){let i=ia(t,n)===`user`?nt:tt;r.push(a(e,[ea(i,$i(e))]))}return r}if(i===`tool`){let e=st(t.tool),n=t.state,i=ct(n?.input),o=ct(n?.output),s=st(n?.error)??(typeof n?.error==`object`&&n?.error!==null?ct(n.error):null);if(e||i){let t=[];e&&t.push(ea(it,e)),i&&t.push(ea(rt,$i(i))),r.push(a(null,t))}let c=o??s;if(c){let t=[ea(at,$i(c))];e&&t.push(ea(it,e)),r.push(a(c,t))}return r}return r}if(e.type===`session.next.text.delta`||e.type===`session.next.text.ended`){let t=e.properties??{},n=st(t.text)??(e.type===`session.next.text.delta`?st(t.delta):null);return n&&r.push(a(n,[ea(tt,$i(n))])),r}return r}function oa(e=process.env.OTEL_RESOURCE_ATTRIBUTES){if(!e)return null;for(let t of e.split(`,`)){let e=t.indexOf(`=`);if(e===-1||t.slice(0,e).trim()!==ot)continue;let n=t.slice(e+1).trim();if(n.length>0)return n}return null}function sa(e,t){if(e.length===0)return null;let n=[ea(`service.name`,`opencode`),ea(`gen_ai.system`,`opencode`),ea(`telemetry.sdk.name`,Zi)];return t&&t.trim().length>0&&n.push(ea(ot,t.trim())),{resourceLogs:[{resource:{attributes:n},scopeLogs:[{scope:{name:Zi,version:`1.0.0`},logRecords:e}]}]}}function ca(e){return(e??process.env.OPENCODE_BASE_URL??`http://127.0.0.1:4096`).replace(/\/+$/,``)}async function la(e){let t=Ai(e.endpoint),n=await(e.fetchImpl??fetch)(`${t}/v1/logs`,{method:`POST`,headers:{Authorization:`Bearer ${e.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(e.request),signal:e.timeoutMs&&e.timeoutMs>0?AbortSignal.timeout(e.timeoutMs):void 0});if(!n.ok){let e=await n.text().catch(()=>``);throw Error(`OpenCode OTLP logs ingest failed: ${n.status}${e?` ${e}`:``}`)}}var ua=class extends Error{partial;constructor(e,t){let n=e instanceof Error?e.message:String(e);super(n),this.name=`OpencodeExporterError`,this.partial=t,e instanceof Error&&(this.cause=e)}};function da(){return(BigInt(Date.now())*1000000n).toString()}async function fa(e){let t=ca(e.opencodeBaseUrl),n=e.nowUnixNano??da,r=e.fetchImpl??fetch,i=e.subjectKey===void 0?oa():e.subjectKey,a=await r(`${t}/event`,{headers:{Accept:`text/event-stream`},signal:e.signal});if(!a.ok){let e=await a.text().catch(()=>``);throw Error(`OpenCode event subscribe failed: ${a.status} at ${t}/event${e?` ${e}`:``}. Is OpenCode running with 'opencode serve'?`)}if(!a.body)throw Error(`OpenCode event stream at ${t}/event returned no body — cannot subscribe`);let o={eventsSeen:0,contentEventsExported:0,recordsExported:0},s=new Map,c=e=>e?s.get(e)??null:null;try{for await(let t of oe(a.body,{signal:e.signal})){o.eventsSeen++;let a=ta(t.data);if(!a)continue;if(a.type===`message.updated`){let e=a.properties?.info,t=st(e?.id),n=st(e?.role);t&&n&&s.set(t,n);continue}let l=aa(a,n(),c),u=sa(l,i);u&&(await la({endpoint:e.endpoint,apiKey:e.apiKey,request:u,timeoutMs:e.postTimeoutMs,fetchImpl:r}),o.contentEventsExported++,o.recordsExported+=l.length,e.onExport?.({eventType:a.type,records:l.length}))}}catch(e){if(e instanceof Error&&(e.name===`AbortError`||e.message.toLowerCase().includes(`abort`)))return o;throw new ua(e,o)}return o}function pa(e,t){let n=Number(e);if(!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}const ma=[`claude-code`,`codex`,`opencode`,`openclaw`,`hermes`,`nanoclaw`],ha={"claude-code":`Claude Code`,codex:`Codex`,opencode:`OpenCode`,openclaw:`OpenClaw`,hermes:`Hermes`,nanoclaw:`NanoClaw`};function ga(e){return ma.includes(e)}function _a(e){return Pe(e)?Ie(e,`utf8`):``}function va(e,t){Fe(ue(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;ze(n,t,{mode:384}),Me(n,384),Re(n,e)}const ya=`# >>> tangle intelligence (claude-code) >>>`,ba=`# <<< tangle intelligence (claude-code) <<<`,xa={full:[{key:`OTEL_LOG_USER_PROMPTS`,comment:`the user/task prompt text`},{key:`OTEL_LOG_TOOL_DETAILS`,comment:`tool arguments`},{key:`OTEL_LOG_TOOL_CONTENT`,comment:`full tool input+output bodies`},{key:`OTEL_LOG_RAW_API_BODIES`,comment:`full prompt+completion JSON (richest)`}],prompts:[{key:`OTEL_LOG_USER_PROMPTS`,comment:`the user/task prompt text`},{key:`OTEL_LOG_TOOL_DETAILS`,comment:`tool arguments`}],metadata:[]};function Sa(e,t){return t===`env`?e:/\s/.test(e)?`"${e}"`:e}function Ca(e,t){let n=t===`shell`?`export `:t===`dockerfile`?`ENV `:``,r=[];for(let i of e){if(i.kind===`blank`){t===`shell`&&r.push(``);continue}if(i.kind===`comment`){t===`shell`&&r.push(`# ${i.text}`);continue}let e=t===`shell`&&i.comment?` # ${i.comment}`:``;r.push(`${n}${i.key}=${Sa(i.value,t)}${e}`)}return r.join(`
134
+ `)}function wa(e){let t=Ai(e.endpoint),n=e.apiKey??"${TANGLE_API_KEY}",r=e.content??`full`,i=e.format??`shell`,a=[{kind:`comment`,text:`Enable + point Claude Code at Tangle (JSON protocol — matches our adapter)`},{kind:`set`,key:`CLAUDE_CODE_ENABLE_TELEMETRY`,value:`1`},{kind:`set`,key:`OTEL_EXPORTER_OTLP_PROTOCOL`,value:`http/json`},{kind:`set`,key:`OTEL_EXPORTER_OTLP_ENDPOINT`,value:t},{kind:`set`,key:`OTEL_EXPORTER_OTLP_HEADERS`,value:`Authorization=Bearer ${n}`}];e.projectKey?a.push({kind:`blank`},{kind:`comment`,text:`Groups your runs into a project so Tangle can roll up + automate per-project:`},{kind:`set`,key:`OTEL_RESOURCE_ATTRIBUTES`,value:`tangle.subject.key=${e.projectKey}`}):a.push({kind:`blank`},{kind:`comment`,text:`Label this project so Tangle rolls up + automates per-project (pick your own):`},{kind:`comment`,text:` export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=<your project>`}),a.push({kind:`blank`},{kind:`comment`,text:`CONTENT rides LOG EVENTS, so the logs exporter is MANDATORY.`},{kind:`set`,key:`OTEL_LOGS_EXPORTER`,value:`otlp`,comment:`required for prompt/completion/tool content`},{kind:`set`,key:`OTEL_METRICS_EXPORTER`,value:`otlp`,comment:`tokens / cost`},{kind:`set`,key:`OTEL_TRACES_EXPORTER`,value:`otlp`,comment:`spans (beta)`},{kind:`blank`});let o=xa[r];if(o.length===0)a.push({kind:`comment`,text:`Content gates intentionally OFF (metadata-only: tokens, durations, tool names — no prompt/completion/tool bodies).`});else{a.push({kind:`comment`,text:`THE CONTENT GATES (all default OFF):`});for(let e of o)a.push({kind:`set`,key:e.key,value:`1`,comment:e.comment})}return Ca(a,i)}function Ta(e){return[ya,wa(e),ba].join(`
135
+ `)}function Ea(e,t){let n=e.indexOf(ya);if(n!==-1){let r=e.indexOf(ba,n);if(r===-1)throw Error(`shell rc has a '${ya}' marker without its closing '${ba}' — fix it by hand and re-run`);let i=r+43,a=`${e.slice(0,n)}${t}${e.slice(i)}`;return{contents:a,changed:a!==e}}return{contents:`${e.length===0?``:Da(e)}${t}\n`,changed:!0}}function Da(e){return e.endsWith(`
136
136
 
137
137
  `)?e:e.endsWith(`
138
- `)?`${e}\n`:`${e}\n\n`}function Aa(){let e=process.env.SHELL??``;return e.includes(`zsh`)?M(F(),`.zshrc`):e.includes(`bash`)?M(F(),`.bashrc`):M(F(),`.zshrc`)}function ja(e){if(e===`shell`||e===`env`||e===`dockerfile`)return e;throw Error(`--format must be one of: shell, env, dockerfile (got '${e}')`)}function Ma(e){if(e===`full`||e===`prompts`||e===`metadata`)return e;throw Error(`--content must be one of: full, prompts, metadata (got '${e}')`)}async function Na(e){let t=Ea({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format});if(console.log(t),e.format!==`shell`){console.log(),l(e.format===`env`?"Cron/container path: feed these to your service env (.env, `docker run --env-file`, k8s envFrom). No shell-rc edit, no TTY needed.":`Dockerfile path: paste these ENV lines into your image. No shell-rc edit, no TTY needed.`);return}if(console.log(),l(`Privacy tiers: --content full ships the whole conversation; --content prompts keeps task, prompts, and tool args only; --content metadata turns content off (telemetry still flows). Secrets are scrubbed server-side regardless.`),!e.write)return;let n=e.rcPath??Aa(),i=process.stdin.isTTY?await dr(`Append this idempotent block to ${n}? (y/N)`,`n`):`n`;if(i.toLowerCase()!==`y`&&i.toLowerCase()!==`yes`){console.log(),l(`Not writing. To append later: tangle connect claude-code --rc ${n}`);return}let a=Da({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format}),{contents:o,changed:s}=Oa(ya(n),a);if(!s){console.log(),r(`Already present in ${n} — nothing to change.`);return}ba(n,o),console.log(),r(`Wrote Tangle Intelligence env block to ${n}.`),l(`Reload your shell (e.g. 'source ${n}') before running the agent.`)}function Pa(e){let t=[],n={header:null,body:[]};for(let r of e.split(`
139
- `))Fa(r)?(t.push(n),n={header:r.trim(),body:[]}):n.body.push(r);return t.push(n),t.length>1&&t[0].header===null&&t[0].body.every(e=>e.trim()===``)&&t.shift(),t}function Fa(e){let t=e.trim();return t.startsWith(`[`)&&t.endsWith(`]`)&&!t.includes(`=`)||t.startsWith(`[[`)&&t.endsWith(`]]`)}function Ia(e){let t=[];for(let n of e)n.header!==null&&t.push(n.header),t.push(...n.body);return t.join(`
140
- `)}function La(e){return[{key:`environment`,line:`environment = "prod"`},{key:`log_user_prompt`,line:`log_user_prompt = true`},{key:`exporter`,line:`exporter = { otlp-http = { endpoint = "${Mi(e.endpoint)}/v1/logs", protocol = "json", headers = { "Authorization" = "Bearer ${e.apiKey??"${TANGLE_API_KEY}"}" } } }`}]}function Ra(e){let t=e.trim();if(t===``||t.startsWith(`#`))return null;let n=t.indexOf(`=`);if(n===-1)return null;let r=t.slice(0,n).trim();return/^[A-Za-z0-9_-]+$/.test(r)?r:null}function za(e,t){let n=La(t),r=new Set(n.map(e=>e.key));if(e.trim()===``)return{contents:`${[`[otel]`,...n.map(e=>e.line)].join(`
141
- `)}\n`,changed:!0};let i=Pa(e),a=i.find(e=>e.header===`[otel]`);if(!a){let t={header:`[otel]`,body:n.map(e=>e.line)},r=i[i.length-1];r&&!Ba(r)&&r.body.push(``),i.push(t);let a=Va(Ia(i));return{contents:a,changed:a!==Va(e)}}let o=a.body.filter(e=>{let t=Ra(e);return t===null||!r.has(t)}),s=[];for(;o.length>0&&o[o.length-1].trim()===``;)s.unshift(o.pop());a.body=[...o,...n.map(e=>e.line),...s];let c=Va(Ia(i));return{contents:c,changed:c!==Va(e)}}function Ba(e){return e.body.length>0&&e.body[e.body.length-1].trim()===``}function Va(e){return e.endsWith(`
142
- `)?e:`${e}\n`}function Ha(e){let t=M(F(),`.codex`,`config.toml`),{contents:n,changed:i}=za(ya(t),{endpoint:e.endpoint,apiKey:e.apiKey});if(!e.write){console.log(n.trimEnd());return}if(!i){r(`${t} already has the Tangle [otel] block — nothing to change.`);return}ba(t,n),r(`Merged the Tangle [otel] block into ${t}.`),l("Codex emits content on the logs signal (codex.* events). Set TANGLE_API_KEY in your env before running if you kept the ${TANGLE_API_KEY} reference."),l(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=${e.projectKey??`<your project>`} before running codex.`)}function Ua(e){switch(e){case`claude-code`:return`Claude Code: set OTEL_LOGS_EXPORTER=otlp and the four OTEL_LOG_* gates (OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_DETAILS, OTEL_LOG_TOOL_CONTENT, OTEL_LOG_RAW_API_BODIES).`;case`codex`:return`Codex: set log_user_prompt = true in [otel] (default false redacts content).`;case`opencode`:return`OpenCode: a standalone install emits nothing without the tangle-opencode-exporter shim; inside a Tangle sandbox it is already instrumented.`;case`openclaw`:case`hermes`:case`nanoclaw`:return`${_a[e]}: no native OTLP exporter and no standalone server to subscribe to — run it inside a Tangle sandbox, where the sidecar adapter exports its content with gen_ai.system=${e}. A bare standalone install emits metadata only.`}}async function Wa(e){let t=Date.now()+e.timeoutSeconds*1e3,n=3e3,r=Math.min(e.timeoutSeconds*1e3,1e4),i=f(`Checking whether content is flowing…`);i.start();let a;try{for(;;){try{a=await ji({endpoint:e.endpoint,apiKey:e.apiKey,timeoutMs:r})}catch(e){if(Date.now()>=t)throw e;await et(n);continue}if(a.contentSeen||Date.now()>=t)break;await et(n)}}finally{i.stop()}if(!a)throw Error(`onboarding status check returned no result`);Ga(a,e.agent),a.contentSeen||(process.exitCode=1)}function Ga(e,t){if(e.contentSeen){r(`Content flowing — Tangle Intelligence can analyze this feed.`),s({"Last seen":e.lastSeenAt??`just now`,Window:`${e.windowDays}d`});return}if(e.tracesSeen){c(`Metadata-only — traces are arriving but carry no content. You missed a content gate.`);let n=t?[t]:Object.keys(e.byAgent).filter(va),r=n.length>0?n:ga;for(let n of r){let r=e.byAgent[n];(t||!r||r.tracesSeen&&!r.contentSeen)&&l(Ua(n))}return}c(`No traces yet for your tenant. Run your agent once on a real task, then re-run --verify.`),t&&l(Ua(t))}function Ka(e){let t=e??process.env.TANGLE_INTELLIGENCE_API_KEY??gn(void 0);if(!t)throw Error(`No Tangle API key found. Pass --api-key, set TANGLE_API_KEY, or run: tangle auth login`);return t}function qa(){return new N(`connect`).description(`Connect a local coding agent's telemetry to Tangle Intelligence, content on (for SDK integration snippets, see 'tangle agent connect')`).argument(`[agent]`,`claude-code | codex | opencode | openclaw | hermes | nanoclaw`).option(`--endpoint <url>`,`OTLP endpoint base`,gi).option(`-p, --project <key>`,`Project label (tangle.subject.key) to group runs; omit to set it yourself`).option(`--rc <path>`,`Shell rc file to append the Claude Code env block to`).option(`--no-write`,`Print the config instead of writing files (Claude Code / Codex)`).option(`--inline-key`,"Embed the resolved API key literally in the config (default: keep ${TANGLE_API_KEY})").option(`--verify`,`Poll onboarding status and report whether CONTENT is flowing`).option(`--timeout <seconds>`,`Verify poll timeout in seconds`,`120`).option(`--run`,`OpenCode only: run the content exporter against a live OpenCode server until interrupted`).option(`--opencode-url <url>`,`OpenCode server base URL for --run (or set OPENCODE_BASE_URL)`).option(`--format <kind>`,`Claude Code output: shell (export block) | env (.env / docker --env-file) | dockerfile (ENV lines). env/dockerfile are the cron/container path — printed to stdout, no shell-rc edit, no TTY`,`shell`).option(`--content <tier>`,`Claude Code content tier: full (everything) | prompts (task+prompts+tool-args) | metadata (telemetry on, content off)`,`full`).action(async(e,t)=>{let n=Mi(t.endpoint);if(t.run){if((e?Ya(e):`opencode`)!==`opencode`)throw Error(`--run is OpenCode-only: it runs the content exporter against a live OpenCode server. Other agents export natively once configured.`);await $a({endpoint:n,apiKey:Ka(t.apiKey),opencodeUrl:t.opencodeUrl});return}if(t.verify){await Wa({endpoint:n,apiKey:Ka(t.apiKey),agent:e?Ya(e):void 0,timeoutSeconds:ha(t.timeout,`--timeout`)});return}let r=e?Ya(e):await Xa(),i=t.inlineKey?Ka(t.apiKey):void 0;r===`claude-code`?await Na({endpoint:n,apiKey:i,projectKey:t.project,rcPath:t.rc,write:t.write!==!1,content:Ma(t.content),format:ja(t.format)}):r===`codex`?Ha({endpoint:n,apiKey:i,projectKey:t.project,write:t.write!==!1}):r===`opencode`?Za({endpoint:n}):Qa(r,{endpoint:n}),console.log(),l(`Run your agent on a real task, then verify content is flowing: tangle connect ${r} --verify`)})}function Ja(){return new N(`opencode-exporter`).description(`Export a running OpenCode's content to Tangle Intelligence (standalone shim)`).option(`--endpoint <url>`,`OTLP endpoint base`,gi).option(`--opencode-url <url>`,`OpenCode server base URL (or set OPENCODE_BASE_URL)`).action(async e=>{await $a({endpoint:Mi(e.endpoint),apiKey:Ka(e.apiKey),opencodeUrl:e.opencodeUrl})})}function Ya(e){if(va(e))return e;throw Error(`Unknown agent '${e}'. Choose one of: ${ga.join(`, `)}`)}async function Xa(){if(!process.stdin.isTTY)throw Error(`Specify an agent: tangle connect <${ga.join(`|`)}>`);console.log(`Which coding agent are you connecting?`),ga.forEach((e,t)=>{console.log(` ${t+1}) ${_a[e]} (${e})`)});let e=await dr(`Enter a number or name`,`1`);return ga[Number.parseInt(e,10)-1]||Ya(e.trim())}function Za(e){let t=Mi(e.endpoint);c(`OpenCode has no native OTel exporter, so a standalone install emits nothing without a shim.`),console.log(),s({"Inside a Tangle sandbox":`already instrumented — our adapter exports OpenCode's event-stream content. Nothing to do.`,Standalone:`run 'tangle connect opencode --run' alongside a running OpenCode, exporting to ${t}.`}),console.log(),l(`Start OpenCode in server mode ('opencode serve'), then in another terminal run: tangle connect opencode --run`),l(`The exporter subscribes to OpenCode's SSE event bus and exports content-bearing OTLP (prompt/completion/tool content) to Tangle. Verify with: tangle connect opencode --verify`),l(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting the exporter.`)}function Qa(e,t){let n=Mi(t.endpoint),r=_a[e];c(`${r} has no native OTel exporter, so a standalone install emits nothing without instrumentation.`),console.log(),s({"Inside a Tangle sandbox":`already instrumented — the sidecar adapter exports ${r}'s prompt/completion/tool content (gen_ai.system=${e}) to ${n}. Nothing to do.`,Standalone:`${r} exposes no OTLP and no event-bus server; run it inside a Tangle sandbox to capture content.`}),console.log(),l(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting ${r}.`),l(`Verify content is flowing: tangle connect ${e} --verify`)}async function $a(e){let t=ua(e.opencodeUrl),n=new AbortController,i=()=>n.abort();process.on(`SIGINT`,i),process.on(`SIGTERM`,i),l(`Subscribing to OpenCode at ${t} — exporting content to Tangle.`),l(`Run OpenCode tasks now. Press Ctrl-C to stop.`),console.log();let a=0,o;try{o=await ma({endpoint:e.endpoint,apiKey:e.apiKey,opencodeBaseUrl:t,signal:n.signal,onExport:({eventType:e,records:t})=>{a+=t,l(`exported ${t} record(s) from ${e} (total ${a})`)}})}catch(e){if(e instanceof fa){let{recordsExported:t,contentEventsExported:n}=e.partial;console.log(),c(`Exporter failed after exporting ${t} content record(s) from ${n} event(s): ${e.message}`)}throw e}finally{process.off(`SIGINT`,i),process.off(`SIGTERM`,i)}if(console.log(),o.contentEventsExported===0){c(`Saw ${o.eventsSeen} event(s) but none carried content. Run a real OpenCode task (a prompt that produces text or a tool call), then re-run.`);return}r(`Exported ${o.recordsExported} content record(s) from ${o.contentEventsExported} event(s).`),l(`Verify it landed: tangle connect opencode --verify`)}function eo(){let t=new N(`environments`).alias(`env`).description(`Manage sandbox environments`);return t.command(`list`).alias(`ls`).description(`List available environments`).action(async t=>{let{client:n}=G(t),r=f(`Fetching environments...`);t.json||r.start();let a=await n.environments.list();r.stop(),t.json?e(a):a.length===0?console.log(`No environments found`):i([`ID`,`Description`,`Version`,`Runtimes`],a.map(e=>[e.id,e.description??``,e.version,e.runtimes.join(`, `)]))}),t.command(`get`).description(`Get environment details`).argument(`<id>`,`Environment ID`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Fetching environment...`);n.json||i.start();let a=await r.environments.get(t);if(i.stop(),!a){console.error(`Environment not found: ${t}`),process.exit(1);return}n.json?e(a):(console.log(`ID: ${a.id}`),console.log(`Description: ${a.description??`-`}`),console.log(`Version: ${a.version}`),console.log(`Runtimes: ${a.runtimes.join(`, `)}`),a.base&&console.log(`Base: ${a.base}`))}),t}const to=I.string().trim().toLowerCase().min(1).max(64).regex(/^[a-z][a-z0-9-]*$/),no=I.string().trim().toLowerCase().min(1).max(128).regex(/^[a-z0-9][a-z0-9._-]*$/),ro=I.object({kind:no,count:I.number().int().positive().default(1),vramGb:I.number().positive().optional()}).strict();I.object({command:I.string().min(1).max(8192),timeoutMs:I.number().int().positive().max(2147453647).optional(),env:I.record(I.string(),I.string()).optional(),cwd:I.string().min(1).max(2048).optional()}).strict(),I.object({refresh:I.enum([`true`,`false`]).optional(),acceleratorKind:no.optional(),acceleratorCount:I.coerce.number().pipe(ro.shape.count.unwrap()).optional(),acceleratorVramGb:I.coerce.number().positive().optional()}).strict(),I.object({maxSpendUsd:I.number().positive().max(1e4).optional(),maxLifetimeSeconds:I.number().int().positive().max(1440*60).optional()}).strict().refine(e=>e.maxSpendUsd!==void 0||e.maxLifetimeSeconds!==void 0,`Renewal requires a lifetime or spend cap`);const io=I.object({provider:to.optional(),image:I.string().min(1).max(512).optional(),env:I.record(I.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),I.string()).optional(),diskGb:I.number().int().positive().optional(),volumeGb:I.number().int().nonnegative().optional(),volumeMountPath:I.string().startsWith(`/`).max(2048).optional(),region:I.string().min(1).max(128).optional(),manifest:I.record(I.string(),I.unknown()).optional(),command:I.array(I.string().max(8192)).min(1).max(256).optional(),ports:I.array(I.number().int().min(1).max(65535)).max(32).optional(),endpoint:I.object({port:I.number().int().min(1).max(65535),healthPath:I.string().regex(/^\/(?![/\\])/).refine(e=>![`\r`,`
143
- `,` `].some(t=>e.includes(t))).max(2048).optional()}).strict().optional(),allowSpot:I.boolean().optional(),maxHourlyUsd:I.number().positive().optional(),weights:I.object({manifestSha:I.string().regex(/^[a-f0-9]{64}$/),sizeBytes:I.number().int().positive().safe()}).strict().optional(),arms:I.array(I.unknown()).min(1).max(256).optional(),maxSpendUsd:I.number().positive().max(1e4),maxLifetimeSeconds:I.number().int().positive().max(1440*60),idleTimeoutSeconds:I.number().int().positive().optional()}).strict();io.extend({accelerator:ro});const ao=ro,oo=to;I.object({...io.omit({env:!0}).shape,id:I.string(),projectRef:I.string(),ownerUserId:I.string(),productId:I.string().optional(),provider:oo,providerLeaseId:I.string().optional(),providerInstanceType:I.string().optional(),endpointUrl:I.string().optional(),status:I.enum([`provisioning`,`ready`,`detaching`,`destroyed`,`failed`]),accelerator:ao,providerCostPerHourUsd:I.number().optional(),customerPricePerHourUsd:I.number().optional(),estimatedProviderCostUsd:I.number().optional(),estimatedCustomerCostUsd:I.number().optional(),providerSelection:I.object({strategy:I.enum([`explicit`,`cheapest`,`ranked`]),selectedProvider:oo,requestedProvider:oo.optional(),candidates:I.array(I.object({provider:oo,accelerator:ao,providerInstanceType:I.string().optional(),region:I.string().optional(),pricingSource:I.enum([`live`,`configured`]).optional(),providerCostPerHourUsd:I.number(),customerPricePerHourUsd:I.number(),maxLifetimeSeconds:I.number(),estimatedProviderCostUsd:I.number(),estimatedCustomerCostUsd:I.number()})),rejected:I.array(I.object({provider:oo,error:I.string()}))}).optional(),createdAt:I.string(),updatedAt:I.string(),readyAt:I.string().optional(),startedAt:I.string().optional(),lastUsedAt:I.string().optional(),destroyedAt:I.string().optional(),failure:I.string().optional(),billing:I.object({seconds:I.number(),providerCostUsd:I.number(),customerCostUsd:I.number(),providerCostPerHourUsd:I.number(),customerPricePerHourUsd:I.number(),startedAt:I.string(),stoppedAt:I.string()}).optional()});function so(e){return{kind:go(e.kind),count:e.count?ho(e.count,`--accelerator-count`):1,...e.memory?{vramGb:vo(e.memory,`--accelerator-memory`)}:{}}}function co(e,t,n){if(!t&&Object.values(e).some(Boolean))throw Error(n);return t?uo(e,`--gpu-`):void 0}function lo(e){return{...uo(e,`--`),accelerator:so({kind:e.acceleratorKind,count:e.acceleratorCount,memory:e.acceleratorMemory})}}function uo(e,t){let{provider:n,image:r,env:i,maxSpendUsd:a,maxLifetime:o,idleTimeout:s}=e;if(!a||!o)throw Error(`--accelerator-kind requires ${t}max-spend-usd and ${t}max-lifetime`);return{...n?{provider:_o(n,`${t}provider`)}:{},...r?{image:r}:{},...i?{env:mo(i,`${t}env`,`env`)}:{},maxSpendUsd:vo(a,`${t}max-spend-usd`),maxLifetimeSeconds:ho(o,`${t}max-lifetime`),...s?{idleTimeoutSeconds:ho(s,`${t}idle-timeout`)}:{}}}function fo(e){return e.length===1?e[0]:e.map(ut).join(` `)}function po(e){return{timeoutMs:e.timeout?ho(String(e.timeout),`--timeout`):void 0,env:e.env?mo(e.env,`--env`,`env`):void 0}}function mo(e,t,n){let r={};for(let i of e){let[e,...a]=i.split(`=`);if(!e||a.length===0)throw Error(`${t} expects ${n} values in KEY=VALUE format`);r[e]=a.join(`=`)}return r}function ho(e,t){if(!/^\d+$/.test(e))throw Error(`${t} must be a positive integer`);let n=Number.parseInt(e,10);if(Number.isNaN(n)||n<1)throw Error(`${t} must be a positive integer`);return n}function go(e){let t=no.safeParse(e);if(t.success)return t.data;throw Error(`--accelerator-kind must contain only letters, numbers, dots, underscores, or hyphens`)}function _o(e,t){let n=to.safeParse(e);if(n.success)return n.data;throw Error(`${t} must start with a letter and contain only letters, numbers, or hyphens`)}function vo(e,t){if(!/^(?:\d+|\d+\.\d+|\.\d+)$/.test(e))throw Error(`${t} must be a positive number`);let n=Number.parseFloat(e);if(!Number.isFinite(n)||n<=0)throw Error(`${t} must be a positive number`);return n}function yo(){return new N(`exec`).description(`Execute a command in a sandbox`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<command...>`,`Command and arguments, or one shell script`).option(`--cwd <dir>`,`Working directory`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).option(`-t, --timeout <ms>`,`Timeout in milliseconds`,`60000`).allowUnknownOption(!0).action(async(t,n,r)=>{try{let{context:i,client:a}=G(r),o=fo(n),s=mo(r.env??[],`--env`,`env`),c=f(`Executing: ${o}`);r.json||c.start();let l=await q(a,i,t);l=await J(l);let u=await l.exec(o,{cwd:r.cwd,env:Object.keys(s).length>0?s:void 0,timeoutMs:Number.parseInt(r.timeout,10)});c.stop(),r.json?e(u):(u.stdout&&process.stdout.write(u.stdout),u.stderr&&process.stderr.write(u.stderr)),u.exitCode!==0&&(process.exitCode=u.exitCode)}catch(e){if(e instanceof S){let t=`Exec transport lost before command status was confirmed. Remote command status is unknown. Original error: ${e.message}. For long-running commands, use \`tangle process spawn\`, \`tangle process logs\`, and \`tangle process kill --tree\`.`;return H(Error(t,{cause:e}))}H(e)}})}function bo(n){n.command(`capabilities`).description(`List fleet drivers and their supported features`).action(async n=>{let{client:r}=G(n),i=f(`Fetching capabilities...`);i.start();let a=await r.fleets.capabilities();i.stop(),n.json?e(a):t(a.drivers,[{key:`driverType`,header:`Driver`,width:16},{key:`sharedWorkspace`,header:`Shared WS`,width:12},{key:`accelerators`,header:`Accel`,width:8},{key:`queueTimings`,header:`Queue`,width:8}])}),n.command(`usage <fleet-id>`).description(`Show fleet usage and reliability insights`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Fetching usage...`);i.start();let a=await r.fleets.usage(t);if(i.stop(),n.json)e(a);else if(s({"Fleet ID":a.usage.fleetId,Status:a.usage.status,Machines:a.usage.machineCount,Running:a.usage.runningMachines,Failed:a.usage.failedMachines,"Runtime (ms)":a.usage.meteredUsage?.runtimeMs,"Reliability score":a.insights.reliabilityScore,"Failure rate":a.insights.failureRate}),a.insights.recommendedActions.length>0){console.log(`
144
- Recommended actions:`);for(let e of a.insights.recommendedActions)console.log(` - ${e}`)}}),n.command(`cost <fleet-id>`).description(`Show the fleet's cost estimate`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Estimating cost...`);i.start();let a=await r.fleets.cost(t);i.stop(),n.json?e(a):s({Plan:a.plan,Currency:a.currency,"Hourly (USD)":a.hourlyUsd,"Max lifetime (s)":a.maxLifetimeSeconds,"Estimated max lifetime (USD)":a.estimatedMaxLifetimeUsd,Machines:a.requestedResources.machines,"Total CPU":a.requestedResources.totalCpu,"Total memory (MB)":a.requestedResources.totalMemoryMb})})}function xo(e){return[...e.entries()].map(([e,t])=>({machineId:e,sandboxId:t.id,status:t.status}))}function So(n){n.command(`list <fleet-id>`).description(`List the machines of one fleet (fleet id is required)`).option(`--status <status>`,`Filter machines by status`).action(async(n,r)=>{let{client:i}=G(r),a=f(`Fetching fleet...`);a.start();let o=await i.fleets.list({fleetId:n,status:r.status});a.stop();let s=xo(o.machines);r.json?e({fleetId:o.fleetId,machines:s}):t(s,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}])}),n.command(`get <fleet-id>`).description(`Show one fleet's manifest (server record)`).action(async(n,r)=>{let{client:i}=G(r),a=f(`Fetching manifest...`);a.start();let o=await i.fleets.manifest(n);a.stop(),r.json?e(o):(s({"Fleet ID":o.fleetId??o.id,Machines:o.machines.length,"Workspace mode":o.workspace?.mode,"Workspace status":o.workspace?.status,"Max lifetime (s)":o.policy?.maxLifetimeSeconds,"Max spend (USD)":o.policy?.maxSpendUsd,Created:o.createdAt,Updated:o.updatedAt}),t(o.machines,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`role`,header:`Role`,width:14},{key:`status`,header:`Status`,width:14}]))}),n.command(`delete <fleet-id>`).description(`Delete a fleet's machine sandboxes and its record`).option(`--continue-on-error`,`Keep deleting remaining machines if one delete fails`).action(async(t,n)=>{let{client:i}=G(n),a=f(`Deleting fleet...`);a.start(),await i.fleets.delete(t,{continueOnError:n.continueOnError}),a.stop(),n.json?e({success:!0,fleetId:t}):r(`Fleet deleted: ${t}`)}),n.command(`reap`).description(`TTL cleanup of all expired fleets (fleet-wide)`).option(`--dry-run`,`Report what would be reaped without deleting`).action(async n=>{let{client:r}=G(n),i=f(`Reaping expired fleets...`);i.start();let a=await r.fleets.reapExpired({dryRun:n.dryRun});i.stop(),n.json?e(a):(s({"Dry run":a.dryRun,Expired:a.expired,Deleted:a.deleted}),t(a.fleets,[{key:`fleetId`,header:`Fleet`,width:24},{key:`expiredAt`,header:`Expired`,width:18},{key:`deleted`,header:`Deleted`,width:10}]))}),n.command(`reconcile`).description(`Drop fleet records whose underlying sandboxes vanished`).option(`--dry-run`,`Report orphans without removing them`).action(async n=>{let{client:r}=G(n),i=f(`Reconciling fleets...`);i.start();let a=await r.fleets.reconcile({dryRun:n.dryRun});i.stop(),n.json?e(a):(s({"Dry run":a.dryRun,Checked:a.checked,Orphaned:a.orphaned,Removed:a.removed}),t(a.machines,[{key:`fleetId`,header:`Fleet`,width:24},{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`removed`,header:`Removed`,width:10}]))})}async function Co(e,t){let n=await Jn({apiKey:t.apiKey,baseUrl:t.baseUrl??Cn()}),r=await fetch(`${n.baseUrl}/v1/agent-profiles/${encodeURIComponent(e)}`,{headers:{authorization:`Bearer ${n.token}`,accept:`application/json`}});if(!r.ok){let t=await r.text().catch(()=>``);throw r.status===404?Error(`profile '${e}' not found in the platform catalog (it may be a built-in, a stored profile you own, or neither — run 'tangle profile list' to see what is available)`):Error(`platform returned ${r.status}: ${t.slice(0,200)}`)}let i=await r.json();if(!i.definition||typeof i.definition!=`object`)throw Error(`profile '${e}' resolved but has no definition — the catalog entry is malformed`);return i.definition}async function wo(e){let t=typeof e.envVarName==`string`&&e.envVarName.length>0?e.envVarName:null,n=!!e.fromStdin;if(t&&n)throw Error(`Pass either ${e.flagPrefix}-env or ${e.flagPrefix}-stdin, not both`);if(t){let n=process.env[t];if(!n||n.length===0)throw Error(`${e.flagPrefix}-env points at ${t}, but that environment variable is empty or unset`);return n}if(n){let t=await fr();if(t.length===0)throw Error(`${e.flagPrefix}-stdin received empty input on stdin`);return t}}function To(e){if(e.secret===void 0)return;let t=e.backend===`claude-code`?`token`:e.backend===`codex`?`bundle`:void 0;if(!t)throw Error(`--cli-auth needs --backend claude-code or --backend codex`);if(e.apiKeyGiven)throw Error(`--cli-auth cannot be combined with --backend-api-key-env or --backend-api-key-stdin`);return{account:`cli`,secretEnv:e.secret,format:t}}function Eo(e){if(e!==void 0)return e.map(e=>{if(e.includes(`@`)||e.includes(`:`))throw Error(`--secret ${e}: bare secret names only (box delivery). For proxy custody use --proxy-secret with a canonical binding`);return e})}function Do(e,t){let n={};return e.cpu!==void 0&&(n.cpuCores=ho(e.cpu,`--cpu`)),e.memory!==void 0&&(n.memoryMB=ho(e.memory,`--memory`)),e.disk!==void 0&&(n.diskGB=ho(e.disk,`--disk`)),t&&(n.accelerator=t),Object.keys(n).length>0?n:void 0}function Oo(e){let t=e.split(`/`);return t.length>=2?{provider:t[0],model:t.slice(1).join(`/`)}:{model:e}}function ko(e){let t={};for(let n of e){let[e,...r]=n.split(`=`);if(!e||r.length===0)throw Error(`--metadata expects values in KEY=VALUE or KEY=JSON format`);t[e]=Ao(r.join(`=`))}return t}function Ao(e){try{return JSON.parse(e)}catch{return e}}function jo(e,t){if(!(!e.gitUrl&&!e.gitRef&&!e.gitDepth&&!e.gitSparse&&!t)){if(!e.gitUrl||typeof e.gitUrl!=`string`)throw Error(`--git-url is required when using git provisioning options`);return{url:e.gitUrl,ref:typeof e.gitRef==`string`?e.gitRef:void 0,depth:typeof e.gitDepth==`string`?ho(e.gitDepth,`--git-depth`):void 0,sparse:Array.isArray(e.gitSparse)?e.gitSparse:void 0,auth:t?{token:t}:void 0}}}function Mo(e,t){if(!(!e.storageType&&!e.storageBucket&&!e.storageEndpoint&&!e.storageRegion&&!e.storagePrefix&&!e.storageAccessKeyId&&!t)){if(typeof e.storageType!=`string`||typeof e.storageBucket!=`string`||typeof e.storageAccessKeyId!=`string`||!t)throw Error(`Storage config requires --storage-type, --storage-bucket, --storage-access-key-id, and one of --storage-secret-access-key-env / --storage-secret-access-key-stdin`);return{type:No(e.storageType),bucket:e.storageBucket,endpoint:typeof e.storageEndpoint==`string`?e.storageEndpoint:void 0,region:typeof e.storageRegion==`string`?e.storageRegion:void 0,prefix:typeof e.storagePrefix==`string`?e.storagePrefix:void 0,credentials:{accessKeyId:e.storageAccessKeyId,secretAccessKey:t}}}}function No(e){if(e===`s3`||e===`gcs`||e===`r2`)return e;throw Error(`--storage-type must be one of s3, gcs, or r2`)}function Po(e){if(e===void 0)return;let t=[];for(let n of e){let e=n,r=`--proxy-secret <json>`;if(n.startsWith(`@`)){let t=n.slice(1);r=`--proxy-secret @${t}`;try{e=Ie(t,`utf8`)}catch{throw Error(`${r}: file could not be read`)}}let i;try{i=JSON.parse(e)}catch(e){throw Error(`${r}: not valid JSON (${e instanceof Error?e.message:String(e)})`)}if(Array.isArray(i))t.push(...i);else if(typeof i==`object`&&i)t.push(i);else throw Error(`${r}: expected a binding object or an array of bindings`)}let n=xe.parse(t);return n.length>0?n:void 0}function Fo(e){l(` Status: ${e.status}`),l(` Provider: ${e.provider}`),l(` GPU: ${e.accelerator.kind} x ${e.accelerator.count}`),e.customerPricePerHourUsd!==void 0&&l(` Customer price: $${e.customerPricePerHourUsd}/hr`),e.estimatedCustomerCostUsd!==void 0&&l(` Max estimate: $${e.estimatedCustomerCostUsd}`),e.billing&&(l(` Billed seconds: ${e.billing.seconds}`),l(` Customer cost: $${e.billing.customerCostUsd}`))}function Io(e){e.result.stdout&&process.stdout.write(e.result.stdout),e.result.stderr&&process.stderr.write(e.result.stderr),l(`Exit code: ${e.result.exitCode}`)}function Lo(n){let i=n.command(`gpu`).description(`Manage on-demand GPU leases for a sandbox`);i.command(`providers <id-or-name>`).description(`List GPU clouds, whether each credential works, and current prices`).option(`--accelerator-kind <kind>`,`Price this GPU kind, for example nvidia-h100`).option(`--accelerator-count <count>`,`GPU device count`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Checking GPU providers...`);o.start();let s=await(await q(a,i,n)).gpu.providers(r.acceleratorKind?{accelerator:so({kind:r.acceleratorKind,count:r.acceleratorCount,memory:r.acceleratorMemory})}:{});if(o.stop(),r.json){e(s);return}t(s.statuses.map(e=>({provider:e.provider,state:e.state,gpu:e.estimate?.providerInstanceType??``,usdHr:e.estimate?e.estimate.customerPricePerHourUsd.toFixed(4):``,pricing:e.estimate?.pricingSource??``,needs:e.envVars.join(` `)})),[{key:`provider`,header:`Provider`},{key:`state`,header:`State`},{key:`gpu`,header:`GPU`},{key:`usdHr`,header:`$/hr`},{key:`pricing`,header:`Price`},{key:`needs`,header:`Needs`}]);for(let e of s.statuses){let t=e.state===`credential-invalid`?e.credential?.detail:e.estimateError;t&&l(`${e.provider}: ${t}`)}s.usable.length===0&&l(`No GPU provider is usable on this deployment: set the variables in Needs for one provider on the server.`)}),i.command(`attach <id-or-name>`).description(`Attach a temporary GPU worker to a sandbox`).requiredOption(`--accelerator-kind <kind>`,`GPU kind, for example nvidia-h100`).option(`--accelerator-count <count>`,`GPU device count`,`1`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--provider <provider>`,`GPU cloud provider; omitted picks the cheapest configured provider`).option(`--image <image>`,`GPU worker image override`).option(`--env <vars...>`,`Environment variables for the GPU worker (KEY=VALUE)`).requiredOption(`--max-spend-usd <usd>`,`Maximum customer spend for this lease`).requiredOption(`--max-lifetime <seconds>`,`Maximum lease lifetime in seconds`).option(`--idle-timeout <seconds>`,`Destroy after this many idle seconds`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=f(`Attaching GPU lease...`);o.start();let s=await(await q(a,i,t)).gpu.attach(lo(n));o.stop(),n.json?e(s):(r(`GPU lease attached: ${s.id}`),Fo(s))}),i.command(`run <id-or-name> <command...>`).description(`Attach a GPU, run a command or script, then destroy it`).requiredOption(`--accelerator-kind <kind>`,`GPU kind, for example nvidia-h100`).option(`--accelerator-count <count>`,`GPU device count`,`1`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--provider <provider>`,`GPU cloud provider; omitted picks the cheapest configured provider`).option(`--image <image>`,`GPU worker image override`).option(`--env <vars...>`,`Environment variables for the GPU worker and command (KEY=VALUE)`).requiredOption(`--max-spend-usd <usd>`,`Maximum customer spend for this lease`).requiredOption(`--max-lifetime <seconds>`,`Maximum lease lifetime in seconds`).option(`--idle-timeout <seconds>`,`Destroy after this many idle seconds`).option(`--timeout <ms>`,`Command timeout in milliseconds`).option(`--cwd <path>`,`Working directory`).action(async(t,n,i)=>{let a,o,s,c;try{let{context:e,client:r}=G(i),s=await q(r,e,t),c=f(`Attaching GPU lease...`);c.start(),a=await s.gpu.attach(lo(i)),c.stop();let l=f(`Running GPU command...`);l.start(),o=await s.gpu.exec(a.id,{command:fo(n),...po(i),cwd:i.cwd}),l.stop(),i.json||Io(o)}catch(e){s=e}finally{if(a)try{let{context:e,client:n}=G(i);a=await(await q(n,e,t)).gpu.detach(a.id)}catch(e){c=e}}if(s){H(s),c&&H(c);return}if(c){H(c);return}i.json?e({lease:a,result:o}):a&&r(`GPU lease detached: ${a.id}`);let l=o?.result.exitCode;l&&l!==0&&(process.exitCode=l)}),i.command(`list <id-or-name>`).description(`List GPU leases attached to a sandbox`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching GPU leases...`);o.start();let s=await(await q(a,i,n)).gpu.list();o.stop(),r.json?e(s):s.length===0?l(`No GPU leases attached.`):t(s.map(e=>({id:e.id,status:e.status,provider:e.provider,accelerator:`${e.accelerator.kind}x${e.accelerator.count}`,customerUsdHr:e.customerPricePerHourUsd??``})),[{key:`id`,header:`ID`,width:28},{key:`status`,header:`Status`,width:12},{key:`provider`,header:`Provider`,width:12},{key:`accelerator`,header:`GPU`,width:24},{key:`customerUsdHr`,header:`$/hr`,width:10}])}),i.command(`exec <id-or-name> <lease-id> <command...>`).description(`Run a command or script on an attached GPU lease`).option(`--timeout <ms>`,`Command timeout in milliseconds`).option(`--cwd <path>`,`Working directory`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).action(async(t,n,r,i)=>{let{context:a,client:o}=G(i),s=f(`Running GPU command...`);s.start();let c=await(await q(o,a,t)).gpu.exec(n,{command:fo(r),...po(i),cwd:i.cwd});s.stop(),i.json?e(c):Io(c)}),i.command(`detach <id-or-name> <lease-id>`).description(`Detach and destroy a GPU lease`).action(async(t,n,i)=>{let{context:a,client:o}=G(i),s=f(`Detaching GPU lease...`);s.start();let c=await(await q(o,a,t)).gpu.detach(n);s.stop(),i.json?e(c):(r(`GPU lease detached: ${c.id}`),Fo(c))})}function Ro(t,n){if(n){e(t);return}if(!t.id){t.kind===`snapshot`&&t.result?.snapshot?r(`Snapshot created: ${t.result.snapshot.snapshotId}`):r(`Sandbox ${t.sandboxId} stopped.`);return}r(`${t.kind===`snapshot`?`Snapshot`:`Stop`} of sandbox ${t.sandboxId} accepted.`),l(`Operation: ${t.id}`),l(`Status: ${t.statusUrl}`)}function zo(e){return`${e.name} (${e.id})`}async function Bo(e,t){if(t.startsWith(`team_`))return e.teams.get(t);let n=(await e.teams.list()).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(n.length===0)throw Error(`Team not found: ${t}`);if(n.length>1)throw Error(`Team name is ambiguous: ${t}. Use a team id instead.`);return n[0]}async function Vo(e,t,n){if(t)return Bo(e,t);let r=En(n);if(!r.activeTeamId)throw Error("No active team. Run `tangle team switch <team>` or pass `--team <team>`.");return e.teams.get(r.activeTeamId)}function Ho(e,t){Dn({id:e.id,name:e.name},t)}function Uo(e){On(e)}async function Wo(e){if(e.explicitTeam&&e.personal)throw Error(`--team and --personal cannot be used together`);if(!e.personal)return e.explicitTeam?(await Bo(e.client,e.explicitTeam)).id:e.activeTeamId}async function Go(e){if([!!e.explicitTeam,!!e.personal,!!e.allScopes].filter(Boolean).length>1)throw Error(`--team, --personal, and --all-scopes are mutually exclusive`);if(e.allScopes)return`all`;if(e.personal)return`personal`;if(e.explicitTeam)return`team:${(await Bo(e.client,e.explicitTeam)).id}`;if(e.activeTeamId)return`team:${e.activeTeamId}`}function Ko(e){if(!e)return e;let t={...e};for(let e of[`authToken`,`execToken`])t[e]!==void 0&&(t[e]=`[REDACTED]`);return t}function qo(n){n.command(`attestation <id-or-name>`).description(`Fetch TEE attestation evidence for a sandbox`).option(`--nonce <hex|auto>`,`Nonce to bind into a fresh attestation report; use auto to generate one`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=n.nonce===`auto`?ie():n.nonce,s=f(`Fetching TEE attestation...`);s.start();let c=await(await q(a,i,t)).getTeeAttestation(o?{attestationNonce:o}:void 0);s.stop(),n.json?e(c):(r(`Attestation fetched for ${t}`),console.log(`TEE type: ${c.attestation.tee_type}`),console.log(`Evidence bytes: ${c.attestation.evidence.length}`),console.log(`Measurement bytes: ${c.attestation.measurement.length}`),console.log(`Timestamp: ${c.attestation.timestamp}`),c.attestationNonce&&console.log(`Nonce: ${c.attestationNonce}`))}),n.command(`list`).description(`List all sandboxes`).option(`-s, --status <status>`,`Filter by status (running, stopped, all)`).option(`-l, --limit <n>`,`Limit results`,`50`).option(`--team <team>`,`List sandboxes for a team by id or name`).option(`--personal`,`List personal sandboxes`).option(`--all-scopes`,`List personal and team sandboxes`).action(async n=>{let{context:r,client:i}=G(n),a=f(`Fetching sandboxes...`);a.start();let o=await Go({client:i,explicitTeam:n.team,personal:n.personal,allScopes:n.allScopes,activeTeamId:r.activeTeamId}),s=await i.list({status:n.status===`all`?void 0:n.status,limit:Number.parseInt(n.limit,10),scope:o});a.stop(),n.json?e(s):t(s.map(e=>({id:e.id,status:e.status,createdAt:e.createdAt,name:e.name??``})),[{key:`id`,header:`ID`,width:24},{key:`status`,header:`Status`,width:14},{key:`createdAt`,header:`Created`,width:16},{key:`name`,header:`Name`,width:20}])}),n.command(`get <id-or-name>`).description(`Get sandbox details`).option(`--profile`,`Show the active agent profile provenance (name, hash, skills)`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching sandbox...`);a.start();let o=await q(i,r,t);if(a.stop(),n.profile){let e=o.getProfileProvenance?.();e?(l(`Agent profile provenance:`),l(` Base profile: ${e.base.name??`(inline)`} (${e.base.sha256.slice(0,12)}...)`),l(` Effective: ${e.effective.name??`(inline)`} (${e.effective.sha256.slice(0,12)}...)`),l(` Materialized: ${e.materializedAt}`),e.base.sha256!==e.effective.sha256&&l(` ⚠ Profile changed since creation (base ≠ effective)`)):l(`No profile materialized (bare sandbox). Create with --profile <name> to install one.`);return}n.json?e(o):u({id:o.id,name:o.name,status:o.status,resources:o.resources,createdAt:o.createdAt?.toISOString(),expiresAt:o.expiresAt?.toISOString(),connection:o.connection})}),n.command(`shapes`).description(`List the named sandbox sizes, the default, and this account's ceiling`).action(async n=>{let{client:r}=G(n),i=await r.shapes();if(n.json){e(i);return}let a=e=>e.cpuCores<=i.ceiling.cpuCores&&e.memoryMB<=i.ceiling.memoryMB&&e.diskGB<=i.ceiling.diskGB;t(i.presets.map(e=>({name:e.name===i.default?`${e.name} (default)`:e.name,cpu:e.cpuCores,memory:`${e.memoryMB} MB`,disk:`${e.diskGB} GB`,available:a(e)?`yes`:e.name===i.default?`clamped to ceiling`:`above ceiling`})),[{key:`name`,header:`Shape`,width:18},{key:`cpu`,header:`vCPU`,width:6},{key:`memory`,header:`Memory`,width:10},{key:`disk`,header:`Disk`,width:8},{key:`available`,header:`Available`,width:14}]),l(`Ceiling for this account: ${o(i.ceiling)}`)}),n.command(`delete <id-or-name>`).description(`Delete a sandbox`).option(`-f, --force`,`Skip confirmation`).option(`--name`,`Treat the reference as a sandbox name`).addOption(new _e(`--until <state>`,`Wait for physical removal`).choices([`removed`])).option(`--retry-cleanup`,`Retry server-side cleanup after the sandbox disappeared from get/list`).action(async(e,t)=>{if(!t.force&&!await ur(`Delete sandbox ${e}? [y/N] `,`--force`)){l(`Cancelled.`);return}let{context:n,client:i}=G(t),a=f(`Deleting sandbox...`);a.start();let o=await rr(i,n,e,{retryCleanup:t.retryCleanup,name:t.name,until:t.until});a.stop(),r(o===`already_absent`?`Sandbox ${e} was already gone.`:`Sandbox ${e} deleted.`)}),n.command(`stop <id-or-name>`).description(`Stop a running sandbox`).option(`--name`,`Treat the reference as a sandbox name`).option(`--no-wait`,`Return once the stop is accepted and print the operation to poll`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Stopping sandbox...`);a.start();let o=await q(i,n,e,{nameOnly:t.name});if(t.wait===!1){let e=await o.stop({wait:!1});a.stop(),Ro(e.info,!!t.json);return}await o.stop(),a.stop(),r(`Sandbox ${e} stopped.`)}),n.command(`resume <id-or-name>`).description(`Resume a stopped sandbox`).option(`--wait`,`Wait for sandbox to be running`,!0).option(`-t, --timeout <ms>`,`Resume timeout in milliseconds; a cold resume re-provisions the sandbox, so this defaults higher than other commands (default 120000)`,`120000`).action(async(e,t)=>{let n=Number.parseInt(t.timeout,10);if(!Number.isFinite(n)||n<=0)throw Error(`--timeout must be a positive number of milliseconds`);let i=U({apiKey:t.apiKey,baseUrl:t.baseUrl,timeout:n}),a=W(i),o=f(`Resuming sandbox...`);o.start();let s=await q(a,i,e);await s.resume({timeoutMs:n}),t.wait&&(o.text=`Waiting for sandbox to start...`,await s.waitFor(`running`,{timeoutMs:n})),o.stop(),r(`Sandbox ${s.id} resumed.`)})}function Jo(t){t.command(`create`).option(`--cpu-features <flags>`,`Required Linux CPU flags, comma-separated`).description(`Create a new sandbox`).option(`-n, --name <name>`,`Sandbox name`).option(`-e, --environment <environment>`,Yo).addOption(Xo()).option(`--bare`,`Create a bare sandbox without the agent runtime`).option(`--ssh`,`Enable SSH access`).option(`--ssh-key <key>`,`SSH public key for authentication`).option(`--ssh-keys <names...>`,`Stored SSH key names or IDs for authentication`).option(`--ssh-key-file <paths...>`,`SSH public key file paths for authentication`).option(`--web-terminal`,`Enable web terminal`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).option(`--secret <names...>`,`Secrets selected by bare name for box delivery (value in the sandbox env). For proxy custody use --proxy-secret`).option(`--proxy-secret <bindings...>`,`Canonical proxy custody binding(s): one binding as inline JSON, or @file with a JSON array. The value stays at the egress proxy and is redeemed only within the binding's scope (hosts/methods/paths/TTL); the box reads a placeholder. Repeatable`).option(`--metadata <entries...>`,`Metadata entries (KEY=VALUE or KEY=JSON)`).option(`--cpu <cores>`,"CPU cores (omit for the platform default; see `sandbox shapes`)").option(`--memory <mb>`,`Memory in MB (omit for the platform default)`).option(`--disk <gb>`,`Disk size in GB (omit for the platform default)`).option(`--accelerator-kind <kind>`,`Accelerator kind, for example nvidia-h100 or amd-mi300x`).option(`--accelerator-count <count>`,`Accelerator device count`,`1`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--gpu-provider <provider>`,`GPU cloud provider; omitted picks the cheapest configured provider`).option(`--gpu-worker-image <image>`,`GPU worker image override`).option(`--gpu-env <vars...>`,`Environment variables for the GPU worker (KEY=VALUE)`).option(`--gpu-max-spend-usd <usd>`,`Maximum customer spend for the create-time GPU lease`).option(`--gpu-max-lifetime <seconds>`,`Maximum create-time GPU lease lifetime in seconds`).option(`--gpu-idle-timeout <seconds>`,`Destroy the create-time GPU lease after this many idle seconds`).option(`--lifetime <seconds>`,`Max wall-clock lifetime before the sandbox is suspended — stopped, not deleted; resume it within the cold window (default 3600 = 1h). Raise it for long sessions, e.g. --lifetime 7200`,`3600`).option(`--idle-timeout <seconds>`,"Idle time before the sandbox is stopped — not deleted (default 900 = 15m). Resume it later with `tangle sandbox resume <id-or-name>`, or it auto-resumes on next use. Raise it for demos, e.g. --idle-timeout 3600",`900`).option(`--from-snapshot <id>`,`Create the sandbox from a snapshot`).option(`--public-template <id-or-slug>`,`Create the sandbox from a published public template`).option(`--public-template-version <id>`,`Pin creation to a specific published public-template version`).option(`--billing-owner <userId>`,`Platform user that pays for the sandbox. The API accepts this only from a first-party service key that is listed as a billing delegate, and refuses such a key that names no payer.`).option(`--team <team>`,`Create in a team by id or name`).option(`--personal`,`Create a personal sandbox even when a team is active`).option(`--git-url <url>`,`Git repository URL to clone during provisioning`).option(`--git-ref <ref>`,`Git branch, tag, or commit to checkout`).option(`--git-depth <depth>`,`Git clone depth`).option(`--git-sparse <paths...>`,`Sparse checkout paths`).option(`--git-token-env <name>`,`Name of an environment variable containing the Git HTTPS auth token`).option(`--git-token-stdin`,`Read the Git HTTPS auth token from stdin`).option(`--storage-type <type>`,`BYOS3 storage type (s3, gcs, r2)`).option(`--storage-bucket <name>`,`BYOS3 bucket name`).option(`--storage-endpoint <url>`,`BYOS3 endpoint URL`).option(`--storage-region <region>`,`BYOS3 region`).option(`--storage-prefix <prefix>`,`BYOS3 path prefix`).option(`--storage-access-key-id <id>`,`BYOS3 access key ID`).option(`--storage-secret-access-key-env <name>`,`Name of an environment variable containing the BYOS3 secret access key`).option(`--storage-secret-access-key-stdin`,`Read the BYOS3 secret access key from stdin`).addOption(new _e(`--driver <type>`,`Run on Tangle network operators instead of the platform's hosts (--tee needs it)`).choices([`tangle`])).option(`--backend <type>`,`Backend agent type (${y.join(`, `)})`).option(`--backend-model <model>`,`Model override (format: provider/model)`).addOption(new _e(`--reasoning-effort <level>`,`Reasoning effort for the backend's model; overrides the profile's model.reasoningEffort`).choices(Se)).option(`--backend-api-key-env <name>`,`Name of an environment variable containing the BYOK backend API key`).option(`--backend-api-key-stdin`,`Read the BYOK backend API key from stdin`).option(`--cli-auth <secret>`,"Run --backend claude-code or codex on your own subscription: the stored secret holding a `claude setup-token` token or a Codex auth.json (see `tangle secret create`)").option(`--profile <path>`,`Path to an AgentProfile JSON file to install as the sandbox's backend profile (carries skills, tools, MCP, model). Use with --backend; the profile's inline skills materialize into the harness's native skill directory on first turn`).option(`--profile-stdin`,`Read the AgentProfile JSON from stdin instead of a file (use with --profile)`).option(`--tee <type>`,`Require a TEE backend (any, tdx, nitro, sev-snp, phala-dstack)`).option(`--sealed`,`Request TEE sealed-secret support`).option(`--attestation-nonce <hex|auto>`,`Deploy-time attestation nonce; use auto to generate one`).option(`--attestation-refresh`,`Generate a fresh deploy-time attestation nonce when --tee is set`).option(`--require-attestation`,`Fail unless TEE attestation evidence is returned`).option(`--wait`,`Wait for sandbox to be running`,!0).option(`--timeout <ms>`,`HTTP timeout in milliseconds`,`30000`).action(async t=>{let n=await wo({envVarName:t.gitTokenEnv,fromStdin:t.gitTokenStdin,flagPrefix:`--git-token`}),i=await wo({envVarName:t.storageSecretAccessKeyEnv,fromStdin:t.storageSecretAccessKeyStdin,flagPrefix:`--storage-secret-access-key`}),a=await wo({envVarName:t.backendApiKeyEnv,fromStdin:t.backendApiKeyStdin,flagPrefix:`--backend-api-key`}),o=To({secret:t.cliAuth,backend:t.backend,apiKeyGiven:a!==void 0}),s;if(t.profileStdin){let e=await fr(`--profile-stdin`,`the AgentProfile JSON`);try{s=JSON.parse(e)}catch{H(Error(`--profile-stdin: the input is not valid JSON`));return}}else if(t.profile){let e=String(t.profile);if(e.startsWith(`.`)||e.startsWith(`/`)||e.endsWith(`.json`))try{s=JSON.parse(Ie(e,`utf8`))}catch(t){H(Error(`--profile ${e}: ${t.message}`));return}else try{s=await Co(e,t)}catch(t){H(Error(`--profile ${e}: ${t.message}`));return}}s=Qo(s,t.reasoningEffort);let c=U({apiKey:t.apiKey,baseUrl:t.baseUrl,timeout:t.timeout?Number.parseInt(t.timeout,10):void 0}),l=W(c),d=f(`Creating sandbox...`);d.start();let p=await Wo({client:l,explicitTeam:t.team,personal:t.personal,activeTeamId:c.activeTeamId}),m=mo(t.env??[],`--env`,`env`),h=t.metadata?ko(t.metadata):void 0,g=jo(t,n),_=Mo(t,i),v=t.acceleratorKind?so({kind:String(t.acceleratorKind),count:String(t.acceleratorCount),memory:typeof t.acceleratorMemory==`string`?t.acceleratorMemory:void 0}):void 0,y=co({provider:typeof t.gpuProvider==`string`?t.gpuProvider:void 0,image:typeof t.gpuWorkerImage==`string`?t.gpuWorkerImage:void 0,env:Array.isArray(t.gpuEnv)?t.gpuEnv:void 0,maxSpendUsd:typeof t.gpuMaxSpendUsd==`string`?t.gpuMaxSpendUsd:void 0,maxLifetime:typeof t.gpuMaxLifetime==`string`?t.gpuMaxLifetime:void 0,idleTimeout:typeof t.gpuIdleTimeout==`string`?t.gpuIdleTimeout:void 0},!!v,`Create-time GPU lease flags require --accelerator-kind`),b=t.driver?{type:`tangle`}:void 0,x=t.backend||t.backendModel||s?{...t.backend?{type:ae(t.backend)}:{},...s?{profile:s}:{},model:t.backendModel||a||o?{...t.backendModel?Oo(t.backendModel):{},apiKey:a,...o?{cliAuth:o}:{}}:void 0}:void 0,S=Eo(t.secret),C=o?[...new Set([...S??[],o.secretEnv])]:S,w=Po(t.proxySecret),T=Do(t,v),ee=t.sshKeyFile??(t.ssh&&!t.sshKey&&!t.sshKeys?.length?[Zo()]:[]),E=[...t.sshKey?[t.sshKey]:[],...ee.map(e=>Ie(e,`utf8`).trim())],D={name:t.name,environment:t.environment,runtime:t.runtime,cpuFeatures:t.cpuFeatures?.split(`,`).map(e=>e.trim()),bare:t.bare||void 0,sshEnabled:t.ssh||!!t.sshKey||E.length>0||!!t.sshKeys?.length,sshPublicKeys:E.length>0?E:void 0,sshKeyIds:t.sshKeys,webTerminalEnabled:t.webTerminal,env:Object.keys(m).length>0?m:void 0,git:g,...T?{resources:T}:{},gpuLease:y,maxLifetimeSeconds:Number.parseInt(t.lifetime,10),idleTimeoutSeconds:Number.parseInt(t.idleTimeout,10),storage:_,fromSnapshot:t.fromSnapshot,publicTemplateId:t.publicTemplate,publicTemplateVersionId:t.publicTemplateVersion,teamId:p,...t.billingOwner?{billingOwnerId:t.billingOwner}:{},secrets:C,...w?{proxySecrets:w}:{},metadata:h,driver:b,backend:x},O=t.tee?{tee:t.tee,sealed:t.sealed||void 0,attestationRefresh:t.attestationRefresh||t.attestationNonce===`auto`||void 0}:void 0,k=O?await re(l,{...D,confidential:O,attestationNonce:t.attestationNonce??(t.attestationRefresh?`auto`:void 0),requireAttestation:t.requireAttestation??!0}):void 0,A=k?.sandbox??await l.create(D);t.wait&&(d.text=`Waiting for sandbox to start...`,await A.waitFor(`running`,{timeoutMs:12e4}),await A.refresh()),d.stop(),t.json?e({id:A.id,name:A.name,status:A.status,resources:A.resources,createdAt:A.createdAt,expiresAt:A.expiresAt,connection:Ko(A.connection),teamId:p,gpuLease:A.gpuLease,confidential:O,attestation:k?.attestation,attestationNonce:k?.attestationNonce}):(r(`Sandbox created: ${A.id}`),u({id:A.id,name:A.name,status:A.status,resources:A.resources,createdAt:A.createdAt?.toISOString(),expiresAt:A.expiresAt?.toISOString(),connection:A.connection}),p&&console.log(`Team: ${p}`),A.gpuLease&&(console.log(`GPU lease: ${A.gpuLease.id}`),Fo(A.gpuLease)),O&&(console.log(`TEE: ${O.tee}`),console.log(`Attestation: ${k?.attestation?`present`:`not returned`}`),k?.attestationNonce&&console.log(`Attestation nonce: ${k.attestationNonce}`)))})}const Yo="A catalog environment, a container image reference, or a built image ID. Firecracker runs only images pinned by repository@sha256 that the cell's Firecracker hosts carry; `environments list` shows each image's runtimes";function Xo(){return new _e(`--runtime <runtime>`,`Isolation on the platform's hosts: docker runs a container on the host kernel, firecracker a microVM with its own kernel. Omit for the platform default`).choices(ee)}function Zo(){let e=[`id_ed25519`,`id_ecdsa`,`id_rsa`].map(e=>`${F()}/.ssh/${e}.pub`),t=e.find(e=>Pe(e));if(!t)throw Error(`--ssh needs a public key and found none at ${e.join(`, `)}. Run ssh-keygen -t ed25519, or pass --ssh-key-file.`);return t}function Qo(e,t){if(!t)return e;let n=e?.model??{};return{...e,model:{...n,reasoningEffort:t}}}function $o(e){if(e.spec){let t=JSON.parse(Ie(e.spec,`utf8`));return{base:{fleetId:e.fleetId,defaults:t.defaults,policy:t.policy,workspace:t.workspace,metadata:t.metadata},machines:t.machines??[]}}let t=ns(e),n=rs(e,!!t?.accelerator),r={...e.environment?{environment:e.environment}:{},...t?{resources:t}:{},...e.runtime?{runtime:e.runtime}:{},...n?{gpuLease:n}:{},...e.backend?{backend:{type:e.backend}}:{}},i=is(e),a=Math.max(1,Number(e.count)||1),o=Array.from({length:a},(e,t)=>({machineId:`worker-${t+1}`}));return{base:{fleetId:e.fleetId,defaults:Object.keys(r).length>0?r:void 0,policy:i,workspace:{mode:e.workspace}},machines:o}}function es(e){let{base:t,machines:n}=$o(e);return{...t,machines:n}}function ts(e){let{base:t,machines:n}=$o(e);return{...t,workers:n}}function ns(e){let t={};if(e.cpu&&(t.cpuCores=Number(e.cpu)),e.memory&&(t.memoryMB=Number(e.memory)),e.disk&&(t.diskGB=Number(e.disk)),e.acceleratorKind)t.accelerator=so({kind:e.acceleratorKind,count:e.acceleratorCount,memory:e.acceleratorMemory});else if(e.acceleratorCount||e.acceleratorMemory)throw Error(`--accelerator-count and --accelerator-memory require --accelerator-kind`);return Object.keys(t).length>0?t:void 0}function rs(e,t){return co({provider:e.gpuProvider,image:e.gpuWorkerImage,env:e.gpuEnv,maxSpendUsd:e.gpuMaxSpendUsd,maxLifetime:e.gpuMaxLifetime,idleTimeout:e.gpuIdleTimeout},t,`Fleet GPU lease flags require --accelerator-kind`)}function is(e){let t={};return e.maxSpendUsd&&(t.maxSpendUsd=Number(e.maxSpendUsd)),e.maxLifetime&&(t.maxLifetimeSeconds=Number(e.maxLifetime)),Object.keys(t).length>0?t:void 0}function as(n){n.command(`create`).description(`Create a sandbox fleet`).option(`--fleet-id <id>`,`Stable fleet id (generated when omitted)`).option(`--count <n>`,`Number of worker machines`,`1`).option(`--environment <environment>`,Yo).addOption(Xo()).option(`--cpu <cores>`,`CPU cores per machine`).option(`--memory <mb>`,`Memory in MB per machine`).option(`--disk <gb>`,`Disk in GB per machine`).option(`--accelerator-kind <kind>`,`Accelerator kind per machine, for example nvidia-l4 or nvidia-h100`).option(`--accelerator-count <count>`,`Accelerator devices per machine`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--gpu-provider <provider>`,`GPU cloud provider per machine; omitted picks the cheapest configured provider`).option(`--gpu-worker-image <image>`,`GPU worker image override`).option(`--gpu-env <vars...>`,`Environment variables for each GPU worker (KEY=VALUE)`).option(`--gpu-max-spend-usd <usd>`,`Maximum spend per machine GPU lease`).option(`--gpu-max-lifetime <seconds>`,`Maximum GPU lease lifetime per machine in seconds`).option(`--gpu-idle-timeout <seconds>`,`Destroy each GPU lease after this many idle seconds`).option(`--backend <id>`,`Agent backend type`).option(`--workspace <mode>`,`Workspace mode: isolated (no driver supports shared yet)`,`isolated`).option(`--max-spend-usd <n>`,`Fleet spend cap in USD (policy)`).option(`--max-lifetime <s>`,`Max machine lifetime in seconds (policy)`).option(`--spec <file.json>`,`Path to a JSON file describing the fleet (overrides synthesized machines)`).option(`--coordinator`,`Create a coordinator + workers fleet (routes to createWithCoordinator)`).action(async n=>{let{client:i}=G(n),a=f(`Creating fleet...`);a.start();let o=n.coordinator?await i.fleets.createWithCoordinator(ts(n)):await i.fleets.create(es(n));a.stop();let s=xo(o.machines);n.json?e({fleetId:o.fleetId,machines:s}):(r(`Fleet created: ${o.fleetId}`),t(s,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}]))})}function os(n){n.command(`exec <fleet-id> <command>`).description(`Run a shell command across the fleet's machines`).option(`--machine <id...>`,`Restrict to a subset of machine ids (default: all)`).option(`--cwd <dir>`,`Working directory for the command`).option(`--timeout <ms>`,`Per-machine timeout in milliseconds`).option(`--max-concurrent <n>`,`Max concurrent dispatches`).action(async(n,r,i)=>{let{client:a}=G(i),o=f(`Dispatching command...`);o.start();let s=await(await a.fleets.list({fleetId:n})).dispatchExecDetailed(r,{machines:i.machine,cwd:i.cwd,timeoutMs:i.timeout?Number(i.timeout):void 0,maxConcurrent:i.maxConcurrent?Number(i.maxConcurrent):void 0});if(o.stop(),i.json)e(s);else{t(s.results.map(e=>({machineId:e.machineId,ok:e.ok,exitCode:e.result?.exitCode,durationMs:e.durationMs})),[{key:`machineId`,header:`Machine`,width:20},{key:`ok`,header:`OK`,width:6},{key:`exitCode`,header:`Exit`,width:8},{key:`durationMs`,header:`Duration(ms)`,width:14}]);for(let e of s.results){let t=e.result?.stdout,n=e.result?.stderr;t&&(console.log(`\n[${e.machineId}] stdout:`),console.log(t)),n&&(console.log(`\n[${e.machineId}] stderr:`),console.log(n)),e.error&&console.log(`\n[${e.machineId}] error: ${e.error.message}`)}}s.results.some(e=>e.ok===!1)&&(process.exitCode=1)}),n.command(`run [prompt]`).description(`Create a fleet of agents, run one turn on every agent, print each result, then delete the fleet`).requiredOption(`--agents <n|file>`,`Number of agents, or a JSON file with an array of agent specs (agentId, harness, model, profile or { profileId, revision }, task)`).option(`--placement <mode>`,`auto (pack by sandbox memory), dedicated (one sandbox per agent), or a number of agents per sandbox`,`auto`).option(`--model <id>`,`Model every agent runs, e.g. gpt-4.1-mini`).option(`--memory <mb>`,`Memory in MB per sandbox; auto placement packs by it`).option(`--environment <environment>`,`Environment for each sandbox`).option(`--max-spend-usd <usd>`,`Budget for the fleet in USD, enforced by the Platform on the fleet's own key`).option(`--timeout <ms>`,`Per-agent turn timeout in milliseconds`).option(`--fleet-id <id>`,`Stable fleet id (generated when omitted)`).option(`--parent-fleet <id>`,`Fleet that spawns this one; its cap must cover this cap`).option(`--parent-agent <id>`,`Agent of --parent-fleet that spawns this one`).option(`--keep`,`Keep the fleet after the run instead of deleting it`).action(async(t,n)=>{let i=/^\d+$/.test(n.agents)?Number(n.agents):JSON.parse(Ie(n.agents,`utf8`));if(!Array.isArray(i)&&t===void 0)throw Error(`A prompt is required unless --agents names a file whose agents carry tasks`);let{client:a}=G(n);if(!!n.parentFleet!=!!n.parentAgent)throw Error(`--parent-fleet and --parent-agent go together`);let o=n.placement===`auto`||n.placement===`dedicated`?n.placement:{agentsPerSandbox:Number(n.placement)},c=n.maxSpendUsd?Number(n.maxSpendUsd):void 0,l=f(`Creating fleet...`);l.start();let u=Date.now(),d=await a.fleets.create({fleetId:n.fleetId,agents:i,placement:o,defaults:{...n.environment?{environment:n.environment}:{},...n.memory?{resources:{memoryMB:Number(n.memory)}}:{},...n.model?{backend:{type:`opencode`,model:{model:n.model}}}:{}},...c===void 0?{}:{budgetUsd:c},...n.parentFleet?{parent:{fleetId:n.parentFleet,agentId:n.parentAgent}}:{}}),p=Date.now()-u;l.stop(),n.json||r(`Fleet ${d.fleetId}: ${d.agents.length} agents on ${d.machines.size} sandboxes in ${p} ms`);let m=[],h;try{for await(let e of d.run(t,{timeoutMs:n.timeout?Number(n.timeout):void 0})){if(e.type===`agent.finished`&&!n.json){let t=e.result;console.log(`[${t.agentId}] ${t.harness??`default`}/${t.model??`default`} ${t.status} ${t.durationMs}ms ${t.costUsd===void 0?`no cost reported`:`$${t.costUsd.toFixed(5)}`} ${t.result?.response??t.error??``}`)}e.type===`fleet.finished`&&(m=e.results,h=e.spend)}}finally{n.keep||await d.delete({continueOnError:!0})}n.json?e({fleetId:d.fleetId,createMs:p,sandboxes:d.machines.size,results:m,spend:h,deleted:!n.keep}):s({fleetId:d.fleetId,completed:m.filter(e=>e.status===`completed`).length,agents:m.length,spend:JSON.stringify(h),deleted:!n.keep}),m.some(e=>e.status!==`completed`)&&(process.exitCode=1)}),n.command(`cancel <fleet-id>`).description(`Interrupt every agent of a fleet and cancel its child fleets; sandboxes keep running`).action(async(t,n)=>{let{client:i}=G(n),a=await(await i.fleets.list({fleetId:t})).cancel();n.json?e({fleetId:t,...a}):r(`Fleet ${t}: interrupted ${a.interrupted} agents, cancelled ${a.children} child fleets`)})}const ss=[`list`,`create`,`delete`,`exec`,`prompt`,`read`,`write`];function cs(e){if(!(!e||e.length===0)){for(let t of e)if(!ss.includes(t))throw Error(`Invalid token action '${t}'. Allowed: ${ss.join(`, `)}`);return e}}function ls(e){return e.length<=12?`****`:`${e.slice(0,6)}...${e.slice(-4)} (masked — use --json for full value)`}function us(t){t.command(`token <fleet-id>`).description(`Mint a scoped fleet bearer token (treated as a secret)`).option(`--action <a...>`,`Allowed actions: list create delete exec prompt read write (prompt grants nothing since fleet prompt dispatch was removed)`).option(`--ttl-minutes <n>`,`Token lifetime in minutes`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Minting fleet token...`);i.start();let a=await r.fleets.createToken(t,{actions:cs(n.action),ttlMinutes:n.ttlMinutes?Number(n.ttlMinutes):void 0});i.stop(),n.json?e(a):(s({"Fleet ID":a.fleetId,Token:ls(a.token),"Expires at":new Date(a.expiresAt).toISOString(),Actions:a.actions.join(`, `)}),console.log(`
145
- Re-run with --json to print the full token value.`))})}function ds(){let n=new N(`workspace`).description(`Manage a fleet's shared workspace`);return n.command(`snapshot <fleet-id>`).description(`Snapshot the fleet's shared workspace`).action(async(t,n)=>{let{client:i}=G(n),a=f(`Creating workspace snapshot...`);a.start();let o=await i.fleets.createWorkspaceSnapshot(t);a.stop(),n.json?e(o):r(`Workspace snapshot created: ${o.snapshotId??o.id}`)}),n.command(`restore <fleet-id> <snapshot-id>`).description(`Restore the fleet's shared workspace from a snapshot`).action(async(t,n,i)=>{let{client:a}=G(i),o=f(`Restoring workspace...`);o.start();let s=await a.fleets.restoreWorkspaceSnapshot(t,n);o.stop(),i.json?e(s):r(`Workspace restored from ${s.snapshotId??n}`)}),n.command(`reconcile <fleet-id>`).description(`Re-mount the shared workspace on all fleet machines`).action(async(n,r)=>{let{client:i}=G(r),a=f(`Reconciling workspace...`);a.start();let o=await i.fleets.reconcileWorkspace(n);a.stop(),r.json?e(o):(s({"Fleet ID":o.fleetId,Checked:o.checked,"Orphaned mounts":o.orphanedMounts}),t(o.machines,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`mounted`,header:`Mounted`,width:10}]))}),n}function fs(){let e=new N(`fleet`).description(`Manage sandbox fleets`);return as(e),So(e),e.addCommand(ds()),os(e),bo(e),us(e),e}function ps(){let t=new N(`fs`).description(`File system operations on sandboxes`);return t.command(`upload`).description(`Upload a file to a sandbox`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<local-path>`,`Local file path`).argument(`<remote-path>`,`Remote destination path`).action(async(t,n,r,i)=>{let{context:a,client:o}=G(i),s=await q(o,a,t);if(s=await J(s),!je.existsSync(n))throw Error(`Local file not found: ${n}`);let c=je.statSync(n),l=Date.now();i.json||console.error(`Uploading ${n} to ${r}...`),await s.fs.upload(n,r,{onProgress:e=>{if(i.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesUploaded}/${e.totalBytes} bytes)`)}});let u=Date.now()-l;i.json||console.error(``),i.json?e({success:!0,localPath:n,remotePath:r,size:c.size,durationMs:u}):console.log(`✓ Uploaded ${c.size} bytes in ${u}ms`)}),t.command(`download`).description(`Download a file from a sandbox`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<remote-path>`,`Remote file path`).argument(`<local-path>`,`Local destination path`).action(async(t,n,r,i)=>{let{context:a,client:o}=G(i),s=await q(o,a,t);s=await J(s);let c=Date.now();i.json||console.error(`Downloading ${n} to ${r}...`),await s.fs.download(n,r,{onProgress:e=>{if(i.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesDownloaded}/${e.totalBytes} bytes)`)}});let l=Date.now()-c,u=je.statSync(r);i.json||console.error(``),i.json?e({success:!0,remotePath:n,localPath:r,size:u.size,durationMs:l}):console.log(`✓ Downloaded ${u.size} bytes in ${l}ms`)}),t.command(`ls`).description(`List directory contents`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`[path]`,`Directory path`,`.`).option(`-l, --long`,`Show detailed information`).option(`-a, --all`,`Include hidden files`).action(async(t,n,r)=>{let{context:a,client:o}=G(r),s=await q(o,a,t);s=await J(s);let c=await s.fs.list(n,{all:r.all,long:r.long});if(r.json)e(c);else if(r.long)i([`Mode`,`Owner`,`Group`,`Size`,`Modified`,`Name`],c.map(e=>{let t=e.isDir?`d`:e.isSymlink?`l`:`-`,n=ms(e.permissions),r=e.isDir?`<DIR>`:hs(e.size),i=e.modTime.toLocaleDateString();return[t+n,e.owner,e.group,r,i,e.name]}));else{let e=c.map(e=>e.isDir?`${e.name}/`:e.name);console.log(e.join(` `))}}),t.command(`stat`).description(`Get file or directory information`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to file or directory`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o);let s=await o.fs.stat(n);r.json?e(s):(console.log(` File: ${s.name}`),console.log(` Path: ${s.path}`),console.log(` Size: ${hs(s.size)} (${s.size} bytes)`),console.log(` Type: ${s.isDir?`directory`:s.isSymlink?`symlink`:`file`}`),console.log(` Mode: ${ms(s.permissions)} (${s.permissions.toString(8)})`),console.log(` Owner: ${s.owner}`),console.log(` Group: ${s.group}`),console.log(` Modified: ${s.modTime.toISOString()}`),console.log(` Accessed: ${s.accessTime.toISOString()}`))}),t.command(`cat`).description(`Print file contents`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to file`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o);let s=await o.read(n);r.json?e({path:n,content:s}):console.log(s)}),t.command(`rm`).description(`Delete a file or directory`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to delete`).option(`-r, --recursive`,`Delete directories recursively`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o),await o.fs.delete(n,{recursive:r.recursive}),r.json?e({success:!0,path:n,deleted:!0}):console.log(`✓ Deleted: ${n}`)}),t.command(`mkdir`).description(`Create a directory`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Directory path to create`).option(`-p, --parents`,`Create parent directories as needed`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o),await o.fs.mkdir(n,{recursive:r.parents}),r.json?e({success:!0,path:n,created:!0}):console.log(`✓ Created: ${n}`)}),t.command(`exists`).description(`Check if a path exists`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to check`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o);let s=await o.fs.exists(n);r.json?e({path:n,exists:s}):(console.log(s?`exists`:`not found`),process.exit(+!s))}),t}function ms(e){let t=[`r`,`w`,`x`],n=``;for(let r=2;r>=0;r--){let i=r*3;for(let r=0;r<3;r++)n+=e>>i+(2-r)&1?t[r]:`-`}return n}function hs(e){let t=[`B`,`KB`,`MB`,`GB`,`TB`],n=e,r=0;for(;n>=1024&&r<t.length-1;)n/=1024,r++;return r===0?`${n}${t[r]}`:`${n.toFixed(1)}${t[r]}`}function gs(){let t=new N(`git`).description(`Git operations in a sandbox workspace`);return t.command(`status`).description(`Show git repository status`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching status...`);n.json||a.start();let o=await q(i,r,t);o=await J(o);let s=await o.git.status();if(a.stop(),n.json)e(s);else if(!s.isRepo)console.log(`No git repository in the sandbox workspace.`);else{if(console.log(`Branch: ${s.branch??`unknown`}`),console.log(`HEAD: ${s.head.slice(0,7)||`(no commits)`}`),console.log(`Dirty: ${s.isDirty?`yes`:`no`}`),s.ahead&&console.log(`Ahead: ${s.ahead}`),s.behind&&console.log(`Behind: ${s.behind}`),s.staged.length>0){console.log(`\nStaged (${s.staged.length}):`);for(let e of s.staged)console.log(` + ${e}`)}if(s.modified.length>0){console.log(`\nModified (${s.modified.length}):`);for(let e of s.modified)console.log(` M ${e}`)}if(s.untracked.length>0){console.log(`\nUntracked (${s.untracked.length}):`);for(let e of s.untracked)console.log(` ? ${e}`)}}}),t.command(`log`).description(`Show commit log`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`-n, --limit <count>`,`Max commits to show`,`10`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching log...`);n.json||a.start();let o=await q(i,r,t);o=await J(o);let s=await o.git.log(Number.parseInt(n.limit,10));if(a.stop(),n.json)e(s);else if(s.length===0)console.log(`No commits found`);else for(let e of s)console.log(`${e.shortSha} ${e.message.split(`
146
- `)[0]} (${e.author}, ${e.date.toLocaleDateString()})`)}),t.command(`diff`).description(`Show diff`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--ref <ref>`,`Ref to diff against`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching diff...`);n.json||a.start();let o=await q(i,r,t);o=await J(o);let s=await o.git.diff(n.ref);a.stop(),n.json?e(s):s.raw?console.log(s.raw):console.log(`${s.additions} additions, ${s.deletions} deletions across ${s.files.length} files`)}),t.command(`add`).description(`Stage files`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<paths...>`,`Paths to stage`).action(async(e,t,n)=>{let{context:i,client:a}=G(n),o=await q(a,i,e);o=await J(o),await o.git.add(t),r(`Staged: ${t.join(`, `)}`)}),t.command(`commit`).description(`Create a commit`).argument(`<id-or-name>`,`Sandbox ID or name`).requiredOption(`-m, --message <msg>`,`Commit message`).option(`--amend`,`Amend the previous commit`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=await q(a,i,t);o=await J(o);let s=await o.git.commit(n.message,{amend:n.amend});n.json?e(s):r(`Committed: ${s.shortSha} ${s.message}`)}),t.command(`push`).description(`Push to remote`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--force`,`Force push`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Pushing...`);a.start();let o=await q(i,n,e);o=await J(o),await o.git.push({force:t.force}),a.stop(),r(`Pushed to remote`)}),t.command(`pull`).description(`Pull from remote`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--rebase`,`Rebase instead of merge`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Pulling...`);a.start();let o=await q(i,n,e);o=await J(o),await o.git.pull({rebase:t.rebase}),a.stop(),r(`Pulled from remote`)}),t.command(`branches`).description(`List branches`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(t,n)=>{let{context:r,client:a}=G(n),o=f(`Fetching branches...`);n.json||o.start();let s=await q(a,r,t);s=await J(s);let c=await s.git.branches();o.stop(),n.json?e(c):c.length===0?console.log(`No branches found`):i([`Name`,`Current`,`Remote`],c.map(e=>[e.name,e.current?`* `:` `,e.upstream??`-`]))}),t.command(`checkout`).description(`Checkout a branch or ref`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<ref>`,`Branch name or ref`).option(`-b, --create`,`Create a new branch`).action(async(e,t,n)=>{let{context:i,client:a}=G(n),o=await q(a,i,e);o=await J(o),await o.git.checkout(t,{create:n.create}),r(`Checked out: ${t}${n.create?` (new)`:``}`)}),t}function _s(e,t=16){if(!Number.isInteger(t)||t<=0||t>64)throw TypeError(`stableHashHex: lengthHex must be in [1, 64] (got ${t})`);let n=typeof e==`string`?e:JSON.stringify(e,(e,t)=>{if(t&&typeof t==`object`&&!Array.isArray(t)){let e={},n=t;for(let t of Object.keys(n).sort())e[t]=n[t];return e}return t});return ve(`sha256`).update(n).digest(`hex`).slice(0,t)}Object.freeze([`HS256`]),Object.freeze([`RS256`]);async function vs(e,t,n=`tangle --help`){let r=new AbortController,i=e??r.signal,a=()=>{r.abort(),process.stderr.write(`Stopping…
147
- `)};e||(process.once(`SIGINT`,a),process.once(`SIGTERM`,a));try{return i.throwIfAborted(),await t(i)}catch(e){if(!i.aborted||e instanceof B&&e.code===`RUN_STOPPED`)throw e;let t=new B(`RUN_STOPPED`,`Command interrupted`,`A stop request ended this execution`,n);throw e instanceof Error&&`runId`in e&&typeof e.runId==`string`&&Object.assign(t,{runId:e.runId}),t}finally{e||(process.off(`SIGINT`,a),process.off(`SIGTERM`,a))}}function ys(e,t){for(let[n,r]of Object.entries(t)){let t=e.gates?.find(e=>e.id===n);if(!t||!t.choices.includes(r))throw new B(`GATE_CHOICE_INVALID`,`Invalid choice for gate '${n}'`,t?`Choose one of: ${t.choices.join(`, `)}`:`The graph does not declare this gate`,`tangle graph run --help`)}}function bs(e,t){let n=t.signal;return async r=>{let i=Object.hasOwn(e,r.gate)?e[r.gate]:void 0,a=`--param ${ut(`gate.${r.gate}=<choice>`)}`,o=`${r.question} Choose one of: ${r.choices.join(`, `)}`,s=()=>new B(`GATE_ANSWER_REQUIRED`,`Gate '${r.gate}' needs an answer. ${o}. Pass ${a}`,o,`tangle graph run <graph> ${a}`);if(i!==void 0)return{kind:`choose`,choice:i,by:`cli:param`};if(t.json||!process.stdin.isTTY)throw s();let c;try{c=await dr(`${r.question} [${r.choices.join(` / `)}]`,void 0,n)}catch{if(n.aborted)return{kind:`stop`,reason:`Gate input interrupted or timed out`,by:`cli:terminal`};throw s()}if(!r.choices.includes(c))throw s();return{kind:`choose`,choice:c,by:`cli:terminal`}}}const xs=()=>import(`./dist-CzrZj_46.mjs`);async function Ss(e,t,n,r){if(e==null)return;let{graphKnowledgeBindingSchema:i,graphKnowledgeResolver:a}=await xs(),o=i.parse(e);if(o.kind!==`local`)throw Error(`A local graph needs a pinned local Knowledge binding; Hub generations require the hosted workflow owner`);return a({binding:o,storeRoot:M(t,`knowledge`),signal:r,record:async e=>n.put({executionId:e.context.nodeId,purpose:`executor-native-evidence`,bytes:Buffer.from(JSON.stringify(e))}),recordProposal:async e=>n.put({executionId:e.context.nodeId,purpose:`task-output`,bytes:Buffer.from(JSON.stringify(e))})})}function Cs(t){let n=t.command(`knowledge`).description(`Exact measured Knowledge candidate transitions`);n.command(`bind <root>`).description(`Identify exact bytes of an existing local Knowledge store`).action(async t=>e(await(await xs()).pinLocalGraphKnowledge(t)));for(let t of[`promote`,`restore`])n.command(`${t} <binding> <candidate>`).description(`${t} the exact measured local Knowledge candidate through its owner`).action(async(n,r)=>{let{graphKnowledgeBindingSchema:i,transitionGraphKnowledge:a}=await xs(),o=i.parse(JSON.parse(await L(n,`utf8`))),s=await a(o,JSON.parse(await L(r,`utf8`)),t);e({...s,nextBinding:{...o,sourceDigest:`sha256:${s.mutation.afterHash}`}})})}const ws=()=>new _e(`--mcp-secret <key=variable>`,`Private local MCP secret reference binding; repeatable, values are never recorded`).argParser((e,t)=>[...t,e]).default([]);function Ts(e=[]){let t=new Map;for(let n of e){let e=n.indexOf(`=`),r=n.slice(0,e).trim(),i=n.slice(e+1).trim();if(e<1||!r||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)||t.has(r)&&t.get(r)!==i)throw new B(`GRAPH_MCP_SECRET_BINDING`,`Invalid private MCP credential binding`,`Use one unambiguous key=ENVIRONMENT_VARIABLE per declared secret reference`,`tangle graph run --help`);t.set(r,i)}return Object.fromEntries(t)}async function Es(e){try{return Ke.parse(JSON.parse(await L(e,`utf8`)))}catch(e){throw new B(`GRAPH_MCP_POLICY_INVALID`,`The graph MCP policy is invalid`,e instanceof Error?e.message:String(e),`tangle graph run --help`)}}const Ds=[`claude-code`,`opencode`,`codex`,`kimi-code`,`prime`],Os=process.env.TANGLE_ROUTER_URL??`https://router.tangle.tools/v1`;function ks(e){let t=Oe(e);if(t)return t;throw Error(`--model '${e}' has no provider. Pass a canonical id, for example 'google/${e}'.`)}function As(e){let t=e.harness??`claude-code`;if(!Ds.includes(t))throw Error(`Unknown --harness '${t}'. Supported: ${Ds.join(`, `)}.`);let n=js(e.maxTokens,2e5,`--max-tokens`),r=js(e.maxIterations,50,`--max-iterations`),i=e.maxWorkers===void 0?void 0:js(e.maxWorkers,0,`--max-workers`);return{harness:t,...e.model?{model:e.model}:{},maxTokens:n,maxIterations:r,...i===void 0?{}:{maxWorkers:i}}}function js(e,t,n){if(e===void 0)return t;let r=Number.parseInt(e,10);if(!Number.isFinite(r)||r<=0)throw Error(`${n} must be a positive integer, got '${e}'.`);return r}function Ms(e){let t={maxTokens:e.maxTokens,maxIterations:e.maxIterations};return e.maxWorkers===void 0?{budget:t}:{budget:t,perWorker:{maxTokens:Math.max(1,Math.floor(e.maxTokens/e.maxWorkers)),maxIterations:Math.max(1,Math.floor(e.maxIterations/e.maxWorkers))}}}function Ns(e){let t=e.spentTotal,n=e.kind===`no-winner`?``:e.out;return{text:typeof n==`string`?n:typeof n==`object`&&n&&`content`in n&&typeof n.content==`string`?n.content:JSON.stringify(n),tokenUsage:{input:t.tokensKnown===!1?null:t.tokens.input,output:t.tokensKnown===!1?null:t.tokens.output},costUsd:t.usdKnown===!1?null:t.usd,status:e.kind===`no-winner`?`no-winner (${e.reason})`:`winner`}}let Ps=null;function Fs(){return Ps??=import(`@tangle-network/agent-runtime/kernel`).catch(e=>{throw Ps=null,e?.code===`ERR_MODULE_NOT_FOUND`?new B(`RUNTIME_UNAVAILABLE`,`Agent Runtime could not be loaded`,e.message,`npm install -g @tangle-network/sandbox-cli@latest`):e}),Ps}async function Is(e,t,n){let r=U({apiKey:n.apiKey,baseUrl:n.baseUrl}),i=W(r),{budget:a,perWorker:o}=Ms(t),s=[],c={async create(e){let{TANGLE_API_KEY:t,...r}=e?.env??{},a=await i.create(e?.env?{...e,env:r}:e);return s.push({id:a.id,status:`spawned`}),n.json||l(`worker ${a.id} spawned`),a}},u=await Fs(),d=u.workerFromBackend({backend:`sandbox`,sandboxClient:c,maxIterations:1}),f=(e,n)=>d({...e,harness:t.harness},n),p={name:`supervisor`,harness:`cli-base`,model:{default:t.model??`gemini-3.5-flash-lite`,provider:t.model?ks(t.model):`google`},tools:{agent_runtime_coordination_spawn_worker:!0,agent_runtime_coordination_observe_agent:!0}},m={routerBaseUrl:Os,routerKey:r.apiKey},h=Ns(await u.supervise(p,{goal:e},{budget:a,makeWorkerAgent:f,router:m,...o?{perWorker:o}:{},...t.model?{allowedModels:[t.model]}:{},runId:`supervise-${be()}`})),g=h.status===`winner`?`settled`:`failed`;for(let e of s)e.status=g,n.json||l(`worker ${e.id} settled (${e.status})`);return{task:e,result:h.text,workers:s,tokenUsage:h.tokenUsage,costUsd:h.costUsd,status:h.status}}function Ls(){let t=new N(`supervise`);return t.description(`Run a budget-conserving supervisor that spawns isolated sandbox workers to deliver a task.`).argument(`<task>`,`What the supervisor should accomplish`).option(`--harness <name>`,`Worker harness (${Ds.join(` | `)})`,`claude-code`).option(`--model <id>`,`Model for the supervisor + workers`).option(`--max-tokens <n>`,`Conserved token budget for the whole run`,`200000`).option(`--max-iterations <n>`,`Conserved iteration budget for the whole run`,`50`).option(`--max-workers <n>`,`Bound the fanout; each worker reserves floor(max-tokens / n) tokens and floor(max-iterations / n) iterations`).action(async(t,n)=>{let r=As({harness:n.harness,model:n.model,maxTokens:n.maxTokens,maxIterations:n.maxIterations,maxWorkers:n.maxWorkers});n.json||(l(`Supervising: ${t}`),l(`harness=${r.harness} budget=${r.maxTokens}tok/${r.maxIterations}it`),console.log());let i=await Is(t,r,{apiKey:n.apiKey,baseUrl:n.baseUrl,json:n.json});if(n.json){e(i),i.status!==`winner`&&(process.exitCode=1);return}if(console.log(),i.result&&(console.log(i.result),console.log()),s({"Input Tokens":i.tokenUsage.input??`Unavailable`,"Output Tokens":i.tokenUsage.output??`Unavailable`,Cost:i.costUsd===null?`Unavailable`:`$${i.costUsd.toFixed(4)}`}),i.status!==`winner`)throw Error(`Supervisor finished without a winner: ${i.status}`)}),t}function Rs(e,t){let n=me(e,t);return n!==`..`&&!n.startsWith(`..${ge}`)&&!fe(n)}const zs=()=>import(`@tangle-network/agent-eval/campaign`),Bs=()=>import(`@tangle-network/agent-runtime/candidate-execution`),Vs=`graph-task-workspaces`,Hs=I.number().int().positive().max(2**53-1),Us=I.strictObject({maxArchiveBytes:Hs.optional(),maxEmbeddedArtifactBytes:Hs.optional(),maxFiles:Hs.optional(),maxFileBytes:Hs.optional(),maxTotalFileBytes:Hs.optional(),maxPathBytes:Hs.optional(),maxRepositoryBundleBytes:Hs.optional()}),Ws=we.shape,Gs=I.strictObject({snapshot:I.strictObject({kind:Ws.kind,digest:Ws.digest,manifest:Ce,archive:Ce}).superRefine((e,t)=>{(e.digest!==e.manifest.sha256||!e.manifest.byteLength||!e.archive.byteLength)&&t.addIssue({code:`custom`,message:`The canonical workspace manifest, digest and archive must agree`})}),capture:I.strictObject({mode:I.literal(`git-working-tree`),runtimeVersion:I.string().min(1),limits:Us}),gaps:I.tuple([I.literal(`environment-and-toolchain-not-snapshotted`),I.literal(`git-ignored-files-excluded`)])}),Ks=e=>P(Gs.parse(e));function qs(e){for(let t of[e.snapshot.manifest,e.snapshot.archive])if(t.locator.kind!==`private-cas`||t.locator.namespace!==Vs)throw Error(`Task workspace artifacts require their original local private CAS; cross-backend activation is unsupported`)}async function Js(){let e=M(F(),`.tangle`);return await ft(e,{recursive:!0,mode:448}),R(e)}const Ys=async e=>(await import(`@tangle-network/agent-runtime/kernel`)).createPrivateCasArtifactPort(M(e,`artifacts`),Vs);async function Xs(e){let t=await mt(he(e),Ne.O_RDONLY|Ne.O_NOFOLLOW);try{if(!(await t.stat()).isFile())throw Error(`Task workspace reference must be a regular file`);let e=Gs.parse(JSON.parse(await t.readFile(`utf8`)));return qs(e),e}finally{await t.close()}}async function Zs(e,t={}){t.signal?.throwIfAborted();let n=he(e),r=await dt(n);if(!r.isDirectory()||r.isSymbolicLink())throw Error(`Task workspace must be one real repository root`);let i=await R(n),a=await R(F()),o=await Js();if(i===a||i===ue(i)||Rs(o,i)||Rs(i,o))throw Error(`Task workspace capture cannot include the home, filesystem or private evidence root`);let{release:s}=(await zs()).acquireSingleRunLock({lockPath:`${i}.graph-workspace.lock`});try{let e=Us.parse(t.limits??{}),n=await(await Bs()).captureAgentWorkspaceSnapshot(i,{includeRepository:!0,repositoryContents:`working-tree`,limits:e,artifactPersistence:{executionId:be(),outputArtifacts:await Ys(o),signal:t.signal}}),r=v(`@tangle-network/agent-runtime`,import.meta.url);if(!r)throw Error(`Cannot identify the Runtime workspace archive owner`);let a=JSON.parse(await L(r,`utf8`));return Gs.parse({snapshot:n,capture:{mode:`git-working-tree`,runtimeVersion:a.version,limits:e},gaps:[`environment-and-toolchain-not-snapshotted`,`git-ignored-files-excluded`]})}finally{s()}}async function Qs(e,t){let n=I.uuid().parse(t.runId),r=Gs.parse(e);qs(r);let i=await Js(),a=M(i,`workspaces`);if(await ft(a,{recursive:!0,mode:448}),await R(a)!==a)throw Error(`Task workspace allocation root redirects elsewhere`);let o=M(a,n),{release:s}=(await zs()).acquireSingleRunLock({lockPath:`${o}.lock`});try{t.signal?.throwIfAborted();let e=`${o}.task-workspace.json`,a;try{a=JSON.parse(await L(e,`utf8`))}catch(e){if(e.code!==`ENOENT`)throw e}let c=Ks(r);if(a!==void 0){let e=I.strictObject({runId:I.uuid(),identity:I.string()}).parse(a);if(e.runId!==n||e.identity!==c||t.resumeCwd!==void 0&&he(t.resumeCwd)!==o||await R(o)!==o||!(await dt(o)).isDirectory())throw Error(`The retained task workspace no longer names this exact native run allocation`)}else{if(t.resumeCwd!==void 0)throw Error(`The retained task workspace allocation receipt is missing`);await(await Bs()).materializeAgentWorkspaceSnapshot({snapshot:r.snapshot,artifacts:await Ys(i),destination:o,limits:r.capture.limits,signal:t.signal}),await z(e,JSON.stringify({runId:n,identity:c}),{flag:`wx`,mode:384,flush:!0})}if(!t.validationOnly||a!==void 0)return{cwd:o,release:s};let l=await Promise.all([dt(o,{bigint:!0}),dt(e,{bigint:!0})]);return{cwd:o,release:async()=>{try{for(let[t,r]of[o,e].entries()){let e=await dt(r,{bigint:!0});if(!(t===0?e.isDirectory():e.isFile())||e.dev!==l[t]?.dev||e.ino!==l[t]?.ino||await R(r)!==r)throw Error(`Validation allocation ${n} changed; retained`)}if(P(JSON.parse(await L(e,`utf8`)))!==P({runId:n,identity:c}))throw Error(`Validation allocation ${n} receipt changed; retained`);try{throw await dt(M(i,`runs`,n)),Error(`Validation allocation ${n} has run state; retained`)}catch(e){if(e.code!==`ENOENT`)throw e}await ht(o,{recursive:!0}),await ht(e)}finally{s()}}}}catch(e){throw s(),e}}function $s(t){t.command(`workspace`).description(`Capture immutable local task files for graph replay`).command(`capture <repository>`).description(`Capture Git HEAD, index, tracked and unignored files into private local artifacts`).requiredOption(`--output <file>`,`New reference file outside the source repository`).option(`--limits <file>`,`JSON overrides for the maintained Runtime archive limits`).action(async(t,n)=>{let r=await R(he(t)),i=M(await R(ue(he(n.output))),le(he(n.output)));if(Rs(r,i))throw Error(`The task reference must be written outside the original workspace`);try{throw await dt(i),Error(`Task workspace reference already exists; choose a new output file`)}catch(e){if(e.code!==`ENOENT`)throw e}let a=await Zs(r,{limits:n.limits?Us.parse(JSON.parse(await L(n.limits,`utf8`))):void 0});await z(i,JSON.stringify(a),{flag:`wx`,mode:384,flush:!0}),e(a)})}const ec=I.string().regex(/^[a-f0-9]{64}$/),tc=I.strictObject({version:I.literal(1),runId:I.uuid(),file:I.string().refine(fe),cwd:I.string().refine(fe),sourceDigest:ec,source:I.string().optional(),graphDigest:ec,params:I.record(I.string(),I.unknown()),trigger:I.record(I.string(),I.unknown()).optional(),gateChoices:I.record(I.string(),I.string()).optional(),startedAt:I.iso.datetime(),seat:I.string().optional(),mcpPolicy:qe.optional(),taskWorkspace:Gs.optional()});async function nc(e){let t=await Fs(),n=t.graphRegistry(M(F(),`.tangle`,`graph-registry`)),r=await t.loadGraph(n,e.graphDigest);if(!r)throw Error(`Retained execution graph is unavailable; configuration is unknown`);let i=t.validateStoredGraph(r);if(i.digest!==e.graphDigest)throw Error(`Retained execution graph changed its identity`);return P({mcpPolicy:qe.parse(e.mcpPolicy??{}),nodes:i.nodes.map(({id:e,profile:t})=>({id:e,harness:t.harness??null,model:t.model??null,seats:t.seats??null,connections:t.connections??null}))})}function Y(e){throw new B(`GRAPH_RESUME_REFUSED`,`The graph run cannot be resumed`,e,`tangle graph run --help`)}async function rc(e){I.uuid().safeParse(e).success||Y(`Use a recorded graph run ID`);let t;try{let n=M(await R(M(F(),`.tangle`)),`runs`,e);await R(n)!==n&&Y(`The run directory redirects elsewhere`),t=await mt(M(n,`input.json`),Ne.O_RDONLY|Ne.O_NOFOLLOW),(await t.stat()).isFile()||Y(`The run input is not a regular file`);let r=tc.parse(JSON.parse(await t.readFile(`utf8`)));return r.runId!==e&&Y(`The recorded run identity changed`),r.source!==void 0&&ac(r,r.source),r}catch(e){if(e instanceof B)throw e;return Y(`The private recorded run input is missing or invalid`)}finally{await t?.close()}}async function ic(e,t){let n=t.source??await L(t.file,`utf8`);ac(t,n),await z(M(e,`input.json`),JSON.stringify({...t,source:n}),{flag:`wx`,mode:384,flush:!0})}function ac(e,t){return ve(`sha256`).update(t).digest(`hex`)!==e.sourceDigest&&Y(`The retained graph source does not match this run`),t}async function oc(e){return ac(e,e.source??await L(e.file,`utf8`))}function sc(e,t,n,r,i={}){e.sourceDigest!==n&&Y(`The authored graph source changed`),t.cloud&&Y(`A local run cannot move to cloud execution`),Object.entries(r).some(([t,n])=>!Object.hasOwn(e.params,t)||P(n)!==P(e.params[t]))&&Y(`A recorded graph parameter changed`),Object.entries(i).some(([t,n])=>e.gateChoices?.[t]!==n)&&Y(`A recorded gate choice changed`),t.seat!==void 0&&t.seat!==e.seat&&Y(`The recorded graph seat override changed`),t.mcpPolicy!==void 0&&(e.mcpPolicy===void 0||P(t.mcpPolicy)!==P(e.mcpPolicy))&&Y(`The recorded graph MCP policy changed`)}const cc=e=>Object.entries(e).map(([e,t])=>`${e}=${typeof t==`string`?t:JSON.stringify(t)}`),lc=`claude,codex,kimi,opencode,gemini,pi`;function uc(e,t){let n;return async(r,{node:i,lastCandidate:a})=>{t.throwIfAborted();let o;try{o=r===void 0?void 0:ke(r)}catch(e){throw e instanceof Error&&Object.assign(e,{node:i,seat:r,fixCommand:`tangle graph run --help`}),e}n??=import(`cli-bridge`).then(({listLocalModels:n,loadConfig:r})=>n({cwd:e,signal:t,config:r({...process.env,BRIDGE_BACKENDS:lc,BRIDGE_SUBSCRIPTIONS_ONLY:`1`})}));let s=await n;t.throwIfAborted();let c=e=>e.authentication?.status===`authenticated`&&e.authentication.authMode===`subscription`,l=o?.harness??s.find(e=>e.provider&&c(e))?.backend,u=s.filter(e=>e.backend===l),d=u.filter(c),f=o?u.find(e=>e.id===`${o.harness}/${o.model}`)??d.find(e=>e.provider===o.provider):d.find(e=>e.default)??d.find(e=>e.recommended)??d[0];if(!f||!c(f)){if(a===!1)return;let e=f?.authentication??u[0]?.authentication??(o?void 0:s.find(e=>e.authentication?.fix)?.authentication);throw Object.assign(new B(o?`SEAT_NOT_LOGGED_IN`:`SEAT_NONE_DETECTED`,`Node '${i}' has no available subscription${o?` for ${o.harness}`:``}`,e?`Selected provider: ${e.status} (${e.authMode})`:`No authenticated subscription route was detected`,e?.fix??`tangle graph run --help`),{node:i,seat:r})}let p=o?.harness??ke(f.id).harness,m=o?.provider??f.provider,h=o?.model??f.id.slice(p.length+1);if(!m||!h)throw new B(`MODEL_PROVIDER_MISMATCH`,`Node '${i}' has an unresolved model provider`,`Bridge has no configured provider for ${r??p}`,`tangle graph run --help`);return{harness:p,provider:m,model:h,selector:{kind:`all-eligible`},...o?.reasoningEffort===void 0?{}:{reasoningEffort:o.reasoningEffort}}}}const dc=gt(He);function fc(e,t,n=`tangle graph run --help`){throw new B(`SEAT_NONE_DETECTED`,e,t,n)}function pc(e){let t=[];for(let n of e.nodes)for(let e of n.check?.egress??[]){let n=e.trim().toLowerCase();if(n){if(/[\s*]|\/|:\/\//u.test(n))throw new B(`GRAPH_EGRESS_HOST`,`Graph egress host "${e.trim()}" is not a DNS hostname`,`A check egress entry has whitespace, a wildcard, or a URL`,`tangle graph run --help`);t.includes(n)||t.push(n)}}return t.length>0?t.join(`,`):void 0}function mc(e){return e.some(e=>(e.profile?.seats?.length??0)>0)}function hc(e){let t=e?.trim();if(t)return/\s/u.test(t)&&fc(`A seat account, command, or credential must be a single token`,`The seat command is an executable path, not a shell line`),t}function gc(e){let t=hc(e.seatAccount),n=hc(e.seatCommand),r=hc(e.seatCredential);return r&&!n&&!t&&fc(`A seat credential needs a seat command`,`The credential is an argument to the configured command`,`tangle graph run --seat-command <program>`),{...t?{account:t}:{},...n?{command:n}:{},...r?{credential:r}:{}}}async function _c(e,t,n){if(e.account)return e.account;e.command||fc(`This graph needs a seat account or a seat command`,`No account was authored and no seat command is configured`,`tangle graph run --seat-account <account>`);let r=``;try{r=(await dc(e.command,[t,...e.credential?[e.credential]:[]],{timeout:3e4,maxBuffer:4096,signal:n,encoding:`utf8`})).stdout}catch(e){n.throwIfAborted();let t=e.code===`ENOENT`;fc(t?`The seat command was not found`:`The seat command failed`,t?`The configured executable is not on PATH`:`The seat command exited without an account id`)}let i=r.trim();return(!i||/\s/u.test(i))&&fc(`The seat command did not print an account id`,`The command must print one account id and nothing else`),i}function vc(e,t,n){let r=new Map;return async i=>{n.throwIfAborted();let a=i.stage.harness,o=i.stage.selector.kind===`seat`?i.stage.selector.id.trim():``,s=`${a}\0${t.credential??``}`,c=o||t.account||r.get(s)||await _c(t,a,n);!o&&!t.account&&r.set(s,c),(!c||/\s/u.test(c)||i.resumeSeatId!==void 0&&i.resumeSeatId!==c)&&fc(`Node '${i.nodeId}' has no seat account`,`The authored seat, account flag, or seat command did not yield one`);let{createCliBridgeProvider:l}=await import(`@tangle-network/agent-provider-cli-bridge`);return{seat:c,backend:{backend:`provider`,provider:l({baseUrl:e.bridgeUrl,bearerToken:e.bridgeBearer}),defaults:{workspace:{cwd:{base:`host`,path:e.cwd}}},runtime:`cli`,outputFormat:`json`,destroyOnSettle:!0,requireTerminalEvent:!0}}}}function X(e){return Qn({signal:e.signal,...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.baseUrl===void 0?{}:{baseUrl:e.baseUrl}})}const yc=I.object({version:I.literal(1),type:I.enum([`state`,`ack`,`error`,`event`]),requestId:I.string().optional(),operationId:I.string().optional(),command:I.string().optional(),code:I.string().optional(),message:I.string().optional(),result:I.unknown().optional()}).passthrough(),bc=I.object({state:I.object({runConfiguration:I.unknown()}),view:I.object({capabilities:I.record(I.string(),I.object({available:I.boolean(),reason:I.string().optional()}))})}),xc=I.object({status:I.enum([`completed`,`failed`,`cancelled`]),analysis:I.object({id:I.string().min(1)}).passthrough(),source:I.object({runtimeRun:I.unknown()}).passthrough()}).passthrough(),Sc=`TANGLE_GRAPH_ANALYSIS_SOURCE`;async function Cc(e,t,n){if(!e.startsWith(`wfrun_`)){let t=M(await R(M(F(),`.tangle`)),`runs`,e);if(await R(t)!==t)throw new B(`RUN_NOT_FOUND`,`The run directory redirects elsewhere`,`Use the recorded local run directory`,`tangle graph inspect --help`);return{source:`runtime:${e}@${t}`,env:{},schema:I.object({runId:I.literal(e),runDir:I.literal(t)})}}let r={signal:n,...t.apiKey===void 0?{}:{apiKey:t.apiKey},...t.baseUrl===void 0?{}:{baseUrl:t.baseUrl}},i=await X(r),a=I.object({id:I.literal(e),workflowId:I.string(),revUsed:I.number().int(),execution:I.object({kind:I.literal(`graph`),sourceSha:I.string(),authoredGraphDigest:I.string(),graphDigest:I.string()}),runtime:I.object({snapshot:I.object({supervisors:I.tuple([I.object({id:I.string()})])})})}).parse(await i.workflows.getRun(e,{signal:n})),o=a.runtime.snapshot.supervisors[0];if(!o)throw new B(`BRAID_RPC_FAILED`,`The cloud run has no retained Runtime root`,`Wait for execution evidence before analysis`,`tangle graph inspect ${e}`);let s=await Jn(r);if(new URL(s.baseUrl.replace(/\/+$/,``)).href!==new URL(i.baseUrl.replace(/\/+$/,``)).href)throw new B(`AUTH_REQUIRED`,`The analysis source origin changed`,`Use the same authenticated platform origin`,`tangle auth status --json`);return{source:`runtime:${e}@${Sc}`,env:{[Sc]:JSON.stringify({url:`${s.baseUrl.replace(/\/+$/,``)}/v1/workflows/runs/${encodeURIComponent(e)}`,headers:{Authorization:`Bearer ${s.token}`}})},schema:I.object({runId:I.literal(e),remoteEndpointEnv:I.literal(Sc),checkpoint:I.object({workflowId:I.literal(a.workflowId),runtimeRunId:I.literal(o.id),revUsed:I.literal(a.revUsed),sourceSha:I.literal(a.execution.sourceSha),authoredGraphDigest:I.literal(a.execution.authoredGraphDigest),graphDigest:I.literal(a.execution.graphDigest)})})}}async function wc(e,t){if(!e.startsWith(`wfrun_`)&&!I.uuid().safeParse(e).success)throw new B(`RUN_NOT_FOUND`,`Use a recorded graph run ID`,`The run identifier is invalid`,`tangle graph inspect --help`);if(!Number.isSafeInteger(t.timeout)||t.timeout<1)throw new B(`INVALID_TIMEOUT`,`Use a positive analysis timeout`,`The timeout must be an integer number of milliseconds`,`tangle graph analyze --help`);let n=t.profile;if(!n?.trim())throw new B(`USAGE_INVALID`,`Select the canonical analysis profile`,`Graph analysis requires an existing canonical AgentProfile reference`,`tangle graph analyze `+e+` --profile <name|path>`);let r=/^(?:\.\.?)[/\\]/.test(n)?he(process.cwd(),n):n;return vs(t.signal,async n=>{let i=await Cc(e,t,n),a=i.source;return Jl({signal:n,errorRunId:e},async n=>{let o=await n.bridge(),s=await pt(M(n.runDir,`analysis-`)),c=M(s,`config.json`),l=M(s,`database.key`),u=M(s,`state.sqlite`),d=`connection-owned-graph-bridge`,f=new Date().toISOString();await z(l,ye(32),{mode:384,flag:`wx`}),await z(c,JSON.stringify({format:`braid-startup-config`,schemaVersion:2,profile:r,connectionId:d,connections:[{id:d,name:`Graph analysis`,kind:`cli-bridge`,endpoint:o.bridgeUrl,providerOptions:{transport:`local`},createdAt:f,updatedAt:f,lastHealth:{status:`unknown`}}]}),{mode:384,flag:`wx`});let p=n.signal,m=`op-${be()}`,h=`op-${be()}`,g=`${m}:initialize`,_=`${m}:analyze`,v=`${m}:shutdown`,y={version:1,requestId:g,command:`initialize`,params:{workspace:n.cwd,subscribe:!1}},b={version:1,requestId:_,operationId:m,command:`analyze`,params:{source:a,recipe:`all`,totalTimeoutMs:t.timeout}},x={version:1,requestId:v,operationId:h,command:`shutdown`,params:{mode:`wait`}},S,C,w,T,ee={transform:e=>{let t=yc.parse(e);return t.type===`error`||t.type===`state`&&t.requestId===g||t.type===`ack`&&[_,v].includes(t.requestId??``)?t:null},onError:e=>{T??=e},onEvent:e=>{e.type===`error`&&(T??=new B(e.code??`BRAID_RPC_FAILED`,`Braid refused graph analysis`,e.message??`The RPC response omitted its cause`,`tangle graph analyze --help`)),e.requestId===g&&e.type===`state`&&(S??=e),e.requestId===_&&e.type===`ack`&&(C??=e),e.requestId===v&&e.type===`ack`&&(w??=e)}},E=await lt({command:process.env.BRAID_BIN??`braid`,args:[`rpc`,`--workspace`,n.cwd,`--config`,c,`--profile`,r,`--database-key-file`,l],cwd:n.cwd,env:{...i.env,BRAID_STATE_PATH:u,BRAID_CLI_BRIDGE_ENDPOINT:o.bridgeUrl,BRAID_CLI_BRIDGE_AUTH:o.bridgeBearer},timeoutMs:t.timeout,signal:p,ownProcessGroup:!0},ee,{stdin:[y,...t.dryRun?[]:[b],x].map(e=>JSON.stringify(e)).join(`
138
+ `)?`${e}\n`:`${e}\n\n`}function Oa(){let e=process.env.SHELL??``;return e.includes(`zsh`)?M(F(),`.zshrc`):e.includes(`bash`)?M(F(),`.bashrc`):M(F(),`.zshrc`)}function ka(e){if(e===`shell`||e===`env`||e===`dockerfile`)return e;throw Error(`--format must be one of: shell, env, dockerfile (got '${e}')`)}function Aa(e){if(e===`full`||e===`prompts`||e===`metadata`)return e;throw Error(`--content must be one of: full, prompts, metadata (got '${e}')`)}async function ja(e){let t=wa({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format});if(console.log(t),e.format!==`shell`){console.log(),l(e.format===`env`?"Cron/container path: feed these to your service env (.env, `docker run --env-file`, k8s envFrom). No shell-rc edit, no TTY needed.":`Dockerfile path: paste these ENV lines into your image. No shell-rc edit, no TTY needed.`);return}if(console.log(),l(`Privacy tiers: --content full ships the whole conversation; --content prompts keeps task, prompts, and tool args only; --content metadata turns content off (telemetry still flows). Secrets are scrubbed server-side regardless.`),!e.write)return;let n=e.rcPath??Oa(),i=process.stdin.isTTY?await lr(`Append this idempotent block to ${n}? (y/N)`,`n`):`n`;if(i.toLowerCase()!==`y`&&i.toLowerCase()!==`yes`){console.log(),l(`Not writing. To append later: tangle connect claude-code --rc ${n}`);return}let a=Ta({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format}),{contents:o,changed:s}=Ea(_a(n),a);if(!s){console.log(),r(`Already present in ${n} — nothing to change.`);return}va(n,o),console.log(),r(`Wrote Tangle Intelligence env block to ${n}.`),l(`Reload your shell (e.g. 'source ${n}') before running the agent.`)}function Ma(e){let t=[],n={header:null,body:[]};for(let r of e.split(`
139
+ `))Na(r)?(t.push(n),n={header:r.trim(),body:[]}):n.body.push(r);return t.push(n),t.length>1&&t[0].header===null&&t[0].body.every(e=>e.trim()===``)&&t.shift(),t}function Na(e){let t=e.trim();return t.startsWith(`[`)&&t.endsWith(`]`)&&!t.includes(`=`)||t.startsWith(`[[`)&&t.endsWith(`]]`)}function Pa(e){let t=[];for(let n of e)n.header!==null&&t.push(n.header),t.push(...n.body);return t.join(`
140
+ `)}function Fa(e){return[{key:`environment`,line:`environment = "prod"`},{key:`log_user_prompt`,line:`log_user_prompt = true`},{key:`exporter`,line:`exporter = { otlp-http = { endpoint = "${Ai(e.endpoint)}/v1/logs", protocol = "json", headers = { "Authorization" = "Bearer ${e.apiKey??"${TANGLE_API_KEY}"}" } } }`}]}function Ia(e){let t=e.trim();if(t===``||t.startsWith(`#`))return null;let n=t.indexOf(`=`);if(n===-1)return null;let r=t.slice(0,n).trim();return/^[A-Za-z0-9_-]+$/.test(r)?r:null}function La(e,t){let n=Fa(t),r=new Set(n.map(e=>e.key));if(e.trim()===``)return{contents:`${[`[otel]`,...n.map(e=>e.line)].join(`
141
+ `)}\n`,changed:!0};let i=Ma(e),a=i.find(e=>e.header===`[otel]`);if(!a){let t={header:`[otel]`,body:n.map(e=>e.line)},r=i[i.length-1];r&&!Ra(r)&&r.body.push(``),i.push(t);let a=za(Pa(i));return{contents:a,changed:a!==za(e)}}let o=a.body.filter(e=>{let t=Ia(e);return t===null||!r.has(t)}),s=[];for(;o.length>0&&o[o.length-1].trim()===``;)s.unshift(o.pop());a.body=[...o,...n.map(e=>e.line),...s];let c=za(Pa(i));return{contents:c,changed:c!==za(e)}}function Ra(e){return e.body.length>0&&e.body[e.body.length-1].trim()===``}function za(e){return e.endsWith(`
142
+ `)?e:`${e}\n`}function Ba(e){let t=M(F(),`.codex`,`config.toml`),{contents:n,changed:i}=La(_a(t),{endpoint:e.endpoint,apiKey:e.apiKey});if(!e.write){console.log(n.trimEnd());return}if(!i){r(`${t} already has the Tangle [otel] block — nothing to change.`);return}va(t,n),r(`Merged the Tangle [otel] block into ${t}.`),l("Codex emits content on the logs signal (codex.* events). Set TANGLE_API_KEY in your env before running if you kept the ${TANGLE_API_KEY} reference."),l(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=${e.projectKey??`<your project>`} before running codex.`)}function Va(e){switch(e){case`claude-code`:return`Claude Code: set OTEL_LOGS_EXPORTER=otlp and the four OTEL_LOG_* gates (OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_DETAILS, OTEL_LOG_TOOL_CONTENT, OTEL_LOG_RAW_API_BODIES).`;case`codex`:return`Codex: set log_user_prompt = true in [otel] (default false redacts content).`;case`opencode`:return`OpenCode: a standalone install emits nothing without the tangle-opencode-exporter shim; inside a Tangle sandbox it is already instrumented.`;case`openclaw`:case`hermes`:case`nanoclaw`:return`${ha[e]}: no native OTLP exporter and no standalone server to subscribe to — run it inside a Tangle sandbox, where the sidecar adapter exports its content with gen_ai.system=${e}. A bare standalone install emits metadata only.`}}async function Ha(e){let t=Date.now()+e.timeoutSeconds*1e3,n=3e3,r=Math.min(e.timeoutSeconds*1e3,1e4),i=f(`Checking whether content is flowing…`);i.start();let a;try{for(;;){try{a=await ki({endpoint:e.endpoint,apiKey:e.apiKey,timeoutMs:r})}catch(e){if(Date.now()>=t)throw e;await et(n);continue}if(a.contentSeen||Date.now()>=t)break;await et(n)}}finally{i.stop()}if(!a)throw Error(`onboarding status check returned no result`);Ua(a,e.agent),a.contentSeen||(process.exitCode=1)}function Ua(e,t){if(e.contentSeen){r(`Content flowing — Tangle Intelligence can analyze this feed.`),s({"Last seen":e.lastSeenAt??`just now`,Window:`${e.windowDays}d`});return}if(e.tracesSeen){c(`Metadata-only — traces are arriving but carry no content. You missed a content gate.`);let n=t?[t]:Object.keys(e.byAgent).filter(ga),r=n.length>0?n:ma;for(let n of r){let r=e.byAgent[n];(t||!r||r.tracesSeen&&!r.contentSeen)&&l(Va(n))}return}c(`No traces yet for your tenant. Run your agent once on a real task, then re-run --verify.`),t&&l(Va(t))}function Wa(e){let t=e??process.env.TANGLE_INTELLIGENCE_API_KEY??mn(void 0);if(!t)throw Error(`No Tangle API key found. Pass --api-key, set TANGLE_API_KEY, or run: tangle auth login`);return t}function Ga(){return new N(`connect`).description(`Connect a local coding agent's telemetry to Tangle Intelligence, content on (for SDK integration snippets, see 'tangle agent connect')`).argument(`[agent]`,`claude-code | codex | opencode | openclaw | hermes | nanoclaw`).option(`--endpoint <url>`,`OTLP endpoint base`,mi).option(`-p, --project <key>`,`Project label (tangle.subject.key) to group runs; omit to set it yourself`).option(`--rc <path>`,`Shell rc file to append the Claude Code env block to`).option(`--no-write`,`Print the config instead of writing files (Claude Code / Codex)`).option(`--inline-key`,"Embed the resolved API key literally in the config (default: keep ${TANGLE_API_KEY})").option(`--verify`,`Poll onboarding status and report whether CONTENT is flowing`).option(`--timeout <seconds>`,`Verify poll timeout in seconds`,`120`).option(`--run`,`OpenCode only: run the content exporter against a live OpenCode server until interrupted`).option(`--opencode-url <url>`,`OpenCode server base URL for --run (or set OPENCODE_BASE_URL)`).option(`--format <kind>`,`Claude Code output: shell (export block) | env (.env / docker --env-file) | dockerfile (ENV lines). env/dockerfile are the cron/container path — printed to stdout, no shell-rc edit, no TTY`,`shell`).option(`--content <tier>`,`Claude Code content tier: full (everything) | prompts (task+prompts+tool-args) | metadata (telemetry on, content off)`,`full`).action(async(e,t)=>{let n=Ai(t.endpoint);if(t.run){if((e?qa(e):`opencode`)!==`opencode`)throw Error(`--run is OpenCode-only: it runs the content exporter against a live OpenCode server. Other agents export natively once configured.`);await Za({endpoint:n,apiKey:Wa(t.apiKey),opencodeUrl:t.opencodeUrl});return}if(t.verify){await Ha({endpoint:n,apiKey:Wa(t.apiKey),agent:e?qa(e):void 0,timeoutSeconds:pa(t.timeout,`--timeout`)});return}let r=e?qa(e):await Ja(),i=t.inlineKey?Wa(t.apiKey):void 0;r===`claude-code`?await ja({endpoint:n,apiKey:i,projectKey:t.project,rcPath:t.rc,write:t.write!==!1,content:Aa(t.content),format:ka(t.format)}):r===`codex`?Ba({endpoint:n,apiKey:i,projectKey:t.project,write:t.write!==!1}):r===`opencode`?Ya({endpoint:n}):Xa(r,{endpoint:n}),console.log(),l(`Run your agent on a real task, then verify content is flowing: tangle connect ${r} --verify`)})}function Ka(){return new N(`opencode-exporter`).description(`Export a running OpenCode's content to Tangle Intelligence (standalone shim)`).option(`--endpoint <url>`,`OTLP endpoint base`,mi).option(`--opencode-url <url>`,`OpenCode server base URL (or set OPENCODE_BASE_URL)`).action(async e=>{await Za({endpoint:Ai(e.endpoint),apiKey:Wa(e.apiKey),opencodeUrl:e.opencodeUrl})})}function qa(e){if(ga(e))return e;throw Error(`Unknown agent '${e}'. Choose one of: ${ma.join(`, `)}`)}async function Ja(){if(!process.stdin.isTTY)throw Error(`Specify an agent: tangle connect <${ma.join(`|`)}>`);console.log(`Which coding agent are you connecting?`),ma.forEach((e,t)=>{console.log(` ${t+1}) ${ha[e]} (${e})`)});let e=await lr(`Enter a number or name`,`1`);return ma[Number.parseInt(e,10)-1]||qa(e.trim())}function Ya(e){let t=Ai(e.endpoint);c(`OpenCode has no native OTel exporter, so a standalone install emits nothing without a shim.`),console.log(),s({"Inside a Tangle sandbox":`already instrumented — our adapter exports OpenCode's event-stream content. Nothing to do.`,Standalone:`run 'tangle connect opencode --run' alongside a running OpenCode, exporting to ${t}.`}),console.log(),l(`Start OpenCode in server mode ('opencode serve'), then in another terminal run: tangle connect opencode --run`),l(`The exporter subscribes to OpenCode's SSE event bus and exports content-bearing OTLP (prompt/completion/tool content) to Tangle. Verify with: tangle connect opencode --verify`),l(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting the exporter.`)}function Xa(e,t){let n=Ai(t.endpoint),r=ha[e];c(`${r} has no native OTel exporter, so a standalone install emits nothing without instrumentation.`),console.log(),s({"Inside a Tangle sandbox":`already instrumented — the sidecar adapter exports ${r}'s prompt/completion/tool content (gen_ai.system=${e}) to ${n}. Nothing to do.`,Standalone:`${r} exposes no OTLP and no event-bus server; run it inside a Tangle sandbox to capture content.`}),console.log(),l(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting ${r}.`),l(`Verify content is flowing: tangle connect ${e} --verify`)}async function Za(e){let t=ca(e.opencodeUrl),n=new AbortController,i=()=>n.abort();process.on(`SIGINT`,i),process.on(`SIGTERM`,i),l(`Subscribing to OpenCode at ${t} — exporting content to Tangle.`),l(`Run OpenCode tasks now. Press Ctrl-C to stop.`),console.log();let a=0,o;try{o=await fa({endpoint:e.endpoint,apiKey:e.apiKey,opencodeBaseUrl:t,signal:n.signal,onExport:({eventType:e,records:t})=>{a+=t,l(`exported ${t} record(s) from ${e} (total ${a})`)}})}catch(e){if(e instanceof ua){let{recordsExported:t,contentEventsExported:n}=e.partial;console.log(),c(`Exporter failed after exporting ${t} content record(s) from ${n} event(s): ${e.message}`)}throw e}finally{process.off(`SIGINT`,i),process.off(`SIGTERM`,i)}if(console.log(),o.contentEventsExported===0){c(`Saw ${o.eventsSeen} event(s) but none carried content. Run a real OpenCode task (a prompt that produces text or a tool call), then re-run.`);return}r(`Exported ${o.recordsExported} content record(s) from ${o.contentEventsExported} event(s).`),l(`Verify it landed: tangle connect opencode --verify`)}function Qa(){let t=new N(`environments`).alias(`env`).description(`Manage sandbox environments`);return t.command(`list`).alias(`ls`).description(`List available environments`).action(async t=>{let{client:n}=G(t),r=f(`Fetching environments...`);t.json||r.start();let a=await n.environments.list();r.stop(),t.json?e(a):a.length===0?console.log(`No environments found`):i([`ID`,`Description`,`Version`,`Runtimes`],a.map(e=>[e.id,e.description??``,e.version,e.runtimes.join(`, `)]))}),t.command(`get`).description(`Get environment details`).argument(`<id>`,`Environment ID`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Fetching environment...`);n.json||i.start();let a=await r.environments.get(t);if(i.stop(),!a){console.error(`Environment not found: ${t}`),process.exit(1);return}n.json?e(a):(console.log(`ID: ${a.id}`),console.log(`Description: ${a.description??`-`}`),console.log(`Version: ${a.version}`),console.log(`Runtimes: ${a.runtimes.join(`, `)}`),a.base&&console.log(`Base: ${a.base}`))}),t}const $a=I.string().trim().toLowerCase().min(1).max(64).regex(/^[a-z][a-z0-9-]*$/),eo=I.string().trim().toLowerCase().min(1).max(128).regex(/^[a-z0-9][a-z0-9._-]*$/),to=I.object({kind:eo,count:I.number().int().positive().default(1),vramGb:I.number().positive().optional()}).strict();I.object({command:I.string().min(1).max(8192),timeoutMs:I.number().int().positive().max(2147453647).optional(),env:I.record(I.string(),I.string()).optional(),cwd:I.string().min(1).max(2048).optional()}).strict(),I.object({refresh:I.enum([`true`,`false`]).optional(),acceleratorKind:eo.optional(),acceleratorCount:I.coerce.number().pipe(to.shape.count.unwrap()).optional(),acceleratorVramGb:I.coerce.number().positive().optional()}).strict(),I.object({maxSpendUsd:I.number().positive().max(1e4).optional(),maxLifetimeSeconds:I.number().int().positive().max(1440*60).optional()}).strict().refine(e=>e.maxSpendUsd!==void 0||e.maxLifetimeSeconds!==void 0,`Renewal requires a lifetime or spend cap`);const no=I.object({provider:$a.optional(),image:I.string().min(1).max(512).optional(),env:I.record(I.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),I.string()).optional(),diskGb:I.number().int().positive().optional(),volumeGb:I.number().int().nonnegative().optional(),volumeMountPath:I.string().startsWith(`/`).max(2048).optional(),region:I.string().min(1).max(128).optional(),manifest:I.record(I.string(),I.unknown()).optional(),command:I.array(I.string().max(8192)).min(1).max(256).optional(),ports:I.array(I.number().int().min(1).max(65535)).max(32).optional(),endpoint:I.object({port:I.number().int().min(1).max(65535),healthPath:I.string().regex(/^\/(?![/\\])/).refine(e=>![`\r`,`
143
+ `,` `].some(t=>e.includes(t))).max(2048).optional()}).strict().optional(),allowSpot:I.boolean().optional(),maxHourlyUsd:I.number().positive().optional(),weights:I.object({manifestSha:I.string().regex(/^[a-f0-9]{64}$/),sizeBytes:I.number().int().positive().safe()}).strict().optional(),arms:I.array(I.unknown()).min(1).max(256).optional(),maxSpendUsd:I.number().positive().max(1e4),maxLifetimeSeconds:I.number().int().positive().max(1440*60),idleTimeoutSeconds:I.number().int().positive().optional()}).strict();no.extend({accelerator:to});const ro=to,io=$a;I.object({...no.omit({env:!0}).shape,id:I.string(),projectRef:I.string(),ownerUserId:I.string(),productId:I.string().optional(),provider:io,providerLeaseId:I.string().optional(),providerInstanceType:I.string().optional(),endpointUrl:I.string().optional(),status:I.enum([`provisioning`,`ready`,`detaching`,`destroyed`,`failed`]),accelerator:ro,providerCostPerHourUsd:I.number().optional(),customerPricePerHourUsd:I.number().optional(),estimatedProviderCostUsd:I.number().optional(),estimatedCustomerCostUsd:I.number().optional(),providerSelection:I.object({strategy:I.enum([`explicit`,`cheapest`,`ranked`]),selectedProvider:io,requestedProvider:io.optional(),candidates:I.array(I.object({provider:io,accelerator:ro,providerInstanceType:I.string().optional(),region:I.string().optional(),pricingSource:I.enum([`live`,`configured`]).optional(),providerCostPerHourUsd:I.number(),customerPricePerHourUsd:I.number(),maxLifetimeSeconds:I.number(),estimatedProviderCostUsd:I.number(),estimatedCustomerCostUsd:I.number()})),rejected:I.array(I.object({provider:io,error:I.string()}))}).optional(),createdAt:I.string(),updatedAt:I.string(),readyAt:I.string().optional(),startedAt:I.string().optional(),lastUsedAt:I.string().optional(),destroyedAt:I.string().optional(),failure:I.string().optional(),billing:I.object({seconds:I.number(),providerCostUsd:I.number(),customerCostUsd:I.number(),providerCostPerHourUsd:I.number(),customerPricePerHourUsd:I.number(),startedAt:I.string(),stoppedAt:I.string()}).optional()});function ao(e){return{kind:mo(e.kind),count:e.count?po(e.count,`--accelerator-count`):1,...e.memory?{vramGb:go(e.memory,`--accelerator-memory`)}:{}}}function oo(e,t,n){if(!t&&Object.values(e).some(Boolean))throw Error(n);return t?co(e,`--gpu-`):void 0}function so(e){return{...co(e,`--`),accelerator:ao({kind:e.acceleratorKind,count:e.acceleratorCount,memory:e.acceleratorMemory})}}function co(e,t){let{provider:n,image:r,env:i,maxSpendUsd:a,maxLifetime:o,idleTimeout:s}=e;if(!a||!o)throw Error(`--accelerator-kind requires ${t}max-spend-usd and ${t}max-lifetime`);return{...n?{provider:ho(n,`${t}provider`)}:{},...r?{image:r}:{},...i?{env:fo(i,`${t}env`,`env`)}:{},maxSpendUsd:go(a,`${t}max-spend-usd`),maxLifetimeSeconds:po(o,`${t}max-lifetime`),...s?{idleTimeoutSeconds:po(s,`${t}idle-timeout`)}:{}}}function lo(e){return e.length===1?e[0]:e.map(ut).join(` `)}function uo(e){return{timeoutMs:e.timeout?po(String(e.timeout),`--timeout`):void 0,env:e.env?fo(e.env,`--env`,`env`):void 0}}function fo(e,t,n){let r={};for(let i of e){let[e,...a]=i.split(`=`);if(!e||a.length===0)throw Error(`${t} expects ${n} values in KEY=VALUE format`);r[e]=a.join(`=`)}return r}function po(e,t){if(!/^\d+$/.test(e))throw Error(`${t} must be a positive integer`);let n=Number.parseInt(e,10);if(Number.isNaN(n)||n<1)throw Error(`${t} must be a positive integer`);return n}function mo(e){let t=eo.safeParse(e);if(t.success)return t.data;throw Error(`--accelerator-kind must contain only letters, numbers, dots, underscores, or hyphens`)}function ho(e,t){let n=$a.safeParse(e);if(n.success)return n.data;throw Error(`${t} must start with a letter and contain only letters, numbers, or hyphens`)}function go(e,t){if(!/^(?:\d+|\d+\.\d+|\.\d+)$/.test(e))throw Error(`${t} must be a positive number`);let n=Number.parseFloat(e);if(!Number.isFinite(n)||n<=0)throw Error(`${t} must be a positive number`);return n}function _o(){return new N(`exec`).description(`Execute a command in a sandbox`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<command...>`,`Command and arguments, or one shell script`).option(`--cwd <dir>`,`Working directory`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).option(`-t, --timeout <ms>`,`Timeout in milliseconds`,`60000`).allowUnknownOption(!0).action(async(t,n,r)=>{try{let{context:i,client:a}=G(r),o=lo(n),s=fo(r.env??[],`--env`,`env`),c=f(`Executing: ${o}`);r.json||c.start();let l=await q(a,i,t);l=await J(l);let u=await l.exec(o,{cwd:r.cwd,env:Object.keys(s).length>0?s:void 0,timeoutMs:Number.parseInt(r.timeout,10)});c.stop(),r.json?e(u):(u.stdout&&process.stdout.write(u.stdout),u.stderr&&process.stderr.write(u.stderr)),u.exitCode!==0&&(process.exitCode=u.exitCode)}catch(e){if(e instanceof S){let t=`Exec transport lost before command status was confirmed. Remote command status is unknown. Original error: ${e.message}. For long-running commands, use \`tangle process spawn\`, \`tangle process logs\`, and \`tangle process kill --tree\`.`;return H(Error(t,{cause:e}))}H(e)}})}function vo(n){n.command(`capabilities`).description(`List fleet drivers and their supported features`).action(async n=>{let{client:r}=G(n),i=f(`Fetching capabilities...`);i.start();let a=await r.fleets.capabilities();i.stop(),n.json?e(a):t(a.drivers,[{key:`driverType`,header:`Driver`,width:16},{key:`sharedWorkspace`,header:`Shared WS`,width:12},{key:`accelerators`,header:`Accel`,width:8},{key:`queueTimings`,header:`Queue`,width:8}])}),n.command(`usage <fleet-id>`).description(`Show fleet usage and reliability insights`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Fetching usage...`);i.start();let a=await r.fleets.usage(t);if(i.stop(),n.json)e(a);else if(s({"Fleet ID":a.usage.fleetId,Status:a.usage.status,Machines:a.usage.machineCount,Running:a.usage.runningMachines,Failed:a.usage.failedMachines,"Runtime (ms)":a.usage.meteredUsage?.runtimeMs,"Reliability score":a.insights.reliabilityScore,"Failure rate":a.insights.failureRate}),a.insights.recommendedActions.length>0){console.log(`
144
+ Recommended actions:`);for(let e of a.insights.recommendedActions)console.log(` - ${e}`)}}),n.command(`cost <fleet-id>`).description(`Show the fleet's cost estimate`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Estimating cost...`);i.start();let a=await r.fleets.cost(t);i.stop(),n.json?e(a):s({Plan:a.plan,Currency:a.currency,"Hourly (USD)":a.hourlyUsd,"Max lifetime (s)":a.maxLifetimeSeconds,"Estimated max lifetime (USD)":a.estimatedMaxLifetimeUsd,Machines:a.requestedResources.machines,"Total CPU":a.requestedResources.totalCpu,"Total memory (MB)":a.requestedResources.totalMemoryMb})})}function yo(e){return[...e.entries()].map(([e,t])=>({machineId:e,sandboxId:t.id,status:t.status}))}function bo(n){n.command(`list <fleet-id>`).description(`List the machines of one fleet (fleet id is required)`).option(`--status <status>`,`Filter machines by status`).action(async(n,r)=>{let{client:i}=G(r),a=f(`Fetching fleet...`);a.start();let o=await i.fleets.list({fleetId:n,status:r.status});a.stop();let s=yo(o.machines);r.json?e({fleetId:o.fleetId,machines:s}):t(s,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}])}),n.command(`get <fleet-id>`).description(`Show one fleet's manifest (server record)`).action(async(n,r)=>{let{client:i}=G(r),a=f(`Fetching manifest...`);a.start();let o=await i.fleets.manifest(n);a.stop(),r.json?e(o):(s({"Fleet ID":o.fleetId??o.id,Machines:o.machines.length,"Workspace mode":o.workspace?.mode,"Workspace status":o.workspace?.status,"Max lifetime (s)":o.policy?.maxLifetimeSeconds,"Max spend (USD)":o.policy?.maxSpendUsd,Created:o.createdAt,Updated:o.updatedAt}),t(o.machines,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`role`,header:`Role`,width:14},{key:`status`,header:`Status`,width:14}]))}),n.command(`delete <fleet-id>`).description(`Delete a fleet's machine sandboxes and its record`).option(`--continue-on-error`,`Keep deleting remaining machines if one delete fails`).action(async(t,n)=>{let{client:i}=G(n),a=f(`Deleting fleet...`);a.start(),await i.fleets.delete(t,{continueOnError:n.continueOnError}),a.stop(),n.json?e({success:!0,fleetId:t}):r(`Fleet deleted: ${t}`)}),n.command(`reap`).description(`TTL cleanup of all expired fleets (fleet-wide)`).option(`--dry-run`,`Report what would be reaped without deleting`).action(async n=>{let{client:r}=G(n),i=f(`Reaping expired fleets...`);i.start();let a=await r.fleets.reapExpired({dryRun:n.dryRun});i.stop(),n.json?e(a):(s({"Dry run":a.dryRun,Expired:a.expired,Deleted:a.deleted}),t(a.fleets,[{key:`fleetId`,header:`Fleet`,width:24},{key:`expiredAt`,header:`Expired`,width:18},{key:`deleted`,header:`Deleted`,width:10}]))}),n.command(`reconcile`).description(`Drop fleet records whose underlying sandboxes vanished`).option(`--dry-run`,`Report orphans without removing them`).action(async n=>{let{client:r}=G(n),i=f(`Reconciling fleets...`);i.start();let a=await r.fleets.reconcile({dryRun:n.dryRun});i.stop(),n.json?e(a):(s({"Dry run":a.dryRun,Checked:a.checked,Orphaned:a.orphaned,Removed:a.removed}),t(a.machines,[{key:`fleetId`,header:`Fleet`,width:24},{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`removed`,header:`Removed`,width:10}]))})}async function xo(e,t){let n=await Kn({apiKey:t.apiKey,baseUrl:t.baseUrl??xn()}),r=await fetch(`${n.baseUrl}/v1/agent-profiles/${encodeURIComponent(e)}`,{headers:{authorization:`Bearer ${n.token}`,accept:`application/json`}});if(!r.ok){let t=await r.text().catch(()=>``);throw r.status===404?Error(`profile '${e}' not found in the platform catalog (it may be a built-in, a stored profile you own, or neither — run 'tangle profile list' to see what is available)`):Error(`platform returned ${r.status}: ${t.slice(0,200)}`)}let i=await r.json();if(!i.definition||typeof i.definition!=`object`)throw Error(`profile '${e}' resolved but has no definition — the catalog entry is malformed`);return i.definition}async function So(e){let t=typeof e.envVarName==`string`&&e.envVarName.length>0?e.envVarName:null,n=!!e.fromStdin;if(t&&n)throw Error(`Pass either ${e.flagPrefix}-env or ${e.flagPrefix}-stdin, not both`);if(t){let n=process.env[t];if(!n||n.length===0)throw Error(`${e.flagPrefix}-env points at ${t}, but that environment variable is empty or unset`);return n}if(n){let t=await ur();if(t.length===0)throw Error(`${e.flagPrefix}-stdin received empty input on stdin`);return t}}function Co(e){if(e.secret===void 0)return;let t=e.backend===`claude-code`?`token`:e.backend===`codex`?`bundle`:void 0;if(!t)throw Error(`--cli-auth needs --backend claude-code or --backend codex`);if(e.apiKeyGiven)throw Error(`--cli-auth cannot be combined with --backend-api-key-env or --backend-api-key-stdin`);return{account:`cli`,secretEnv:e.secret,format:t}}function wo(e){if(e!==void 0)return e.map(e=>{if(e.includes(`@`)||e.includes(`:`))throw Error(`--secret ${e}: bare secret names only (box delivery). For proxy custody use --proxy-secret with a canonical binding`);return e})}function To(e,t){let n={};return e.cpu!==void 0&&(n.cpuCores=po(e.cpu,`--cpu`)),e.memory!==void 0&&(n.memoryMB=po(e.memory,`--memory`)),e.disk!==void 0&&(n.diskGB=po(e.disk,`--disk`)),t&&(n.accelerator=t),Object.keys(n).length>0?n:void 0}function Eo(e){let t=e.split(`/`);return t.length>=2?{provider:t[0],model:t.slice(1).join(`/`)}:{model:e}}function Do(e){let t={};for(let n of e){let[e,...r]=n.split(`=`);if(!e||r.length===0)throw Error(`--metadata expects values in KEY=VALUE or KEY=JSON format`);t[e]=Oo(r.join(`=`))}return t}function Oo(e){try{return JSON.parse(e)}catch{return e}}function ko(e,t){if(!(!e.gitUrl&&!e.gitRef&&!e.gitDepth&&!e.gitSparse&&!t)){if(!e.gitUrl||typeof e.gitUrl!=`string`)throw Error(`--git-url is required when using git provisioning options`);return{url:e.gitUrl,ref:typeof e.gitRef==`string`?e.gitRef:void 0,depth:typeof e.gitDepth==`string`?po(e.gitDepth,`--git-depth`):void 0,sparse:Array.isArray(e.gitSparse)?e.gitSparse:void 0,auth:t?{token:t}:void 0}}}function Ao(e,t){if(!(!e.storageType&&!e.storageBucket&&!e.storageEndpoint&&!e.storageRegion&&!e.storagePrefix&&!e.storageAccessKeyId&&!t)){if(typeof e.storageType!=`string`||typeof e.storageBucket!=`string`||typeof e.storageAccessKeyId!=`string`||!t)throw Error(`Storage config requires --storage-type, --storage-bucket, --storage-access-key-id, and one of --storage-secret-access-key-env / --storage-secret-access-key-stdin`);return{type:jo(e.storageType),bucket:e.storageBucket,endpoint:typeof e.storageEndpoint==`string`?e.storageEndpoint:void 0,region:typeof e.storageRegion==`string`?e.storageRegion:void 0,prefix:typeof e.storagePrefix==`string`?e.storagePrefix:void 0,credentials:{accessKeyId:e.storageAccessKeyId,secretAccessKey:t}}}}function jo(e){if(e===`s3`||e===`gcs`||e===`r2`)return e;throw Error(`--storage-type must be one of s3, gcs, or r2`)}function Mo(e){if(e===void 0)return;let t=[];for(let n of e){let e=n,r=`--proxy-secret <json>`;if(n.startsWith(`@`)){let t=n.slice(1);r=`--proxy-secret @${t}`;try{e=Ie(t,`utf8`)}catch{throw Error(`${r}: file could not be read`)}}let i;try{i=JSON.parse(e)}catch(e){throw Error(`${r}: not valid JSON (${e instanceof Error?e.message:String(e)})`)}if(Array.isArray(i))t.push(...i);else if(typeof i==`object`&&i)t.push(i);else throw Error(`${r}: expected a binding object or an array of bindings`)}let n=xe.parse(t);return n.length>0?n:void 0}function No(e){l(` Status: ${e.status}`),l(` Provider: ${e.provider}`),l(` GPU: ${e.accelerator.kind} x ${e.accelerator.count}`),e.customerPricePerHourUsd!==void 0&&l(` Customer price: $${e.customerPricePerHourUsd}/hr`),e.estimatedCustomerCostUsd!==void 0&&l(` Max estimate: $${e.estimatedCustomerCostUsd}`),e.billing&&(l(` Billed seconds: ${e.billing.seconds}`),l(` Customer cost: $${e.billing.customerCostUsd}`))}function Po(e){e.result.stdout&&process.stdout.write(e.result.stdout),e.result.stderr&&process.stderr.write(e.result.stderr),l(`Exit code: ${e.result.exitCode}`)}function Fo(n){let i=n.command(`gpu`).description(`Manage on-demand GPU leases for a sandbox`);i.command(`providers <id-or-name>`).description(`List GPU clouds, whether each credential works, and current prices`).option(`--accelerator-kind <kind>`,`Price this GPU kind, for example nvidia-h100`).option(`--accelerator-count <count>`,`GPU device count`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Checking GPU providers...`);o.start();let s=await(await q(a,i,n)).gpu.providers(r.acceleratorKind?{accelerator:ao({kind:r.acceleratorKind,count:r.acceleratorCount,memory:r.acceleratorMemory})}:{});if(o.stop(),r.json){e(s);return}t(s.statuses.map(e=>({provider:e.provider,state:e.state,gpu:e.estimate?.providerInstanceType??``,usdHr:e.estimate?e.estimate.customerPricePerHourUsd.toFixed(4):``,pricing:e.estimate?.pricingSource??``,needs:e.envVars.join(` `)})),[{key:`provider`,header:`Provider`},{key:`state`,header:`State`},{key:`gpu`,header:`GPU`},{key:`usdHr`,header:`$/hr`},{key:`pricing`,header:`Price`},{key:`needs`,header:`Needs`}]);for(let e of s.statuses){let t=e.state===`credential-invalid`?e.credential?.detail:e.estimateError;t&&l(`${e.provider}: ${t}`)}s.usable.length===0&&l(`No GPU provider is usable on this deployment: set the variables in Needs for one provider on the server.`)}),i.command(`attach <id-or-name>`).description(`Attach a temporary GPU worker to a sandbox`).requiredOption(`--accelerator-kind <kind>`,`GPU kind, for example nvidia-h100`).option(`--accelerator-count <count>`,`GPU device count`,`1`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--provider <provider>`,`GPU cloud provider; omitted picks the cheapest configured provider`).option(`--image <image>`,`GPU worker image override`).option(`--env <vars...>`,`Environment variables for the GPU worker (KEY=VALUE)`).requiredOption(`--max-spend-usd <usd>`,`Maximum customer spend for this lease`).requiredOption(`--max-lifetime <seconds>`,`Maximum lease lifetime in seconds`).option(`--idle-timeout <seconds>`,`Destroy after this many idle seconds`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=f(`Attaching GPU lease...`);o.start();let s=await(await q(a,i,t)).gpu.attach(so(n));o.stop(),n.json?e(s):(r(`GPU lease attached: ${s.id}`),No(s))}),i.command(`run <id-or-name> <command...>`).description(`Attach a GPU, run a command or script, then destroy it`).requiredOption(`--accelerator-kind <kind>`,`GPU kind, for example nvidia-h100`).option(`--accelerator-count <count>`,`GPU device count`,`1`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--provider <provider>`,`GPU cloud provider; omitted picks the cheapest configured provider`).option(`--image <image>`,`GPU worker image override`).option(`--env <vars...>`,`Environment variables for the GPU worker and command (KEY=VALUE)`).requiredOption(`--max-spend-usd <usd>`,`Maximum customer spend for this lease`).requiredOption(`--max-lifetime <seconds>`,`Maximum lease lifetime in seconds`).option(`--idle-timeout <seconds>`,`Destroy after this many idle seconds`).option(`--timeout <ms>`,`Command timeout in milliseconds`).option(`--cwd <path>`,`Working directory`).action(async(t,n,i)=>{let a,o,s,c;try{let{context:e,client:r}=G(i),s=await q(r,e,t),c=f(`Attaching GPU lease...`);c.start(),a=await s.gpu.attach(so(i)),c.stop();let l=f(`Running GPU command...`);l.start(),o=await s.gpu.exec(a.id,{command:lo(n),...uo(i),cwd:i.cwd}),l.stop(),i.json||Po(o)}catch(e){s=e}finally{if(a)try{let{context:e,client:n}=G(i);a=await(await q(n,e,t)).gpu.detach(a.id)}catch(e){c=e}}if(s){H(s),c&&H(c);return}if(c){H(c);return}i.json?e({lease:a,result:o}):a&&r(`GPU lease detached: ${a.id}`);let l=o?.result.exitCode;l&&l!==0&&(process.exitCode=l)}),i.command(`list <id-or-name>`).description(`List GPU leases attached to a sandbox`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching GPU leases...`);o.start();let s=await(await q(a,i,n)).gpu.list();o.stop(),r.json?e(s):s.length===0?l(`No GPU leases attached.`):t(s.map(e=>({id:e.id,status:e.status,provider:e.provider,accelerator:`${e.accelerator.kind}x${e.accelerator.count}`,customerUsdHr:e.customerPricePerHourUsd??``})),[{key:`id`,header:`ID`,width:28},{key:`status`,header:`Status`,width:12},{key:`provider`,header:`Provider`,width:12},{key:`accelerator`,header:`GPU`,width:24},{key:`customerUsdHr`,header:`$/hr`,width:10}])}),i.command(`exec <id-or-name> <lease-id> <command...>`).description(`Run a command or script on an attached GPU lease`).option(`--timeout <ms>`,`Command timeout in milliseconds`).option(`--cwd <path>`,`Working directory`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).action(async(t,n,r,i)=>{let{context:a,client:o}=G(i),s=f(`Running GPU command...`);s.start();let c=await(await q(o,a,t)).gpu.exec(n,{command:lo(r),...uo(i),cwd:i.cwd});s.stop(),i.json?e(c):Po(c)}),i.command(`detach <id-or-name> <lease-id>`).description(`Detach and destroy a GPU lease`).action(async(t,n,i)=>{let{context:a,client:o}=G(i),s=f(`Detaching GPU lease...`);s.start();let c=await(await q(o,a,t)).gpu.detach(n);s.stop(),i.json?e(c):(r(`GPU lease detached: ${c.id}`),No(c))})}function Io(t,n){if(n){e(t);return}if(!t.id){t.kind===`snapshot`&&t.result?.snapshot?r(`Snapshot created: ${t.result.snapshot.snapshotId}`):r(`Sandbox ${t.sandboxId} stopped.`);return}r(`${t.kind===`snapshot`?`Snapshot`:`Stop`} of sandbox ${t.sandboxId} accepted.`),l(`Operation: ${t.id}`),l(`Status: ${t.statusUrl}`)}function Lo(e){return`${e.name} (${e.id})`}async function Ro(e,t){if(t.startsWith(`team_`))return e.teams.get(t);let n=(await e.teams.list()).filter(e=>e.name.toLowerCase()===t.toLowerCase());if(n.length===0)throw Error(`Team not found: ${t}`);if(n.length>1)throw Error(`Team name is ambiguous: ${t}. Use a team id instead.`);return n[0]}async function zo(e,t,n){if(t)return Ro(e,t);let r=wn(n);if(!r.activeTeamId)throw Error("No active team. Run `tangle team switch <team>` or pass `--team <team>`.");return e.teams.get(r.activeTeamId)}function Bo(e,t){Tn({id:e.id,name:e.name},t)}function Vo(e){En(e)}async function Ho(e){if(e.explicitTeam&&e.personal)throw Error(`--team and --personal cannot be used together`);if(!e.personal)return e.explicitTeam?(await Ro(e.client,e.explicitTeam)).id:e.activeTeamId}async function Uo(e){if([!!e.explicitTeam,!!e.personal,!!e.allScopes].filter(Boolean).length>1)throw Error(`--team, --personal, and --all-scopes are mutually exclusive`);if(e.allScopes)return`all`;if(e.personal)return`personal`;if(e.explicitTeam)return`team:${(await Ro(e.client,e.explicitTeam)).id}`;if(e.activeTeamId)return`team:${e.activeTeamId}`}function Wo(e){if(!e)return e;let t={...e};for(let e of[`authToken`,`execToken`])t[e]!==void 0&&(t[e]=`[REDACTED]`);return t}function Go(n){n.command(`attestation <id-or-name>`).description(`Fetch TEE attestation evidence for a sandbox`).option(`--nonce <hex|auto>`,`Nonce to bind into a fresh attestation report; use auto to generate one`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=n.nonce===`auto`?ie():n.nonce,s=f(`Fetching TEE attestation...`);s.start();let c=await(await q(a,i,t)).getTeeAttestation(o?{attestationNonce:o}:void 0);s.stop(),n.json?e(c):(r(`Attestation fetched for ${t}`),console.log(`TEE type: ${c.attestation.tee_type}`),console.log(`Evidence bytes: ${c.attestation.evidence.length}`),console.log(`Measurement bytes: ${c.attestation.measurement.length}`),console.log(`Timestamp: ${c.attestation.timestamp}`),c.attestationNonce&&console.log(`Nonce: ${c.attestationNonce}`))}),n.command(`list`).description(`List all sandboxes`).option(`-s, --status <status>`,`Filter by status (running, stopped, all)`).option(`-l, --limit <n>`,`Limit results`,`50`).option(`--team <team>`,`List sandboxes for a team by id or name`).option(`--personal`,`List personal sandboxes`).option(`--all-scopes`,`List personal and team sandboxes`).action(async n=>{let{context:r,client:i}=G(n),a=f(`Fetching sandboxes...`);a.start();let o=await Uo({client:i,explicitTeam:n.team,personal:n.personal,allScopes:n.allScopes,activeTeamId:r.activeTeamId}),s=await i.list({status:n.status===`all`?void 0:n.status,limit:Number.parseInt(n.limit,10),scope:o});a.stop(),n.json?e(s):t(s.map(e=>({id:e.id,status:e.status,createdAt:e.createdAt,name:e.name??``})),[{key:`id`,header:`ID`,width:24},{key:`status`,header:`Status`,width:14},{key:`createdAt`,header:`Created`,width:16},{key:`name`,header:`Name`,width:20}])}),n.command(`get <id-or-name>`).description(`Get sandbox details`).option(`--profile`,`Show the active agent profile provenance (name, hash, skills)`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching sandbox...`);a.start();let o=await q(i,r,t);if(a.stop(),n.profile){let e=o.getProfileProvenance?.();e?(l(`Agent profile provenance:`),l(` Base profile: ${e.base.name??`(inline)`} (${e.base.sha256.slice(0,12)}...)`),l(` Effective: ${e.effective.name??`(inline)`} (${e.effective.sha256.slice(0,12)}...)`),l(` Materialized: ${e.materializedAt}`),e.base.sha256!==e.effective.sha256&&l(` ⚠ Profile changed since creation (base ≠ effective)`)):l(`No profile materialized (bare sandbox). Create with --profile <name> to install one.`);return}n.json?e(o):u({id:o.id,name:o.name,status:o.status,resources:o.resources,createdAt:o.createdAt?.toISOString(),expiresAt:o.expiresAt?.toISOString(),connection:o.connection})}),n.command(`shapes`).description(`List the named sandbox sizes, the default, and this account's ceiling`).action(async n=>{let{client:r}=G(n),i=await r.shapes();if(n.json){e(i);return}let a=e=>e.cpuCores<=i.ceiling.cpuCores&&e.memoryMB<=i.ceiling.memoryMB&&e.diskGB<=i.ceiling.diskGB;t(i.presets.map(e=>({name:e.name===i.default?`${e.name} (default)`:e.name,cpu:e.cpuCores,memory:`${e.memoryMB} MB`,disk:`${e.diskGB} GB`,available:a(e)?`yes`:e.name===i.default?`clamped to ceiling`:`above ceiling`})),[{key:`name`,header:`Shape`,width:18},{key:`cpu`,header:`vCPU`,width:6},{key:`memory`,header:`Memory`,width:10},{key:`disk`,header:`Disk`,width:8},{key:`available`,header:`Available`,width:14}]),l(`Ceiling for this account: ${o(i.ceiling)}`)}),n.command(`delete <id-or-name>`).description(`Delete a sandbox`).option(`-f, --force`,`Skip confirmation`).option(`--name`,`Treat the reference as a sandbox name`).addOption(new _e(`--until <state>`,`Wait for physical removal`).choices([`removed`])).option(`--retry-cleanup`,`Retry server-side cleanup after the sandbox disappeared from get/list`).action(async(e,t)=>{if(!t.force&&!await cr(`Delete sandbox ${e}? [y/N] `,`--force`)){l(`Cancelled.`);return}let{context:n,client:i}=G(t),a=f(`Deleting sandbox...`);a.start();let o=await tr(i,n,e,{retryCleanup:t.retryCleanup,name:t.name,until:t.until});a.stop(),r(o===`already_absent`?`Sandbox ${e} was already gone.`:`Sandbox ${e} deleted.`)}),n.command(`stop <id-or-name>`).description(`Stop a running sandbox`).option(`--name`,`Treat the reference as a sandbox name`).option(`--no-wait`,`Return once the stop is accepted and print the operation to poll`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Stopping sandbox...`);a.start();let o=await q(i,n,e,{nameOnly:t.name});if(t.wait===!1){let e=await o.stop({wait:!1});a.stop(),Io(e.info,!!t.json);return}await o.stop(),a.stop(),r(`Sandbox ${e} stopped.`)}),n.command(`resume <id-or-name>`).description(`Resume a stopped sandbox`).option(`--wait`,`Wait for sandbox to be running`,!0).option(`-t, --timeout <ms>`,`Resume timeout in milliseconds; a cold resume re-provisions the sandbox, so this defaults higher than other commands (default 120000)`,`120000`).action(async(e,t)=>{let n=Number.parseInt(t.timeout,10);if(!Number.isFinite(n)||n<=0)throw Error(`--timeout must be a positive number of milliseconds`);let i=U({apiKey:t.apiKey,baseUrl:t.baseUrl,timeout:n}),a=W(i),o=f(`Resuming sandbox...`);o.start();let s=await q(a,i,e);await s.resume({timeoutMs:n}),t.wait&&(o.text=`Waiting for sandbox to start...`,await s.waitFor(`running`,{timeoutMs:n})),o.stop(),r(`Sandbox ${s.id} resumed.`)})}function Ko(t){t.command(`create`).option(`--cpu-features <flags>`,`Required Linux CPU flags, comma-separated`).description(`Create a new sandbox`).option(`-n, --name <name>`,`Sandbox name`).option(`-e, --environment <environment>`,qo).addOption(Jo()).option(`--bare`,`Create a bare sandbox without the agent runtime`).option(`--ssh`,`Enable SSH access`).option(`--ssh-key <key>`,`SSH public key for authentication`).option(`--ssh-keys <names...>`,`Stored SSH key names or IDs for authentication`).option(`--ssh-key-file <paths...>`,`SSH public key file paths for authentication`).option(`--web-terminal`,`Enable web terminal`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).option(`--secret <names...>`,`Secrets selected by bare name for box delivery (value in the sandbox env). For proxy custody use --proxy-secret`).option(`--proxy-secret <bindings...>`,`Canonical proxy custody binding(s): one binding as inline JSON, or @file with a JSON array. The value stays at the egress proxy and is redeemed only within the binding's scope (hosts/methods/paths/TTL); the box reads a placeholder. Repeatable`).option(`--metadata <entries...>`,`Metadata entries (KEY=VALUE or KEY=JSON)`).option(`--cpu <cores>`,"CPU cores (omit for the platform default; see `sandbox shapes`)").option(`--memory <mb>`,`Memory in MB (omit for the platform default)`).option(`--disk <gb>`,`Disk size in GB (omit for the platform default)`).option(`--accelerator-kind <kind>`,`Accelerator kind, for example nvidia-h100 or amd-mi300x`).option(`--accelerator-count <count>`,`Accelerator device count`,`1`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--gpu-provider <provider>`,`GPU cloud provider; omitted picks the cheapest configured provider`).option(`--gpu-worker-image <image>`,`GPU worker image override`).option(`--gpu-env <vars...>`,`Environment variables for the GPU worker (KEY=VALUE)`).option(`--gpu-max-spend-usd <usd>`,`Maximum customer spend for the create-time GPU lease`).option(`--gpu-max-lifetime <seconds>`,`Maximum create-time GPU lease lifetime in seconds`).option(`--gpu-idle-timeout <seconds>`,`Destroy the create-time GPU lease after this many idle seconds`).option(`--lifetime <seconds>`,`Max wall-clock lifetime before the sandbox is suspended — stopped, not deleted; resume it within the cold window (default 3600 = 1h). Raise it for long sessions, e.g. --lifetime 7200`,`3600`).option(`--idle-timeout <seconds>`,"Idle time before the sandbox is stopped — not deleted (default 900 = 15m). Resume it later with `tangle sandbox resume <id-or-name>`, or it auto-resumes on next use. Raise it for demos, e.g. --idle-timeout 3600",`900`).option(`--from-snapshot <id>`,`Create the sandbox from a snapshot`).option(`--public-template <id-or-slug>`,`Create the sandbox from a published public template`).option(`--public-template-version <id>`,`Pin creation to a specific published public-template version`).option(`--billing-owner <userId>`,`Platform user that pays for the sandbox. The API accepts this only from a first-party service key that is listed as a billing delegate, and refuses such a key that names no payer.`).option(`--team <team>`,`Create in a team by id or name`).option(`--personal`,`Create a personal sandbox even when a team is active`).option(`--git-url <url>`,`Git repository URL to clone during provisioning`).option(`--git-ref <ref>`,`Git branch, tag, or commit to checkout`).option(`--git-depth <depth>`,`Git clone depth`).option(`--git-sparse <paths...>`,`Sparse checkout paths`).option(`--git-token-env <name>`,`Name of an environment variable containing the Git HTTPS auth token`).option(`--git-token-stdin`,`Read the Git HTTPS auth token from stdin`).option(`--storage-type <type>`,`BYOS3 storage type (s3, gcs, r2)`).option(`--storage-bucket <name>`,`BYOS3 bucket name`).option(`--storage-endpoint <url>`,`BYOS3 endpoint URL`).option(`--storage-region <region>`,`BYOS3 region`).option(`--storage-prefix <prefix>`,`BYOS3 path prefix`).option(`--storage-access-key-id <id>`,`BYOS3 access key ID`).option(`--storage-secret-access-key-env <name>`,`Name of an environment variable containing the BYOS3 secret access key`).option(`--storage-secret-access-key-stdin`,`Read the BYOS3 secret access key from stdin`).addOption(new _e(`--driver <type>`,`Run on Tangle network operators instead of the platform's hosts (--tee needs it)`).choices([`tangle`])).option(`--backend <type>`,`Backend agent type (${y.join(`, `)})`).option(`--backend-model <model>`,`Model override (format: provider/model)`).addOption(new _e(`--reasoning-effort <level>`,`Reasoning effort for the backend's model; overrides the profile's model.reasoningEffort`).choices(Se)).option(`--backend-api-key-env <name>`,`Name of an environment variable containing the BYOK backend API key`).option(`--backend-api-key-stdin`,`Read the BYOK backend API key from stdin`).option(`--cli-auth <secret>`,"Run --backend claude-code or codex on your own subscription: the stored secret holding a `claude setup-token` token or a Codex auth.json (see `tangle secret create`)").option(`--profile <path>`,`Path to an AgentProfile JSON file to install as the sandbox's backend profile (carries skills, tools, MCP, model). Use with --backend; the profile's inline skills materialize into the harness's native skill directory on first turn`).option(`--profile-stdin`,`Read the AgentProfile JSON from stdin instead of a file (use with --profile)`).option(`--tee <type>`,`Require a TEE backend (any, tdx, nitro, sev-snp, phala-dstack)`).option(`--sealed`,`Request TEE sealed-secret support`).option(`--attestation-nonce <hex|auto>`,`Deploy-time attestation nonce; use auto to generate one`).option(`--attestation-refresh`,`Generate a fresh deploy-time attestation nonce when --tee is set`).option(`--require-attestation`,`Fail unless TEE attestation evidence is returned`).option(`--wait`,`Wait for sandbox to be running`,!0).option(`--timeout <ms>`,`HTTP timeout in milliseconds`,`30000`).action(async t=>{let n=await So({envVarName:t.gitTokenEnv,fromStdin:t.gitTokenStdin,flagPrefix:`--git-token`}),i=await So({envVarName:t.storageSecretAccessKeyEnv,fromStdin:t.storageSecretAccessKeyStdin,flagPrefix:`--storage-secret-access-key`}),a=await So({envVarName:t.backendApiKeyEnv,fromStdin:t.backendApiKeyStdin,flagPrefix:`--backend-api-key`}),o=Co({secret:t.cliAuth,backend:t.backend,apiKeyGiven:a!==void 0}),s;if(t.profileStdin){let e=await ur(`--profile-stdin`,`the AgentProfile JSON`);try{s=JSON.parse(e)}catch{H(Error(`--profile-stdin: the input is not valid JSON`));return}}else if(t.profile){let e=String(t.profile);if(e.startsWith(`.`)||e.startsWith(`/`)||e.endsWith(`.json`))try{s=JSON.parse(Ie(e,`utf8`))}catch(t){H(Error(`--profile ${e}: ${t.message}`));return}else try{s=await xo(e,t)}catch(t){H(Error(`--profile ${e}: ${t.message}`));return}}s=Xo(s,t.reasoningEffort);let c=U({apiKey:t.apiKey,baseUrl:t.baseUrl,timeout:t.timeout?Number.parseInt(t.timeout,10):void 0}),l=W(c),d=f(`Creating sandbox...`);d.start();let p=await Ho({client:l,explicitTeam:t.team,personal:t.personal,activeTeamId:c.activeTeamId}),m=fo(t.env??[],`--env`,`env`),h=t.metadata?Do(t.metadata):void 0,g=ko(t,n),_=Ao(t,i),v=t.acceleratorKind?ao({kind:String(t.acceleratorKind),count:String(t.acceleratorCount),memory:typeof t.acceleratorMemory==`string`?t.acceleratorMemory:void 0}):void 0,y=oo({provider:typeof t.gpuProvider==`string`?t.gpuProvider:void 0,image:typeof t.gpuWorkerImage==`string`?t.gpuWorkerImage:void 0,env:Array.isArray(t.gpuEnv)?t.gpuEnv:void 0,maxSpendUsd:typeof t.gpuMaxSpendUsd==`string`?t.gpuMaxSpendUsd:void 0,maxLifetime:typeof t.gpuMaxLifetime==`string`?t.gpuMaxLifetime:void 0,idleTimeout:typeof t.gpuIdleTimeout==`string`?t.gpuIdleTimeout:void 0},!!v,`Create-time GPU lease flags require --accelerator-kind`),b=t.driver?{type:`tangle`}:void 0,x=t.backend||t.backendModel||s?{...t.backend?{type:ae(t.backend)}:{},...s?{profile:s}:{},model:t.backendModel||a||o?{...t.backendModel?Eo(t.backendModel):{},apiKey:a,...o?{cliAuth:o}:{}}:void 0}:void 0,S=wo(t.secret),C=o?[...new Set([...S??[],o.secretEnv])]:S,w=Mo(t.proxySecret),T=To(t,v),ee=t.sshKeyFile??(t.ssh&&!t.sshKey&&!t.sshKeys?.length?[Yo()]:[]),E=[...t.sshKey?[t.sshKey]:[],...ee.map(e=>Ie(e,`utf8`).trim())],D={name:t.name,environment:t.environment,runtime:t.runtime,cpuFeatures:t.cpuFeatures?.split(`,`).map(e=>e.trim()),bare:t.bare||void 0,sshEnabled:t.ssh||!!t.sshKey||E.length>0||!!t.sshKeys?.length,sshPublicKeys:E.length>0?E:void 0,sshKeyIds:t.sshKeys,webTerminalEnabled:t.webTerminal,env:Object.keys(m).length>0?m:void 0,git:g,...T?{resources:T}:{},gpuLease:y,maxLifetimeSeconds:Number.parseInt(t.lifetime,10),idleTimeoutSeconds:Number.parseInt(t.idleTimeout,10),storage:_,fromSnapshot:t.fromSnapshot,publicTemplateId:t.publicTemplate,publicTemplateVersionId:t.publicTemplateVersion,teamId:p,...t.billingOwner?{billingOwnerId:t.billingOwner}:{},secrets:C,...w?{proxySecrets:w}:{},metadata:h,driver:b,backend:x},O=t.tee?{tee:t.tee,sealed:t.sealed||void 0,attestationRefresh:t.attestationRefresh||t.attestationNonce===`auto`||void 0}:void 0,k=O?await re(l,{...D,confidential:O,attestationNonce:t.attestationNonce??(t.attestationRefresh?`auto`:void 0),requireAttestation:t.requireAttestation??!0}):void 0,A=k?.sandbox??await l.create(D);t.wait&&(d.text=`Waiting for sandbox to start...`,await A.waitFor(`running`,{timeoutMs:12e4}),await A.refresh()),d.stop(),t.json?e({id:A.id,name:A.name,status:A.status,resources:A.resources,createdAt:A.createdAt,expiresAt:A.expiresAt,connection:Wo(A.connection),teamId:p,gpuLease:A.gpuLease,confidential:O,attestation:k?.attestation,attestationNonce:k?.attestationNonce}):(r(`Sandbox created: ${A.id}`),u({id:A.id,name:A.name,status:A.status,resources:A.resources,createdAt:A.createdAt?.toISOString(),expiresAt:A.expiresAt?.toISOString(),connection:A.connection}),p&&console.log(`Team: ${p}`),A.gpuLease&&(console.log(`GPU lease: ${A.gpuLease.id}`),No(A.gpuLease)),O&&(console.log(`TEE: ${O.tee}`),console.log(`Attestation: ${k?.attestation?`present`:`not returned`}`),k?.attestationNonce&&console.log(`Attestation nonce: ${k.attestationNonce}`)))})}const qo="A catalog environment, a container image reference, or a built image ID. Firecracker runs only images pinned by repository@sha256 that the cell's Firecracker hosts carry; `environments list` shows each image's runtimes";function Jo(){return new _e(`--runtime <runtime>`,`Isolation on the platform's hosts: docker runs a container on the host kernel, firecracker a microVM with its own kernel. Omit for the platform default`).choices(ee)}function Yo(){let e=[`id_ed25519`,`id_ecdsa`,`id_rsa`].map(e=>`${F()}/.ssh/${e}.pub`),t=e.find(e=>Pe(e));if(!t)throw Error(`--ssh needs a public key and found none at ${e.join(`, `)}. Run ssh-keygen -t ed25519, or pass --ssh-key-file.`);return t}function Xo(e,t){if(!t)return e;let n=e?.model??{};return{...e,model:{...n,reasoningEffort:t}}}function Zo(e){if(e.spec){let t=JSON.parse(Ie(e.spec,`utf8`));return{base:{fleetId:e.fleetId,defaults:t.defaults,policy:t.policy,workspace:t.workspace,metadata:t.metadata},machines:t.machines??[]}}let t=es(e),n=ts(e,!!t?.accelerator),r={...e.environment?{environment:e.environment}:{},...t?{resources:t}:{},...e.runtime?{runtime:e.runtime}:{},...n?{gpuLease:n}:{},...e.backend?{backend:{type:e.backend}}:{}},i=ns(e),a=Math.max(1,Number(e.count)||1),o=Array.from({length:a},(e,t)=>({machineId:`worker-${t+1}`}));return{base:{fleetId:e.fleetId,defaults:Object.keys(r).length>0?r:void 0,policy:i,workspace:{mode:e.workspace}},machines:o}}function Qo(e){let{base:t,machines:n}=Zo(e);return{...t,machines:n}}function $o(e){let{base:t,machines:n}=Zo(e);return{...t,workers:n}}function es(e){let t={};if(e.cpu&&(t.cpuCores=Number(e.cpu)),e.memory&&(t.memoryMB=Number(e.memory)),e.disk&&(t.diskGB=Number(e.disk)),e.acceleratorKind)t.accelerator=ao({kind:e.acceleratorKind,count:e.acceleratorCount,memory:e.acceleratorMemory});else if(e.acceleratorCount||e.acceleratorMemory)throw Error(`--accelerator-count and --accelerator-memory require --accelerator-kind`);return Object.keys(t).length>0?t:void 0}function ts(e,t){return oo({provider:e.gpuProvider,image:e.gpuWorkerImage,env:e.gpuEnv,maxSpendUsd:e.gpuMaxSpendUsd,maxLifetime:e.gpuMaxLifetime,idleTimeout:e.gpuIdleTimeout},t,`Fleet GPU lease flags require --accelerator-kind`)}function ns(e){let t={};return e.maxSpendUsd&&(t.maxSpendUsd=Number(e.maxSpendUsd)),e.maxLifetime&&(t.maxLifetimeSeconds=Number(e.maxLifetime)),Object.keys(t).length>0?t:void 0}function rs(n){n.command(`create`).description(`Create a sandbox fleet`).option(`--fleet-id <id>`,`Stable fleet id (generated when omitted)`).option(`--count <n>`,`Number of worker machines`,`1`).option(`--environment <environment>`,qo).addOption(Jo()).option(`--cpu <cores>`,`CPU cores per machine`).option(`--memory <mb>`,`Memory in MB per machine`).option(`--disk <gb>`,`Disk in GB per machine`).option(`--accelerator-kind <kind>`,`Accelerator kind per machine, for example nvidia-l4 or nvidia-h100`).option(`--accelerator-count <count>`,`Accelerator devices per machine`).option(`--accelerator-memory <gb>`,`Minimum memory per GPU in decimal GB`).option(`--gpu-provider <provider>`,`GPU cloud provider per machine; omitted picks the cheapest configured provider`).option(`--gpu-worker-image <image>`,`GPU worker image override`).option(`--gpu-env <vars...>`,`Environment variables for each GPU worker (KEY=VALUE)`).option(`--gpu-max-spend-usd <usd>`,`Maximum spend per machine GPU lease`).option(`--gpu-max-lifetime <seconds>`,`Maximum GPU lease lifetime per machine in seconds`).option(`--gpu-idle-timeout <seconds>`,`Destroy each GPU lease after this many idle seconds`).option(`--backend <id>`,`Agent backend type`).option(`--workspace <mode>`,`Workspace mode: isolated (no driver supports shared yet)`,`isolated`).option(`--max-spend-usd <n>`,`Fleet spend cap in USD (policy)`).option(`--max-lifetime <s>`,`Max machine lifetime in seconds (policy)`).option(`--spec <file.json>`,`Path to a JSON file describing the fleet (overrides synthesized machines)`).option(`--coordinator`,`Create a coordinator + workers fleet (routes to createWithCoordinator)`).action(async n=>{let{client:i}=G(n),a=f(`Creating fleet...`);a.start();let o=n.coordinator?await i.fleets.createWithCoordinator($o(n)):await i.fleets.create(Qo(n));a.stop();let s=yo(o.machines);n.json?e({fleetId:o.fleetId,machines:s}):(r(`Fleet created: ${o.fleetId}`),t(s,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}]))})}function is(n){n.command(`exec <fleet-id> <command>`).description(`Run a shell command across the fleet's machines`).option(`--machine <id...>`,`Restrict to a subset of machine ids (default: all)`).option(`--cwd <dir>`,`Working directory for the command`).option(`--timeout <ms>`,`Per-machine timeout in milliseconds`).option(`--max-concurrent <n>`,`Max concurrent dispatches`).action(async(n,r,i)=>{let{client:a}=G(i),o=f(`Dispatching command...`);o.start();let s=await(await a.fleets.list({fleetId:n})).dispatchExecDetailed(r,{machines:i.machine,cwd:i.cwd,timeoutMs:i.timeout?Number(i.timeout):void 0,maxConcurrent:i.maxConcurrent?Number(i.maxConcurrent):void 0});if(o.stop(),i.json)e(s);else{t(s.results.map(e=>({machineId:e.machineId,ok:e.ok,exitCode:e.result?.exitCode,durationMs:e.durationMs})),[{key:`machineId`,header:`Machine`,width:20},{key:`ok`,header:`OK`,width:6},{key:`exitCode`,header:`Exit`,width:8},{key:`durationMs`,header:`Duration(ms)`,width:14}]);for(let e of s.results){let t=e.result?.stdout,n=e.result?.stderr;t&&(console.log(`\n[${e.machineId}] stdout:`),console.log(t)),n&&(console.log(`\n[${e.machineId}] stderr:`),console.log(n)),e.error&&console.log(`\n[${e.machineId}] error: ${e.error.message}`)}}s.results.some(e=>e.ok===!1)&&(process.exitCode=1)}),n.command(`run [prompt]`).description(`Create a fleet of agents, run one turn on every agent, print each result, then delete the fleet`).requiredOption(`--agents <n|file>`,`Number of agents, or a JSON file with an array of agent specs (agentId, harness, model, profile or { profileId, revision }, task)`).option(`--placement <mode>`,`auto (pack by sandbox memory), dedicated (one sandbox per agent), or a number of agents per sandbox`,`auto`).option(`--model <id>`,`Model every agent runs, e.g. gpt-4.1-mini`).option(`--memory <mb>`,`Memory in MB per sandbox; auto placement packs by it`).option(`--environment <environment>`,`Environment for each sandbox`).option(`--max-spend-usd <usd>`,`Budget for the fleet in USD, enforced by the Platform on the fleet's own key`).option(`--timeout <ms>`,`Per-agent turn timeout in milliseconds`).option(`--fleet-id <id>`,`Stable fleet id (generated when omitted)`).option(`--parent-fleet <id>`,`Fleet that spawns this one; its cap must cover this cap`).option(`--parent-agent <id>`,`Agent of --parent-fleet that spawns this one`).option(`--keep`,`Keep the fleet after the run instead of deleting it`).action(async(t,n)=>{let i=/^\d+$/.test(n.agents)?Number(n.agents):JSON.parse(Ie(n.agents,`utf8`));if(!Array.isArray(i)&&t===void 0)throw Error(`A prompt is required unless --agents names a file whose agents carry tasks`);let{client:a}=G(n);if(!!n.parentFleet!=!!n.parentAgent)throw Error(`--parent-fleet and --parent-agent go together`);let o=n.placement===`auto`||n.placement===`dedicated`?n.placement:{agentsPerSandbox:Number(n.placement)},c=n.maxSpendUsd?Number(n.maxSpendUsd):void 0,l=f(`Creating fleet...`);l.start();let u=Date.now(),d=await a.fleets.create({fleetId:n.fleetId,agents:i,placement:o,defaults:{...n.environment?{environment:n.environment}:{},...n.memory?{resources:{memoryMB:Number(n.memory)}}:{},...n.model?{backend:{type:`opencode`,model:{model:n.model}}}:{}},...c===void 0?{}:{budgetUsd:c},...n.parentFleet?{parent:{fleetId:n.parentFleet,agentId:n.parentAgent}}:{}}),p=Date.now()-u;l.stop(),n.json||r(`Fleet ${d.fleetId}: ${d.agents.length} agents on ${d.machines.size} sandboxes in ${p} ms`);let m=[],h;try{for await(let e of d.run(t,{timeoutMs:n.timeout?Number(n.timeout):void 0})){if(e.type===`agent.finished`&&!n.json){let t=e.result;console.log(`[${t.agentId}] ${t.harness??`default`}/${t.model??`default`} ${t.status} ${t.durationMs}ms ${t.costUsd===void 0?`no cost reported`:`$${t.costUsd.toFixed(5)}`} ${t.result?.response??t.error??``}`)}e.type===`fleet.finished`&&(m=e.results,h=e.spend)}}finally{n.keep||await d.delete({continueOnError:!0})}n.json?e({fleetId:d.fleetId,createMs:p,sandboxes:d.machines.size,results:m,spend:h,deleted:!n.keep}):s({fleetId:d.fleetId,completed:m.filter(e=>e.status===`completed`).length,agents:m.length,spend:JSON.stringify(h),deleted:!n.keep}),m.some(e=>e.status!==`completed`)&&(process.exitCode=1)}),n.command(`cancel <fleet-id>`).description(`Interrupt every agent of a fleet and cancel its child fleets; sandboxes keep running`).action(async(t,n)=>{let{client:i}=G(n),a=await(await i.fleets.list({fleetId:t})).cancel();n.json?e({fleetId:t,...a}):r(`Fleet ${t}: interrupted ${a.interrupted} agents, cancelled ${a.children} child fleets`)})}const as=[`list`,`create`,`delete`,`exec`,`prompt`,`read`,`write`];function os(e){if(!(!e||e.length===0)){for(let t of e)if(!as.includes(t))throw Error(`Invalid token action '${t}'. Allowed: ${as.join(`, `)}`);return e}}function ss(e){return e.length<=12?`****`:`${e.slice(0,6)}...${e.slice(-4)} (masked — use --json for full value)`}function cs(t){t.command(`token <fleet-id>`).description(`Mint a scoped fleet bearer token (treated as a secret)`).option(`--action <a...>`,`Allowed actions: list create delete exec prompt read write (prompt grants nothing since fleet prompt dispatch was removed)`).option(`--ttl-minutes <n>`,`Token lifetime in minutes`).action(async(t,n)=>{let{client:r}=G(n),i=f(`Minting fleet token...`);i.start();let a=await r.fleets.createToken(t,{actions:os(n.action),ttlMinutes:n.ttlMinutes?Number(n.ttlMinutes):void 0});i.stop(),n.json?e(a):(s({"Fleet ID":a.fleetId,Token:ss(a.token),"Expires at":new Date(a.expiresAt).toISOString(),Actions:a.actions.join(`, `)}),console.log(`
145
+ Re-run with --json to print the full token value.`))})}function ls(){let n=new N(`workspace`).description(`Manage a fleet's shared workspace`);return n.command(`snapshot <fleet-id>`).description(`Snapshot the fleet's shared workspace`).action(async(t,n)=>{let{client:i}=G(n),a=f(`Creating workspace snapshot...`);a.start();let o=await i.fleets.createWorkspaceSnapshot(t);a.stop(),n.json?e(o):r(`Workspace snapshot created: ${o.snapshotId??o.id}`)}),n.command(`restore <fleet-id> <snapshot-id>`).description(`Restore the fleet's shared workspace from a snapshot`).action(async(t,n,i)=>{let{client:a}=G(i),o=f(`Restoring workspace...`);o.start();let s=await a.fleets.restoreWorkspaceSnapshot(t,n);o.stop(),i.json?e(s):r(`Workspace restored from ${s.snapshotId??n}`)}),n.command(`reconcile <fleet-id>`).description(`Re-mount the shared workspace on all fleet machines`).action(async(n,r)=>{let{client:i}=G(r),a=f(`Reconciling workspace...`);a.start();let o=await i.fleets.reconcileWorkspace(n);a.stop(),r.json?e(o):(s({"Fleet ID":o.fleetId,Checked:o.checked,"Orphaned mounts":o.orphanedMounts}),t(o.machines,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`mounted`,header:`Mounted`,width:10}]))}),n}function us(){let e=new N(`fleet`).description(`Manage sandbox fleets`);return rs(e),bo(e),e.addCommand(ls()),is(e),vo(e),cs(e),e}function ds(){let t=new N(`fs`).description(`File system operations on sandboxes`);return t.command(`upload`).description(`Upload a file to a sandbox`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<local-path>`,`Local file path`).argument(`<remote-path>`,`Remote destination path`).action(async(t,n,r,i)=>{let{context:a,client:o}=G(i),s=await q(o,a,t);if(s=await J(s),!je.existsSync(n))throw Error(`Local file not found: ${n}`);let c=je.statSync(n),l=Date.now();i.json||console.error(`Uploading ${n} to ${r}...`),await s.fs.upload(n,r,{onProgress:e=>{if(i.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesUploaded}/${e.totalBytes} bytes)`)}});let u=Date.now()-l;i.json||console.error(``),i.json?e({success:!0,localPath:n,remotePath:r,size:c.size,durationMs:u}):console.log(`✓ Uploaded ${c.size} bytes in ${u}ms`)}),t.command(`download`).description(`Download a file from a sandbox`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<remote-path>`,`Remote file path`).argument(`<local-path>`,`Local destination path`).action(async(t,n,r,i)=>{let{context:a,client:o}=G(i),s=await q(o,a,t);s=await J(s);let c=Date.now();i.json||console.error(`Downloading ${n} to ${r}...`),await s.fs.download(n,r,{onProgress:e=>{if(i.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesDownloaded}/${e.totalBytes} bytes)`)}});let l=Date.now()-c,u=je.statSync(r);i.json||console.error(``),i.json?e({success:!0,remotePath:n,localPath:r,size:u.size,durationMs:l}):console.log(`✓ Downloaded ${u.size} bytes in ${l}ms`)}),t.command(`ls`).description(`List directory contents`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`[path]`,`Directory path`,`.`).option(`-l, --long`,`Show detailed information`).option(`-a, --all`,`Include hidden files`).action(async(t,n,r)=>{let{context:a,client:o}=G(r),s=await q(o,a,t);s=await J(s);let c=await s.fs.list(n,{all:r.all,long:r.long});if(r.json)e(c);else if(r.long)i([`Mode`,`Owner`,`Group`,`Size`,`Modified`,`Name`],c.map(e=>{let t=e.isDir?`d`:e.isSymlink?`l`:`-`,n=fs(e.permissions),r=e.isDir?`<DIR>`:ps(e.size),i=e.modTime.toLocaleDateString();return[t+n,e.owner,e.group,r,i,e.name]}));else{let e=c.map(e=>e.isDir?`${e.name}/`:e.name);console.log(e.join(` `))}}),t.command(`stat`).description(`Get file or directory information`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to file or directory`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o);let s=await o.fs.stat(n);r.json?e(s):(console.log(` File: ${s.name}`),console.log(` Path: ${s.path}`),console.log(` Size: ${ps(s.size)} (${s.size} bytes)`),console.log(` Type: ${s.isDir?`directory`:s.isSymlink?`symlink`:`file`}`),console.log(` Mode: ${fs(s.permissions)} (${s.permissions.toString(8)})`),console.log(` Owner: ${s.owner}`),console.log(` Group: ${s.group}`),console.log(` Modified: ${s.modTime.toISOString()}`),console.log(` Accessed: ${s.accessTime.toISOString()}`))}),t.command(`cat`).description(`Print file contents`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to file`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o);let s=await o.read(n);r.json?e({path:n,content:s}):console.log(s)}),t.command(`rm`).description(`Delete a file or directory`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to delete`).option(`-r, --recursive`,`Delete directories recursively`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o),await o.fs.delete(n,{recursive:r.recursive}),r.json?e({success:!0,path:n,deleted:!0}):console.log(`✓ Deleted: ${n}`)}),t.command(`mkdir`).description(`Create a directory`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Directory path to create`).option(`-p, --parents`,`Create parent directories as needed`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o),await o.fs.mkdir(n,{recursive:r.parents}),r.json?e({success:!0,path:n,created:!0}):console.log(`✓ Created: ${n}`)}),t.command(`exists`).description(`Check if a path exists`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to check`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=await q(a,i,t);o=await J(o);let s=await o.fs.exists(n);r.json?e({path:n,exists:s}):(console.log(s?`exists`:`not found`),process.exit(+!s))}),t}function fs(e){let t=[`r`,`w`,`x`],n=``;for(let r=2;r>=0;r--){let i=r*3;for(let r=0;r<3;r++)n+=e>>i+(2-r)&1?t[r]:`-`}return n}function ps(e){let t=[`B`,`KB`,`MB`,`GB`,`TB`],n=e,r=0;for(;n>=1024&&r<t.length-1;)n/=1024,r++;return r===0?`${n}${t[r]}`:`${n.toFixed(1)}${t[r]}`}function ms(){let t=new N(`git`).description(`Git operations in a sandbox workspace`);return t.command(`status`).description(`Show git repository status`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching status...`);n.json||a.start();let o=await q(i,r,t);o=await J(o);let s=await o.git.status();if(a.stop(),n.json)e(s);else if(!s.isRepo)console.log(`No git repository in the sandbox workspace.`);else{if(console.log(`Branch: ${s.branch??`unknown`}`),console.log(`HEAD: ${s.head.slice(0,7)||`(no commits)`}`),console.log(`Dirty: ${s.isDirty?`yes`:`no`}`),s.ahead&&console.log(`Ahead: ${s.ahead}`),s.behind&&console.log(`Behind: ${s.behind}`),s.staged.length>0){console.log(`\nStaged (${s.staged.length}):`);for(let e of s.staged)console.log(` + ${e}`)}if(s.modified.length>0){console.log(`\nModified (${s.modified.length}):`);for(let e of s.modified)console.log(` M ${e}`)}if(s.untracked.length>0){console.log(`\nUntracked (${s.untracked.length}):`);for(let e of s.untracked)console.log(` ? ${e}`)}}}),t.command(`log`).description(`Show commit log`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`-n, --limit <count>`,`Max commits to show`,`10`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching log...`);n.json||a.start();let o=await q(i,r,t);o=await J(o);let s=await o.git.log(Number.parseInt(n.limit,10));if(a.stop(),n.json)e(s);else if(s.length===0)console.log(`No commits found`);else for(let e of s)console.log(`${e.shortSha} ${e.message.split(`
146
+ `)[0]} (${e.author}, ${e.date.toLocaleDateString()})`)}),t.command(`diff`).description(`Show diff`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--ref <ref>`,`Ref to diff against`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching diff...`);n.json||a.start();let o=await q(i,r,t);o=await J(o);let s=await o.git.diff(n.ref);a.stop(),n.json?e(s):s.raw?console.log(s.raw):console.log(`${s.additions} additions, ${s.deletions} deletions across ${s.files.length} files`)}),t.command(`add`).description(`Stage files`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<paths...>`,`Paths to stage`).action(async(e,t,n)=>{let{context:i,client:a}=G(n),o=await q(a,i,e);o=await J(o),await o.git.add(t),r(`Staged: ${t.join(`, `)}`)}),t.command(`commit`).description(`Create a commit`).argument(`<id-or-name>`,`Sandbox ID or name`).requiredOption(`-m, --message <msg>`,`Commit message`).option(`--amend`,`Amend the previous commit`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=await q(a,i,t);o=await J(o);let s=await o.git.commit(n.message,{amend:n.amend});n.json?e(s):r(`Committed: ${s.shortSha} ${s.message}`)}),t.command(`push`).description(`Push to remote`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--force`,`Force push`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Pushing...`);a.start();let o=await q(i,n,e);o=await J(o),await o.git.push({force:t.force}),a.stop(),r(`Pushed to remote`)}),t.command(`pull`).description(`Pull from remote`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--rebase`,`Rebase instead of merge`).action(async(e,t)=>{let{context:n,client:i}=G(t),a=f(`Pulling...`);a.start();let o=await q(i,n,e);o=await J(o),await o.git.pull({rebase:t.rebase}),a.stop(),r(`Pulled from remote`)}),t.command(`branches`).description(`List branches`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(t,n)=>{let{context:r,client:a}=G(n),o=f(`Fetching branches...`);n.json||o.start();let s=await q(a,r,t);s=await J(s);let c=await s.git.branches();o.stop(),n.json?e(c):c.length===0?console.log(`No branches found`):i([`Name`,`Current`,`Remote`],c.map(e=>[e.name,e.current?`* `:` `,e.upstream??`-`]))}),t.command(`checkout`).description(`Checkout a branch or ref`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<ref>`,`Branch name or ref`).option(`-b, --create`,`Create a new branch`).action(async(e,t,n)=>{let{context:i,client:a}=G(n),o=await q(a,i,e);o=await J(o),await o.git.checkout(t,{create:n.create}),r(`Checked out: ${t}${n.create?` (new)`:``}`)}),t}function hs(e,t=16){if(!Number.isInteger(t)||t<=0||t>64)throw TypeError(`stableHashHex: lengthHex must be in [1, 64] (got ${t})`);let n=typeof e==`string`?e:JSON.stringify(e,(e,t)=>{if(t&&typeof t==`object`&&!Array.isArray(t)){let e={},n=t;for(let t of Object.keys(n).sort())e[t]=n[t];return e}return t});return ve(`sha256`).update(n).digest(`hex`).slice(0,t)}Object.freeze([`HS256`]),Object.freeze([`RS256`]);async function gs(e,t,n=`tangle --help`){let r=new AbortController,i=e??r.signal,a=()=>{r.abort(),process.stderr.write(`Stopping…
147
+ `)};e||(process.once(`SIGINT`,a),process.once(`SIGTERM`,a));try{return i.throwIfAborted(),await t(i)}catch(e){if(!i.aborted||e instanceof B&&e.code===`RUN_STOPPED`)throw e;let t=new B(`RUN_STOPPED`,`Command interrupted`,`A stop request ended this execution`,n);throw e instanceof Error&&`runId`in e&&typeof e.runId==`string`&&Object.assign(t,{runId:e.runId}),t}finally{e||(process.off(`SIGINT`,a),process.off(`SIGTERM`,a))}}function _s(e,t){for(let[n,r]of Object.entries(t)){let t=e.gates?.find(e=>e.id===n);if(!t||!t.choices.includes(r))throw new B(`GATE_CHOICE_INVALID`,`Invalid choice for gate '${n}'`,t?`Choose one of: ${t.choices.join(`, `)}`:`The graph does not declare this gate`,`tangle graph run --help`)}}function vs(e,t){let n=t.signal;return async r=>{let i=Object.hasOwn(e,r.gate)?e[r.gate]:void 0,a=`--param ${ut(`gate.${r.gate}=<choice>`)}`,o=`${r.question} Choose one of: ${r.choices.join(`, `)}`,s=()=>new B(`GATE_ANSWER_REQUIRED`,`Gate '${r.gate}' needs an answer. ${o}. Pass ${a}`,o,`tangle graph run <graph> ${a}`);if(i!==void 0)return{kind:`choose`,choice:i,by:`cli:param`};if(t.json||!process.stdin.isTTY)throw s();let c;try{c=await lr(`${r.question} [${r.choices.join(` / `)}]`,void 0,n)}catch{if(n.aborted)return{kind:`stop`,reason:`Gate input interrupted or timed out`,by:`cli:terminal`};throw s()}if(!r.choices.includes(c))throw s();return{kind:`choose`,choice:c,by:`cli:terminal`}}}const ys=()=>import(`./dist-CzrZj_46.mjs`);async function bs(e,t,n,r){if(e==null)return;let{graphKnowledgeBindingSchema:i,graphKnowledgeResolver:a}=await ys(),o=i.parse(e);if(o.kind!==`local`)throw Error(`A local graph needs a pinned local Knowledge binding; Hub generations require the hosted workflow owner`);return a({binding:o,storeRoot:M(t,`knowledge`),signal:r,record:async e=>n.put({executionId:e.context.nodeId,purpose:`executor-native-evidence`,bytes:Buffer.from(JSON.stringify(e))}),recordProposal:async e=>n.put({executionId:e.context.nodeId,purpose:`task-output`,bytes:Buffer.from(JSON.stringify(e))})})}function xs(t){let n=t.command(`knowledge`).description(`Exact measured Knowledge candidate transitions`);n.command(`bind <root>`).description(`Identify exact bytes of an existing local Knowledge store`).action(async t=>e(await(await ys()).pinLocalGraphKnowledge(t)));for(let t of[`promote`,`restore`])n.command(`${t} <binding> <candidate>`).description(`${t} the exact measured local Knowledge candidate through its owner`).action(async(n,r)=>{let{graphKnowledgeBindingSchema:i,transitionGraphKnowledge:a}=await ys(),o=i.parse(JSON.parse(await L(n,`utf8`))),s=await a(o,JSON.parse(await L(r,`utf8`)),t);e({...s,nextBinding:{...o,sourceDigest:`sha256:${s.mutation.afterHash}`}})})}const Ss=()=>new _e(`--mcp-secret <key=variable>`,`Private local MCP secret reference binding; repeatable, values are never recorded`).argParser((e,t)=>[...t,e]).default([]);function Cs(e=[]){let t=new Map;for(let n of e){let e=n.indexOf(`=`),r=n.slice(0,e).trim(),i=n.slice(e+1).trim();if(e<1||!r||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i)||t.has(r)&&t.get(r)!==i)throw new B(`GRAPH_MCP_SECRET_BINDING`,`Invalid private MCP credential binding`,`Use one unambiguous key=ENVIRONMENT_VARIABLE per declared secret reference`,`tangle graph run --help`);t.set(r,i)}return Object.fromEntries(t)}async function ws(e){try{return Ke.parse(JSON.parse(await L(e,`utf8`)))}catch(e){throw new B(`GRAPH_MCP_POLICY_INVALID`,`The graph MCP policy is invalid`,e instanceof Error?e.message:String(e),`tangle graph run --help`)}}const Ts=[`claude-code`,`opencode`,`codex`,`kimi-code`,`prime`],Es=process.env.TANGLE_ROUTER_URL??`https://router.tangle.tools/v1`;function Ds(e){let t=Oe(e);if(t)return t;throw Error(`--model '${e}' has no provider. Pass a canonical id, for example 'google/${e}'.`)}function Os(e){let t=e.harness??`claude-code`;if(!Ts.includes(t))throw Error(`Unknown --harness '${t}'. Supported: ${Ts.join(`, `)}.`);let n=ks(e.maxTokens,2e5,`--max-tokens`),r=ks(e.maxIterations,50,`--max-iterations`),i=e.maxWorkers===void 0?void 0:ks(e.maxWorkers,0,`--max-workers`);return{harness:t,...e.model?{model:e.model}:{},maxTokens:n,maxIterations:r,...i===void 0?{}:{maxWorkers:i}}}function ks(e,t,n){if(e===void 0)return t;let r=Number.parseInt(e,10);if(!Number.isFinite(r)||r<=0)throw Error(`${n} must be a positive integer, got '${e}'.`);return r}function As(e){let t={maxTokens:e.maxTokens,maxIterations:e.maxIterations};return e.maxWorkers===void 0?{budget:t}:{budget:t,perWorker:{maxTokens:Math.max(1,Math.floor(e.maxTokens/e.maxWorkers)),maxIterations:Math.max(1,Math.floor(e.maxIterations/e.maxWorkers))}}}function js(e){let t=e.spentTotal,n=e.kind===`no-winner`?``:e.out;return{text:typeof n==`string`?n:typeof n==`object`&&n&&`content`in n&&typeof n.content==`string`?n.content:JSON.stringify(n),tokenUsage:{input:t.tokensKnown===!1?null:t.tokens.input,output:t.tokensKnown===!1?null:t.tokens.output},costUsd:t.usdKnown===!1?null:t.usd,status:e.kind===`no-winner`?`no-winner (${e.reason})`:`winner`}}let Ms=null;function Ns(){return Ms??=import(`@tangle-network/agent-runtime/kernel`).catch(e=>{throw Ms=null,e?.code===`ERR_MODULE_NOT_FOUND`?new B(`RUNTIME_UNAVAILABLE`,`Agent Runtime could not be loaded`,e.message,`npm install -g @tangle-network/sandbox-cli@latest`):e}),Ms}async function Ps(e,t,n){let r=U({apiKey:n.apiKey,baseUrl:n.baseUrl}),i=W(r),{budget:a,perWorker:o}=As(t),s=[],c={async create(e){let{TANGLE_API_KEY:t,...r}=e?.env??{},a=await i.create(e?.env?{...e,env:r}:e);return s.push({id:a.id,status:`spawned`}),n.json||l(`worker ${a.id} spawned`),a}},u=await Ns(),d=u.workerFromBackend({backend:`sandbox`,sandboxClient:c,maxIterations:1}),f=(e,n)=>d({...e,harness:t.harness},n),p={name:`supervisor`,harness:`cli-base`,model:{default:t.model??`gemini-3.5-flash-lite`,provider:t.model?Ds(t.model):`google`},tools:{agent_runtime_coordination_spawn_worker:!0,agent_runtime_coordination_observe_agent:!0}},m={routerBaseUrl:Es,routerKey:r.apiKey},h=js(await u.supervise(p,{goal:e},{budget:a,makeWorkerAgent:f,router:m,...o?{perWorker:o}:{},...t.model?{allowedModels:[t.model]}:{},runId:`supervise-${be()}`})),g=h.status===`winner`?`settled`:`failed`;for(let e of s)e.status=g,n.json||l(`worker ${e.id} settled (${e.status})`);return{task:e,result:h.text,workers:s,tokenUsage:h.tokenUsage,costUsd:h.costUsd,status:h.status}}function Fs(){let t=new N(`supervise`);return t.description(`Run a budget-conserving supervisor that spawns isolated sandbox workers to deliver a task.`).argument(`<task>`,`What the supervisor should accomplish`).option(`--harness <name>`,`Worker harness (${Ts.join(` | `)})`,`claude-code`).option(`--model <id>`,`Model for the supervisor + workers`).option(`--max-tokens <n>`,`Conserved token budget for the whole run`,`200000`).option(`--max-iterations <n>`,`Conserved iteration budget for the whole run`,`50`).option(`--max-workers <n>`,`Bound the fanout; each worker reserves floor(max-tokens / n) tokens and floor(max-iterations / n) iterations`).action(async(t,n)=>{let r=Os({harness:n.harness,model:n.model,maxTokens:n.maxTokens,maxIterations:n.maxIterations,maxWorkers:n.maxWorkers});n.json||(l(`Supervising: ${t}`),l(`harness=${r.harness} budget=${r.maxTokens}tok/${r.maxIterations}it`),console.log());let i=await Ps(t,r,{apiKey:n.apiKey,baseUrl:n.baseUrl,json:n.json});if(n.json){e(i),i.status!==`winner`&&(process.exitCode=1);return}if(console.log(),i.result&&(console.log(i.result),console.log()),s({"Input Tokens":i.tokenUsage.input??`Unavailable`,"Output Tokens":i.tokenUsage.output??`Unavailable`,Cost:i.costUsd===null?`Unavailable`:`$${i.costUsd.toFixed(4)}`}),i.status!==`winner`)throw Error(`Supervisor finished without a winner: ${i.status}`)}),t}function Is(e,t){let n=me(e,t);return n!==`..`&&!n.startsWith(`..${ge}`)&&!fe(n)}const Ls=()=>import(`@tangle-network/agent-eval/campaign`),Rs=()=>import(`@tangle-network/agent-runtime/candidate-execution`),zs=`graph-task-workspaces`,Bs=I.number().int().positive().max(2**53-1),Vs=I.strictObject({maxArchiveBytes:Bs.optional(),maxEmbeddedArtifactBytes:Bs.optional(),maxFiles:Bs.optional(),maxFileBytes:Bs.optional(),maxTotalFileBytes:Bs.optional(),maxPathBytes:Bs.optional(),maxRepositoryBundleBytes:Bs.optional()}),Hs=we.shape,Us=I.strictObject({snapshot:I.strictObject({kind:Hs.kind,digest:Hs.digest,manifest:Ce,archive:Ce}).superRefine((e,t)=>{(e.digest!==e.manifest.sha256||!e.manifest.byteLength||!e.archive.byteLength)&&t.addIssue({code:`custom`,message:`The canonical workspace manifest, digest and archive must agree`})}),capture:I.strictObject({mode:I.literal(`git-working-tree`),runtimeVersion:I.string().min(1),limits:Vs}),gaps:I.tuple([I.literal(`environment-and-toolchain-not-snapshotted`),I.literal(`git-ignored-files-excluded`)])}),Ws=e=>P(Us.parse(e));function Gs(e){for(let t of[e.snapshot.manifest,e.snapshot.archive])if(t.locator.kind!==`private-cas`||t.locator.namespace!==zs)throw Error(`Task workspace artifacts require their original local private CAS; cross-backend activation is unsupported`)}async function Ks(){let e=M(F(),`.tangle`);return await ft(e,{recursive:!0,mode:448}),R(e)}const qs=async e=>(await import(`@tangle-network/agent-runtime/kernel`)).createPrivateCasArtifactPort(M(e,`artifacts`),zs);async function Js(e){let t=await mt(he(e),Ne.O_RDONLY|Ne.O_NOFOLLOW);try{if(!(await t.stat()).isFile())throw Error(`Task workspace reference must be a regular file`);let e=Us.parse(JSON.parse(await t.readFile(`utf8`)));return Gs(e),e}finally{await t.close()}}async function Ys(e,t={}){t.signal?.throwIfAborted();let n=he(e),r=await dt(n);if(!r.isDirectory()||r.isSymbolicLink())throw Error(`Task workspace must be one real repository root`);let i=await R(n),a=await R(F()),o=await Ks();if(i===a||i===ue(i)||Is(o,i)||Is(i,o))throw Error(`Task workspace capture cannot include the home, filesystem or private evidence root`);let{release:s}=(await Ls()).acquireSingleRunLock({lockPath:`${i}.graph-workspace.lock`});try{let e=Vs.parse(t.limits??{}),n=await(await Rs()).captureAgentWorkspaceSnapshot(i,{includeRepository:!0,repositoryContents:`working-tree`,limits:e,artifactPersistence:{executionId:be(),outputArtifacts:await qs(o),signal:t.signal}}),r=v(`@tangle-network/agent-runtime`,import.meta.url);if(!r)throw Error(`Cannot identify the Runtime workspace archive owner`);let a=JSON.parse(await L(r,`utf8`));return Us.parse({snapshot:n,capture:{mode:`git-working-tree`,runtimeVersion:a.version,limits:e},gaps:[`environment-and-toolchain-not-snapshotted`,`git-ignored-files-excluded`]})}finally{s()}}async function Xs(e,t){let n=I.uuid().parse(t.runId),r=Us.parse(e);Gs(r);let i=await Ks(),a=M(i,`workspaces`);if(await ft(a,{recursive:!0,mode:448}),await R(a)!==a)throw Error(`Task workspace allocation root redirects elsewhere`);let o=M(a,n),{release:s}=(await Ls()).acquireSingleRunLock({lockPath:`${o}.lock`});try{t.signal?.throwIfAborted();let e=`${o}.task-workspace.json`,a;try{a=JSON.parse(await L(e,`utf8`))}catch(e){if(e.code!==`ENOENT`)throw e}let c=Ws(r);if(a!==void 0){let e=I.strictObject({runId:I.uuid(),identity:I.string()}).parse(a);if(e.runId!==n||e.identity!==c||t.resumeCwd!==void 0&&he(t.resumeCwd)!==o||await R(o)!==o||!(await dt(o)).isDirectory())throw Error(`The retained task workspace no longer names this exact native run allocation`)}else{if(t.resumeCwd!==void 0)throw Error(`The retained task workspace allocation receipt is missing`);await(await Rs()).materializeAgentWorkspaceSnapshot({snapshot:r.snapshot,artifacts:await qs(i),destination:o,limits:r.capture.limits,signal:t.signal}),await z(e,JSON.stringify({runId:n,identity:c}),{flag:`wx`,mode:384,flush:!0})}if(!t.validationOnly||a!==void 0)return{cwd:o,release:s};let l=await Promise.all([dt(o,{bigint:!0}),dt(e,{bigint:!0})]);return{cwd:o,release:async()=>{try{for(let[t,r]of[o,e].entries()){let e=await dt(r,{bigint:!0});if(!(t===0?e.isDirectory():e.isFile())||e.dev!==l[t]?.dev||e.ino!==l[t]?.ino||await R(r)!==r)throw Error(`Validation allocation ${n} changed; retained`)}if(P(JSON.parse(await L(e,`utf8`)))!==P({runId:n,identity:c}))throw Error(`Validation allocation ${n} receipt changed; retained`);try{throw await dt(M(i,`runs`,n)),Error(`Validation allocation ${n} has run state; retained`)}catch(e){if(e.code!==`ENOENT`)throw e}await ht(o,{recursive:!0}),await ht(e)}finally{s()}}}}catch(e){throw s(),e}}function Zs(t){t.command(`workspace`).description(`Capture immutable local task files for graph replay`).command(`capture <repository>`).description(`Capture Git HEAD, index, tracked and unignored files into private local artifacts`).requiredOption(`--output <file>`,`New reference file outside the source repository`).option(`--limits <file>`,`JSON overrides for the maintained Runtime archive limits`).action(async(t,n)=>{let r=await R(he(t)),i=M(await R(ue(he(n.output))),le(he(n.output)));if(Is(r,i))throw Error(`The task reference must be written outside the original workspace`);try{throw await dt(i),Error(`Task workspace reference already exists; choose a new output file`)}catch(e){if(e.code!==`ENOENT`)throw e}let a=await Ys(r,{limits:n.limits?Vs.parse(JSON.parse(await L(n.limits,`utf8`))):void 0});await z(i,JSON.stringify(a),{flag:`wx`,mode:384,flush:!0}),e(a)})}const Qs=I.string().regex(/^[a-f0-9]{64}$/),$s=I.strictObject({version:I.literal(1),runId:I.uuid(),file:I.string().refine(fe),cwd:I.string().refine(fe),sourceDigest:Qs,source:I.string().optional(),graphDigest:Qs,params:I.record(I.string(),I.unknown()),trigger:I.record(I.string(),I.unknown()).optional(),gateChoices:I.record(I.string(),I.string()).optional(),startedAt:I.iso.datetime(),seat:I.string().optional(),mcpPolicy:qe.optional(),taskWorkspace:Us.optional()});async function ec(e){let t=await Ns(),n=t.graphRegistry(M(F(),`.tangle`,`graph-registry`)),r=await t.loadGraph(n,e.graphDigest);if(!r)throw Error(`Retained execution graph is unavailable; configuration is unknown`);let i=t.validateStoredGraph(r);if(i.digest!==e.graphDigest)throw Error(`Retained execution graph changed its identity`);return P({mcpPolicy:qe.parse(e.mcpPolicy??{}),nodes:i.nodes.map(({id:e,profile:t})=>({id:e,harness:t.harness??null,model:t.model??null,seats:t.seats??null,connections:t.connections??null}))})}function Y(e){throw new B(`GRAPH_RESUME_REFUSED`,`The graph run cannot be resumed`,e,`tangle graph run --help`)}async function tc(e){I.uuid().safeParse(e).success||Y(`Use a recorded graph run ID`);let t;try{let n=M(await R(M(F(),`.tangle`)),`runs`,e);await R(n)!==n&&Y(`The run directory redirects elsewhere`),t=await mt(M(n,`input.json`),Ne.O_RDONLY|Ne.O_NOFOLLOW),(await t.stat()).isFile()||Y(`The run input is not a regular file`);let r=$s.parse(JSON.parse(await t.readFile(`utf8`)));return r.runId!==e&&Y(`The recorded run identity changed`),r.source!==void 0&&rc(r,r.source),r}catch(e){if(e instanceof B)throw e;return Y(`The private recorded run input is missing or invalid`)}finally{await t?.close()}}async function nc(e,t){let n=t.source??await L(t.file,`utf8`);rc(t,n),await z(M(e,`input.json`),JSON.stringify({...t,source:n}),{flag:`wx`,mode:384,flush:!0})}function rc(e,t){return ve(`sha256`).update(t).digest(`hex`)!==e.sourceDigest&&Y(`The retained graph source does not match this run`),t}async function ic(e){return rc(e,e.source??await L(e.file,`utf8`))}function ac(e,t,n,r,i={}){e.sourceDigest!==n&&Y(`The authored graph source changed`),t.cloud&&Y(`A local run cannot move to cloud execution`),Object.entries(r).some(([t,n])=>!Object.hasOwn(e.params,t)||P(n)!==P(e.params[t]))&&Y(`A recorded graph parameter changed`),Object.entries(i).some(([t,n])=>e.gateChoices?.[t]!==n)&&Y(`A recorded gate choice changed`),t.seat!==void 0&&t.seat!==e.seat&&Y(`The recorded graph seat override changed`),t.mcpPolicy!==void 0&&(e.mcpPolicy===void 0||P(t.mcpPolicy)!==P(e.mcpPolicy))&&Y(`The recorded graph MCP policy changed`)}const oc=e=>Object.entries(e).map(([e,t])=>`${e}=${typeof t==`string`?t:JSON.stringify(t)}`),sc=`claude,codex,kimi,opencode,gemini,pi`;function cc(e,t){let n;return async(r,{node:i,lastCandidate:a})=>{t.throwIfAborted();let o;try{o=r===void 0?void 0:ke(r)}catch(e){throw e instanceof Error&&Object.assign(e,{node:i,seat:r,fixCommand:`tangle graph run --help`}),e}n??=import(`cli-bridge`).then(({listLocalModels:n,loadConfig:r})=>n({cwd:e,signal:t,config:r({...process.env,BRIDGE_BACKENDS:sc,BRIDGE_SUBSCRIPTIONS_ONLY:`1`})}));let s=await n;t.throwIfAborted();let c=e=>e.authentication?.status===`authenticated`&&e.authentication.authMode===`subscription`,l=o?.harness??s.find(e=>e.provider&&c(e))?.backend,u=s.filter(e=>e.backend===l),d=u.filter(c),f=o?u.find(e=>e.id===`${o.harness}/${o.model}`)??d.find(e=>e.provider===o.provider):d.find(e=>e.default)??d.find(e=>e.recommended)??d[0];if(!f||!c(f)){if(a===!1)return;let e=f?.authentication??u[0]?.authentication??(o?void 0:s.find(e=>e.authentication?.fix)?.authentication);throw Object.assign(new B(o?`SEAT_NOT_LOGGED_IN`:`SEAT_NONE_DETECTED`,`Node '${i}' has no available subscription${o?` for ${o.harness}`:``}`,e?`Selected provider: ${e.status} (${e.authMode})`:`No authenticated subscription route was detected`,e?.fix??`tangle graph run --help`),{node:i,seat:r})}let p=o?.harness??ke(f.id).harness,m=o?.provider??f.provider,h=o?.model??f.id.slice(p.length+1);if(!m||!h)throw new B(`MODEL_PROVIDER_MISMATCH`,`Node '${i}' has an unresolved model provider`,`Bridge has no configured provider for ${r??p}`,`tangle graph run --help`);return{harness:p,provider:m,model:h,selector:{kind:`all-eligible`},...o?.reasoningEffort===void 0?{}:{reasoningEffort:o.reasoningEffort}}}}const lc=gt(He);function uc(e,t,n=`tangle graph run --help`){throw new B(`SEAT_NONE_DETECTED`,e,t,n)}function dc(e){let t=[];for(let n of e.nodes)for(let e of n.check?.egress??[]){let n=e.trim().toLowerCase();if(n){if(/[\s*]|\/|:\/\//u.test(n))throw new B(`GRAPH_EGRESS_HOST`,`Graph egress host "${e.trim()}" is not a DNS hostname`,`A check egress entry has whitespace, a wildcard, or a URL`,`tangle graph run --help`);t.includes(n)||t.push(n)}}return t.length>0?t.join(`,`):void 0}function fc(e){return e.some(e=>(e.profile?.seats?.length??0)>0)}function pc(e){let t=e?.trim();if(t)return/\s/u.test(t)&&uc(`A seat account, command, or credential must be a single token`,`The seat command is an executable path, not a shell line`),t}function mc(e){let t=pc(e.seatAccount),n=pc(e.seatCommand),r=pc(e.seatCredential);return r&&!n&&!t&&uc(`A seat credential needs a seat command`,`The credential is an argument to the configured command`,`tangle graph run --seat-command <program>`),{...t?{account:t}:{},...n?{command:n}:{},...r?{credential:r}:{}}}async function hc(e,t,n){if(e.account)return e.account;e.command||uc(`This graph needs a seat account or a seat command`,`No account was authored and no seat command is configured`,`tangle graph run --seat-account <account>`);let r=``;try{r=(await lc(e.command,[t,...e.credential?[e.credential]:[]],{timeout:3e4,maxBuffer:4096,signal:n,encoding:`utf8`})).stdout}catch(e){n.throwIfAborted();let t=e.code===`ENOENT`;uc(t?`The seat command was not found`:`The seat command failed`,t?`The configured executable is not on PATH`:`The seat command exited without an account id`)}let i=r.trim();return(!i||/\s/u.test(i))&&uc(`The seat command did not print an account id`,`The command must print one account id and nothing else`),i}function gc(e,t,n){let r=new Map;return async i=>{n.throwIfAborted();let a=i.stage.harness,o=i.stage.selector.kind===`seat`?i.stage.selector.id.trim():``,s=`${a}\0${t.credential??``}`,c=o||t.account||r.get(s)||await hc(t,a,n);!o&&!t.account&&r.set(s,c),(!c||/\s/u.test(c)||i.resumeSeatId!==void 0&&i.resumeSeatId!==c)&&uc(`Node '${i.nodeId}' has no seat account`,`The authored seat, account flag, or seat command did not yield one`);let{createCliBridgeProvider:l}=await import(`@tangle-network/agent-provider-cli-bridge`);return{seat:c,backend:{backend:`provider`,provider:l({baseUrl:e.bridgeUrl,bearerToken:e.bridgeBearer}),defaults:{workspace:{cwd:{base:`host`,path:e.cwd}}},runtime:`cli`,outputFormat:`json`,destroyOnSettle:!0,requireTerminalEvent:!0}}}}function X(e){return Xn({signal:e.signal,...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.baseUrl===void 0?{}:{baseUrl:e.baseUrl}})}const _c=I.object({version:I.literal(1),type:I.enum([`state`,`ack`,`error`,`event`]),requestId:I.string().optional(),operationId:I.string().optional(),command:I.string().optional(),code:I.string().optional(),message:I.string().optional(),result:I.unknown().optional()}).passthrough(),vc=I.object({state:I.object({runConfiguration:I.unknown()}),view:I.object({capabilities:I.record(I.string(),I.object({available:I.boolean(),reason:I.string().optional()}))})}),yc=I.object({status:I.enum([`completed`,`failed`,`cancelled`]),analysis:I.object({id:I.string().min(1)}).passthrough(),source:I.object({runtimeRun:I.unknown()}).passthrough()}).passthrough(),bc=`TANGLE_GRAPH_ANALYSIS_SOURCE`;async function xc(e,t,n){if(!e.startsWith(`wfrun_`)){let t=M(await R(M(F(),`.tangle`)),`runs`,e);if(await R(t)!==t)throw new B(`RUN_NOT_FOUND`,`The run directory redirects elsewhere`,`Use the recorded local run directory`,`tangle graph inspect --help`);return{source:`runtime:${e}@${t}`,env:{},schema:I.object({runId:I.literal(e),runDir:I.literal(t)})}}let r={signal:n,...t.apiKey===void 0?{}:{apiKey:t.apiKey},...t.baseUrl===void 0?{}:{baseUrl:t.baseUrl}},i=await X(r),a=I.object({id:I.literal(e),workflowId:I.string(),revUsed:I.number().int(),execution:I.object({kind:I.literal(`graph`),sourceSha:I.string(),authoredGraphDigest:I.string(),graphDigest:I.string()}),runtime:I.object({snapshot:I.object({supervisors:I.tuple([I.object({id:I.string()})])})})}).parse(await i.workflows.getRun(e,{signal:n})),o=a.runtime.snapshot.supervisors[0];if(!o)throw new B(`BRAID_RPC_FAILED`,`The cloud run has no retained Runtime root`,`Wait for execution evidence before analysis`,`tangle graph inspect ${e}`);let s=await Kn(r);if(new URL(s.baseUrl.replace(/\/+$/,``)).href!==new URL(i.baseUrl.replace(/\/+$/,``)).href)throw new B(`AUTH_REQUIRED`,`The analysis source origin changed`,`Use the same authenticated platform origin`,`tangle auth status --json`);return{source:`runtime:${e}@${bc}`,env:{[bc]:JSON.stringify({url:`${s.baseUrl.replace(/\/+$/,``)}/v1/workflows/runs/${encodeURIComponent(e)}`,headers:{Authorization:`Bearer ${s.token}`}})},schema:I.object({runId:I.literal(e),remoteEndpointEnv:I.literal(bc),checkpoint:I.object({workflowId:I.literal(a.workflowId),runtimeRunId:I.literal(o.id),revUsed:I.literal(a.revUsed),sourceSha:I.literal(a.execution.sourceSha),authoredGraphDigest:I.literal(a.execution.authoredGraphDigest),graphDigest:I.literal(a.execution.graphDigest)})})}}async function Sc(e,t){if(!e.startsWith(`wfrun_`)&&!I.uuid().safeParse(e).success)throw new B(`RUN_NOT_FOUND`,`Use a recorded graph run ID`,`The run identifier is invalid`,`tangle graph inspect --help`);if(!Number.isSafeInteger(t.timeout)||t.timeout<1)throw new B(`INVALID_TIMEOUT`,`Use a positive analysis timeout`,`The timeout must be an integer number of milliseconds`,`tangle graph analyze --help`);let n=t.profile;if(!n?.trim())throw new B(`USAGE_INVALID`,`Select the canonical analysis profile`,`Graph analysis requires an existing canonical AgentProfile reference`,`tangle graph analyze `+e+` --profile <name|path>`);let r=/^(?:\.\.?)[/\\]/.test(n)?he(process.cwd(),n):n;return gs(t.signal,async n=>{let i=await xc(e,t,n),a=i.source;return Kl({signal:n,errorRunId:e},async n=>{let o=await n.bridge(),s=await pt(M(n.runDir,`analysis-`)),c=M(s,`config.json`),l=M(s,`database.key`),u=M(s,`state.sqlite`),d=`connection-owned-graph-bridge`,f=new Date().toISOString();await z(l,ye(32),{mode:384,flag:`wx`}),await z(c,JSON.stringify({format:`braid-startup-config`,schemaVersion:2,profile:r,connectionId:d,connections:[{id:d,name:`Graph analysis`,kind:`cli-bridge`,endpoint:o.bridgeUrl,providerOptions:{transport:`local`},createdAt:f,updatedAt:f,lastHealth:{status:`unknown`}}]}),{mode:384,flag:`wx`});let p=n.signal,m=`op-${be()}`,h=`op-${be()}`,g=`${m}:initialize`,_=`${m}:analyze`,v=`${m}:shutdown`,y={version:1,requestId:g,command:`initialize`,params:{workspace:n.cwd,subscribe:!1}},b={version:1,requestId:_,operationId:m,command:`analyze`,params:{source:a,recipe:`all`,totalTimeoutMs:t.timeout}},x={version:1,requestId:v,operationId:h,command:`shutdown`,params:{mode:`wait`}},S,C,w,T,ee={transform:e=>{let t=_c.parse(e);return t.type===`error`||t.type===`state`&&t.requestId===g||t.type===`ack`&&[_,v].includes(t.requestId??``)?t:null},onError:e=>{T??=e},onEvent:e=>{e.type===`error`&&(T??=new B(e.code??`BRAID_RPC_FAILED`,`Braid refused graph analysis`,e.message??`The RPC response omitted its cause`,`tangle graph analyze --help`)),e.requestId===g&&e.type===`state`&&(S??=e),e.requestId===_&&e.type===`ack`&&(C??=e),e.requestId===v&&e.type===`ack`&&(w??=e)}},E=await lt({command:process.env.BRAID_BIN??`braid`,args:[`rpc`,`--workspace`,n.cwd,`--config`,c,`--profile`,r,`--database-key-file`,l],cwd:n.cwd,env:{...i.env,BRAID_STATE_PATH:u,BRAID_CLI_BRIDGE_ENDPOINT:o.bridgeUrl,BRAID_CLI_BRIDGE_AUTH:o.bridgeBearer},timeoutMs:t.timeout,signal:p,ownProcessGroup:!0},ee,{stdin:[y,...t.dryRun?[]:[b],x].map(e=>JSON.stringify(e)).join(`
148
148
  `)+`
149
- `});if(T)throw T;let D=E.exit;if(!D.success||!S||!w||w.operationId!==h||w.command!==`shutdown`)throw new B(`BRAID_RPC_FAILED`,`Braid graph analysis did not finish`,D.spawnError??D.timeoutDiagnostic??D.stdinError??D.processGroupError??D.captureError??D.terminateError??(E.stderr||`Exit ${D.code}, signal ${D.signal}; complete shutdown acknowledgement: ${!!w}`),`npm install --global @tangle-network/braid`);let O=bc.parse(S),k=O.view.capabilities[`analysis.recipe`];if(t.dryRun)return{source:a,statePath:u,configuration:O.state.runConfiguration,capability:k};if(!C||C.operationId!==m||C.command!==`analyze`)throw Error(`Braid did not acknowledge this analysis operation`);let A=xc.parse(C.result);if(!i.schema.safeParse(A.source.runtimeRun).success)throw new B(`BRAID_RPC_FAILED`,`Braid returned analysis of another source`,`Its saved run or immutable checkpoint identity does not match this request`,`tangle graph inspect ${e}`);return{...A,statePath:u}})},`tangle graph analyze ${e}`)}function Tc(t){t.command(`analyze <run>`).description(`Analyze retained graph evidence through Braid`).addHelpText(`after`,`
149
+ `});if(T)throw T;let D=E.exit;if(!D.success||!S||!w||w.operationId!==h||w.command!==`shutdown`)throw new B(`BRAID_RPC_FAILED`,`Braid graph analysis did not finish`,D.spawnError??D.timeoutDiagnostic??D.stdinError??D.processGroupError??D.captureError??D.terminateError??(E.stderr||`Exit ${D.code}, signal ${D.signal}; complete shutdown acknowledgement: ${!!w}`),`npm install --global @tangle-network/braid`);let O=vc.parse(S),k=O.view.capabilities[`analysis.recipe`];if(t.dryRun)return{source:a,statePath:u,configuration:O.state.runConfiguration,capability:k};if(!C||C.operationId!==m||C.command!==`analyze`)throw Error(`Braid did not acknowledge this analysis operation`);let A=yc.parse(C.result);if(!i.schema.safeParse(A.source.runtimeRun).success)throw new B(`BRAID_RPC_FAILED`,`Braid returned analysis of another source`,`Its saved run or immutable checkpoint identity does not match this request`,`tangle graph inspect ${e}`);return{...A,statePath:u}})},`tangle graph analyze ${e}`)}function Cc(t){t.command(`analyze <run>`).description(`Analyze retained graph evidence through Braid`).addHelpText(`after`,`
150
150
  Requires the Braid companion CLI: npm install --global @tangle-network/braid.
151
151
  BRAID_BIN may select its installed executable. Select an existing canonical AgentProfile with --profile. Analysis uses the owned subscription-only Bridge.
152
- `).requiredOption(`--profile <name|path>`,`Use a canonical analysis AgentProfile, distinct from the Tangle account profile`).option(`--dry-run`,`Inspect Braid's selected analysis configuration without dispatch`).option(`--timeout <ms>`,`Bound the analysis process in milliseconds`,Number,3e5).action(async(t,n)=>{let r=await wc(t,n);e(r),`status`in r&&r.status!==`completed`&&(process.exitCode=1)})}async function Ec(t,n){let r=[],i=[],a=(e,t)=>{if(!t||typeof t!=`object`)return;let n=I.object({status:I.string(),files:I.array(I.object({path:I.string(),artifact:Ce})),missing:I.unknown()}).parse(t);i.push({node:e,status:n.status,missing:n.missing}),r.push(...n.files.map(t=>({node:e,...t})))},o;if(t.startsWith(`wfrun_`)){let e=await X(n),r=await e.workflows.getRun(t);for(let e of r.runtime?.checks??[])a(e.nodeId,e.outputs);o=async({artifact:n})=>{let i=(await e.workflows.listArtifacts(r.workflowId,t)).artifacts.find(e=>e.name===`runtime/${n.sha256}`&&e.byteSize===n.byteLength);if(!i)throw Error(`The workflow owner has no retained bytes for this artifact`);return(await e.workflows.downloadArtifact(r.workflowId,t,i.id)).bytes}}else{if(!I.uuid().safeParse(t).success)throw Error(`Use a recorded graph run ID`);let e=M(await R(M(F(),`.tangle`,`runs`)),t);if(await R(e)!==e)throw Error(`The graph run directory redirects elsewhere`);let{FileSpawnJournal:n,FileResultBlobStore:r,loadSpawnForest:i,createPrivateCasArtifactPort:s}=await import(`@tangle-network/agent-runtime/kernel`),c=new r(M(e,`blobs`)),l=await i(new n(M(e,`spawn-journal.jsonl`)),t);for(let e of l.nodes){if(e.runtime!==`graph-check`||!e.outRef)continue;let t=await c.get(e.outRef);a(e.id,t?.outputs)}let u=s(M(e,`artifacts`),t);o=e=>u.read(e.artifact)}if(!n.artifact)return e({runId:t,capture:i,files:r});if(!n.out)throw new B(`USAGE_INVALID`,`Select an output file`,`Artifact downloads require --out`,`tangle graph inspect ${t} --artifact <node/path> --out <file>`);let s=r.filter(e=>`${e.node}/${e.path}`===n.artifact||e.artifact.sha256===n.artifact);if(s.length!==1)throw Error(`Select one exact node/path from graph inspect --artifacts`);let c=s[0],u=await o(c);if(u.byteLength!==c.artifact.byteLength||`sha256:${Q(Buffer.from(u))}`!==c.artifact.sha256)throw Error(`Retained artifact bytes do not match their recorded identity`);let d=he(n.out);await ft(ue(d),{recursive:!0}),await z(d,u,{mode:384,flag:`wx`});let f={runId:t,node:c.node,path:c.path,artifact:c.artifact,destination:d};n.json?e(f):l(`Saved ${c.path} to ${d}`)}const Dc=1e3;function Oc(e,t){return[...t,e]}function kc(e,t=`input`,n){if(n===void 0&&!e?.length)return;let r={};if(n!==void 0)try{if(r=JSON.parse(Ie(n,`utf8`)),!r||typeof r!=`object`||Array.isArray(r)||Object.entries(r).some(([e,t])=>!e.length||typeof t!=`string`))throw Error(`Invalid input map`)}catch{throw new B(`WORKFLOW_INPUT_FILE_INVALID`,`Could not load --input-file '${n}'`,`Expected a readable JSON object with nonempty keys and string values`,`tangle workflows run --help`)}let i=Object.entries(r);for(let n of e??[]){let e=n.indexOf(`=`);if(e<=0)throw Error(`Invalid --${t} "${n}": expected key=value (e.g. pull_request.number=123)`);i.push([n.slice(0,e),n.slice(e+1)])}return Object.fromEntries(i)}function Ac(e){t(e.map(e=>({id:e.id,status:e.status,attempts:e.attempts,created:e.createdAt,completed:e.completedAt??``})),[{key:`id`,header:`Run ID`},{key:`status`,header:`Status`},{key:`attempts`,header:`Attempts`},{key:`created`,header:`Created`},{key:`completed`,header:`Completed`}])}function jc(e){if(s({"Run ID":e.id,Workflow:e.workflowId,Status:e.status,Error:e.error??``,Attempts:e.attempts,Created:e.createdAt,Started:e.startedAt??``,Completed:e.completedAt??``}),e.actionResults.length>0){l(`Actions`);let n=e.actionResults.some(e=>e.nodeId!==void 0||e.visit!==void 0);t(e.actionResults.map(e=>({index:e.index,...n?{node:e.nodeId??``,visit:e.visit??``}:{},kind:e.kind,status:e.status,error:e.error??``,cost:e.costUsd??``})),[{key:`index`,header:`#`},...n?[{key:`node`,header:`Node`},{key:`visit`,header:`Visit`}]:[],{key:`kind`,header:`Kind`},{key:`status`,header:`Status`},{key:`error`,header:`Error`},{key:`cost`,header:`Cost (USD)`}])}e.graph&&(l(`Graph`),s({Nodes:e.graph.nodes.length,Edges:e.graph.edges.length,"Max node visits":e.graph.maxNodeVisits}),t(e.graph.edges.map(e=>({from:e.from,to:e.to,guard:e.when===void 0?``:JSON.stringify(e.when)})),[{key:`from`,header:`From`},{key:`to`,header:`To`},{key:`guard`,header:`Guard`}])),e.edgeVerdicts&&e.edgeVerdicts.length>0&&(l(`Edge verdicts`),t(e.edgeVerdicts.flatMap(e=>Object.entries(e.verdicts).map(([t,n])=>({node:e.nodeId,edge:t,verdict:n?`taken`:`not taken`}))),[{key:`node`,header:`Node`},{key:`edge`,header:`Edge`},{key:`verdict`,header:`Verdict`}]))}function Mc(e){if(e.status===`cancelled`){l(`Cancelled run ${e.runId}.`);return}if(e.signalled){l(`Cancelling run ${e.runId} — signalled the worker; it will stop shortly.`);return}l(`Requested cancellation of run ${e.runId}, but couldn't confirm it — the run may have just finished, or it's running on another instance and will stop on its own.`)}function Nc(e){switch(e.type){case`snapshot`:l(`snapshot: ${e.run.status} (${e.run.actionResults.length} action(s))`);break;case`action.started`:console.log(`→ action[${e.index}] ${e.kind} started`);break;case`action.finished`:{let t=e.status===`succeeded`?`✓`:e.status===`skipped`?`⊘`:`✗`;console.log(`${t} action[${e.index}] ${e.kind} ${e.status}${e.error?`: ${e.error}`:``}`);break}case`iteration.started`:console.log(` · action[${e.actionIndex}] iteration ${e.iterationIndex} started`);break;case`iteration.ended`:console.log(` · action[${e.actionIndex}] iteration ${e.iterationIndex} ${e.status}`);break;case`token`:typeof e.delta==`string`&&process.stdout.write(e.delta);break;case`ping`:break;case`run.done`:console.log(`\nrun.done: ${e.status}${e.error?`: ${e.error}`:``}`);break;case`run.waiting`:console.log(`\nrun.waiting: parked on a human decision (${e.decisionId}) — resolve it to resume`);break}}function Pc(t){t.command(`run`).description(`Trigger an immediate run of a workflow`).argument(`<id>`,`Workflow ID`).option(`--input-file <file>`,`Trigger inputs from a flat JSON string map; --input overrides its keys`).option(`--input <key=value>`,`Trigger input as key=value (e.g. pull_request.number=123). Repeatable.`,Oc,[]).option(`--wait`,`Wait for the run to finish and print its result`).option(`--timeout <ms>`,`With --wait, fail if the run has not finished after this many milliseconds`).option(`--poll-interval <ms>`,`With --wait, how often to poll for completion (default 2000)`).action(async(t,n)=>{let r=kc(n.input,`input`,n.inputFile),i=n.timeout===void 0?void 0:ha(n.timeout,`--timeout`),a=n.pollInterval===void 0?void 0:ha(n.pollInterval,`--poll-interval`),o=await X(n),{runId:s}=await o.workflows.run(t,r);if(!n.wait){if(n.json)return e({runId:s});l(`Started run ${s} for workflow ${t}.`),l(`Inspect it with: tangle workflows run-detail ${t} ${s}`);return}let c=n.json?null:f(`Waiting for run ${s} to finish...`).start(),u;try{u=await o.workflows.waitForRun(t,s,{...i===void 0?{}:{timeoutMs:i},...a===void 0?{}:{pollIntervalMs:a}})}finally{c?.stop()}if(u.status===`failed`&&(process.exitCode=1),n.json)return e(u);jc(u)}),t.command(`runs`).description(`List a workflow's run history (newest first)`).argument(`<id>`,`Workflow ID`).option(`--limit <n>`,`Runs per page (1-100)`).option(`--cursor <cursor>`,`Pagination cursor from a previous page`).option(`--all`,`Fetch every page, not just the first`).action(async(t,n)=>{let r=await X(n),i=n.limit===void 0?void 0:ha(n.limit,`--limit`);if(n.all){let a=[],o=n.cursor,s=0,c=null;for(;;){let e=await r.workflows.listRuns(t,{...i===void 0?{}:{limit:i},...o===void 0?{}:{cursor:o}});if(a.push(...e.runs),s+=1,!e.nextCursor)break;if(s>=Dc){c=e.nextCursor,n.json||l(`Stopped after ${Dc} pages (${a.length} runs); more may exist — resume with --cursor ${e.nextCursor}`);break}o=e.nextCursor}if(n.json)return e({runs:a,nextCursor:c});Ac(a);return}let a=await r.workflows.listRuns(t,{...i===void 0?{}:{limit:i},...n.cursor===void 0?{}:{cursor:n.cursor}});if(n.json)return e(a);Ac(a.runs),a.nextCursor&&l(`More runs available — next page: --cursor ${a.nextCursor}`)}),t.command(`run-detail`).description(`Show a single run's detail (per-action output and errors)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.getRun(t,n);if(r.json)return e(i);jc(i)}),t.command(`cancel`).description(`Cancel a queued or in-progress run`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.cancel(t,n);if(r.json)return e(i);Mc(i)}),t.command(`retry`).description(`Re-run a failed or cancelled run (a fresh run with the same trigger context)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID of the failed/cancelled run to retry`).option(`--wait`,`Wait for the new run to finish and print its result`).option(`--timeout <ms>`,`With --wait, fail if the run has not finished after this many milliseconds`).option(`--poll-interval <ms>`,`With --wait, how often to poll for completion (default 2000)`).action(async(t,n,r)=>{let i=r.timeout===void 0?void 0:ha(r.timeout,`--timeout`),a=r.pollInterval===void 0?void 0:ha(r.pollInterval,`--poll-interval`),o=await X(r),s=await o.workflows.retryRun(t,n);if(!r.wait){if(r.json)return e(s);l(`Started run ${s.runId} (retry of ${n}).`),l(`Inspect it with: tangle workflows run-detail ${t} ${s.runId}`);return}let c=r.json?null:f(`Waiting for run ${s.runId} to finish...`).start(),u;try{u=await o.workflows.waitForRun(t,s.runId,{...i===void 0?{}:{timeoutMs:i},...a===void 0?{}:{pollIntervalMs:a}})}finally{c?.stop()}if(u.status===`failed`&&(process.exitCode=1),r.json)return e(u);jc(u)}),t.command(`events`).description(`Tail a run's live progress events until it finishes`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(e,t,n)=>{let r=await X(n);for await(let i of r.workflows.watchRun(e,t))n.json?console.log(JSON.stringify(i)):Nc(i),i.type===`run.done`&&i.status===`failed`&&(process.exitCode=1)})}async function Fc(e,t){let n;try{if(n=t.deploy?(await import(`yaml`)).parse(await L(t.deploy,`utf8`)):{name:le(e).replace(/(\.graph)?\.(yaml|yml|json)$/i,``)},!n||typeof n!=`object`||Array.isArray(n)||typeof n.name!=`string`||!n.name.trim())throw Error(`Invalid deployment`)}catch{throw new B(`GRAPH_DEPLOY_INVALID`,`Cannot read graph deployment settings`,`Use a YAML or JSON object containing name and the platform's graph deployment fields`,`tangle graph apply --help`)}let r=kc(t.param,`param`),i=t.mcpPolicy??n.mcpPolicy;return{...n,...r?{params:{...n.params,...r}}:{},...t.seat?{seat:t.seat}:{},...i===void 0?{}:{mcpPolicy:Ke.parse(i)}}}function Ic(e){if(e.execution?.kind!==`graph`||!e.headRev)throw new B(`GRAPH_DEPLOY_CONFLICT`,`The deployment is not a versioned native graph`,`Choose a graph workflow or a new deployment name`,`tangle workflows list`)}async function Lc(e,t){let n=await e.workflows.list({name:t});if(n.length>1)throw new B(`GRAPH_DEPLOY_CONFLICT`,`More than one workflow has this name`,`Select the intended deployment with --workflow <id>`,`tangle workflows list`);return n[0]?e.workflows.get(n[0].id):void 0}async function Rc(e,t,n,r){let i={on:[],...n,...n.mcpPolicy===void 0?{}:{mcpPolicy:Ke.parse(n.mcpPolicy)}},a;a=r?await e.workflows.get(r):await Lc(e,n.name);let o=await e.workflows.validate(t,{format:`graph`,deploy:i});if(!o.valid)throw new B(`GRAPH_DEPLOY_INVALID`,`Graph deployment validation failed`,o.errors.map(e=>`${e.path}: ${e.message}`).join(`
153
- `),`tangle graph apply --help`);a||=await e.workflows.create(t,{format:`graph`,deploy:{...i,on:[],enabled:!1},dedupeKey:`graph-cli:${n.name}`}),Ic(a);let s=e=>!e.triggers?.some(e=>e.kind===`provider_event`)&&e.enabled===(i.enabled??!0)&&e.execution.sourceSha===Q(t)&&o.graphDigest!==void 0&&e.execution.graphDigest===o.graphDigest&&P(e.execution.deploy)===P(i);if(s(a))return{action:`unchanged`,workflow:a};try{return{action:`applied`,workflow:await e.workflows.update(a.id,t,{format:`graph`,deploy:i,expectedRev:a.headRev})}}catch(t){if(!(t&&typeof t==`object`&&`status`in t&&t.status===409))throw t;let n=await e.workflows.get(a.id);if(Ic(n),!s(n))throw t;return{action:`unchanged`,workflow:n}}}function zc(t,n){t.command(`webhook <workflow>`).description(`Reveal a new webhook bearer for a deployed graph; retire its previous bearer`).requiredOption(`--rotate`,`Explicitly authorize minting and revealing a new webhook token`).action(async(t,n)=>{let r=await X(n);Ic(await r.workflows.get(t)),e(await r.workflows.rotateHookToken(t))}),t.command(`apply <name-or-file>`).description(`Publish a native graph without running it; update its stable cloud deployment`).option(`--deploy <file>`,`YAML/JSON deployment settings: name, on, params, seat, enabled and maxRunCostUsd`).option(`--workflow <id>`,`Update this workflow instead of matching its name`).option(`--seat <seat>`,`Override the deployment's harness/model@effort`).option(`--param <key=value>`,`Override a deployment parameter; repeatable`,(e,t)=>[...t,e],[]).option(`--dry-run`,`Validate graph and bindings without publishing`).action(async(t,r)=>vs(void 0,async i=>{let a=n(t,process.cwd()),o=await L(a,`utf8`),s=await Fc(a,r),c=await X({...r,signal:i}),u=r.dryRun?await c.workflows.validate(o,{format:`graph`,deploy:s}):await Rc(c,o,s,r.workflow);`valid`in u&&!u.valid&&(process.exitCode=1),r.json||`valid`in u?e(u):l(`${u.action} · ${u.workflow.id} · revision ${u.workflow.headRev}`)},`tangle graph apply --help`))}async function Bc(e,t,n,r){if(n.mcpSecret?.length)throw new B(`GRAPH_CLOUD_SECRET_BINDING`,`Local MCP credentials cannot be uploaded`,`Cloud secret references must bind through the cloud owner's credential environment`,`tangle graph run --help`);let i=await X({...n,signal:r}),a=Q(t),o=kc(n.param,`param`),s=await Fc(e,n),c,l;if(n.resume){let e=await i.workflows.getRun(n.resume,{signal:r});e.id!==n.resume&&Y(`The cloud owner returned another run identity`),n.workflow&&e.workflowId!==n.workflow&&Y(`The recorded cloud deployment changed`);let t=e.execution;if((t?.kind!==`graph`||t.sourceSha!==a)&&Y(`The authored cloud graph source changed`),n.deploy&&P(t.deploy)!==P({on:[],...s})&&Y(`The recorded cloud deployment settings changed`),Object.entries(o??{}).some(([e,n])=>!Object.hasOwn(t.params,e)||P(t.params[e])!==P(n))&&Y(`A recorded cloud graph parameter changed`),n.seat!==void 0&&n.seat!==t.deploy.seat&&Y(`The recorded cloud seat override changed`),n.mcpPolicy!==void 0&&P(n.mcpPolicy)!==P(t.deploy.mcpPolicy??{allowLocalMcp:!1,allowedMcpHosts:[]})&&Y(`The recorded cloud MCP policy changed`),n.dryRun)return{run:e};if((e.status===`cancelled`||e.status===`failed`)&&Y(`The cloud run is terminal: ${e.status}`),e.status===`succeeded`)return e.graphResult||Y(`The settled cloud run has no retained Runtime result`),{workflowId:e.workflowId,runId:e.id,sourceDigest:a,result:e.graphResult,replayed:!0,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(e.workflowId)}/runs/${encodeURIComponent(e.id)}`};if(e.recovery?.state===`running`)return{workflowId:e.workflowId,runId:e.id,sourceDigest:a,run:e,attached:!0,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(e.workflowId)}/runs/${encodeURIComponent(e.id)}`};e.recovery?.state!==`queued`&&e.recovery?.state!==`recoverable`&&Y(`The owner has not confirmed recovery eligibility`),c=e.workflowId,l=e.revUsed??Y(`The captured cloud revision is unavailable`)}else{let e=n.workflow?await i.workflows.get(n.workflow):!n.deploy&&!n.dryRun?await Lc(i,s.name):void 0;if(e){if((e.execution?.kind!==`graph`||e.execution.sourceSha!==a)&&Y(`The selected deployment does not contain this graph source; use graph apply first`),(n.deploy&&P(e.execution.deploy)!==P({on:[],...s})||Object.entries(o??{}).some(([t,n])=>!Object.hasOwn(e.execution?.kind===`graph`?e.execution.params:{},t)||P(e.execution?.kind===`graph`?e.execution.params[t]:null)!==P(n))||n.seat!==void 0&&n.seat!==e.execution.deploy.seat||n.mcpPolicy!==void 0&&P(n.mcpPolicy)!==P(e.execution.deploy.mcpPolicy??{allowLocalMcp:!1,allowedMcpHosts:[]}))&&Y(`The selected deployment bindings changed; use graph apply first`),n.dryRun)return{workflow:e};c=e.id,l=e.headRev??Y(`The selected deployment has no retained revision`)}else{if(n.dryRun)return i.workflows.validate(t,{format:`graph`,deploy:s});let{workflow:e}=await Rc(i,t,s);c=e.id,l=e.headRev??Y(`The cloud workflow has no retained revision`)}}r.throwIfAborted();let u=await i.workflows.run(c,void 0,{signal:r,sourceSha:a,expectedRev:l,...n.resume?{resumeRunId:n.resume}:{}});return n.resume&&u.runId!==n.resume&&Y(`The cloud owner recovered another run identity`),{...u,workflowId:c,sourceDigest:a,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(c)}/runs/${encodeURIComponent(u.runId)}`}}const Vc=I.strictObject({runId:I.uuid(),identity:I.string(),request:I.string()});function Hc(t,n){t.command(`dispatch <name-or-file>`).description(`Admit a local scheduler/webhook delivery once, retaining its event and run for retries`).requiredOption(`--event <file>`,`JSON object supplied as trigger data`).requiredOption(`--delivery <id>`,`Stable provider delivery id or nominal cron occurrence, reused on retries`).option(`--seat <seat>`,`Use harness/model@effort for every node`).addOption(ws()).option(`--mcp-policy <file>`,`Use the same explicit local MCP policy as graph run`).option(`--param <key=value>`,`Graph parameter; repeatable`,(e,t)=>[...t,e],[]).action(async(t,r)=>{let i={...r,mcpPolicy:r.mcpPolicy===void 0?void 0:await Es(r.mcpPolicy)},a=e=>{throw new B(`GRAPH_DELIVERY_REFUSED`,`Local graph delivery was not admitted`,e,`tangle graph dispatch --help`)};i.delivery.trim()||a(`A stable nonempty delivery id is required`);let o;try{o=I.record(I.string(),I.unknown()).parse(JSON.parse(await L(i.event,`utf8`)))}catch{return a(`The event file must contain a JSON object`)}let s=await R(n(t,process.cwd())),c=await R(process.cwd()),u=await L(s,`utf8`),d=P({file:s,cwd:c,delivery:i.delivery}),f=P({source:Q(u),trigger:o,mcpPolicy:qe.parse(i.mcpPolicy??{}),params:kc(i.param,`param`)??{},...i.seat===void 0?{}:{seat:i.seat}}),p=M(F(),`.tangle`,`deliveries`,Q(d));await ft(p,{recursive:!0,mode:448}),await R(p)!==p&&a(`The delivery store redirects elsewhere`);let m=M(p,`delivery.json`),h;try{let e=await mt(m,Ne.O_WRONLY|Ne.O_CREAT|Ne.O_EXCL|Ne.O_NOFOLLOW,384);try{h={runId:be(),identity:d,request:f},await e.writeFile(JSON.stringify(h)),await e.sync()}finally{await e.close()}}catch(e){if(e.code!==`EEXIST`)throw e;let t=await mt(m,Ne.O_RDONLY|Ne.O_NOFOLLOW);try{h=Vc.parse(JSON.parse(await t.readFile(`utf8`)))}catch{return a(`The durable delivery record is incomplete; inspect it before retrying`)}finally{await t.close()}}(h.identity!==d||h.request!==f)&&a(`This delivery id already belongs to different graph bytes, event data or parameters`);let g;try{let{acquireSingleRunLock:e}=await import(`@tangle-network/agent-eval/campaign`);g=e({lockPath:`${m}.lock`}).release}catch(e){return a(`Delivery ${i.delivery} cannot acquire its owner lock; inspect run ${h.runId}: ${e instanceof Error?e.message:`lock unavailable`}`)}try{let t=M(F(),`.tangle`,`runs`,h.runId,`input.json`),n=!1;try{await L(t),n=!0}catch(e){if(e.code!==`ENOENT`)throw e}let r=await Xl(s,{...i,...n?{resume:h.runId}:{}},{cwd:c,source:u,trigger:o,runId:h.runId});i.json?e({delivery:i.delivery,...r}):l(`Delivery ${i.delivery} · run ${h.runId}`)}finally{await g()}})}const Uc=new Map([[`train`,`search`],[`test`,`holdout`]]);async function Wc(e,t,n,r){let i={mcpPolicy:n.mcpPolicy?await Es(n.mcpPolicy):void 0,mcpSecret:n.mcpSecret},a=[e,...n.arm],o=n.split===`test`;if(o?a.length!==2||!n.unseal:n.split!==`train`)throw Error(`--split is train, or test with one --arm and --unseal`);let s=o?`holdout`:`search`,c=await L(M(t,`cases.jsonl.gz`)),l=vt(c).toString().trim().split(`
154
- `).map(e=>JSON.parse(e)),u=new Map(l.map(e=>[e.id,e])),d=e=>u.get(e.split(`:`).pop()??e),f=l.some(e=>e.split!==void 0)&&l.find(e=>!Uc.has(e.split));if(f)throw Error(`Dataset row ${f.id} has split ${JSON.stringify(f.split)??`none`}; when one row names a split, every row names train or test`);let p=e=>`graph-improve-js::${d(e).upstream}`,m=e=>Uc.get(d(e).split)??r.deterministicSplit(p(e),`agent-eval-v1`,[.32,.38]),h=[...u.keys()].filter(e=>m(e)===s).sort();if(!h.length)throw Error(`--split ${n.split} selects no case of this dataset`);let g=(e,t)=>[`issue=https://github.com/${e.upstream}/issues/${e.issue}`,`repo=${e.upstream}`,...[`deliver=branch`,`base=main`,`test=${e.test}`],`verify_image=${t}`,`agent_tools={"websearch":false,"webfetch":false}`],_=g(l[0],`none`),v=[];for(let e of a){let t=await L(e,`utf8`),n=await Xl(e,{...i,param:_,dryRun:!0},{source:t});if(!(`graph`in n))throw Error(`${e} did not load locally`);let r=n.graph.nodes.filter(({check:e,profile:{tools:t}})=>!e&&(t?.websearch!==!1||t?.webfetch!==!1));if(r.length)throw Error(`${r.map(e=>e.id)} can use web tools; refusing`);let a=n.graph.budget?.maxTokens;if(!a)throw Error(`${e} sets no budget.maxTokens to book at`);let{maxIterations:o,deadlineMs:s}=n.graph.budget??{};if(!o||!s)throw Error(`${e} needs finite iteration and deadline budgets`);v.push({file:e,source:t,sourceDigest:Q(t),digest:n.graph.digest,cap:a,iterations:o,deadline:s})}return{bindings:i,files:a,sealed:s,manifest:c,tasks:h,at:d,split:m,params:g,arms:v}}const Gc=()=>import(`./graph-dataset-DL_Fx_EH.mjs`),Kc=()=>import(`./graph-operating-evidence-CGGxszAi.mjs`),qc=gt(He),Jc=async(e,...t)=>(await qc(`bash`,[`-ec`,e,`gi`,...t],{maxBuffer:3e8})).stdout,Yc=M(F(),`.tangle`,`graph-improve`,`v5`),Xc=M(F(),`.tangle`,`runs`),Zc=e=>({inputTokens:0,outputTokens:e,usageUnknown:!0}),Qc=e=>!!e&&e.owner!==`work`&&e.code!==`budget-exhausted`;async function $c(e){let[t,n]=[M(e,`bin`),M(e,`remotes`)];for(let e of[t,n])await ft(e,{recursive:!0});let r=`#!/bin/sh
152
+ `).requiredOption(`--profile <name|path>`,`Use a canonical analysis AgentProfile, distinct from the Tangle account profile`).option(`--dry-run`,`Inspect Braid's selected analysis configuration without dispatch`).option(`--timeout <ms>`,`Bound the analysis process in milliseconds`,Number,3e5).action(async(t,n)=>{let r=await Sc(t,n);e(r),`status`in r&&r.status!==`completed`&&(process.exitCode=1)})}async function wc(t,n){let r=[],i=[],a=(e,t)=>{if(!t||typeof t!=`object`)return;let n=I.object({status:I.string(),files:I.array(I.object({path:I.string(),artifact:Ce})),missing:I.unknown()}).parse(t);i.push({node:e,status:n.status,missing:n.missing}),r.push(...n.files.map(t=>({node:e,...t})))},o;if(t.startsWith(`wfrun_`)){let e=await X(n),r=await e.workflows.getRun(t);for(let e of r.runtime?.checks??[])a(e.nodeId,e.outputs);o=async({artifact:n})=>{let i=(await e.workflows.listArtifacts(r.workflowId,t)).artifacts.find(e=>e.name===`runtime/${n.sha256}`&&e.byteSize===n.byteLength);if(!i)throw Error(`The workflow owner has no retained bytes for this artifact`);return(await e.workflows.downloadArtifact(r.workflowId,t,i.id)).bytes}}else{if(!I.uuid().safeParse(t).success)throw Error(`Use a recorded graph run ID`);let e=M(await R(M(F(),`.tangle`,`runs`)),t);if(await R(e)!==e)throw Error(`The graph run directory redirects elsewhere`);let{FileSpawnJournal:n,FileResultBlobStore:r,loadSpawnForest:i,createPrivateCasArtifactPort:s}=await import(`@tangle-network/agent-runtime/kernel`),c=new r(M(e,`blobs`)),l=await i(new n(M(e,`spawn-journal.jsonl`)),t);for(let e of l.nodes){if(e.runtime!==`graph-check`||!e.outRef)continue;let t=await c.get(e.outRef);a(e.id,t?.outputs)}let u=s(M(e,`artifacts`),t);o=e=>u.read(e.artifact)}if(!n.artifact)return e({runId:t,capture:i,files:r});if(!n.out)throw new B(`USAGE_INVALID`,`Select an output file`,`Artifact downloads require --out`,`tangle graph inspect ${t} --artifact <node/path> --out <file>`);let s=r.filter(e=>`${e.node}/${e.path}`===n.artifact||e.artifact.sha256===n.artifact);if(s.length!==1)throw Error(`Select one exact node/path from graph inspect --artifacts`);let c=s[0],u=await o(c);if(u.byteLength!==c.artifact.byteLength||`sha256:${Q(Buffer.from(u))}`!==c.artifact.sha256)throw Error(`Retained artifact bytes do not match their recorded identity`);let d=he(n.out);await ft(ue(d),{recursive:!0}),await z(d,u,{mode:384,flag:`wx`});let f={runId:t,node:c.node,path:c.path,artifact:c.artifact,destination:d};n.json?e(f):l(`Saved ${c.path} to ${d}`)}const Tc=1e3;function Ec(e,t){return[...t,e]}function Dc(e,t=`input`,n){if(n===void 0&&!e?.length)return;let r={};if(n!==void 0)try{if(r=JSON.parse(Ie(n,`utf8`)),!r||typeof r!=`object`||Array.isArray(r)||Object.entries(r).some(([e,t])=>!e.length||typeof t!=`string`))throw Error(`Invalid input map`)}catch{throw new B(`WORKFLOW_INPUT_FILE_INVALID`,`Could not load --input-file '${n}'`,`Expected a readable JSON object with nonempty keys and string values`,`tangle workflows run --help`)}let i=Object.entries(r);for(let n of e??[]){let e=n.indexOf(`=`);if(e<=0)throw Error(`Invalid --${t} "${n}": expected key=value (e.g. pull_request.number=123)`);i.push([n.slice(0,e),n.slice(e+1)])}return Object.fromEntries(i)}function Oc(e){t(e.map(e=>({id:e.id,status:e.status,attempts:e.attempts,created:e.createdAt,completed:e.completedAt??``})),[{key:`id`,header:`Run ID`},{key:`status`,header:`Status`},{key:`attempts`,header:`Attempts`},{key:`created`,header:`Created`},{key:`completed`,header:`Completed`}])}function kc(e){if(s({"Run ID":e.id,Workflow:e.workflowId,Status:e.status,Error:e.error??``,Attempts:e.attempts,Created:e.createdAt,Started:e.startedAt??``,Completed:e.completedAt??``}),e.actionResults.length>0){l(`Actions`);let n=e.actionResults.some(e=>e.nodeId!==void 0||e.visit!==void 0);t(e.actionResults.map(e=>({index:e.index,...n?{node:e.nodeId??``,visit:e.visit??``}:{},kind:e.kind,status:e.status,error:e.error??``,cost:e.costUsd??``})),[{key:`index`,header:`#`},...n?[{key:`node`,header:`Node`},{key:`visit`,header:`Visit`}]:[],{key:`kind`,header:`Kind`},{key:`status`,header:`Status`},{key:`error`,header:`Error`},{key:`cost`,header:`Cost (USD)`}])}e.graph&&(l(`Graph`),s({Nodes:e.graph.nodes.length,Edges:e.graph.edges.length,"Max node visits":e.graph.maxNodeVisits}),t(e.graph.edges.map(e=>({from:e.from,to:e.to,guard:e.when===void 0?``:JSON.stringify(e.when)})),[{key:`from`,header:`From`},{key:`to`,header:`To`},{key:`guard`,header:`Guard`}])),e.edgeVerdicts&&e.edgeVerdicts.length>0&&(l(`Edge verdicts`),t(e.edgeVerdicts.flatMap(e=>Object.entries(e.verdicts).map(([t,n])=>({node:e.nodeId,edge:t,verdict:n?`taken`:`not taken`}))),[{key:`node`,header:`Node`},{key:`edge`,header:`Edge`},{key:`verdict`,header:`Verdict`}]))}function Ac(e){if(e.status===`cancelled`){l(`Cancelled run ${e.runId}.`);return}if(e.signalled){l(`Cancelling run ${e.runId} — signalled the worker; it will stop shortly.`);return}l(`Requested cancellation of run ${e.runId}, but couldn't confirm it — the run may have just finished, or it's running on another instance and will stop on its own.`)}function jc(e){switch(e.type){case`snapshot`:l(`snapshot: ${e.run.status} (${e.run.actionResults.length} action(s))`);break;case`action.started`:console.log(`→ action[${e.index}] ${e.kind} started`);break;case`action.finished`:{let t=e.status===`succeeded`?`✓`:e.status===`skipped`?`⊘`:`✗`;console.log(`${t} action[${e.index}] ${e.kind} ${e.status}${e.error?`: ${e.error}`:``}`);break}case`iteration.started`:console.log(` · action[${e.actionIndex}] iteration ${e.iterationIndex} started`);break;case`iteration.ended`:console.log(` · action[${e.actionIndex}] iteration ${e.iterationIndex} ${e.status}`);break;case`token`:typeof e.delta==`string`&&process.stdout.write(e.delta);break;case`ping`:break;case`run.done`:console.log(`\nrun.done: ${e.status}${e.error?`: ${e.error}`:``}`);break;case`run.waiting`:console.log(`\nrun.waiting: parked on a human decision (${e.decisionId}) — resolve it to resume`);break}}function Mc(t){t.command(`run`).description(`Trigger an immediate run of a workflow`).argument(`<id>`,`Workflow ID`).option(`--input-file <file>`,`Trigger inputs from a flat JSON string map; --input overrides its keys`).option(`--input <key=value>`,`Trigger input as key=value (e.g. pull_request.number=123). Repeatable.`,Ec,[]).option(`--wait`,`Wait for the run to finish and print its result`).option(`--timeout <ms>`,`With --wait, fail if the run has not finished after this many milliseconds`).option(`--poll-interval <ms>`,`With --wait, how often to poll for completion (default 2000)`).action(async(t,n)=>{let r=Dc(n.input,`input`,n.inputFile),i=n.timeout===void 0?void 0:pa(n.timeout,`--timeout`),a=n.pollInterval===void 0?void 0:pa(n.pollInterval,`--poll-interval`),o=await X(n),{runId:s}=await o.workflows.run(t,r);if(!n.wait){if(n.json)return e({runId:s});l(`Started run ${s} for workflow ${t}.`),l(`Inspect it with: tangle workflows run-detail ${t} ${s}`);return}let c=n.json?null:f(`Waiting for run ${s} to finish...`).start(),u;try{u=await o.workflows.waitForRun(t,s,{...i===void 0?{}:{timeoutMs:i},...a===void 0?{}:{pollIntervalMs:a}})}finally{c?.stop()}if(u.status===`failed`&&(process.exitCode=1),n.json)return e(u);kc(u)}),t.command(`runs`).description(`List a workflow's run history (newest first)`).argument(`<id>`,`Workflow ID`).option(`--limit <n>`,`Runs per page (1-100)`).option(`--cursor <cursor>`,`Pagination cursor from a previous page`).option(`--all`,`Fetch every page, not just the first`).action(async(t,n)=>{let r=await X(n),i=n.limit===void 0?void 0:pa(n.limit,`--limit`);if(n.all){let a=[],o=n.cursor,s=0,c=null;for(;;){let e=await r.workflows.listRuns(t,{...i===void 0?{}:{limit:i},...o===void 0?{}:{cursor:o}});if(a.push(...e.runs),s+=1,!e.nextCursor)break;if(s>=Tc){c=e.nextCursor,n.json||l(`Stopped after ${Tc} pages (${a.length} runs); more may exist — resume with --cursor ${e.nextCursor}`);break}o=e.nextCursor}if(n.json)return e({runs:a,nextCursor:c});Oc(a);return}let a=await r.workflows.listRuns(t,{...i===void 0?{}:{limit:i},...n.cursor===void 0?{}:{cursor:n.cursor}});if(n.json)return e(a);Oc(a.runs),a.nextCursor&&l(`More runs available — next page: --cursor ${a.nextCursor}`)}),t.command(`run-detail`).description(`Show a single run's detail (per-action output and errors)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.getRun(t,n);if(r.json)return e(i);kc(i)}),t.command(`cancel`).description(`Cancel a queued or in-progress run`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.cancel(t,n);if(r.json)return e(i);Ac(i)}),t.command(`retry`).description(`Re-run a failed or cancelled run (a fresh run with the same trigger context)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID of the failed/cancelled run to retry`).option(`--wait`,`Wait for the new run to finish and print its result`).option(`--timeout <ms>`,`With --wait, fail if the run has not finished after this many milliseconds`).option(`--poll-interval <ms>`,`With --wait, how often to poll for completion (default 2000)`).action(async(t,n,r)=>{let i=r.timeout===void 0?void 0:pa(r.timeout,`--timeout`),a=r.pollInterval===void 0?void 0:pa(r.pollInterval,`--poll-interval`),o=await X(r),s=await o.workflows.retryRun(t,n);if(!r.wait){if(r.json)return e(s);l(`Started run ${s.runId} (retry of ${n}).`),l(`Inspect it with: tangle workflows run-detail ${t} ${s.runId}`);return}let c=r.json?null:f(`Waiting for run ${s.runId} to finish...`).start(),u;try{u=await o.workflows.waitForRun(t,s.runId,{...i===void 0?{}:{timeoutMs:i},...a===void 0?{}:{pollIntervalMs:a}})}finally{c?.stop()}if(u.status===`failed`&&(process.exitCode=1),r.json)return e(u);kc(u)}),t.command(`events`).description(`Tail a run's live progress events until it finishes`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(e,t,n)=>{let r=await X(n);for await(let i of r.workflows.watchRun(e,t))n.json?console.log(JSON.stringify(i)):jc(i),i.type===`run.done`&&i.status===`failed`&&(process.exitCode=1)})}async function Nc(e,t){let n;try{if(n=t.deploy?(await import(`yaml`)).parse(await L(t.deploy,`utf8`)):{name:le(e).replace(/(\.graph)?\.(yaml|yml|json)$/i,``)},!n||typeof n!=`object`||Array.isArray(n)||typeof n.name!=`string`||!n.name.trim())throw Error(`Invalid deployment`)}catch{throw new B(`GRAPH_DEPLOY_INVALID`,`Cannot read graph deployment settings`,`Use a YAML or JSON object containing name and the platform's graph deployment fields`,`tangle graph apply --help`)}let r=Dc(t.param,`param`),i=t.mcpPolicy??n.mcpPolicy;return{...n,...r?{params:{...n.params,...r}}:{},...t.seat?{seat:t.seat}:{},...i===void 0?{}:{mcpPolicy:Ke.parse(i)}}}function Pc(e){if(e.execution?.kind!==`graph`||!e.headRev)throw new B(`GRAPH_DEPLOY_CONFLICT`,`The deployment is not a versioned native graph`,`Choose a graph workflow or a new deployment name`,`tangle workflows list`)}async function Fc(e,t){let n=await e.workflows.list({name:t});if(n.length>1)throw new B(`GRAPH_DEPLOY_CONFLICT`,`More than one workflow has this name`,`Select the intended deployment with --workflow <id>`,`tangle workflows list`);return n[0]?e.workflows.get(n[0].id):void 0}async function Ic(e,t,n,r){let i={on:[],...n,...n.mcpPolicy===void 0?{}:{mcpPolicy:Ke.parse(n.mcpPolicy)}},a;a=r?await e.workflows.get(r):await Fc(e,n.name);let o=await e.workflows.validate(t,{format:`graph`,deploy:i});if(!o.valid)throw new B(`GRAPH_DEPLOY_INVALID`,`Graph deployment validation failed`,o.errors.map(e=>`${e.path}: ${e.message}`).join(`
153
+ `),`tangle graph apply --help`);a||=await e.workflows.create(t,{format:`graph`,deploy:{...i,on:[],enabled:!1},dedupeKey:`graph-cli:${n.name}`}),Pc(a);let s=e=>!e.triggers?.some(e=>e.kind===`provider_event`)&&e.enabled===(i.enabled??!0)&&e.execution.sourceSha===Q(t)&&o.graphDigest!==void 0&&e.execution.graphDigest===o.graphDigest&&P(e.execution.deploy)===P(i);if(s(a))return{action:`unchanged`,workflow:a};try{return{action:`applied`,workflow:await e.workflows.update(a.id,t,{format:`graph`,deploy:i,expectedRev:a.headRev})}}catch(t){if(!(t&&typeof t==`object`&&`status`in t&&t.status===409))throw t;let n=await e.workflows.get(a.id);if(Pc(n),!s(n))throw t;return{action:`unchanged`,workflow:n}}}function Lc(t,n){t.command(`webhook <workflow>`).description(`Reveal a new webhook bearer for a deployed graph; retire its previous bearer`).requiredOption(`--rotate`,`Explicitly authorize minting and revealing a new webhook token`).action(async(t,n)=>{let r=await X(n);Pc(await r.workflows.get(t)),e(await r.workflows.rotateHookToken(t))}),t.command(`apply <name-or-file>`).description(`Publish a native graph without running it; update its stable cloud deployment`).option(`--deploy <file>`,`YAML/JSON deployment settings: name, on, params, seat, enabled and maxRunCostUsd`).option(`--workflow <id>`,`Update this workflow instead of matching its name`).option(`--seat <seat>`,`Override the deployment's harness/model@effort`).option(`--param <key=value>`,`Override a deployment parameter; repeatable`,(e,t)=>[...t,e],[]).option(`--dry-run`,`Validate graph and bindings without publishing`).action(async(t,r)=>gs(void 0,async i=>{let a=n(t,process.cwd()),o=await L(a,`utf8`),s=await Nc(a,r),c=await X({...r,signal:i}),u=r.dryRun?await c.workflows.validate(o,{format:`graph`,deploy:s}):await Ic(c,o,s,r.workflow);`valid`in u&&!u.valid&&(process.exitCode=1),r.json||`valid`in u?e(u):l(`${u.action} · ${u.workflow.id} · revision ${u.workflow.headRev}`)},`tangle graph apply --help`))}async function Rc(e,t,n,r){if(n.mcpSecret?.length)throw new B(`GRAPH_CLOUD_SECRET_BINDING`,`Local MCP credentials cannot be uploaded`,`Cloud secret references must bind through the cloud owner's credential environment`,`tangle graph run --help`);let i=await X({...n,signal:r}),a=Q(t),o=Dc(n.param,`param`),s=await Nc(e,n),c,l;if(n.resume){let e=await i.workflows.getRun(n.resume,{signal:r});e.id!==n.resume&&Y(`The cloud owner returned another run identity`),n.workflow&&e.workflowId!==n.workflow&&Y(`The recorded cloud deployment changed`);let t=e.execution;if((t?.kind!==`graph`||t.sourceSha!==a)&&Y(`The authored cloud graph source changed`),n.deploy&&P(t.deploy)!==P({on:[],...s})&&Y(`The recorded cloud deployment settings changed`),Object.entries(o??{}).some(([e,n])=>!Object.hasOwn(t.params,e)||P(t.params[e])!==P(n))&&Y(`A recorded cloud graph parameter changed`),n.seat!==void 0&&n.seat!==t.deploy.seat&&Y(`The recorded cloud seat override changed`),n.mcpPolicy!==void 0&&P(n.mcpPolicy)!==P(t.deploy.mcpPolicy??{allowLocalMcp:!1,allowedMcpHosts:[]})&&Y(`The recorded cloud MCP policy changed`),n.dryRun)return{run:e};if((e.status===`cancelled`||e.status===`failed`)&&Y(`The cloud run is terminal: ${e.status}`),e.status===`succeeded`)return e.graphResult||Y(`The settled cloud run has no retained Runtime result`),{workflowId:e.workflowId,runId:e.id,sourceDigest:a,result:e.graphResult,replayed:!0,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(e.workflowId)}/runs/${encodeURIComponent(e.id)}`};if(e.recovery?.state===`running`)return{workflowId:e.workflowId,runId:e.id,sourceDigest:a,run:e,attached:!0,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(e.workflowId)}/runs/${encodeURIComponent(e.id)}`};e.recovery?.state!==`queued`&&e.recovery?.state!==`recoverable`&&Y(`The owner has not confirmed recovery eligibility`),c=e.workflowId,l=e.revUsed??Y(`The captured cloud revision is unavailable`)}else{let e=n.workflow?await i.workflows.get(n.workflow):!n.deploy&&!n.dryRun?await Fc(i,s.name):void 0;if(e){if((e.execution?.kind!==`graph`||e.execution.sourceSha!==a)&&Y(`The selected deployment does not contain this graph source; use graph apply first`),(n.deploy&&P(e.execution.deploy)!==P({on:[],...s})||Object.entries(o??{}).some(([t,n])=>!Object.hasOwn(e.execution?.kind===`graph`?e.execution.params:{},t)||P(e.execution?.kind===`graph`?e.execution.params[t]:null)!==P(n))||n.seat!==void 0&&n.seat!==e.execution.deploy.seat||n.mcpPolicy!==void 0&&P(n.mcpPolicy)!==P(e.execution.deploy.mcpPolicy??{allowLocalMcp:!1,allowedMcpHosts:[]}))&&Y(`The selected deployment bindings changed; use graph apply first`),n.dryRun)return{workflow:e};c=e.id,l=e.headRev??Y(`The selected deployment has no retained revision`)}else{if(n.dryRun)return i.workflows.validate(t,{format:`graph`,deploy:s});let{workflow:e}=await Ic(i,t,s);c=e.id,l=e.headRev??Y(`The cloud workflow has no retained revision`)}}r.throwIfAborted();let u=await i.workflows.run(c,void 0,{signal:r,sourceSha:a,expectedRev:l,...n.resume?{resumeRunId:n.resume}:{}});return n.resume&&u.runId!==n.resume&&Y(`The cloud owner recovered another run identity`),{...u,workflowId:c,sourceDigest:a,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(c)}/runs/${encodeURIComponent(u.runId)}`}}const zc=I.strictObject({runId:I.uuid(),identity:I.string(),request:I.string()});function Bc(t,n){t.command(`dispatch <name-or-file>`).description(`Admit a local scheduler/webhook delivery once, retaining its event and run for retries`).requiredOption(`--event <file>`,`JSON object supplied as trigger data`).requiredOption(`--delivery <id>`,`Stable provider delivery id or nominal cron occurrence, reused on retries`).option(`--seat <seat>`,`Use harness/model@effort for every node`).addOption(Ss()).option(`--mcp-policy <file>`,`Use the same explicit local MCP policy as graph run`).option(`--param <key=value>`,`Graph parameter; repeatable`,(e,t)=>[...t,e],[]).action(async(t,r)=>{let i={...r,mcpPolicy:r.mcpPolicy===void 0?void 0:await ws(r.mcpPolicy)},a=e=>{throw new B(`GRAPH_DELIVERY_REFUSED`,`Local graph delivery was not admitted`,e,`tangle graph dispatch --help`)};i.delivery.trim()||a(`A stable nonempty delivery id is required`);let o;try{o=I.record(I.string(),I.unknown()).parse(JSON.parse(await L(i.event,`utf8`)))}catch{return a(`The event file must contain a JSON object`)}let s=await R(n(t,process.cwd())),c=await R(process.cwd()),u=await L(s,`utf8`),d=P({file:s,cwd:c,delivery:i.delivery}),f=P({source:Q(u),trigger:o,mcpPolicy:qe.parse(i.mcpPolicy??{}),params:Dc(i.param,`param`)??{},...i.seat===void 0?{}:{seat:i.seat}}),p=M(F(),`.tangle`,`deliveries`,Q(d));await ft(p,{recursive:!0,mode:448}),await R(p)!==p&&a(`The delivery store redirects elsewhere`);let m=M(p,`delivery.json`),h;try{let e=await mt(m,Ne.O_WRONLY|Ne.O_CREAT|Ne.O_EXCL|Ne.O_NOFOLLOW,384);try{h={runId:be(),identity:d,request:f},await e.writeFile(JSON.stringify(h)),await e.sync()}finally{await e.close()}}catch(e){if(e.code!==`EEXIST`)throw e;let t=await mt(m,Ne.O_RDONLY|Ne.O_NOFOLLOW);try{h=zc.parse(JSON.parse(await t.readFile(`utf8`)))}catch{return a(`The durable delivery record is incomplete; inspect it before retrying`)}finally{await t.close()}}(h.identity!==d||h.request!==f)&&a(`This delivery id already belongs to different graph bytes, event data or parameters`);let g;try{let{acquireSingleRunLock:e}=await import(`@tangle-network/agent-eval/campaign`);g=e({lockPath:`${m}.lock`}).release}catch(e){return a(`Delivery ${i.delivery} cannot acquire its owner lock; inspect run ${h.runId}: ${e instanceof Error?e.message:`lock unavailable`}`)}try{let t=M(F(),`.tangle`,`runs`,h.runId,`input.json`),n=!1;try{await L(t),n=!0}catch(e){if(e.code!==`ENOENT`)throw e}let r=await Jl(s,{...i,...n?{resume:h.runId}:{}},{cwd:c,source:u,trigger:o,runId:h.runId});i.json?e({delivery:i.delivery,...r}):l(`Delivery ${i.delivery} · run ${h.runId}`)}finally{await g()}})}const Vc=new Map([[`train`,`search`],[`test`,`holdout`]]);async function Hc(e,t,n,r){let i={mcpPolicy:n.mcpPolicy?await ws(n.mcpPolicy):void 0,mcpSecret:n.mcpSecret},a=[e,...n.arm],o=n.split===`test`;if(o?a.length!==2||!n.unseal:n.split!==`train`)throw Error(`--split is train, or test with one --arm and --unseal`);let s=o?`holdout`:`search`,c=await L(M(t,`cases.jsonl.gz`)),l=vt(c).toString().trim().split(`
154
+ `).map(e=>JSON.parse(e)),u=new Map(l.map(e=>[e.id,e])),d=e=>u.get(e.split(`:`).pop()??e),f=l.some(e=>e.split!==void 0)&&l.find(e=>!Vc.has(e.split));if(f)throw Error(`Dataset row ${f.id} has split ${JSON.stringify(f.split)??`none`}; when one row names a split, every row names train or test`);let p=e=>`graph-improve-js::${d(e).upstream}`,m=e=>Vc.get(d(e).split)??r.deterministicSplit(p(e),`agent-eval-v1`,[.32,.38]),h=[...u.keys()].filter(e=>m(e)===s).sort();if(!h.length)throw Error(`--split ${n.split} selects no case of this dataset`);let g=(e,t)=>[`issue=https://github.com/${e.upstream}/issues/${e.issue}`,`repo=${e.upstream}`,...[`deliver=branch`,`base=main`,`test=${e.test}`],`verify_image=${t}`,`agent_tools={"websearch":false,"webfetch":false}`],_=g(l[0],`none`),v=[];for(let e of a){let t=await L(e,`utf8`),n=await Jl(e,{...i,param:_,dryRun:!0},{source:t});if(!(`graph`in n))throw Error(`${e} did not load locally`);let r=n.graph.nodes.filter(({check:e,profile:{tools:t}})=>!e&&(t?.websearch!==!1||t?.webfetch!==!1));if(r.length)throw Error(`${r.map(e=>e.id)} can use web tools; refusing`);let a=n.graph.budget?.maxTokens;if(!a)throw Error(`${e} sets no budget.maxTokens to book at`);let{maxIterations:o,deadlineMs:s}=n.graph.budget??{};if(!o||!s)throw Error(`${e} needs finite iteration and deadline budgets`);v.push({file:e,source:t,sourceDigest:Q(t),digest:n.graph.digest,cap:a,iterations:o,deadline:s})}return{bindings:i,files:a,sealed:s,manifest:c,tasks:h,at:d,split:m,params:g,arms:v}}const Uc=()=>import(`./graph-dataset-DL_Fx_EH.mjs`),Wc=()=>import(`./graph-operating-evidence-CGGxszAi.mjs`),Gc=gt(He),Kc=async(e,...t)=>(await Gc(`bash`,[`-ec`,e,`gi`,...t],{maxBuffer:3e8})).stdout,qc=M(F(),`.tangle`,`graph-improve`,`v5`),Jc=M(F(),`.tangle`,`runs`),Yc=e=>({inputTokens:0,outputTokens:e,usageUnknown:!0}),Xc=e=>!!e&&e.owner!==`work`&&e.code!==`budget-exhausted`;async function Zc(e){let[t,n]=[M(e,`bin`),M(e,`remotes`)];for(let e of[t,n])await ft(e,{recursive:!0});let r=`#!/bin/sh
155
155
  [ "$1 $2" = "issue view" ] || { echo "gh: offline replay; only 'gh issue view <n>' answers" >&2; exit 1; }
156
156
  shift 2; n=; repo=; prev=
157
157
  for a; do
@@ -160,17 +160,25 @@ for a; do
160
160
  prev=$a
161
161
  done
162
162
  exec cat "${e}/remotes/$repo.git/tangle-issue-$n.json"
163
- `;for(let t of[`gh`,`gh-drew`])await z(M(e,`bin`,t),r,{mode:493});let i=`[url "${e}/remotes/"]\n\tinsteadOf = https://github.com/\n[user]\n\tname = graph-improve\n\temail = gi@local\n`;await z(M(e,`bin`,`gitconfig`),i);for(let e of Object.keys(process.env))/(^|_)(GH|GITHUB)\w*_(TOKEN|PAT)$|_PAT$/i.test(e)&&delete process.env[e];Object.assign(process.env,{GITHUB_TOKEN:`replay-placeholder`,GIT_CONFIG_NOSYSTEM:`1`,PATH:`${t}:${process.env.PATH}`,BRIDGE_JAIL_RO_PATHS:t,GIT_CONFIG_GLOBAL:M(t,`gitconfig`),BRIDGE_JAIL_RW_PATHS:n})}async function el(t,n,r){let{CostLedger:i,decidePairedPromotion:a,runCampaign:o,wilson:s}=await import(`@tangle-network/agent-eval`),c=await import(`@tangle-network/agent-eval/benchmarks`),{durableRunToolSpans:l,readSettleRecord:u}=await import(`@tangle-network/agent-runtime/durable`),{acquireSingleRunLock:d}=await import(`@tangle-network/agent-eval/campaign`),f=await Wc(t,n,r,c),{bindings:p,files:m,sealed:h,manifest:g,tasks:_,at:v,split:y,arms:b}=f,x={},S,C=r.dockerHost;C&&(process.env.DOCKER_HOST=`ssh://${C}`);let w=c.createHarborBenchmarkAdapter({id:`graph-improve-js`,datasetDir:n,assignSplit:y,tasks:_,source:{name:`js-issues`,revision:Q(g).slice(0,12)},grade:c.gradeHarborPatch({jobsDir:M(Yc,`jobs`)})}),T=new AbortController,ee=await c.benchmarkScenarios(w,[h]),E=new Set(ee.slice(0,r.probe).map(e=>e.id)),D=r.reps??1;if(!Number.isSafeInteger(D)||D<1||r.probe!==void 0&&(!Number.isSafeInteger(r.probe)||r.probe<1))throw Error(`--reps and --probe must be positive integers`);let O={maxTokens:r.maxTokens??b.reduce((e,t)=>e+t.cap,0)*ee.length*D,maxIterations:r.maxIterations??b.reduce((e,t)=>e+t.iterations,0)*ee.length*D,deadlineMs:r.deadlineMs??b.reduce((e,t)=>e+t.deadline,0)*ee.length*D},k=Q(JSON.stringify({dataset:Q(g),sealed:h,arms:b.map(e=>({graph:e.digest,source:e.sourceDigest})),mcpPolicy:p.mcpPolicy??null,seats:r.seat,reps:D})),A=he(r.campaign??M(Yc,`campaigns`,k));await ft(A,{recursive:!0,mode:448}),S=M(A,`environment`);let{release:te}=d({lockPath:`${await R(A)}.lock`});try{await $c(S);for(let[e,t]of b.entries()){t.evidence=await(await Gc()).graphDatasetObject(A,{kind:`graph-arm-source`,source:t.source,sourceDigest:t.sourceDigest});let n=M(A,`arm-${e}.json`),r=JSON.stringify({evidence:t.evidence});try{await z(n,r,{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e;if(await L(n,`utf8`)!==r)throw Error(`Benchmark arm source changed; use a new campaign`)}}let t=await(await import(`./graph-campaign-state-YA-eORZN.mjs`)).openGraphCampaignBudget(A,O,Q(JSON.stringify({identity:k,ceilings:O}))),{pool:n}=t,d=al({prepared:f,bench:c,conserved:t,campaign:A,live:S,host:C,stop:T,state:x,durableRunToolSpans:l,readSettleRecord:u}),p=AbortSignal.any([T.signal,AbortSignal.timeout(Math.max(1,t.startedAt+O.deadlineMs-Date.now()))]),g=new i({costCeilingUsd:0}),_=[...Array(D).keys()],y=[...E].flatMap(e=>_.flatMap(t=>b.map((n,r)=>`${r}|${e}:${t}`))),te=new Map,ne=new Map(y.map(e=>[e,new Promise(t=>te.set(e,t))])),re=new Map([...E].map(e=>[e,D*b.length]));p.addEventListener(`abort`,()=>{x.incomplete??=`Campaign deadline or cancellation interrupted matched comparison`;for(let e of te.values())e()},{once:!0});let ie=b.map(async(e,n)=>{let i=`${e.digest}:${r.seat.join(`,`)}`,a=M(A,`arms`,`${n}`);if(h===`holdout`){await ft(a,{recursive:!0});let e={at:new Date,reason:r.unseal,arms:m};await z(M(a,`holdout-access.jsonl`),`${JSON.stringify(e)}\n`,{flag:`a`})}return o({scenarios:ee,reps:D,runDir:a,resumable:!0,dispatchRef:i,costLedger:g,costCeiling:0,cellFilter:e=>E.has(e.scenario.id),judges:[c.benchmarkJudge(w)],maxConcurrency:3,signal:p,dispatchTimeoutMs:Math.max(1,t.startedAt+O.deadlineMs-Date.now()),onCellSettled:async(e,{id:t,item:r})=>{e.cached&&te.get(`${n}|${e.cellId}`)?.(),re.set(t,(re.get(t)??1)-1),re.get(t)||await c.releaseCaseEnvironment(r,{host:C})},dispatch:async(t,i)=>{let a=y.indexOf(`${n}|${i.cellId}`),o=r.seat[Math.floor(a/b.length)%r.seat.length],s=o??`graph-default`;try{await Promise.all(y.slice(0,a).map(e=>ne.get(e)));let r=await i.cost.runPaidCall({actor:e.file,model:s,signal:i.signal,maximumCharge:{externallyEnforcedMaximumUsd:0},execute:r=>d(e,t.item,{seat:o,signal:r,attempt:`${n}:${i.cellId}`}),receipt:({tokens:e})=>({model:s,...e,actualCostUsd:0}),receiptFromError:()=>({model:s,...Zc(e.cap),actualCostUsd:0})});if(!r.succeeded)throw r.error;return r.value}finally{te.get(`${n}|${i.cellId}`)?.()}}})}),ae=await Promise.allSettled(ie.map(e=>e.catch(e=>{throw T.abort(e),e})));if(T.signal.aborted)throw T.signal.reason;let{reports:oe,paired:se}=ol({campaigns:ae.map(e=>{if(e.status===`rejected`)throw e.reason;return e.value}),files:m,probe:E,reps:D,repList:_,at:v,state:x,wilson:s,decidePairedPromotion:a}),j={split:r.split,arms:oe,paired:se,incomplete:x.incomplete??(oe.some(e=>!e.usageComplete||e.unmeasured.length)?`Campaign evidence is incomplete`:null),campaign:A,campaignBudget:{limits:O,readout:n.readout()},operatingCost:{known:!1,reason:`subscription and environment allocation are not incrementally metered`}};await z(M(A,`result.json`),JSON.stringify(j),{mode:384,flush:!0}),e(j)}finally{await te()}}async function tl(e,t,n){try{let{trigger:r,...i}=n,a=await Xl(e,{param:t,json:!0,...i},{...r&&{trigger:r}});return`runId`in a?a.runId:void 0}catch(e){if(e.code!==`GRAPH_RUN_FAILED`)throw e;return e.runId}}const nl=async(e,t,n=!0)=>{if(!e)throw Error(`The diagnosis has no retained run identity`);let{readSettleRecord:r}=await import(`@tangle-network/agent-runtime/durable`),{FileResultBlobStore:i}=await import(`@tangle-network/agent-runtime/kernel`),a=M(Xc,e),o=(await r(a))?.tree.nodes.filter(e=>e.label===t&&e.outRef).at(-1);if(!o?.outRef&&!n)return{};if(!o?.outRef)throw Error(`The retained ${t} result is unavailable`);let s=await new i(M(a,`blobs`)).get(o.outRef);if(!s||typeof s!=`object`||Array.isArray(s))throw Error(`The retained ${t} result is not an object`);let c=`json`in s?s.json:s;if(!c||typeof c!=`object`||Array.isArray(c))throw Error(`The retained ${t} structured result is unavailable`);return c};async function rl(t,n){let r=await rc(t),i={...n,seat:n.seat??r.seat,mcpPolicy:n.mcpPolicy??r.mcpPolicy,trigger:r.trigger},a=await oc(r),o=M(Yc,`repairs`,t);await ft(o,{recursive:!0});let s=M(o,`original.graph.yaml`);await z(s,a);let{runEvidence:c}=await import(`@tangle-network/agent-runtime/durable`),l=await c(M(Xc,t),{settledChars:4e3,totalChars:48e3}),u=[`from`,`branch`,`failure`,`approved_head`],d=Object.entries(r.params).filter(([e])=>!u.includes(e)).map(([e,t])=>`${e}=${typeof t==`string`?t:JSON.stringify(t)}`),f=JSON.stringify({records:l,graph:a}),p=await tl(s,[...d,`from=diagnose`,`failure=${f}`],i),m=await nl(p,`diagnose`),h={run:t,diagnoseRun:p,verdict:m};if(m.owner!==`graph`||!m.patch)return e(h);let g=M(o,`graph.yaml`);await z(g,a),await z(M(o,`patch.diff`),m.patch),await Jc(`patch -s -p1 -d "$1" -i "$1/patch.diff"`,o);let _=async e=>{let t=await Xl(e,{...i,param:d,dryRun:!0},{...r.trigger&&{trigger:r.trigger}});if(!(`graph`in t))throw Error(`${e} did not load locally`);let{nodes:n,deliverable:a,edges:o}=t.graph,s=e=>o.filter(t=>[`from`in t&&t.from,t.to].flat().includes(e)),c=n.filter(e=>e.check).map(e=>[e.id,e.check,s(e.id)]);return JSON.stringify([a,c])};if(await _(s)!==await _(g))return e({...h,refused:`patch touches a check; not resumed`});let[v,y,b]=await Promise.all([nl(t,`verify`,!1),nl(t,`plan`,!1),nl(t,`intake`)]),{from:x=`intake`,failure:S,approved_head:C}=m.resume??{},w=(...e)=>e.find(e=>typeof e==`string`&&e.trim().length>0),T=w(b.branch,r.params.branch),ee=w(v.test,y.test,r.params.test,b.test),E=w(v.setup,r.params.setup,y.setup,b.setup);if(x!==`intake`&&(!T||!ee))throw Error(`Repair from=${x} requires a retained branch and resolved test command`);let D=[`from=${x}`];x!==`intake`&&D.push(`branch=${T}`),x!==`intake`&&D.push(`test=${ee}`),E&&`setup`in r.params&&D.push(`setup=${E}`),S&&D.push(`failure=${S}`),C&&D.push(`approved_head=${C}`);let O=await tl(g,[...d,...D],i),k={parentRunId:t,sourceDigest:r.sourceDigest,candidateDigest:Q(await L(g)),diagnoseRun:p,resumed:O};await z(M(o,`parent.json`),JSON.stringify(k)),e({...h,patched:g,resumed:O,lineage:k})}function il(t){Cs(t),t.command(`dataset <directory> [runs...]`).description(`Idempotently retain local/cloud attempts in a versioned learning dataset`).option(`--domain <domain>`,`Domain being measured`).option(`--unit <unit>`,`Independent task group; related tasks stay in one split`).option(`--split <split>`,`train, dev or test`).option(`--api-key <key>`,`Platform credential for cloud runs`).option(`--base-url <url>`,`Platform origin for cloud runs`).action(async(t,n,r)=>{if(n.length&&(!r.domain||!r.unit||![`train`,`dev`,`test`].includes(r.split)))throw Error(`Ingestion requires --domain, --unit and --split train|dev|test`);e(n.length?await(await Gc()).ingestGraphDataset(t,n,r):await(await Gc()).readGraphDataset(t))}),t.command(`activate <campaign> <graph>`).description(`Activate the exact promoted graph under a target lock and fresh evidence checks`).action(async(t,n)=>e(await(await Kc()).activateGraph(t,n))),t.command(`observe <campaign> <run>`).description(`Independently grade a subsequent run of an activated graph`).requiredOption(`--unit <unit>`,`Independent production task group, separate from learning cases`).action(async(t,n,r)=>e(await(await Kc()).observeGraph(t,n,r.unit))),t.command(`repair <run>`).description(`Diagnose a failed local graph run; patch and resume it when the graph owns the fix`).option(`--seat-command <program>`,`Executable that prints the account id`).option(`--seat <seat>`,`Repair seat; defaults to the failed run's captured override`).option(`--mcp-policy <file>`,`Trusted host MCP policy; defaults to the failed run's captured policy`).addOption(ws()).action(async(e,t)=>rl(e,{...t,mcpPolicy:t.mcpPolicy?await Es(t.mcpPolicy):void 0}));let n=(e,t)=>[...t,e];t.command(`improve <graph> [dataset]`).description(`Generate and independently compare graph prompt candidates, or replay js-issues arms`).option(`--suite <file>`,`Independent domain evaluator and bounded learning policy`).option(`--campaign <directory>`,`Durable learning campaign (required with --suite)`).option(`--max-tokens <n>`,`Total replay campaign token ceiling across all arms`,Number).option(`--max-iterations <n>`,`Total replay campaign iteration ceiling`,Number).option(`--deadline-ms <n>`,`Total replay campaign wall-clock ceiling in milliseconds`,Number).option(`--arm <graph>`,`Another arm, interleaved; repeatable`,n,[]).option(`--split <split>`,`train, or test (needs --unseal)`,`train`).option(`--unseal <reason>`,`Read the sealed test split, logging why`).option(`--probe <n>`,`Stop after the first n cases`,Number).option(`--reps <n>`,`Reps of every case per arm (default 1)`,Number).option(`--seat <seat>`,`Replay seat; repeatable, one per replay`,n,[]).option(`--docker-host <ssh>`,`Build, verify and grade on this ssh host`).option(`--mcp-policy <file>`,`Trusted host MCP policy; defaults to the retained cohort's matching policy`).addOption(ws()).action(async(t,n,r)=>{if(!r.suite)return el(t,n??M(Yc,`js-issues`),r);if(!n||!r.campaign)throw Error(`Learning requires a retained dataset and --campaign directory`);if(r.arm.length||r.seat.length>1)throw Error(`Learning generates its candidate; use one matched --seat`);e(await(await import(`./graph-learning-CWalyOHM.mjs`)).learnGraph(t,n,r.suite,r.campaign,r.seat[0],{mcpPolicy:r.mcpPolicy?await Es(r.mcpPolicy):void 0,mcpSecret:r.mcpSecret}))})}function al(e){let{prepared:t,conserved:n,campaign:r,live:i,host:a,state:o}=e,{bindings:s,at:c,params:l}=t,{pool:u,checkpoint:d}=n;return async(t,n,{seat:f,signal:p,attempt:m})=>{let{SearchEnvironmentFault:h}=await import(`@tangle-network/agent-runtime`);if(o.incomplete)throw new h(o.incomplete);if(!t.evidence)throw Error(`Benchmark arm has no retained source`);let g=await(await Gc()).readGraphDatasetObject(r,t.evidence);if(Q(g.source)!==t.sourceDigest)throw Error(`Frozen benchmark arm changed`);let _=M(r,`attempts`,`${Q(`${t.digest}:${f??`default`}:${m}`)}.json`);await ft(M(r,`attempts`),{recursive:!0,mode:448});try{await z(_,JSON.stringify({runId:be()}),{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e}let v=I.strictObject({runId:I.uuid()}).parse(JSON.parse(await L(_,`utf8`))),y;try{y=await rc(v.runId)}catch(e){try{throw await L(M(Xc,v.runId,`input.json`)),e}catch(e){if(e.code!==`ENOENT`)throw e}}let b=await e.bench.prepareCaseEnvironment(n,{host:a,signal:p}),x=M(Yc,`remotes`,`${n.id}.git`),S=[...(await L(M(n.payload.taskDir,`environment`,`Dockerfile`),`utf8`)).matchAll(/^\s*WORKDIR\s+(\S+)/gim)].map(e=>e[1]);await Jc(`[ -d "$2/refs" ] && exit; g=$(mktemp -d); trap 'rm -rf "$g"' EXIT
163
+ `;for(let t of[`gh`,`gh-drew`])await z(M(e,`bin`,t),r,{mode:493});let i=`[url "${e}/remotes/"]\n\tinsteadOf = https://github.com/\n[user]\n\tname = graph-improve\n\temail = gi@local\n`;await z(M(e,`bin`,`gitconfig`),i);for(let e of Object.keys(process.env))/(^|_)(GH|GITHUB)\w*_(TOKEN|PAT)$|_PAT$/i.test(e)&&delete process.env[e];Object.assign(process.env,{GITHUB_TOKEN:`replay-placeholder`,GIT_CONFIG_NOSYSTEM:`1`,PATH:`${t}:${process.env.PATH}`,BRIDGE_JAIL_RO_PATHS:t,GIT_CONFIG_GLOBAL:M(t,`gitconfig`),BRIDGE_JAIL_RW_PATHS:n})}async function Qc(t,n,r){let{CostLedger:i,decidePairedPromotion:a,runCampaign:o,wilson:s}=await import(`@tangle-network/agent-eval`),c=await import(`@tangle-network/agent-eval/benchmarks`),{durableRunToolSpans:l,readSettleRecord:u}=await import(`@tangle-network/agent-runtime/durable`),{acquireSingleRunLock:d}=await import(`@tangle-network/agent-eval/campaign`),f=await Hc(t,n,r,c),{bindings:p,files:m,sealed:h,manifest:g,tasks:_,at:v,split:y,arms:b}=f,x={},S,C=r.dockerHost;C&&(process.env.DOCKER_HOST=`ssh://${C}`);let w=c.createHarborBenchmarkAdapter({id:`graph-improve-js`,datasetDir:n,assignSplit:y,tasks:_,source:{name:`js-issues`,revision:Q(g).slice(0,12)},grade:c.gradeHarborPatch({jobsDir:M(qc,`jobs`)})}),T=new AbortController,ee=await c.benchmarkScenarios(w,[h]),E=new Set(ee.slice(0,r.probe).map(e=>e.id)),D=r.reps??1;if(!Number.isSafeInteger(D)||D<1||r.probe!==void 0&&(!Number.isSafeInteger(r.probe)||r.probe<1))throw Error(`--reps and --probe must be positive integers`);let O={maxTokens:r.maxTokens??b.reduce((e,t)=>e+t.cap,0)*ee.length*D,maxIterations:r.maxIterations??b.reduce((e,t)=>e+t.iterations,0)*ee.length*D,deadlineMs:r.deadlineMs??b.reduce((e,t)=>e+t.deadline,0)*ee.length*D},k=Q(JSON.stringify({dataset:Q(g),sealed:h,arms:b.map(e=>({graph:e.digest,source:e.sourceDigest})),mcpPolicy:p.mcpPolicy??null,seats:r.seat,reps:D})),A=he(r.campaign??M(qc,`campaigns`,k));await ft(A,{recursive:!0,mode:448}),S=M(A,`environment`);let{release:te}=d({lockPath:`${await R(A)}.lock`});try{await Zc(S);for(let[e,t]of b.entries()){t.evidence=await(await Uc()).graphDatasetObject(A,{kind:`graph-arm-source`,source:t.source,sourceDigest:t.sourceDigest});let n=M(A,`arm-${e}.json`),r=JSON.stringify({evidence:t.evidence});try{await z(n,r,{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e;if(await L(n,`utf8`)!==r)throw Error(`Benchmark arm source changed; use a new campaign`)}}let t=await(await import(`./graph-campaign-state-YA-eORZN.mjs`)).openGraphCampaignBudget(A,O,Q(JSON.stringify({identity:k,ceilings:O}))),{pool:n}=t,d=rl({prepared:f,bench:c,conserved:t,campaign:A,live:S,host:C,stop:T,state:x,durableRunToolSpans:l,readSettleRecord:u}),p=AbortSignal.any([T.signal,AbortSignal.timeout(Math.max(1,t.startedAt+O.deadlineMs-Date.now()))]),g=new i({costCeilingUsd:0}),_=[...Array(D).keys()],y=[...E].flatMap(e=>_.flatMap(t=>b.map((n,r)=>`${r}|${e}:${t}`))),te=new Map,ne=new Map(y.map(e=>[e,new Promise(t=>te.set(e,t))])),re=new Map([...E].map(e=>[e,D*b.length]));p.addEventListener(`abort`,()=>{x.incomplete??=`Campaign deadline or cancellation interrupted matched comparison`;for(let e of te.values())e()},{once:!0});let ie=b.map(async(e,n)=>{let i=`${e.digest}:${r.seat.join(`,`)}`,a=M(A,`arms`,`${n}`);if(h===`holdout`){await ft(a,{recursive:!0});let e={at:new Date,reason:r.unseal,arms:m};await z(M(a,`holdout-access.jsonl`),`${JSON.stringify(e)}\n`,{flag:`a`})}return o({scenarios:ee,reps:D,runDir:a,resumable:!0,dispatchRef:i,costLedger:g,costCeiling:0,cellFilter:e=>E.has(e.scenario.id),judges:[c.benchmarkJudge(w)],maxConcurrency:3,signal:p,dispatchTimeoutMs:Math.max(1,t.startedAt+O.deadlineMs-Date.now()),onCellSettled:async(e,{id:t,item:r})=>{e.cached&&te.get(`${n}|${e.cellId}`)?.(),re.set(t,(re.get(t)??1)-1),re.get(t)||await c.releaseCaseEnvironment(r,{host:C})},dispatch:async(t,i)=>{let a=y.indexOf(`${n}|${i.cellId}`),o=r.seat[Math.floor(a/b.length)%r.seat.length],s=o??`graph-default`;try{await Promise.all(y.slice(0,a).map(e=>ne.get(e)));let r=await i.cost.runPaidCall({actor:e.file,model:s,signal:i.signal,maximumCharge:{externallyEnforcedMaximumUsd:0},execute:r=>d(e,t.item,{seat:o,signal:r,attempt:`${n}:${i.cellId}`}),receipt:({tokens:e})=>({model:s,...e,actualCostUsd:0}),receiptFromError:()=>({model:s,...Yc(e.cap),actualCostUsd:0})});if(!r.succeeded)throw r.error;return r.value}finally{te.get(`${n}|${i.cellId}`)?.()}}})}),ae=await Promise.allSettled(ie.map(e=>e.catch(e=>{throw T.abort(e),e})));if(T.signal.aborted)throw T.signal.reason;let{reports:oe,paired:se}=il({campaigns:ae.map(e=>{if(e.status===`rejected`)throw e.reason;return e.value}),files:m,probe:E,reps:D,repList:_,at:v,state:x,wilson:s,decidePairedPromotion:a}),j={split:r.split,arms:oe,paired:se,incomplete:x.incomplete??(oe.some(e=>!e.usageComplete||e.unmeasured.length)?`Campaign evidence is incomplete`:null),campaign:A,campaignBudget:{limits:O,readout:n.readout()},operatingCost:{known:!1,reason:`subscription and environment allocation are not incrementally metered`}};await z(M(A,`result.json`),JSON.stringify(j),{mode:384,flush:!0}),e(j)}finally{await te()}}async function $c(e,t,n){try{let{trigger:r,...i}=n,a=await Jl(e,{param:t,json:!0,...i},{...r&&{trigger:r}});return`runId`in a?a.runId:void 0}catch(e){if(e.code!==`GRAPH_RUN_FAILED`)throw e;return e.runId}}const el=async(e,t,n=!0)=>{if(!e)throw Error(`The diagnosis has no retained run identity`);let{readSettleRecord:r}=await import(`@tangle-network/agent-runtime/durable`),{FileResultBlobStore:i}=await import(`@tangle-network/agent-runtime/kernel`),a=M(Jc,e),o=(await r(a))?.tree.nodes.filter(e=>e.label===t&&e.outRef).at(-1);if(!o?.outRef&&!n)return{};if(!o?.outRef)throw Error(`The retained ${t} result is unavailable`);let s=await new i(M(a,`blobs`)).get(o.outRef);if(!s||typeof s!=`object`||Array.isArray(s))throw Error(`The retained ${t} result is not an object`);let c=`json`in s?s.json:s;if(!c||typeof c!=`object`||Array.isArray(c))throw Error(`The retained ${t} structured result is unavailable`);return c};async function tl(t,n){let r=await tc(t),i={...n,seat:n.seat??r.seat,mcpPolicy:n.mcpPolicy??r.mcpPolicy,trigger:r.trigger},a=await ic(r),o=M(qc,`repairs`,t);await ft(o,{recursive:!0});let s=M(o,`original.graph.yaml`);await z(s,a);let{runEvidence:c}=await import(`@tangle-network/agent-runtime/durable`),l=await c(M(Jc,t),{settledChars:4e3,totalChars:48e3}),u=[`from`,`branch`,`failure`,`approved_head`],d=Object.entries(r.params).filter(([e])=>!u.includes(e)).map(([e,t])=>`${e}=${typeof t==`string`?t:JSON.stringify(t)}`),f=JSON.stringify({records:l,graph:a}),p=await $c(s,[...d,`from=diagnose`,`failure=${f}`],i),m=await el(p,`diagnose`),h={run:t,diagnoseRun:p,verdict:m};if(m.owner!==`graph`||!m.patch)return e(h);let g=M(o,`graph.yaml`);await z(g,a),await z(M(o,`patch.diff`),m.patch),await Kc(`patch -s -p1 -d "$1" -i "$1/patch.diff"`,o);let _=async e=>{let t=await Jl(e,{...i,param:d,dryRun:!0},{...r.trigger&&{trigger:r.trigger}});if(!(`graph`in t))throw Error(`${e} did not load locally`);let{nodes:n,deliverable:a,edges:o}=t.graph,s=e=>o.filter(t=>[`from`in t&&t.from,t.to].flat().includes(e)),c=n.filter(e=>e.check).map(e=>[e.id,e.check,s(e.id)]);return JSON.stringify([a,c])};if(await _(s)!==await _(g))return e({...h,refused:`patch touches a check; not resumed`});let[v,y,b]=await Promise.all([el(t,`verify`,!1),el(t,`plan`,!1),el(t,`intake`)]),{from:x=`intake`,failure:S,approved_head:C}=m.resume??{},w=(...e)=>e.find(e=>typeof e==`string`&&e.trim().length>0),T=w(b.branch,r.params.branch),ee=w(v.test,y.test,r.params.test,b.test),E=w(v.setup,r.params.setup,y.setup,b.setup);if(x!==`intake`&&(!T||!ee))throw Error(`Repair from=${x} requires a retained branch and resolved test command`);let D=[`from=${x}`];x!==`intake`&&D.push(`branch=${T}`),x!==`intake`&&D.push(`test=${ee}`),E&&`setup`in r.params&&D.push(`setup=${E}`),S&&D.push(`failure=${S}`),C&&D.push(`approved_head=${C}`);let O=await $c(g,[...d,...D],i),k={parentRunId:t,sourceDigest:r.sourceDigest,candidateDigest:Q(await L(g)),diagnoseRun:p,resumed:O};await z(M(o,`parent.json`),JSON.stringify(k)),e({...h,patched:g,resumed:O,lineage:k})}function nl(t){xs(t),t.command(`dataset <directory> [runs...]`).description(`Idempotently retain local/cloud attempts in a versioned learning dataset`).option(`--domain <domain>`,`Domain being measured`).option(`--unit <unit>`,`Independent task group; related tasks stay in one split`).option(`--split <split>`,`train, dev or test`).option(`--api-key <key>`,`Platform credential for cloud runs`).option(`--base-url <url>`,`Platform origin for cloud runs`).action(async(t,n,r)=>{if(n.length&&(!r.domain||!r.unit||![`train`,`dev`,`test`].includes(r.split)))throw Error(`Ingestion requires --domain, --unit and --split train|dev|test`);e(n.length?await(await Uc()).ingestGraphDataset(t,n,r):await(await Uc()).readGraphDataset(t))}),t.command(`activate <campaign> <graph>`).description(`Activate the exact promoted graph under a target lock and fresh evidence checks`).action(async(t,n)=>e(await(await Wc()).activateGraph(t,n))),t.command(`observe <campaign> <run>`).description(`Independently grade a subsequent run of an activated graph`).requiredOption(`--unit <unit>`,`Independent production task group, separate from learning cases`).action(async(t,n,r)=>e(await(await Wc()).observeGraph(t,n,r.unit))),t.command(`repair <run>`).description(`Diagnose a failed local graph run; patch and resume it when the graph owns the fix`).option(`--seat-command <program>`,`Executable that prints the account id`).option(`--seat <seat>`,`Repair seat; defaults to the failed run's captured override`).option(`--mcp-policy <file>`,`Trusted host MCP policy; defaults to the failed run's captured policy`).addOption(Ss()).action(async(e,t)=>tl(e,{...t,mcpPolicy:t.mcpPolicy?await ws(t.mcpPolicy):void 0}));let n=(e,t)=>[...t,e];t.command(`improve <graph> [dataset]`).description(`Generate and independently compare graph prompt candidates, or replay js-issues arms`).option(`--suite <file>`,`Independent domain evaluator and bounded learning policy`).option(`--campaign <directory>`,`Durable learning campaign (required with --suite)`).option(`--max-tokens <n>`,`Total replay campaign token ceiling across all arms`,Number).option(`--max-iterations <n>`,`Total replay campaign iteration ceiling`,Number).option(`--deadline-ms <n>`,`Total replay campaign wall-clock ceiling in milliseconds`,Number).option(`--arm <graph>`,`Another arm, interleaved; repeatable`,n,[]).option(`--split <split>`,`train, or test (needs --unseal)`,`train`).option(`--unseal <reason>`,`Read the sealed test split, logging why`).option(`--probe <n>`,`Stop after the first n cases`,Number).option(`--reps <n>`,`Reps of every case per arm (default 1)`,Number).option(`--seat <seat>`,`Replay seat; repeatable, one per replay`,n,[]).option(`--docker-host <ssh>`,`Build, verify and grade on this ssh host`).option(`--mcp-policy <file>`,`Trusted host MCP policy; defaults to the retained cohort's matching policy`).addOption(Ss()).action(async(t,n,r)=>{if(!r.suite)return Qc(t,n??M(qc,`js-issues`),r);if(!n||!r.campaign)throw Error(`Learning requires a retained dataset and --campaign directory`);if(r.arm.length||r.seat.length>1)throw Error(`Learning generates its candidate; use one matched --seat`);e(await(await import(`./graph-learning-CWalyOHM.mjs`)).learnGraph(t,n,r.suite,r.campaign,r.seat[0],{mcpPolicy:r.mcpPolicy?await ws(r.mcpPolicy):void 0,mcpSecret:r.mcpSecret}))})}function rl(e){let{prepared:t,conserved:n,campaign:r,live:i,host:a,state:o}=e,{bindings:s,at:c,params:l}=t,{pool:u,checkpoint:d}=n;return async(t,n,{seat:f,signal:p,attempt:m})=>{let{SearchEnvironmentFault:h}=await import(`@tangle-network/agent-runtime`);if(o.incomplete)throw new h(o.incomplete);if(!t.evidence)throw Error(`Benchmark arm has no retained source`);let g=await(await Uc()).readGraphDatasetObject(r,t.evidence);if(Q(g.source)!==t.sourceDigest)throw Error(`Frozen benchmark arm changed`);let _=M(r,`attempts`,`${Q(`${t.digest}:${f??`default`}:${m}`)}.json`);await ft(M(r,`attempts`),{recursive:!0,mode:448});try{await z(_,JSON.stringify({runId:be()}),{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e}let v=I.strictObject({runId:I.uuid()}).parse(JSON.parse(await L(_,`utf8`))),y;try{y=await tc(v.runId)}catch(e){try{throw await L(M(Jc,v.runId,`input.json`)),e}catch(e){if(e.code!==`ENOENT`)throw e}}let b=await e.bench.prepareCaseEnvironment(n,{host:a,signal:p}),x=M(qc,`remotes`,`${n.id}.git`),S=[...(await L(M(n.payload.taskDir,`environment`,`Dockerfile`),`utf8`)).matchAll(/^\s*WORKDIR\s+(\S+)/gim)].map(e=>e[1]);await Kc(`[ -d "$2/refs" ] && exit; g=$(mktemp -d); trap 'rm -rf "$g"' EXIT
164
164
  docker run --rm --network none "$1" tar -C "$3/.git" -c . | tar -x -C "$g"
165
165
  c=$(git -c user.name=graph-improve -c user.email=gi@local --git-dir "$g" commit-tree 'HEAD^{tree}' -m Base)
166
166
  git init -q --bare -b main "$2.partial" && git --git-dir "$g" push -q "$2.partial" "$c:refs/heads/main"
167
- mv "$2.partial" "$2"`,b,x,S.length?pe.resolve(`/`,...S):`/app`);let C=c(n.id),w=M(i,`remotes`,`${C.upstream}.git`),{issueTitle:T,issueBodyClean:ee}=C,E=`https://github.com/${C.upstream}/issues/${C.issue}`,D=JSON.stringify({title:T,body:ee,url:E,state:`OPEN`}),O=v.runId,k;{y||await Jc(`rm -rf "$2" && git clone -q --bare "$1" "$2" && printf %s "$4" > "$2/tangle-issue-$3.json"`,x,w,`${C.issue}`,D);try{let e=l(C,b),n={...s,param:e,json:!0,...f&&{seat:f},...y&&{resume:v.runId}},r=await Xl(t.file,{...n,dryRun:!0},{signal:p,source:g.source,...y&&{cwd:y.cwd}});if(!(`graph`in r))throw Error(`Replay did not load locally`);if(!r.graph.budget)throw Error(`Replay has no runtime budget`);try{await d({runId:v.runId,budget:r.graph.budget,sourceDigest:t.sourceDigest,graphDigest:r.graph.digest})}catch(e){throw o.incomplete=e.message,e}let i;try{i=await Xl(t.file,n,{signal:p,source:g.source,runId:v.runId,graphDigest:r.graph.digest,...y&&{cwd:y.cwd}})}finally{await d()}O=`runId`in i?i.runId:void 0;let a=JSON.parse(`text`in i?i.text:`{}`);k=Object.values(a).find(e=>e?.json?.branch)?.json?.branch??null}catch(e){let t=e;if(t.code!==`GRAPH_RUN_FAILED`)throw e;O=t.runId;let r=u.readout();if(!r.tokensKnown||r.tokensLeft<0||r.iterationsLeft<0||r.deadlineMs>0&&Date.now()>=r.deadlineMs)throw o.incomplete=`Shared campaign budget exhausted or its accounting is incomplete`,new h(o.incomplete,{cause:e});if(e.runtimeFailures?.some(({failure:e})=>Qc(e)))throw new h(n.id,{cause:e})}let r=M(F(),`.tangle`,`runs`,`${O}`),i=(await e.durableRunToolSpans(r)).map(e=>e.toolName).find(e=>/web.?(search|fetch)/i.test(e));if(i&&e.stop.abort(Error(`${O} called ${i}: not offline`)),e.stop.signal.throwIfAborted(),k===null)throw Error(`no node output names a branch`);let a=k?await Jc(`b=$(git --git-dir "$1" rev-parse main); git --git-dir "$2" diff --binary "$b" "$3"`,x,w,k):``,c=await e.readSettleRecord(r),m=c&&Ns(c).tokenUsage,_=u.readout();if(!_.tokensKnown||_.tokensLeft<0||_.iterationsLeft<0||_.deadlineMs>0&&Date.now()>=_.deadlineMs)throw o.incomplete=`Shared campaign budget exhausted or its accounting is incomplete`,new h(o.incomplete);return{patch:a,tokens:m?.input!=null&&m.output!=null?{inputTokens:m.input??0,outputTokens:m.output??0}:Zc(t.cap),...O&&{runId:O}}}}}function ol(e){let{campaigns:t,files:n,probe:r,reps:i,repList:a,at:o,state:s,wilson:c,decidePairedPromotion:l}=e,u=e=>e.reduce((e,t)=>e+t,0)/e.length,d=t.map((e,t)=>{let r=e.cells.filter(e=>!e.error),i=e=>Object.values(e.judgeScores)[0]?.composite??0,a=r.filter(e=>e.rep===0),o=a.filter(e=>i(e)>=1).length,s=e.cells.filter(e=>e.error),{inputTokens:l,outputTokens:u,usageComplete:d}=e.aggregates.cost;return{graph:n[t],resolved:o,n:a.length,runDir:e.runDir,wilson95:c(o,a.length),unmeasured:s.map(e=>`${e.cellId}: ${e.error}`),tokens:l+u,usageComplete:d,rewards:Object.fromEntries(r.map(e=>[e.cellId,i(e)]))}}),f=({rewards:e},t)=>a.flatMap(n=>e[`${t}:${n}`]??[]),[p,...m]=d;return{reports:d,paired:m.map((e,t)=>{let a=[...r].filter(t=>f(p,t).length&&f(e,t).length),c=[...new Set(a.map(e=>o(e).upstream))],d=c.map(e=>a.filter(t=>o(t).upstream===e)),m=e=>d.map(t=>u(t.map(t=>u(f(e,t))))),[h,g]=[m(p),m(e)];if(!(!s.incomplete&&p.usageComplete&&e.usageComplete&&a.length===r.size&&a.every(t=>f(p,t).length===i&&f(e,t).length===i)))return{arm:n[t+1],cases:a.length,repos:c.length,decision:`hold`,why:s.incomplete??`Campaign evidence is incomplete`,sufficient:!1,rates:[h.length?u(h):null,g.length?u(g):null],delta:null,interval95:null,method:null};let _=l(h,g,{continuous:!0}),{n:v,minimumPairs:y,low:b,threshold:x}=_,S=_.promote?void 0:!_.sufficient&&`insufficient pairs: n ${v} < minimumPairs ${y}`||b<=x&&`interval low ${b} ≤ threshold ${x}`||_.exactTestVetoes&&`McNemar exact test vetoes`||`indeterminate interval`;return{arm:n[t+1],cases:a.length,repos:c.length,rates:[u(h),u(g)],delta:_.delta,method:_.method,interval95:[_.low,_.high],sufficient:_.sufficient,decision:_.promote?`promote`:`hold`,why:S}})}}const sl=1e5;function Z(e){throw new B(`GRAPH_INVALID`,`Graph creation failed`,e,`tangle graph new --help`)}function cl(e){return typeof e==`string`&&/^[a-z0-9][a-z0-9-]{0,62}$/i.test(e)}const ll={maxBarren:2,failures:`verbatim`,panel:`off`,bar:`on`,profile:{id:`graph-new-v1`,opening:`The graph has not passed its outside check.`,plan:`Repair the concrete diagnostics with write_graph, run the saved file and submit the actual evidence.`,rules:`Completion requires a successful host run and unchanged YAML. Retain working graph content when blocked.`,headings:{failures:`Failures`,protected:`Passing checks`,changed:`Changes`,findings:`Findings`,bar:`Acceptance`,plan:`Next`,rules:`Rules`}}};var ul=class{owned;lastFailure;pending=Promise.resolve();revision=0;sealed=!1;constructor(e,t,n){this.directory=e,this.options=t,this.cwd=n}async digest(e=this.owned){e||Z(`No graph file was saved`);let t=await mt(e.file,Ne.O_RDONLY|Ne.O_NOFOLLOW);try{let[n,r]=await Promise.all([t.stat(),e.handle.stat()]);return(!n.isFile()||n.dev!==r.dev||n.ino!==r.ino)&&Z(`The owned graph file was replaced`),Q(await t.readFile())}finally{await t.close()}}enqueue(e){let t=++this.revision,n=this.pending.then(()=>e(t));return this.pending=n.then(()=>void 0,()=>void 0),n}check=()=>this.enqueue(async e=>{let t=this.owned;if(!t?.result)return!1;let{digest:n,result:r}=t,i=await this.digest(t),a=this.revision===e&&this.owned===t&&t.digest===n&&t.result===r&&i===n;return a&&(this.sealed=!0),a});receipt(){this.owned?.result||Z(`No successful graph run was recorded`);let{file:e,digest:t,result:n}=this.owned;return{file:e,digest:t,result:n}}invoke(e,t){return this.sealed&&Z(`The graph is accepted; submit its recorded successful run`),this.enqueue(()=>this.write(e,t)).catch(e=>(this.lastFailure=e,{ok:!1,diagnostic:Lt(e)}))}async write(e,t){t.throwIfAborted(),this.lastFailure=void 0;let n=e;(!n||!cl(n.name)||typeof n.source!=`string`||typeof n.run!=`boolean`||Object.keys(n).some(e=>![`name`,`source`,`run`].includes(e)))&&Z(`Expected only name, source and boolean run`),this.options.name!==void 0&&n.name!==this.options.name&&Z(`The graph name must match --name`),this.owned&&(this.owned.result=void 0);let r=M(this.directory,`${n.name}.yaml`);if(this.owned&&this.owned.file!==r&&Z(`This invocation owns one named graph file`),!this.owned)try{this.owned={file:r,handle:await mt(r,Ne.O_RDWR|Ne.O_CREAT|Ne.O_EXCL|Ne.O_NOFOLLOW,384),digest:Q(``)}}catch(e){throw e.code===`EEXIST`&&Z(`Graph already exists: ${r}; choose another --name`),e}let i=this.owned;await this.digest()!==i.digest&&Z(`The owned graph was changed`);let a=Buffer.from(n.source);for(let e=0;e<a.length;){let{bytesWritten:t}=await i.handle.write(a,e,a.length-e,e);if(!t)throw Error(`Graph file write made no progress`);e+=t}await i.handle.truncate(a.length),await i.handle.sync(),i.digest=Q(a);let o={...this.options,param:[]},s={cwd:this.cwd,signal:t,source:n.source},c=await Xl(r,{...o,dryRun:!0},{...s,connectNeeds:!0});`graph`in c||Z(`No canonical graph was returned`),c.graph.deliverable.checkRef===`command`&&Z(`Host command checks need a jailed verifier node`);let{nodes:l,edges:u,budget:d}=c.graph,f=u.reduce((e,t)=>e+(`maxTraversals`in t?(t.maxTraversals??1)-1:0),l.length),p=(f+1)*sl;if(d?.maxTokens!==void 0&&d.maxTokens<p&&Z(`budget.maxTokens ${d.maxTokens} is below ${p}: ${f} agent spawns plus one reservation at ${sl} tokens per native turn`),await this.digest()!==i.digest&&Z(`Graph changed during validation`),!n.run)return{file:r,graphDigest:c.graph.digest,validated:!0};let m=await Xl(r,o,{...s,graphDigest:c.graph.digest});return(!(`status`in m)||m.status!==`winner`||m.graphDigest!==c.graph.digest||await this.digest()!==i.digest)&&Z(`The graph must succeed with unchanged YAML`),i.result=m,this.receipt()}async close(){await this.pending,await this.owned?.handle.close()}};async function dl(e,t,n){let{runId:r,runDir:i,cwd:a,bridge:o,signal:s}=e,c=await o(),l=M(await R(M(F(),`.tangle`)),`graphs`);(Rs(a,l)||Rs(l,a))&&Z(`The graph store must be outside the agent workspace; choose another working directory`);try{await ft(l,{mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}await R(l)!==l&&Z(`The graph store redirects outside its canonical location`);let u=n.seat??en().seat,d=await uc(a,s)(u,{node:`graph-designer`,cwd:a,signal:s,lastCandidate:!0});d||Z(`No authenticated native subscription is available`);let{graphDesignerProfile:f}=await import(`@tangle-network/agent-runtime/profiles`),{supervisePursuit:p}=await import(`@tangle-network/agent-runtime/durable`),m=f({profile:{name:`graph-designer`,harness:d.harness,model:{provider:d.provider,default:d.model,...d.reasoningEffort===void 0?{}:{reasoningEffort:d.reasoningEffort}},prompt:{instructions:[`You are the sole graph designer. Author a canonical YAML graph for the requested intent, then qualify and run it using write_graph. Its nodes are complete AgentProfiles with a real independent verifier and declarative route/data outside check. Command checks execute on the host and are refused here; put executable verification in the verifier node's normal native tools. Read the supplied skills and preserve the user's task and authority.`,`Call write_graph with name, complete YAML source and run:false to validate; repair its concrete diagnostics, then call it with the identical source and run:true. The graph schema and executor are owned by the installed loader. Supply defaults for parameters needed by the first run. Only a real successful host run of the unchanged saved file passes. Submit that evidence using submit_result; explain concrete blockers using report_blocked.`]},tools:{agent_runtime_coordination_write_graph:!0,agent_runtime_coordination_submit_result:!0,agent_runtime_coordination_read_continuation:!0,agent_runtime_coordination_report_blocked:!0}}}),h=De(m),g=new ul(l,{...n,seat:u},a),_={maxIterations:6,maxTokens:2e6,deadlineMs:9e5};try{let e=await p(m,{intent:t,name:n.name},{pursuitId:r,runId:r,runDir:i,signal:s,backend:{...c,timeoutMs:_.deadlineMs},budget:_,maxDepth:0,coordination:{authentication:!0,requestTimeoutMs:_.deadlineMs},deliverable:{describe:`The saved graph succeeds with unchanged YAML`,check:g.check,checkState:g.check},continuation:ll,resolveSupervisorTools:e=>e.runId!==r||e.nodeId!==r||e.depth!==0||e.identity.profileDigest!==h?[]:[{name:`write_graph`,description:`Save, validate and run this graph.`,inputSchema:{type:`object`,properties:{name:{type:`string`},source:{type:`string`},run:{type:`boolean`}},required:[`name`,`source`,`run`],additionalProperties:!1},handler:(t,n)=>((n.nodeId!==e.nodeId||n.ownerId!==e.ownerId||n.runId!==e.runId)&&Z(`Wrong graph tool owner`),g.invoke(t,n.signal))}]});if(e.result.kind===`no-winner`||!await g.check()){if(g.lastFailure)throw g.lastFailure;let t=e.result.kind===`no-winner`?e.result.error?.message??e.result.reason:`The graph file changed after its successful run`;throw Object.assign(new B(`GRAPH_DESIGN_FAILED`,`Graph design did not finish`,t,`tangle graph new --help`),{runId:r,node:`graph-designer`})}return g.receipt()}finally{await g.close()}}function fl(t){t.command(`new <intent>`).description(`Design, validate and run one portable graph`).option(`--seat <seat>`,`Use harness/model@effort for the designer and graph`).option(`--name <name>`,`Save this graph name`).action(async(t,n)=>{process.env.BRIDGE_JAIL_RW_PATHS?.trim()&&Z(`Remove BRIDGE_JAIL_RW_PATHS before graph new; extra native write roots cannot contain its host store`),n.name!==void 0&&!cl(n.name)&&Z(`Use letters, numbers and hyphens in --name`);let r=await Jl({},e=>dl(e,t,n));n.json?e(r):l(`Created ${r.file} · run ${r.result.runId}`)})}const pl={start:[`▶`,j.green],agent:[`●`,j.cyan.bold],check:[`▣`,j.yellow.bold],gate:[`◇`,j.magenta.bold],finish:[`✓`,j.green.bold],stop:[`■`,j.red.bold]};function ml(e){let t=t=>e.nodes.find(e=>e.id===t)?.kind??`agent`,n=e=>{let[n,r]=pl[t(e)];return r(`${n} ${e.replace(/^(finish|stop):/,``)}`)},r=Math.max(...e.nodes.map(e=>e.id.length))+4,i=[`${j.bold(`◆ ${e.name}`)}`,...e.describe?[` ${e.describe}`]:[],``];for(let[t,n]of e.facts)i.push(` ${j.dim(t.padEnd(10))} ${n}`);i.push(``,j.bold(`NODES`));for(let t of e.nodes.filter(e=>[`agent`,`check`,`gate`].includes(e.kind))){let[e,...a]=t.detail.split(`
167
+ mv "$2.partial" "$2"`,b,x,S.length?pe.resolve(`/`,...S):`/app`);let C=c(n.id),w=M(i,`remotes`,`${C.upstream}.git`),{issueTitle:T,issueBodyClean:ee}=C,E=`https://github.com/${C.upstream}/issues/${C.issue}`,D=JSON.stringify({title:T,body:ee,url:E,state:`OPEN`}),O=v.runId,k;{y||await Kc(`rm -rf "$2" && git clone -q --bare "$1" "$2" && printf %s "$4" > "$2/tangle-issue-$3.json"`,x,w,`${C.issue}`,D);try{let e=l(C,b),n={...s,param:e,json:!0,...f&&{seat:f},...y&&{resume:v.runId}},r=await Jl(t.file,{...n,dryRun:!0},{signal:p,source:g.source,...y&&{cwd:y.cwd}});if(!(`graph`in r))throw Error(`Replay did not load locally`);if(!r.graph.budget)throw Error(`Replay has no runtime budget`);try{await d({runId:v.runId,budget:r.graph.budget,sourceDigest:t.sourceDigest,graphDigest:r.graph.digest})}catch(e){throw o.incomplete=e.message,e}let i;try{i=await Jl(t.file,n,{signal:p,source:g.source,runId:v.runId,graphDigest:r.graph.digest,...y&&{cwd:y.cwd}})}finally{await d()}O=`runId`in i?i.runId:void 0;let a=JSON.parse(`text`in i?i.text:`{}`);k=Object.values(a).find(e=>e?.json?.branch)?.json?.branch??null}catch(e){let t=e;if(t.code!==`GRAPH_RUN_FAILED`)throw e;O=t.runId;let r=u.readout();if(!r.tokensKnown||r.tokensLeft<0||r.iterationsLeft<0||r.deadlineMs>0&&Date.now()>=r.deadlineMs)throw o.incomplete=`Shared campaign budget exhausted or its accounting is incomplete`,new h(o.incomplete,{cause:e});if(e.runtimeFailures?.some(({failure:e})=>Xc(e)))throw new h(n.id,{cause:e})}let r=M(F(),`.tangle`,`runs`,`${O}`),i=(await e.durableRunToolSpans(r)).map(e=>e.toolName).find(e=>/web.?(search|fetch)/i.test(e));if(i&&e.stop.abort(Error(`${O} called ${i}: not offline`)),e.stop.signal.throwIfAborted(),k===null)throw Error(`no node output names a branch`);let a=k?await Kc(`b=$(git --git-dir "$1" rev-parse main); git --git-dir "$2" diff --binary "$b" "$3"`,x,w,k):``,c=await e.readSettleRecord(r),m=c&&js(c).tokenUsage,_=u.readout();if(!_.tokensKnown||_.tokensLeft<0||_.iterationsLeft<0||_.deadlineMs>0&&Date.now()>=_.deadlineMs)throw o.incomplete=`Shared campaign budget exhausted or its accounting is incomplete`,new h(o.incomplete);return{patch:a,tokens:m?.input!=null&&m.output!=null?{inputTokens:m.input??0,outputTokens:m.output??0}:Yc(t.cap),...O&&{runId:O}}}}}function il(e){let{campaigns:t,files:n,probe:r,reps:i,repList:a,at:o,state:s,wilson:c,decidePairedPromotion:l}=e,u=e=>e.reduce((e,t)=>e+t,0)/e.length,d=t.map((e,t)=>{let r=e.cells.filter(e=>!e.error),i=e=>Object.values(e.judgeScores)[0]?.composite??0,a=r.filter(e=>e.rep===0),o=a.filter(e=>i(e)>=1).length,s=e.cells.filter(e=>e.error),{inputTokens:l,outputTokens:u,usageComplete:d}=e.aggregates.cost;return{graph:n[t],resolved:o,n:a.length,runDir:e.runDir,wilson95:c(o,a.length),unmeasured:s.map(e=>`${e.cellId}: ${e.error}`),tokens:l+u,usageComplete:d,rewards:Object.fromEntries(r.map(e=>[e.cellId,i(e)]))}}),f=({rewards:e},t)=>a.flatMap(n=>e[`${t}:${n}`]??[]),[p,...m]=d;return{reports:d,paired:m.map((e,t)=>{let a=[...r].filter(t=>f(p,t).length&&f(e,t).length),c=[...new Set(a.map(e=>o(e).upstream))],d=c.map(e=>a.filter(t=>o(t).upstream===e)),m=e=>d.map(t=>u(t.map(t=>u(f(e,t))))),[h,g]=[m(p),m(e)];if(!(!s.incomplete&&p.usageComplete&&e.usageComplete&&a.length===r.size&&a.every(t=>f(p,t).length===i&&f(e,t).length===i)))return{arm:n[t+1],cases:a.length,repos:c.length,decision:`hold`,why:s.incomplete??`Campaign evidence is incomplete`,sufficient:!1,rates:[h.length?u(h):null,g.length?u(g):null],delta:null,interval95:null,method:null};let _=l(h,g,{continuous:!0}),{n:v,minimumPairs:y,low:b,threshold:x}=_,S=_.promote?void 0:!_.sufficient&&`insufficient pairs: n ${v} < minimumPairs ${y}`||b<=x&&`interval low ${b} ≤ threshold ${x}`||_.exactTestVetoes&&`McNemar exact test vetoes`||`indeterminate interval`;return{arm:n[t+1],cases:a.length,repos:c.length,rates:[u(h),u(g)],delta:_.delta,method:_.method,interval95:[_.low,_.high],sufficient:_.sufficient,decision:_.promote?`promote`:`hold`,why:S}})}}const al=1e5;function Z(e){throw new B(`GRAPH_INVALID`,`Graph creation failed`,e,`tangle graph new --help`)}function ol(e){return typeof e==`string`&&/^[a-z0-9][a-z0-9-]{0,62}$/i.test(e)}const sl={maxBarren:2,failures:`verbatim`,panel:`off`,bar:`on`,profile:{id:`graph-new-v1`,opening:`The graph has not passed its outside check.`,plan:`Repair the concrete diagnostics with write_graph, run the saved file and submit the actual evidence.`,rules:`Completion requires a successful host run and unchanged YAML. Retain working graph content when blocked.`,headings:{failures:`Failures`,protected:`Passing checks`,changed:`Changes`,findings:`Findings`,bar:`Acceptance`,plan:`Next`,rules:`Rules`}}};var cl=class{owned;lastFailure;pending=Promise.resolve();revision=0;sealed=!1;constructor(e,t,n){this.directory=e,this.options=t,this.cwd=n}async digest(e=this.owned){e||Z(`No graph file was saved`);let t=await mt(e.file,Ne.O_RDONLY|Ne.O_NOFOLLOW);try{let[n,r]=await Promise.all([t.stat(),e.handle.stat()]);return(!n.isFile()||n.dev!==r.dev||n.ino!==r.ino)&&Z(`The owned graph file was replaced`),Q(await t.readFile())}finally{await t.close()}}enqueue(e){let t=++this.revision,n=this.pending.then(()=>e(t));return this.pending=n.then(()=>void 0,()=>void 0),n}check=()=>this.enqueue(async e=>{let t=this.owned;if(!t?.result)return!1;let{digest:n,result:r}=t,i=await this.digest(t),a=this.revision===e&&this.owned===t&&t.digest===n&&t.result===r&&i===n;return a&&(this.sealed=!0),a});receipt(){this.owned?.result||Z(`No successful graph run was recorded`);let{file:e,digest:t,result:n}=this.owned;return{file:e,digest:t,result:n}}invoke(e,t){return this.sealed&&Z(`The graph is accepted; submit its recorded successful run`),this.enqueue(()=>this.write(e,t)).catch(e=>(this.lastFailure=e,{ok:!1,diagnostic:Ft(e)}))}async write(e,t){t.throwIfAborted(),this.lastFailure=void 0;let n=e;(!n||!ol(n.name)||typeof n.source!=`string`||typeof n.run!=`boolean`||Object.keys(n).some(e=>![`name`,`source`,`run`].includes(e)))&&Z(`Expected only name, source and boolean run`),this.options.name!==void 0&&n.name!==this.options.name&&Z(`The graph name must match --name`),this.owned&&(this.owned.result=void 0);let r=M(this.directory,`${n.name}.yaml`);if(this.owned&&this.owned.file!==r&&Z(`This invocation owns one named graph file`),!this.owned)try{this.owned={file:r,handle:await mt(r,Ne.O_RDWR|Ne.O_CREAT|Ne.O_EXCL|Ne.O_NOFOLLOW,384),digest:Q(``)}}catch(e){throw e.code===`EEXIST`&&Z(`Graph already exists: ${r}; choose another --name`),e}let i=this.owned;await this.digest()!==i.digest&&Z(`The owned graph was changed`);let a=Buffer.from(n.source);for(let e=0;e<a.length;){let{bytesWritten:t}=await i.handle.write(a,e,a.length-e,e);if(!t)throw Error(`Graph file write made no progress`);e+=t}await i.handle.truncate(a.length),await i.handle.sync(),i.digest=Q(a);let o={...this.options,param:[]},s={cwd:this.cwd,signal:t,source:n.source},c=await Jl(r,{...o,dryRun:!0},{...s,connectNeeds:!0});`graph`in c||Z(`No canonical graph was returned`),c.graph.deliverable.checkRef===`command`&&Z(`Host command checks need a jailed verifier node`);let{nodes:l,edges:u,budget:d}=c.graph,f=u.reduce((e,t)=>e+(`maxTraversals`in t?(t.maxTraversals??1)-1:0),l.length),p=(f+1)*al;if(d?.maxTokens!==void 0&&d.maxTokens<p&&Z(`budget.maxTokens ${d.maxTokens} is below ${p}: ${f} agent spawns plus one reservation at ${al} tokens per native turn`),await this.digest()!==i.digest&&Z(`Graph changed during validation`),!n.run)return{file:r,graphDigest:c.graph.digest,validated:!0};let m=await Jl(r,o,{...s,graphDigest:c.graph.digest});return(!(`status`in m)||m.status!==`winner`||m.graphDigest!==c.graph.digest||await this.digest()!==i.digest)&&Z(`The graph must succeed with unchanged YAML`),i.result=m,this.receipt()}async close(){await this.pending,await this.owned?.handle.close()}};async function ll(e,t,n){let{runId:r,runDir:i,cwd:a,bridge:o,signal:s}=e,c=await o(),l=M(await R(M(F(),`.tangle`)),`graphs`);(Is(a,l)||Is(l,a))&&Z(`The graph store must be outside the agent workspace; choose another working directory`);try{await ft(l,{mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}await R(l)!==l&&Z(`The graph store redirects outside its canonical location`);let u=n.seat??Qt().seat,d=await cc(a,s)(u,{node:`graph-designer`,cwd:a,signal:s,lastCandidate:!0});d||Z(`No authenticated native subscription is available`);let{graphDesignerProfile:f}=await import(`@tangle-network/agent-runtime/profiles`),{supervisePursuit:p}=await import(`@tangle-network/agent-runtime/durable`),m=f({profile:{name:`graph-designer`,harness:d.harness,model:{provider:d.provider,default:d.model,...d.reasoningEffort===void 0?{}:{reasoningEffort:d.reasoningEffort}},prompt:{instructions:[`You are the sole graph designer. Author a canonical YAML graph for the requested intent, then qualify and run it using write_graph. Its nodes are complete AgentProfiles with a real independent verifier and declarative route/data outside check. Command checks execute on the host and are refused here; put executable verification in the verifier node's normal native tools. Read the supplied skills and preserve the user's task and authority.`,`Call write_graph with name, complete YAML source and run:false to validate; repair its concrete diagnostics, then call it with the identical source and run:true. The graph schema and executor are owned by the installed loader. Supply defaults for parameters needed by the first run. Only a real successful host run of the unchanged saved file passes. Submit that evidence using submit_result; explain concrete blockers using report_blocked.`]},tools:{agent_runtime_coordination_write_graph:!0,agent_runtime_coordination_submit_result:!0,agent_runtime_coordination_read_continuation:!0,agent_runtime_coordination_report_blocked:!0}}}),h=De(m),g=new cl(l,{...n,seat:u},a),_={maxIterations:6,maxTokens:2e6,deadlineMs:9e5};try{let e=await p(m,{intent:t,name:n.name},{pursuitId:r,runId:r,runDir:i,signal:s,backend:{...c,timeoutMs:_.deadlineMs},budget:_,maxDepth:0,coordination:{authentication:!0,requestTimeoutMs:_.deadlineMs},deliverable:{describe:`The saved graph succeeds with unchanged YAML`,check:g.check,checkState:g.check},continuation:sl,resolveSupervisorTools:e=>e.runId!==r||e.nodeId!==r||e.depth!==0||e.identity.profileDigest!==h?[]:[{name:`write_graph`,description:`Save, validate and run this graph.`,inputSchema:{type:`object`,properties:{name:{type:`string`},source:{type:`string`},run:{type:`boolean`}},required:[`name`,`source`,`run`],additionalProperties:!1},handler:(t,n)=>((n.nodeId!==e.nodeId||n.ownerId!==e.ownerId||n.runId!==e.runId)&&Z(`Wrong graph tool owner`),g.invoke(t,n.signal))}]});if(e.result.kind===`no-winner`||!await g.check()){if(g.lastFailure)throw g.lastFailure;let t=e.result.kind===`no-winner`?e.result.error?.message??e.result.reason:`The graph file changed after its successful run`;throw Object.assign(new B(`GRAPH_DESIGN_FAILED`,`Graph design did not finish`,t,`tangle graph new --help`),{runId:r,node:`graph-designer`})}return g.receipt()}finally{await g.close()}}function ul(t){t.command(`new <intent>`).description(`Design, validate and run one portable graph`).option(`--seat <seat>`,`Use harness/model@effort for the designer and graph`).option(`--name <name>`,`Save this graph name`).action(async(t,n)=>{process.env.BRIDGE_JAIL_RW_PATHS?.trim()&&Z(`Remove BRIDGE_JAIL_RW_PATHS before graph new; extra native write roots cannot contain its host store`),n.name!==void 0&&!ol(n.name)&&Z(`Use letters, numbers and hyphens in --name`);let r=await Kl({},e=>ll(e,t,n));n.json?e(r):l(`Created ${r.file} · run ${r.result.runId}`)})}const dl={start:[`▶`,j.green],agent:[`●`,j.cyan.bold],check:[`▣`,j.yellow.bold],gate:[`◇`,j.magenta.bold],finish:[`✓`,j.green.bold],stop:[`■`,j.red.bold]};function fl(e){let t=t=>e.nodes.find(e=>e.id===t)?.kind??`agent`,n=e=>{let[n,r]=dl[t(e)];return r(`${n} ${e.replace(/^(finish|stop):/,``)}`)},r=Math.max(...e.nodes.map(e=>e.id.length))+4,i=[`${j.bold(`◆ ${e.name}`)}`,...e.describe?[` ${e.describe}`]:[],``];for(let[t,n]of e.facts)i.push(` ${j.dim(t.padEnd(10))} ${n}`);i.push(``,j.bold(`NODES`));for(let t of e.nodes.filter(e=>[`agent`,`check`,`gate`].includes(e.kind))){let[e,...a]=t.detail.split(`
168
168
  `);i.push(` ${n(t.id)}${` `.repeat(Math.max(1,r-t.id.length))}${e}`);for(let e of a)i.push(`${` `.repeat(r+4)}${j.dim(e)}`)}i.push(``,j.bold(`FLOW`));for(let t of e.edges){let e=` ${t.from.map(n).join(j.dim(` + `))} ${j.dim(`─▶`)} ${t.to.map(n).join(j.dim(` ∥ `))}`,r=t.loop?j.magenta(t.label):j.blue(t.label);i.push(...t.label.length+_t(e).length>100?[e,` ${r}`]:[`${e} ${r}`])}return i.join(`
169
- `)}async function hl(e,t){let n=M(t,`dist`,`graph-show`),[r,i]=await Promise.all([`viewer.iife.js`,`styles.css`].map(e=>L(M(n,e),`utf8`))),a=(e=``)=>e.replace(/<\/(script)/gi,`<\\/$1`).replace(/<!--/g,`<\\!--`),o=e.name.replace(/[^\w.-]+/g,`-`),s=`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>${o} · tangle graph</title>
169
+ `)}async function pl(e,t){let n=M(t,`dist`,`graph-show`),[r,i]=await Promise.all([`viewer.iife.js`,`styles.css`].map(e=>L(M(n,e),`utf8`))),a=(e=``)=>e.replace(/<\/(script)/gi,`<\\/$1`).replace(/<!--/g,`<\\!--`),o=e.name.replace(/[^\w.-]+/g,`-`),s=`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>${o} · tangle graph</title>
170
170
  <meta name="description" content="${(e.describe??o).replace(/[&<>"]/g,``)}">
171
171
  <style>${i}html,body,#root{margin:0;height:100%;font-family:ui-sans-serif,system-ui,sans-serif}</style></head>
172
172
  <body><div id="root"></div><script id="graph" type="application/json">${JSON.stringify(e).replace(/</g,`\\u003c`)}<\/script>
173
- <script>${a(r)}<\/script></body></html>`,c=M(await pt(M(Ve(),`tangle-graph-`)),`${o}.html`);return await z(c,s,{mode:384}),c}function gl(t,n,r){t.command(`show <name-or-file>`).description(`Draw a graph file: labelled nodes, routes, loops and stops`).option(`--open`,`Write one offline page and open it in the browser`).action(async(t,i)=>{let a=await R(n(t,process.cwd())),{graphShape:o}=await import(`./graph-view-DOQKwuvP.mjs`),s=o(a,await L(a,`utf8`));if(i.json)return e(s);if(!i.open)return console.log(ml(s));let c=await hl(s,r);l(await Lr(bt(c).href)?`Opened ${c}`:`Open ${c}`)})}async function _l(e){if(!gn(e.apiKey)){if(e.json||e.dryRun||!process.stdin.isTTY)return;await Kr({baseUrl:e.sandboxBaseUrl,signal:e.signal})}return K(e)}async function vl(t,n,r){let i=Vl(n.parameter),a=r??await _l(n);if(!a)throw new B(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured`,`tangle auth login`);let o=await a.connections.start(t,{cli:!0,connectionParameters:i,...n.scope?.length?{requestedScopes:n.scope}:{}});return n.json?(e(Ul(o)),o):(Hl(o,n.browser===!1?!1:await Lr(o.redirectUrl),n.wait),o)}async function yl(e,t,n,r){let i=async()=>{n.signal?.throwIfAborted();let{connections:i}=await e.connections.list(),a=i.filter(e=>e.status===`active`&&e.providerId.toLowerCase()===t.trim().toLowerCase());return a.length?Xe(a,r===void 0?t:`${t}:${r}`):void 0},a=await i();if(a||n.json||n.dryRun||!process.stdin.isTTY)return a;let o=await vl(t,{...n,wait:!0},e);for(;!a&&Date.now()<Date.parse(o.expiresAt);)await et(1e3,void 0,{signal:n.signal}),a=await i();return a}function bl(){let e=new N(`hub`).description(`Discover and run Tangle Hub tools`);return xl(e),Sl(e),Cl(e),wl(e),Tl(e),e}function xl(t){t.command(`connect`).description(`Connect a provider account`).argument(`provider`,`Provider to connect`).option(`--no-browser`,`Print the authorization URL instead of opening it`).option(`--key-env <name>`,`Connect an API-key provider using this environment variable; never prints the key`).option(`--metadata <json>`,`Provider setup metadata for API-key connections`).option(`--scope <scope>`,`Request an OAuth scope; repeatable, must stay within the host's grant`,(e,t)=>[...t,e],[]).option(`--parameter <key=value>`,`Provider-specific OAuth value. Repeatable.`,(e,t)=>[...t,e],[]).action(async(t,n)=>{if(n.keyEnv){if(n.scope?.length)throw Error(`--scope applies to OAuth connections, not --key-env.`);let r=process.env[n.keyEnv];if(!r?.trim())throw Error(`Environment variable '${n.keyEnv}' is empty or unavailable.`);let i=await _l(n);if(!i)throw new B(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured`,`tangle auth login`);let a;if(n.metadata!==void 0)try{a=JSON.parse(n.metadata)}catch{throw Error(`--metadata must be valid JSON.`)}let o=await i.connections.connectApiKey(t,r,a);n.json?e(o):l(`Connected ${o.connection.providerId} as ${o.connection.id}.`);return}if(n.metadata!==void 0)throw Error(`--metadata requires --key-env.`);await vl(t,n)});let n=new N(`connections`).description(`List Hub provider connections`).action(async t=>{let n=await(await K(t)).connections.list();t.json?e(n):Bl(n.connections)});n.command(`revoke <connection-id>`).description(`Revoke a Hub provider connection`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let r=await K(n),i=await Fn(r,t);if(!n.force&&!await ur(`Revoke Hub connection ${i}? `,`--force`)){l(`Revoke cancelled.`);return}let a=await r.connections.revoke(i);if(n.json){e(a);return}l(`Revoked Hub connection ${a.connection.id}.`)}),t.addCommand(n)}function Sl(n){n.command(`providers [provider]`).description(`Show provider setup and action catalog; use hub events for trigger readiness`).action(async(n,r)=>{let i=await(await K(r)).connections.providers(),a=i.providers.filter(e=>!n||e.providerId===n.toLowerCase());if(n&&!a.length)throw Error(`Provider '${n}' is absent from this deployment's catalog.`);if(r.json)return e({...i,providers:a});t(a,[{key:`providerId`,header:`Provider`},{key:`authKind`,header:`Auth`},{key:`configured`,header:`Connect configured`},{key:`actionCount`,header:`Catalog actions`}])}),n.command(`events [provider]`).description(`Discover deployed trigger events and ingress readiness separately from callable tools`).action(async(n,r)=>{let i=await K(r),[a,o]=await Promise.all([i.connections.providers(),i.workflows.catalogs()]),s=[...new Set([...a.providers.map(e=>e.providerId),...o.providerEventProviders])];if(n&&!s.includes(n.toLowerCase()))throw Error(`Provider '${n}' is absent from this deployment's catalog.`);let c=s.filter(e=>!n||e===n.toLowerCase()).map(e=>({provider:e,supported:o.providerEventProviders.includes(e),ingressConfigured:a.providers.find(t=>t.providerId===e)?.eventIngressConfigured??null,catalog:o.triggerEvents[e]??null}));if(r.json)return e({providers:c});t(c.map(e=>({...e,ingress:e.ingressConfigured===null?`unknown`:e.ingressConfigured?`ready`:`setup required`,events:e.catalog?.events.map(e=>e.id).join(`, `)??`no published vocabulary`})),[{key:`provider`,header:`Provider`},{key:`supported`,header:`Event source supported`},{key:`ingress`,header:`Ingress`},{key:`events`,header:`Events`}])})}function Cl(t){let n=new N(`permissions`).description(`Manage Hub action permissions`);n.command(`list`).description(`List Hub permissions for a connection`).requiredOption(`--connection <ref>`,`Hub connection id, or provider[:account]`).action(async t=>{if(!t.connection)throw Error(`--connection is required.`);let n=await K(t),r=await Fn(n,t.connection),i=await n.permissions.list(r);t.json?e(i):Fl(i.policies)}),n.command(`set`).description(`Set Hub permission for one action`).requiredOption(`--connection <ref>`,`Hub connection id, or provider[:account]`).requiredOption(`--action <path>`,`Executor action path`).requiredOption(`--decision <allow|ask|deny>`,`Permission decision`).action(async t=>{if(!t.connection)throw Error(`--connection is required.`);if(!t.action)throw Error(`--action is required.`);let n=Il(t.decision),r=await K(t),i=await Fn(r,t.connection),a=await r.permissions.set({connectionId:i,actionPath:t.action,decision:n});t.json?e(a):Fl([a.policy])}),n.command(`revert-writes`).description("Revoke a bulk `--allow-writes` grant for a connection (deletes only the auto-granted write rows; manual permissions are untouched)").requiredOption(`--connection <ref>`,`Hub connection id, or provider[:account]`).action(async t=>{if(!t.connection)throw Error(`--connection is required.`);let n=await K(t),r=await Fn(n,t.connection),i=await n.permissions.revertWrites(r);if(t.json){e(i);return}l(`Reverted ${i.reverted} write permission${i.reverted===1?``:`s`} for connection ${i.connectionId}.`)}),t.addCommand(n),t.addCommand(Dl())}function wl(t){let n=new N(`tools`).description(`Discover Hub tools`);n.command(`sources`).description(`List Hub tool sources`).action(async t=>{let n=await(await K(t)).tools.sources();t.json?e(n):Ll(n.sources)}),n.command(`describe`).description(`Describe a Hub tool`).argument(`path`,`Executor tool path`).action(async(t,n)=>{let r=await(await K(n)).tools.describe(t);n.json?e(r):Rl(r.tool)}),n.command(`search`).description(`Search Hub tools`).argument(`<query...>`,`Search query`).option(`--provider <provider>`,`Filter by provider/source ID`).action(async(t,n)=>{let r=await(await K(n)).tools.search(t.join(` `),{provider:n.provider});n.json?e(r):Pl(r.tools)}),t.addCommand(n),t.addCommand(El(`call`)),t.addCommand(El(`exec`))}function Tl(t){t.command(`resume`).description(`Resolve a Hub approval created by a paused execution`).argument(`approval-id`,`Hub approval ID from HUB_APPROVAL_REQUIRED`).option(`--accept`,`Approve the execution approval`).option(`--decline`,`Deny the execution approval`).option(`--cancel`,`Unsupported for approval-backed Hub resume`).action(async(e,t)=>{if(kl(e),t.cancel)throw Error(`Hub approval resume does not support --cancel. Use --decline to deny the approval.`);if(t.accept&&t.decline)throw Error(`Choose only one of --accept or --decline.`);if(!t.accept&&!t.decline)throw Error(`Choose --accept to approve or --decline to deny the Hub approval.`);let n=await K(t);jl(t.decline?await n.approvals.deny(e):await n.approvals.approve(e),t.json===!0)}),t.command(`status`).description(`Show Hub auth and connection status`).action(async t=>{let n=await(await K(t)).status();t.json?e(n):Wl(n)})}function El(t){return new N(t).description(`Execute a Hub tool`).argument(`<args...>`,`Tool path tokens followed by JSON input`).option(`--connection <ref>`,`Hub connection id, or provider[:account]`).option(`--auto-approve`,`Approve a HUB_APPROVAL_REQUIRED execution and retry once`).option(`--approve`,`Alias for --auto-approve`).option(`--no-hub-key`,`Do not auto-mint a platform Hub key; use the stored credential as-is`).action(async(t,n)=>{let{args:r,approve:i}=Ol(t,n),{path:a,input:o}=Nl(r),s=await K(n),c=n.connection?await Fn(s,n.connection):void 0;e((await s.tools.invoke(a,o,{connectionId:c,approve:i})).result)})}function Dl(){let t=new N(`approvals`).description(`List and resolve Hub execution approvals`);t.command(`list`).description(`List pending Hub execution approvals`).action(async t=>{let n=await(await K(t)).approvals.list();t.json?e(n):Al(n.approvals)});for(let e of[`approve`,`deny`])t.command(e).description(`${e===`approve`?`Approve`:`Deny`} a pending Hub execution approval`).argument(`approval-id`,`Hub approval ID`).action(async(t,n)=>{kl(t),jl(await(await K(n)).approvals[e](t),n.json===!0)});return t}function Ol(e,t){let n=t.autoApprove;return{args:e.filter(e=>e!==`--approve`&&e!==`--auto-approve`),approve:t.approve===!0||n===!0||e.includes(`--approve`)||e.includes(`--auto-approve`)}}function kl(e){if(!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`Hub approval ID must contain only letters, numbers, underscores, and dashes.`)}function Al(e){t(e,[{key:`id`,header:`ID`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`connectionId`,header:`Connection`},{key:`status`,header:`Status`},{key:`expiresAt`,header:`Expires`}])}function jl(t,n){if(n){e(Ml(t));return}l(`Hub approval ${t.approval.id} ${t.approval.status}.`),t.capabilityToken&&l("Capability token minted. Re-run the original command with `--approve` to execute automatically.")}function Ml(e){return{approval:e.approval,...e.capabilityToken?{capabilityToken:{tokenId:e.capabilityToken.tokenId,expiresAt:e.capabilityToken.expiresAt}}:{}}}function Nl(e){if(e.length<2)throw Error(`Usage: tangle hub call <path> <json-input>`);let t=e[e.length-1];try{return{path:e.slice(0,-1).join(`.`),input:JSON.parse(t)}}catch{throw Error(`Hub call input must be valid JSON.`)}}function Pl(e){t(e.map(e=>({...e,provider:e.providerId??e.requiredConnectionProviderId,connection:zl(e)})),[{key:`path`,header:`Path`},{key:`provider`,header:`Provider`},{key:`title`,header:`Title`},{key:`description`,header:`Description`},{key:`connection`,header:`Connection`},{key:`policyState`,header:`Policy`}])}function Fl(e){t(e,[{key:`connectionId`,header:`Connection`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`decision`,header:`Decision`},{key:`updatedAt`,header:`Updated`}])}function Il(e){if(e===`allow`||e===`ask`||e===`deny`)return e;throw Error(`--decision must be one of: allow, ask, deny.`)}function Ll(e){t(e,[{key:`sourceId`,header:`Source`},{key:`displayName`,header:`Provider`},{key:`toolCount`,header:`Tools`},{key:`connectionStatus`,header:`Connection`},{key:`health`,header:`Health`},{key:`configured`,header:`Configured`}])}function Rl(e){s({Path:e.path,Provider:e.providerId??e.requiredConnectionProviderId,Title:e.title,Description:e.description,Connection:zl(e),Policy:e.policyState}),e.inputSchema!==void 0&&(l(`Input schema`),console.log(JSON.stringify(e.inputSchema,null,2))),e.outputSchema!==void 0&&(l(`Output schema`),console.log(JSON.stringify(e.outputSchema,null,2)))}function zl(e){if(e.connectionRequired===!1)return`not required`;if(e.connectionStatus)return e.connectionStatus}function Bl(e){t(e.map(e=>({...e,account:e.accountDisplay??e.displayName,scopes:e.scopes.join(`, `)})),[{key:`id`,header:`ID`},{key:`providerId`,header:`Provider`},{key:`account`,header:`Account`},{key:`scopes`,header:`Scopes`},{key:`status`,header:`Status`},{key:`health`,header:`Health`},{key:`lastUsedAt`,header:`Last Used`}])}function Vl(e){if(!e||e.length===0)return;let t={};for(let n of e){let e=n.indexOf(`=`);if(e<=0||e===n.length-1)throw Error(`Invalid --parameter "${n}": expected key=value (for example subdomain=acme)`);let r=n.slice(0,e);if(Object.hasOwn(t,r))throw Error(`Duplicate --parameter key "${r}".`);t[r]=n.slice(e+1)}return t}function Hl(e,t,n=!1){t?l(`Opened browser to connect ${e.provider}.`):(l(`Open this URL to connect ${e.provider}:`),console.log(e.redirectUrl)),l(n?`Finish authorization in the browser; this run resumes when connected.`:"Finish authorization in the browser, then rerun `tangle hub status`.")}function Ul(e){return{provider:e.provider,redirectUrl:e.redirectUrl,expiresAt:e.expiresAt,scopes:e.scopes,cli:e.cli}}function Wl(e){let{principal:t,connections:n}=e;l(`Hub status`),s({Principal:t.kind,"User ID":t.userId,"API Key ID":t.apiKeyId,"Sandbox ID":t.sandboxId,"Connected Providers":n.connectedProviderCount,"Unhealthy Providers":n.unhealthyProviderCount}),n.unhealthyProviderCount>0&&l(`Some providers require reconnect.`)}const Gl=v(import.meta.url);if(!Gl)throw Error(`Tangle CLI package metadata was not found`);const Kl=ue(Gl),Q=e=>ve(`sha256`).update(e).digest(`hex`);function ql(e,t){if(/[\\/]/.test(e)||/\.(yaml|yml|json)$/.test(e))return he(t,e);let n=t;for(;!Pe(M(n,`.git`))&&ue(n)!==n;)n=ue(n);Pe(M(n,`.git`))||(n=t);let r=[`yaml`,`yml`,`json`].flatMap(e=>[`graph.${e}`,e]),i=[n,F()].flatMap(t=>r.map(n=>M(t,`.tangle/graphs/${e}.${n}`))),a=i.find(Pe);if(a)return a;throw new B(`GRAPH_NOT_FOUND`,`Graph '${e}' was not found`,`Looked in ${i.join(`, `)}`,`tangle graph --help`)}async function Jl(e,t){return vs(e.signal,async n=>{let r=e.runId??be(),i,a=new Set,{graphNativeRedaction:o}=await import(`./graph-native-BOIC8WzU.mjs`),s=o();try{let o=M(F(),`.tangle`,`runs`,r);await ft(o,{recursive:!0,mode:448});let c=await R(M(F(),`.tangle`)),l=await R(e.cwd??process.cwd()),u=[`runs`,`graph-registry`,`graphs`].some(e=>Rs(l,M(c,e))||Rs(M(c,e),l))?M(F(),`.tangle`,`workspaces`,r):l;await ft(u,{recursive:!0,mode:448});let d;return await t({runId:r,runDir:o,cwd:u,bridge:t=>d??=(async()=>{n.throwIfAborted();let r=ye(32).toString(`hex`),{loadConfig:c,startServer:l}=await import(`cli-bridge`),d=M(Kl,`dist`,`stdio.mjs`),f={...process.env,BRIDGE_HOST:`127.0.0.1`,BRIDGE_BEARER:r,BRIDGE_DATA_DIR:M(o,`bridge`),BRIDGE_BACKENDS:lc,BRIDGE_JAIL_MODE:`fs-jail`,BRIDGE_JAIL_FALLBACK:`deny`,BRIDGE_JAIL_NETWORK:`relay`,BRIDGE_SUBSCRIPTIONS_ONLY:`1`};e.relayAllow?f.BRIDGE_JAIL_RELAY_ALLOW=e.relayAllow:delete f.BRIDGE_JAIL_RELAY_ALLOW;let p=c(f);t&&p.jailReadablePaths.push(d),i=await l({cwd:u,config:{...p,port:0},handleSignals:!1,quiet:!0,onRunRedaction:s.observe,mcpSecrets:{async get(t){let n=e.mcpSecretEnv,r=n&&Object.hasOwn(n,t)?n[t]:void 0,i=r===void 0?void 0:process.env[r];return i&&a.add(i),i}},hub:t?{client:t,hash:_s,serverForGrant:e=>{if(a.add(e),!i)throw Error(`Hub host is not ready`);return{transport:`stdio`,command:process.execPath,args:[{kind:`public`,value:d}],env:{TANGLE_HUB_MCP_ENDPOINT:{kind:`public`,value:`${i.url}/hub/mcp/grants/${e}`}}}}}:void 0});let{graphNativeCapture:m}=await import(`./graph-native-BOIC8WzU.mjs`);return{harnessTranscript:m({bridgeUrl:i.url,bridgeBearer:r,cwd:u,privateMcpSecrets:()=>[...a],redact:s.redact}),backend:`bridge`,bridgeUrl:i.url,bridgeBearer:r,cwd:u}})(),signal:n})}catch(t){throw t instanceof Error&&Object.assign(t,{runId:e.errorRunId??r}),t}finally{try{await i?.close()}finally{s.close(),a.clear()}}},e.fix??`tangle graph --help`)}function Yl(e,t){return[`tangle graph run`,ut(e),...t.dryRun?[`--dry-run`]:[],...t.cloud?[`--cloud`]:[],...t.deploy?[`--deploy`,ut(t.deploy)]:[],...t.workflow?[`--workflow`,ut(t.workflow)]:[],...t.resume?[`--resume`,ut(t.resume)]:[],...t.seat?[`--seat`,ut(t.seat)]:[],...t.seatAccount?[`--seat-account`,ut(t.seatAccount)]:[],...t.seatCommand?[`--seat-command`,ut(t.seatCommand)]:[],...t.param.flatMap(e=>[`--param`,ut(e)])].join(` `)}async function Xl(e,t,n={}){let r=n,i=Yl(e,t);return await vs(r.signal,async n=>{n.throwIfAborted();let a=Ts(t.mcpSecret);if(t.resume&&!t.resume.startsWith(`wfrun_`)&&(t.workflow||t.deploy)&&Y(`A local run cannot move to a cloud deployment`),t.deploy&&!t.cloud&&!t.workflow&&!t.resume?.startsWith(`wfrun_`))throw new B(`GRAPH_DEPLOY_INVALID`,`Deployment settings require cloud placement`,`Use --cloud to bind cloud triggers and settings`,`tangle graph run --help`);let o=await R(ql(e,r.cwd??process.cwd())),s=r.source??await L(o,`utf8`),c=t.resume&&!t.resume.startsWith(`wfrun_`)?await rc(t.resume):void 0,l=r.taskWorkspace??(t.taskWorkspace?await Xs(t.taskWorkspace):void 0)??c?.taskWorkspace;if(c&&(l?Ks(l):null)!==(c.taskWorkspace?Ks(c.taskWorkspace):null)&&Y(`The recorded task workspace snapshot changed`),l&&(t.cloud||t.workflow||t.resume?.startsWith(`wfrun_`)))throw Error(`Local private task workspace artifacts cannot be dispatched to a cloud backend`);let u=c?.runId??r.runId??be(),d=l&&!r.taskWorkspace?await Qs(l,{runId:u,resumeCwd:c?.cwd,signal:n,validationOnly:t.dryRun===!0&&!c&&!r.runId}):void 0;d&&(r={...r,runId:u,cwd:d.cwd,taskWorkspace:l});try{if(!t.resume&&(t.cloud||t.workflow)||t.resume?.startsWith(`wfrun_`))return Bc(o,s,t,n);let e=await Fs(),l=Q(s),u=Object.entries(kc(t.param,`param`)??{}),d=Object.fromEntries(u.filter(([e])=>!e.startsWith(`gate.`))),f=Object.fromEntries(u.filter(([e])=>e.startsWith(`gate.`)).map(([e,t])=>[e.slice(5),t])),p=qe.parse(t.mcpPolicy??c?.mcpPolicy??{}),m=e.graphRegistry(M(F(),`.tangle`,`graph-registry`)),h;if(c){await R(c.cwd)!==c.cwd&&Y(`The recorded workspace identity changed`),c.file!==o&&Y(`The recorded graph source path changed`);let n=await e.loadGraph(m,c.graphDigest);n||Y(`The recorded executable graph is unavailable`),h=e.validateStoredGraph(n),sc(c,t,l,d,f)}let g={apiKey:t.apiKey,sandboxBaseUrl:t.baseUrl,signal:n,json:t.json,dryRun:t.dryRun&&!r.connectNeeds},_,v=()=>_??=_l(g),y=new Map,b=(e,{account:t})=>{let n=e.trim().toLowerCase(),r=JSON.stringify([n,t?.toLowerCase()]),i=y.get(r)??(async()=>{let e=await v(),r=e&&await yl(e,n,g,t);return r?{connectionId:r,capabilities:[`*`]}:void 0})();return y.set(r,i),i},x=async i=>{if(n.throwIfAborted(),c&&h)return ys(h,c.gateChoices??{}),{graph:h,params:c.params};let a=await e.loadGraphFile(o,{source:s,seat:t.seat??(r.defaultSeat===void 0?en().seat:r.defaultSeat??void 0),resolveSeat:uc(i,n),resolveNeed:b,params:d,...r.trigger?{trigger:r.trigger}:{},cwd:i,signal:n});if(n.throwIfAborted(),ys(a.graph,f),r.graphDigest&&a.graph.digest!==r.graphDigest)throw new B(`GRAPH_CHANGED`,`The validated graph changed before execution`,`Its compiled graph digest no longer matches validation`,`tangle graph run --help`);return a},S=r.cwd??process.cwd(),C=await x(c?.cwd??S),w=Je(p,!0),T=[];for(let e of C.graph.nodes){let t=Ae(e.profile,w);if(!t.ok)throw new B(`GRAPH_MCP_POLICY_REQUIRED`,`A graph profile exceeds its host policy`,`${e.id}: ${t.issues.filter(e=>e.level===`error`).map(e=>`${e.code}: ${e.message}`).join(`; `)}`,`tangle graph run --mcp-policy <policy.json> --help`);for(let t of Object.values(e.profile.mcp??{}))t.enabled!==!1&&t.url&&T.push(new URL(t.url).hostname)}let ee=[pc(C.graph),...T].filter(Boolean).join(`,`)||void 0;if(t.dryRun)return C;let E=mc(C.graph.nodes)?gc(t):void 0,D=c?.runId??r.runId??be(),O=c?.cwd??(r.taskWorkspace?S:await e.graphWorkspace(C.graph,{cwd:S,runId:D}));return await Jl({...r,runId:D,cwd:O,signal:n,fix:i,relayAllow:ee,mcpSecretEnv:a},i=>Zl(i,{kernel:e,registry:m,loaded:C,gateChoices:f,file:o,source:s,sourceDigest:l,context:r,options:t,prior:c,mcpPolicy:p,getHub:v,seatSource:E,signal:n}))}finally{await d?.release()}},i)}async function Zl({runId:e,runDir:t,cwd:n,bridge:r},{kernel:i,registry:a,loaded:o,gateChoices:s,file:c,source:u,sourceDigest:d,context:f,options:p,prior:m,mcpPolicy:h,getHub:g,seatSource:_,signal:v}){let{superviseGraphPursuit:y,readSettleRecord:b}=await import(`@tangle-network/agent-runtime/durable`),x=await i.recordStoredGraphRun(a,o.graph),S=m??{version:1,runId:e,cwd:n,file:c,graphDigest:x.digest,sourceDigest:d,source:u,params:o.params,...f.trigger?{trigger:f.trigger}:{},...Object.keys(s).length?{gateChoices:s}:{},startedAt:new Date().toISOString(),...p.seat===void 0?{}:{seat:p.seat},mcpPolicy:h,...f.taskWorkspace&&{taskWorkspace:f.taskWorkspace}};m||await ic(t,S);let C=m?await b(t):void 0;if(C&&C.tree.root!==e&&Y(`The settlement names another run`),C?.kind===`no-winner`&&Y(`The local run is terminal: ${C.reason}`),C)return{runId:e,graphDigest:x.digest,sourceDigest:d,...Ns(C),replayed:!0};let w=i.graphFromStored(x,{trigger:S.trigger}),T=x.nodes.some(e=>e.profile.connections?.length),ee=T?await g():void 0;if(T&&!ee)throw new B(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured for this local graph`,`tangle auth login`);let E=await r(ee),D=i.createPrivateCasArtifactPort(M(t,`artifacts`),e),O=await Ss(o.params.knowledge,t,D,v),k=_?vc(E,_,v):void 0,A=S.startedAt;l(`Run ${e} · ${le(c)} · ${n}`);let te=await Ql(t);l(`Viewer ${te.url}`);let ne=new AbortController,re=await y(w,{pursuitId:x.digest,runDir:t,runId:e,backend:E,checkArtifacts:D,...O?{resolveSupervisorTools:O}:{},...w.entry===void 0?{driverBackend:E}:{},...x.gates?.length?{decideGate:bs(S.gateChoices??{},{json:p.json,signal:AbortSignal.any([v,ne.signal])})}:{},resume:!!m,signal:v,...S.trigger?{trigger:S.trigger}:{},...k?{selectSeat:k,coordination:{authentication:!0}}:{},profileSecurity:Je(S.mcpPolicy,T)}).finally(async()=>{ne.abort(),await te.close()}),ie={runId:e,graphDigest:x.digest,sourceDigest:d,...Ns(re.result.result)},ae=re.result.result,{tokens:oe,tokensKnown:se,iterations:j,ms:ce}=ae.spentTotal;if(await i.recordStoredGraphRun(a,x,{graphDigest:x.digest,evidence:[{kind:`authored-graph`,url:`urn:sha256:${x.digest}`},{kind:`authored-yaml`,url:`urn:sha256:${d}`}],taskDigest:i.taskShapeDigest({graph:le(c),params:o.params,trigger:S.trigger??null,taskWorkspace:S.taskWorkspace?Ks(S.taskWorkspace):null}),startedAt:A,finishedAt:new Date().toISOString(),outcome:ae.kind===`no-winner`?{kind:`no-winner`,reason:ae.reason}:{kind:`delivered`,summary:ie.text},cost:{iterations:j,ms:ce,...se===!1?{}:{tokens:oe.input+oe.output},...ie.costUsd===null?{}:{usd:ie.costUsd}},traversals:re.result.ledger.length,exhaustedEdges:re.result.exhaustedEdges,source:{kind:`tangle-cli-graph`,id:e}}),ae.kind===`no-winner`)throw Object.assign(new B(`GRAPH_RUN_FAILED`,`Graph '${le(c)}' finished without a result`,re.result.stopped?.reason||re.result.ledger.filter(e=>e.outcome===`unpropagated`&&e.reason).pop()?.reason||ae.reason,`tangle graph inspect ${e}`),{runId:e,runtimeFailures:[...ae.tree.nodes.filter(e=>e.failure).map(e=>({node:e.label,failure:e.failure})),...ae.reason===`driver-failed`&&ae.error.failure?[{node:`root`,failure:ae.error.failure}]:[]]});return ie}async function Ql(e){let{serveTopWeb:t}=await import(`@tangle-network/agent-runtime/tui`),{readGraphSessions:n}=await import(`./graph-native-BOIC8WzU.mjs`);return t({roots:[e],assets:M(Kl,`dist`,`graph-viewer`),readSessions:n})}async function $l(t,n){if(n.artifacts||n.artifact)return Ec(t,n);if(t.startsWith(`wfrun_`)){let r=await X(n),i=await r.workflows.getRun(t);if(n.json)return e(i);for(let e of i.runtime?.checks??[])l(`${e.node} ${e.status} · exit ${e.exitCode??`none`} · pass ${e.pass??`none`}\n${e.reason??e.tail}`);return l(`Run ${t} · ${r.baseUrl}/app/workflows/${encodeURIComponent(i.workflowId)}/runs/${encodeURIComponent(t)}`)}let r=M(F(),`.tangle`,`runs`,t);if(!/^[a-f0-9-]{36}$/i.test(t)||!Pe(r))throw new B(`RUN_NOT_FOUND`,`Run '${t}' was not found`,`Use a run ID printed by tangle graph run`,`tangle graph inspect --help`);let{loadTopSnapshot:i}=await import(`@tangle-network/agent-runtime/tui`);if(n.json)return e(await i(process.cwd(),{runDir:r}));l(`Run ${t} · ${(await Ql(r)).url}`)}function eu(){let t=new N(`graph`).description(`Build and run portable agent graphs`);return fl(t),$s(t),zc(t,ql),Hc(t,ql),Tc(t),il(t),gl(t,ql,Kl),t.command(`inspect <run>`).description(`Inspect a live or retained graph run`).option(`--artifacts`,`List complete retained check files and capture gaps`).option(`--artifact <node/path>`,`Download one retained check file by node/path or digest`).option(`--out <file>`,`Save artifact bytes to a new private file`).action($l),t.command(`run <name-or-file>`).description(`Run a saved graph over native subscriptions`).option(`--cloud`,`Run through Tangle's durable cloud workflow owner`).option(`--deploy <file>`,`Cloud deployment settings, including triggers and parameter defaults`).option(`--workflow <id>`,`Run this existing cloud deployment at its exact source and revision`).option(`--resume <run>`,`Resume this run's saved graph and durable execution`).option(`--seat <seat>`,`Use harness/model@effort for every node`).addOption(ws()).option(`--mcp-policy <file>`,`Host-owned JSON policy: allowLocalMcp and allowedMcpHosts; captured for resume`).option(`--seat-account <account>`,`Account id for an all-eligible authored seat`).option(`--seat-command <program>`,`Executable that prints the account id; the harness is its first argument`).option(`--seat-credential <credential>`,`Credential name passed to the seat command after the harness`).option(`--param <key=value>`,`Graph parameter or gate.<id>=<choice>; repeatable`,(e,t)=>[...t,e],[]).option(`--task-workspace <file>`,`Seed a private run copy from an exact local workspace capture`).option(`--dry-run`,`Validate and print the graph without starting agents`).action(async(t,n)=>{let r={...n,mcpPolicy:n.mcpPolicy===void 0?void 0:await Es(n.mcpPolicy)},i=await Xl(t,r);r.json||r.dryRun?e(i):`status`in i?(l(`${i.status} · ${i.runId}`),i.text&&console.log(i.text)):`viewerUrl`in i&&l(`Run ${i.runId} · ${i.viewerUrl}`)}),t}function tu(){let n=new N(`intelligence`).description(`Create and inspect trace intelligence reports`);return n.command(`connect [agent]`).alias(`connect-agent`).description(`Connect local agent CLIs to Tangle Intelligence`).option(`--endpoint <url>`,`OTLP endpoint base`,gi).option(`--workspace <path>`,`Workspace to write hook files into`,`.`).option(`--service-name <name>`,`OTel service.name label`).option(`--environment <name>`,`OTel deployment.environment label`,`local`).option(`--dry-run`,`Print planned writes without changing files`).option(`--hook-command <command>`,`Command native hooks should run`,`tangle intelligence hook`).option(`--no-smoke`,`Skip the install smoke trace`).action(async(t,n)=>{let r=t??`local`;xi(r);let i=ru(n.apiKey),a=await Ei({selection:r,workspace:n.workspace,apiKey:i,endpoint:n.endpoint,serviceName:n.serviceName??Ci(n.workspace),environment:n.environment,smoke:n.smoke,dryRun:!!n.dryRun,hookCommand:n.hookCommand}),o={configPath:a.configPath,agents:a.agents,nativeAgents:a.nativeAgents,manual:a.manual,written:a.written,smokeTraceId:a.smokeTraceId};if(n.json){e(o);return}s({Config:a.configPath,Agents:a.agents.join(`, `),"Native Hooks":a.nativeAgents.join(`, `)||void 0,"Manual Setup":a.manual.length?a.manual.map(e=>`${e.label}: ${e.reason}`).join(` `):void 0,Files:a.written.join(`, `),"Smoke Trace":a.smokeTraceId})}),n.command(`doctor`).description(`Check whether your agent traces carry CONTENT or are metadata-only`).option(`--endpoint <url>`,`OTLP endpoint base`,gi).action(async t=>{let n=Ti(),r=await ji({endpoint:t.endpoint===`https://intelligence.tangle.tools/v1/otlp`?n?.endpoint??`https://intelligence.tangle.tools/v1/otlp`:t.endpoint,apiKey:ru(t.apiKey??n?.apiKey)});t.json?e(r):nu(r),r.contentSeen||(process.exitCode=1)}),n.command(`hook`).description(`Emit one local agent hook event to Tangle Intelligence`).requiredOption(`--agent <agent>`,`Agent surface`).requiredOption(`--event <event>`,`Hook event name`).option(`--payload <json>`,`Hook payload JSON`).option(`--endpoint <url>`,`OTLP endpoint base`).option(`--service-name <name>`,`OTel service.name label`).option(`--environment <name>`,`OTel deployment.environment label`).option(`--session-id <id>`,`Session id override`).option(`--dry-run`,`Build the OTLP request without sending it`).option(`--non-blocking`,`Do not fail the parent agent process`).action(async t=>{try{let n=iu(t.agent),r=Ti(),i={agent:n,event:t.event,endpoint:t.endpoint??r?.endpoint??`https://intelligence.tangle.tools/v1/otlp`,apiKey:ru(t.apiKey??r?.apiKey),serviceName:t.serviceName??r?.serviceName??Ci(process.cwd()),environment:t.environment??r?.environment??`local`,sessionId:t.sessionId,payload:t.payload===void 0?await ou():au(t.payload)};if(t.dryRun){let r=Oi(i);if(t.json){e(r);return}s({Trace:r.traceId,Agent:n,Event:t.event});return}let a=await ki(i);if(t.json){e({traceId:a});return}s({Trace:a,Agent:n,Event:t.event})}catch(n){if(t.nonBlocking){let r=n instanceof Error?n.message:String(n);t.json?e({ok:!1,error:r}):console.error(`Tangle Intelligence hook skipped: ${r}`);return}H(n)}}),n.command(`sandbox <sandbox-id>`).description(`Create an intelligence report for one sandbox`).option(`--mode <mode>`,`deterministic | agentic`,`deterministic`).option(`--max-usd <amount>`,`Maximum customer charge for agentic analysis`).option(`--metadata <json>`,`Metadata JSON object`).action(async(e,t)=>{await su({type:`sandbox`,id:e},t)}),n.command(`fleet <fleet-id>`).description(`Create an intelligence report for a sandbox fleet`).option(`--mode <mode>`,`deterministic | agentic`,`deterministic`).option(`--max-usd <amount>`,`Maximum customer charge for agentic analysis`).option(`--metadata <json>`,`Metadata JSON object`).action(async(e,t)=>{await su({type:`fleet`,id:e},t)}),n.command(`create`).description(`Create a trace intelligence report`).requiredOption(`--subject-type <type>`,`sandbox | fleet`).requiredOption(`--subject-id <id>`,`Subject identifier`).option(`--mode <mode>`,`deterministic | agentic`,`deterministic`).option(`--max-usd <amount>`,`Maximum customer charge for agentic analysis`).option(`--metadata <json>`,`Metadata JSON object`).action(async e=>{await su({type:lu(e.subjectType),id:e.subjectId},e)}),n.command(`get <job-id>`).description(`Get an intelligence report`).action(async(t,n)=>{let{client:r}=G(n),i=n.json?null:f(`Fetching intelligence report...`);i?.start();let a=await r.intelligence.getReport(t);if(i?.stop(),n.json){e(a);return}cu(a)}),n.command(`list`).description(`List intelligence reports`).option(`--subject-type <type>`,`sandbox | fleet`).option(`--subject-id <id>`,`Subject identifier`).option(`--limit <count>`,`Maximum reports to return`).action(async n=>{let{client:r}=G(n),i=n.json?null:f(`Fetching intelligence reports...`);i?.start();let a=await r.intelligence.listReports({subjectType:n.subjectType===void 0?void 0:lu(n.subjectType),subjectId:n.subjectId,limit:n.limit===void 0?void 0:fu(n.limit)});if(i?.stop(),n.json){e(a);return}t(a.map(e=>({jobId:e.jobId,subject:`${e.subject.type}:${e.subject.id}`,mode:e.mode,status:e.status,cost:`$${e.billing.costUsd.toFixed(2)}`,updatedAt:e.updatedAt})),[{key:`jobId`,header:`Job`,width:20},{key:`subject`,header:`Subject`,width:28},{key:`mode`,header:`Mode`,width:15},{key:`status`,header:`Status`,width:14},{key:`cost`,header:`Cost`,width:10},{key:`updatedAt`,header:`Updated`,width:18}])}),n}function nu(e){s({Status:e.contentSeen?`content flowing`:e.tracesSeen?`metadata-only — a content gate is missing`:`no traces yet`,"Traces seen":e.tracesSeen?`yes`:`no`,"Content seen":e.contentSeen?`yes`:`no`,"Last seen":e.lastSeenAt??`never`,Window:`${e.windowDays}d`});let n=Object.entries(e.byAgent);n.length>0&&(console.log(),t(n.map(([e,t])=>({agent:e,traces:t.tracesSeen?`yes`:`no`,content:t.contentSeen?`yes`:`no`})),[{key:`agent`,header:`Agent`,width:18},{key:`traces`,header:`Traces`,width:10},{key:`content`,header:`Content`,width:10}]))}function ru(e){let t=e??process.env.TANGLE_INTELLIGENCE_API_KEY??process.env.TANGLE_API_KEY;if(!t)throw Error(`--api-key, TANGLE_INTELLIGENCE_API_KEY, or TANGLE_API_KEY is required`);return t}function iu(e){if(Si(e))return e;throw Error(`agent must be a known Tangle Intelligence agent surface`)}function au(e){try{return JSON.parse(e)}catch(e){throw Error(`--payload must be JSON: ${e instanceof Error?e.message:String(e)}`)}}async function ou(){if(process.stdin.isTTY)return;let e=``;for await(let t of process.stdin)if(e+=typeof t==`string`?t:t.toString(`utf8`),e.length>65536)throw Error(`hook payload exceeds 65536 bytes`);let t=e.trim();if(t)try{return JSON.parse(t)}catch{return{body:t.slice(0,4096)}}}async function su(t,n){let r=uu(n.mode),i=pu(n.metadata),a=n.maxUsd===void 0?void 0:du(n.maxUsd);if(r===`agentic`&&a===void 0)throw Error(`Agentic intelligence reports require --max-usd`);let{client:o}=G(n),s=n.json?null:f(`Creating intelligence report...`);s?.start();let c=await o.intelligence.createReport({subject:t,mode:r,...a===void 0?{}:{budget:{billTo:`customer`,maxUsd:a}},...i===void 0?{}:{metadata:i}});if(s?.stop(),n.json){e(c);return}cu(c)}function cu(t){s({Job:t.jobId,Subject:`${t.subject.type}:${t.subject.id}`,Mode:t.mode,Status:t.status,"Billed To":t.billing.billedTo,Cost:`$${t.billing.costUsd.toFixed(2)}`,Budget:t.billing.budgetMaxUsd===void 0?void 0:`$${t.billing.budgetMaxUsd.toFixed(2)}`,Updated:t.updatedAt}),t.result!==null&&(console.log(),e(t.result))}function lu(e){if(e===`sandbox`||e===`fleet`)return e;throw Error(`subject type must be sandbox or fleet`)}function uu(e){if(e===`deterministic`||e===`agentic`)return e;throw Error(`mode must be deterministic or agentic`)}function du(e){let t=Number(e);if(!Number.isFinite(t)||t<0)throw Error(`--max-usd must be a non-negative number`);return t}function fu(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}function pu(e){if(e===void 0)return;let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`--metadata must be a JSON object`);return t}const mu=[`router`,`sandbox`,`blueprint-agent`,`evals`,`agent-builder`];async function hu(e,t){let n=await Jn({...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.platformUrl===void 0?{}:{baseUrl:e.platformUrl},...e.baseUrl===void 0?{}:{sandboxBaseUrl:e.baseUrl}});if(!t||!n.minted)return n;throw Error("This command needs a key you minted yourself. A browser login is exchanged for a short-lived key the platform will not accept for key management. Set TANGLE_API_KEY, run `tangle auth login --api-key sk-tan-…`, or mint the key in the web console. `tangle keys list` works from the login alone.")}async function gu(e,t,n={}){let r=new Headers(n.headers);n.body&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`);let i=await Yn(e,t,{...n,headers:r});if(n.expected!==void 0&&i.status!==n.expected)throw Error(await _u(i,t));return i}async function _u(e,t){let n=await e.text().catch(()=>``),r;try{let e=JSON.parse(n),t=typeof e?.error==`string`?e.error:e?.error?.message;typeof t==`string`&&t.trim()&&(r=t)}catch{}if(r)return`${r} (HTTP ${e.status})`;let i=n?`: ${n.slice(0,400)}`:``;return`Platform request to ${t} returned ${e.status}${i}`}const vu=[`ID`,`Prefix`,`Name`,`Product`,`Created`,`Last used`,`Expires`];function yu(e){return[e.id,e.keyPrefix??``,e.name,e.product??`all`,e.createdAt,e.lastUsedAt??`—`,e.expiresAt??`—`]}function bu(){let t=new N(`keys`).description(`Manage sk-tan-* API keys on id.tangle.tools`);return t.command(`list`).description(`List your active API keys`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async t=>{let n=await hu(t,!1),r=n.baseUrl,a=await(await gu(n,`${r}/v1/keys`,{expected:200})).json();if(t.json){e(a);return}i(vu,a.data.map(yu))}),t.command(`create`).description(`Create a new API key`).argument(`<name>`,`Human-readable name for the key`).option(`--product <product>`,`Restrict the key to one product (${mu.join(`|`)}). Omit for all products.`).option(`--budget-usd <amount>`,`Hard budget cap in USD`).option(`--rpm-limit <limit>`,`Requests-per-minute cap`).option(`--expires-in-days <days>`,`Expire the key after N days (integer)`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async(t,n)=>{if(n.product!==void 0&&!mu.includes(n.product))throw Error(`Invalid --product. Expected one of ${mu.join(`, `)}`);let i=await hu(n,!0),a=i.baseUrl,o=n.expiresInDays===void 0?void 0:new Date(Date.now()+Number.parseInt(n.expiresInDays,10)*24*60*60*1e3).toISOString(),s=f(`Creating API key...`);s.start();let c=await gu(i,`${a}/v1/keys`,{method:`POST`,expected:201,body:JSON.stringify({name:t,product:n.product,budgetUsd:n.budgetUsd?Number.parseFloat(n.budgetUsd):void 0,rpmLimit:n.rpmLimit?Number.parseInt(n.rpmLimit,10):void 0,expiresAt:o})});s.stop();let u=await c.json();if(n.json){e(u);return}r(`API key created: ${u.data.prefix}…`),l(`Copy this key now — it will never be shown again:\n${u.data.key}`)}),t.command(`revoke`).description(`Revoke an API key`).argument(`<keyId>`,"Key ID (from `tcloud keys list`)").option(`--yes`,`Skip the confirmation prompt`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async(t,n)=>{let i=await hu(n,!0),a=i.baseUrl;if(!n.yes&&!await ur(`Revoke key ${t}? Any service still using it will start to fail.`,`--yes`)){l(`Aborted.`);return}let o=await(await gu(i,`${a}/v1/keys/${encodeURIComponent(t)}`,{method:`DELETE`,expected:200})).json();if(n.json){e(o);return}r(`Revoked ${t}`)}),t}function xu(e){if(an().token)throw Error(`A line relay cannot manage numbers or attachments. Use your owner CLI outside the agent box.`);return W(U(e))}function Su(e){if(!e.yes)throw Error(`Review the selected line and use --yes to authorize this change. Attaching enables metered agent work.`)}function Cu(e){if(e===`imessage`||e===`whatsapp`||e===`email`||e===`sms`||e===`voice`||e===`telegram`)return e;throw Error(`--transport must be imessage, whatsapp, email, sms, voice, or telegram`)}function wu(e){return e().catch(H)}async function Tu(e){let t=await mt(e,`r`);try{if(!(await t.stat()).isFile())throw Error(`Attachment input must be a regular JSON file`);let e=Buffer.alloc(131073),n=0;for(;n<e.length;){let{bytesRead:r}=await t.read(e,n,e.length-n,null);if(r===0)break;n+=r}if(n===e.length)throw Error(`Attachment JSON exceeds 128 KiB`);let r;try{r=JSON.parse(e.subarray(0,n).toString(`utf8`))}catch{throw Error(`Attachment file is not valid JSON`)}if(!r||typeof r!=`object`||Array.isArray(r))throw Error(`Attachment JSON must be an object`);if(Object.hasOwn(r,`number`))throw Error(`Use the line ID argument, not a number field in the attachment file`);return r}finally{await t.close()}}function Eu(t){t.command(`providers`).description(`List provider transports supported by this Hub deployment`).action(t=>wu(async()=>{e(await xu(t).lines.providers())})),t.command(`list`).description(`List owned lines, optionally for a saved agent profile or sandbox`).option(`--profile-id <id>`,`Stored profile ID`).option(`--sandbox <id>`,`Existing sandbox ID`).action(t=>wu(async()=>{e(await xu(t).lines.list({profileId:t.profileId,sandboxId:t.sandbox}))})),t.command(`get`).argument(`<line-id>`).description(`Inspect a line and its current attachment`).action((t,n)=>wu(async()=>{e(await xu(n).lines.get(t))})),t.command(`numbers`).argument(`<connection-id>`).description(`Discover owned provider numbers; this does not purchase or reserve a number`).option(`--transport <transport>`,`imessage, whatsapp, or sms`,`imessage`).action((t,n)=>wu(async()=>{let r=Cu(n.transport);if(r===`email`)throw Error(`Email uses an owned mailbox, not phone inventory`);if(r===`voice`)throw Error(`Voice numbers are listed by ph0ny; provide the owned number ID to lines connect`);if(r===`telegram`)throw Error(`Telegram uses an owned bot, not phone inventory`);e(await xu(n).lines.numbers(t,r))})),t.command(`connect`).argument(`<connection-id>`).description(`Bind an owned number or identity through Hub; no provider rental is purchased`).option(`--transport <transport>`,`imessage, whatsapp, sms, email, voice, or telegram`,`imessage`).option(`--number-id <id>`,`Exact owned provider number ID; required for voice, SMS, WhatsApp and Linq iMessage`).option(`--address <email>`,`Owned mailbox on a verified email domain`).requiredOption(`--reference <reference>`,`Stable client reference; keep it unchanged on retry`).option(`--label <label>`,`Line display name`).option(`--yes`,`Authorize provider webhook configuration and line binding`).action((t,n)=>wu(async()=>{Su(n);let r=Cu(n.transport);if(r!==`email`&&n.address)throw Error(`--address is email-only`);if((r===`email`||r===`telegram`)&&n.numberId)throw Error(`${r} does not take --number-id`);let i={connectionId:t,label:n.label,clientReference:n.reference},a;if(r===`email`)a={...i,transport:r,address:n.address};else if(r===`telegram`)a={...i,transport:r};else if(r===`imessage`)a={...i,transport:r,phoneNumberId:n.numberId};else{if(!n.numberId)throw Error(`${r} requires --number-id`);a={...i,transport:r,phoneNumberId:n.numberId}}e(await xu(n).lines.fromConnection(a))})),t.command(`attach`).argument(`<line-id>`).description(`Attach a saved agent to any sandbox, or use an isolated on-demand member instance`).option(`--file <path>`,`Reviewed native attachment JSON (exclusive with quick-setup flags)`).option(`--profile-id <id>`,`Owner-scoped saved profile; each turn pins its source revision`).option(`--member <address>`,`The one allowed sender: E.164 phone or email`).option(`--sandbox <id>`,`Use an existing sandbox instead of an on-demand instance`).option(`--instance-prefix <prefix>`,`Stable instance namespace; defaults to profile:<profile-id>:`).option(`--tools <mode>`,`chat denies tools; act applies the profile's tools and permissions`).option(`--turns-per-day <count>`,`Per-member daily turn ceiling (default 30)`).option(`--yes`,`Authorize agent execution and spend against your key limits`).action((t,n)=>wu(async()=>{Su(n);let r=xu(n),i;if(n.file){if(n.profileId||n.member||n.sandbox||n.instancePrefix||n.tools||n.turnsPerDay)throw Error(`Choose --file or quick-setup flags, not both`);i=await Tu(n.file)}else{if(!n.profileId||!n.member)throw Error(`Provide --profile-id and --member, or --file`);if(n.sandbox&&n.instancePrefix)throw Error(`Choose --sandbox or --instance-prefix`);let e=n.tools??`chat`,t=Number(n.turnsPerDay??`30`);if(e!==`chat`&&e!==`act`)throw Error(`--tools must be chat or act`);if(!Number.isSafeInteger(t)||t<1||t>1e4)throw Error(`--turns-per-day must be 1–10000`);if(e===`act`&&n.sandbox)throw Error(`Acting tools require an isolated on-demand instance; omit --sandbox`);i={mode:`personal`,members:[{address:n.member,role:`owner`}],unknownSenders:`reject`,roles:{owner:{context:`own`,tools:e}},respond:{kind:`agent`,profileId:n.profileId,...e===`act`?{rolePolicy:{version:1,roles:{owner:{kind:`general`}},members:{}}}:{}},limits:{turnsPerMemberPerDay:t},...n.sandbox?{sandboxId:n.sandbox}:{instance:{keyPrefix:n.instancePrefix??`profile:${n.profileId}:`,create:{ownerContext:`isolated`,...e===`act`?{egressPolicy:{mode:`strict`,allowDomains:[new URL(Cn()).hostname],includeImplicitDomains:!1}}:{}}}}}}if(typeof i.sandboxId==`string`==(i.instance!==void 0))throw Error(`Attachment requires exactly one of sandboxId and instance`);let{sandboxId:a,instance:o,...s}=i,c;if(a){let e=await r.get(a);if(!e)throw Error(`Sandbox not found`);c=await e.lines.attach({...s,number:t})}else{if(!o)throw Error(`Attachment requires an instance`);c=await r.lines.attach({...s,number:t,instance:o})}e(c)}));for(let n of[`detach`,`release`])t.command(n).argument(`<line-id>`).description(n===`detach`?`Stop dispatch; preserve history and provider rental`:`Retire a detached Hub line; does not cancel provider rental`).option(`--yes`,`Authorize this change`).action((t,r)=>wu(async()=>{Su(r),e({[n]:await xu(r).lines[n](t)})}));t.command(`threads`).argument(`<line-id>`).description(`List this line's separate participant threads`).action((t,n)=>wu(async()=>{e(await xu(n).lines.threads(t).list())})),t.command(`messages`).argument(`<line-id>`).argument(`<thread-id>`).description(`Read one authorized participant thread`).action((t,n,r)=>wu(async()=>{e(await xu(r).lines.threads(t).messages(n))}))}async function Du(e){let{token:t,baseUrl:n}=an();if(t===void 0)return K(e);if(!t.startsWith(`lrc_`)||!n)throw Error(`The line box needs TANGLE_LINE_TOKEN and TANGLE_HUB_URL`);if(e.apiKey||e.baseUrl&&new URL(e.baseUrl).origin!==new URL(n).origin)throw Error(`A line token cannot be sent to another Hub or combined with an API key`);return new Ge({baseUrl:n,authHeaders:()=>({Authorization:`Bearer ${t}`})})}async function Ou(e,t){if(t)return t;if(!an().token)throw Error(`Provide --line <line-id>`);return(await e.lines.context()).line.id}function ku(e){return e().catch(H)}function Au(){return new N(`context`).description(`Show live line identity, members, consent, reminders and quotas`).action(t=>ku(async()=>{e(await(await Du(t)).lines.context())}))}function ju(){let t=new N(`lines`).description(`Connect, manage, message and schedule on a Hub line`);return t.command(`members`).description(`List names, roles and consent on this line`).option(`--line <line-id>`,`Line ID; inferred in a line box`).action(t=>ku(async()=>{let n=await Du(t);e(await n.lines.members.list(await Ou(n,t.line)))})),t.command(`send`).description(`Send to a consenting member through Hub`).argument(`<to-member>`,`Exact member ID for an owner; name, ID, or self in a line box`).argument(`<text>`,`Message text`).option(`--line <line-id>`,`Line ID; inferred in a line box`).option(`--on-behalf-of <member>`,`Verified sender for a member relay`).option(`--not-before <iso-time>`,`Delay delivery until this ISO time`).option(`--idempotency-key <key>`,`Stable key for a retry`).action((t,n,r)=>ku(async()=>{let i=await Du(r),a=await Ou(i,r.line);if(!an().token){if(r.onBehalfOf)throw Error(`--on-behalf-of is only available inside a line box`);if(!r.idempotencyKey)throw Error(`Owner sends require --idempotency-key so a retry keeps the same message`);if(!(await i.lines.members.list(a)).some(e=>e.id===t))throw Error(`Owner sends require an exact member ID from tangle lines members`);e(await i.lines.send(a,{memberId:t,text:n,idempotencyKey:r.idempotencyKey,...r.notBefore?{notBefore:r.notBefore}:{}}));return}e(await i.lines.send(a,{toMember:t,text:n,...r.onBehalfOf?{onBehalfOf:r.onBehalfOf}:{},...r.notBefore?{notBefore:r.notBefore}:{},...r.idempotencyKey?{idempotencyKey:r.idempotencyKey}:{}}))})),t.command(`remind`).description(`Wake the agent at a future time to write your reminder`).argument(`<text>`,`What to remember`).requiredOption(`--at <iso-time>`,`Future ISO time`).option(`--line <line-id>`,`Line ID; inferred in a line box`).option(`--idempotency-key <key>`,`Stable key for a retry`).action((t,n)=>ku(async()=>{if(!n.at)throw Error(`--at is required`);let r=await Du(n),i=n.idempotencyKey??ve(`sha256`).update(JSON.stringify([t,n.at])).digest(`hex`).slice(0,32);e(await r.lines.remind(await Ou(r,n.line),{text:t,notBefore:n.at,idempotencyKey:i}))})),Eu(t),t}function Mu(){let e=new N(`mcp`).description(`Model Context Protocol bridge commands.`);return e.command(`serve <id-or-name>`).description(`Run a local MCP server (stdio) backed by the given sandbox (ID or name). Pipe its stdio from an MCP client config to expose sandbox tools.`).option(`-s, --session <id>`,`Session id for kernel scoping`,`mcp-local`).option(`--name <name>`,`MCP server name reported to clients`,`tangle-sandbox`).action(async(e,t)=>{let n=U({apiKey:t.apiKey,baseUrl:t.baseUrl}),r=await q(W(n),n,e),i;try{i=(await import(`@modelcontextprotocol/sdk/server/stdio.js`)).StdioServerTransport}catch{throw Error("`@modelcontextprotocol/sdk` is not installed in this environment. Install it with: pnpm add -g @modelcontextprotocol/sdk (or as a dev dep in the project running this command).")}let{connect:a,close:o}=await(await import(`@tangle-network/sandbox/agent`)).createMcpServer(r,{sessionId:t.session,name:t.name});await a(new i),process.stdin.resume(),process.stdin.on(`end`,()=>{o().finally(()=>process.exit(0))});for(let e of[`SIGINT`,`SIGTERM`])process.on(e,()=>{o().finally(()=>process.exit(0))})}),e}async function Nu(e,t){if(t.self&&e)throw Error(`Use --self or an explicit sandbox, not both`);if(!t.self&&!e)throw Error(`Specify a sandbox id/name or --self`);let n=Yt(),r=t.baseUrl||n.tangleBaseUrl||n.sandboxBaseUrl,i=n.hubUrl;if(t.self&&!r&&i&&new URL(i).origin!==`https://id.tangle.tools`)throw Error(`This deployment must set SANDBOX_BASE_URL or pass --base-url for self preview access`);let a=t.self?t.apiKey??hn():t.apiKey;if(t.self&&!a)throw Error(`Self preview access requires the injected sandbox runtime credential; it never reads saved owner credentials`);let o=U({apiKey:a,baseUrl:r}),s=W(o);return t.self?Ct(s):q(s,o,e)}async function Pu(e,t,n){let r=f(e);t||r.start();try{return await n()}finally{r.stop()}}function Fu(e){return e}function Iu(){let t=new N(`preview`).description(`Manage sandbox preview links`);return Fu(t.command(`start`).description(`Start/reuse a managed development server and publish its ready preview`).argument(`[id-or-name]`,`Sandbox ID or name`).option(`--self`,`Use only the sandbox bound to the runtime credential`).option(`--cwd <directory>`,`Project directory in the selected workspace`).option(`--session <session-id>`,`Select the agent's session workspace`).option(`--name <name>`,`App/service label`)).action(async(t,n)=>{let i=await Nu(t,n),a=await Pu(`Starting managed preview...`,n.json,()=>xt(i,{cwd:n.cwd,sessionId:n.session,name:n.name}));n.json?e(a):(r(`Preview ready: ${a.url}`),console.log(`Preview ID: ${a.previewId}`))}),Fu(t.command(`list`).alias(`ls`).description(`List active preview links for a sandbox`).argument(`[id-or-name]`,`Sandbox ID or name`).option(`--self`,`Use only the sandbox bound to the runtime credential`)).action(async(t,n)=>{let r=await Nu(t,n),a=await Pu(`Fetching preview links...`,n.json,()=>r.previewLinks.list());n.json?e(a):a.length===0?console.log(`No preview links found`):i([`App`,`Preview ID`,`Port`,`URL`,`Status`],a.map(e=>[Lu(e.metadata),e.previewId.slice(0,12),String(e.port),e.url,e.status]))}),Fu(t.command(`publish`).description(`Publish one existing HTTP service; never starts or replaces a process`).argument(`[id-or-name]`,`Sandbox ID or name`).option(`--self`,`Use only the sandbox bound to the runtime credential`).requiredOption(`--port <port>`,`Existing service port`).option(`--name <name>`,`App/service label`)).action(async(t,n)=>{if(!n.port||!/^\d+$/.test(n.port))throw Error(`An integer service port is required`);let i=await Nu(t,n),a=await Pu(`Publishing service...`,n.json,()=>St(i,{port:Number(n.port),name:n.name}));n.json?e(a):r(`Preview ready: ${a.url}`)}),Fu(t.command(`create`).description(`Create a preview link for a port`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<port>`,`Port number to preview`)).action(async(t,n,i)=>{if(!/^\d+$/.test(n)||Number(n)<1||Number(n)>65535)throw Error(`Port must be an integer between 1 and 65535`);let a=await Nu(t,i),o=await Pu(`Creating preview for port ${n}...`,i.json,()=>a.previewLinks.create(Number(n)));i.json?e(o):(r(`Preview created: ${o.url}`),console.log(`Preview ID: ${o.previewId}`))}),Fu(t.command(`remove`).alias(`rm`).description(`Remove a preview link`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<preview-id>`,`Preview link ID (from 'preview list')`)).action(async(t,n,i)=>{let a=await Nu(t,i);await Pu(`Removing preview...`,i.json,()=>a.previewLinks.remove(n)),i.json?e({success:!0,previewId:n}):r(`Preview removed: ${n}`)}),t}function Lu(e){let t=e?.app;if(!t||typeof t!=`object`)return``;let n=`name`in t?t.name:void 0,r=`cwd`in t?t.cwd:void 0;return typeof n==`string`?n:typeof r==`string`?r:``}function Ru(){let t=new N(`process`).description(`Manage processes in a sandbox`);return t.command(`spawn`).description(`Spawn a process without blocking (returns PID)`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<command>`,`Command to execute`).option(`--cwd <dir>`,`Working directory`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).option(`-t, --timeout <ms>`,`Timeout in milliseconds`).option(`--blocking`,`Wait for completion (default: false)`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=mo(r.env??[],`--env`,`env`),s=f(`Spawning: ${n}`);r.json||s.start();let c=await q(a,i,t);if(c=await J(c),r.blocking){let t=await c.exec(n,{cwd:r.cwd,env:Object.keys(o).length>0?o:void 0,timeoutMs:r.timeout?Number.parseInt(r.timeout,10):void 0});s.stop(),r.json?e(t):(t.stdout&&globalThis.process.stdout.write(t.stdout),t.stderr&&globalThis.process.stderr.write(t.stderr),t.exitCode!==0&&globalThis.process.exit(t.exitCode))}else{let i=await c.process.spawn(n,{cwd:r.cwd,env:Object.keys(o).length>0?o:void 0,timeoutMs:r.timeout?Number.parseInt(r.timeout,10):void 0});s.stop(),r.json?e({pid:i.pid,command:i.command}):(console.log(`Process started with PID: ${i.pid}`),console.log(`Use 'tangle process logs ${t} ${i.pid}' to view output`))}}),t.command(`list`).alias(`ls`).description(`List all processes in a sandbox`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--running`,`Show only running processes`).action(async(t,n)=>{let{context:r,client:a}=G(n),o=f(`Fetching processes...`);n.json||o.start();let s=await q(a,r,t);s=await J(s);let c=await s.process.list();n.running&&(c=c.filter(e=>e.running)),o.stop(),n.json?e(c):c.length===0?console.log(`No processes found`):i([`PID`,`Command`,`Status`,`Exit Code`,`Started`],c.map(e=>[String(e.pid),e.command.length>40?`${e.command.slice(0,37)}...`:e.command,e.running?`running`:`exited`,String(e.exitCode),e.startedAt.toLocaleString()]))}),t.command(`get`).description(`Get detailed info about a process`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching process info...`);r.json||o.start();let s=await q(a,i,t);s=await J(s);let c=await s.process.get(Number.parseInt(n,10));if(o.stop(),!c){console.error(`Process ${n} not found`),globalThis.process.exit(1);return}let l=await c.status();r.json?e(l):(console.log(`PID: ${l.pid}`),console.log(`Command: ${l.command}`),console.log(`CWD: ${l.cwd||`(default)`}`),console.log(`Status: ${l.running?`running`:`exited`}`),console.log(`Exit Code: ${l.exitCode}`),l.exitSignal&&console.log(`Signal: ${l.exitSignal}`),console.log(`Started: ${l.startedAt.toLocaleString()}`),l.exitedAt&&console.log(`Exited: ${l.exitedAt.toLocaleString()}`))}),t.command(`kill`).description(`Kill a process`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).option(`-s, --signal <signal>`,`Signal to send (SIGTERM, SIGKILL, etc.)`,`SIGTERM`).option(`--tree`,`Also kill descendants of the tracked process`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=f(`Sending ${r.signal} to PID ${n}...`);r.json||o.start();let s=await q(a,i,t);s=await J(s);let c=await s.process.get(Number.parseInt(n,10));if(!c){o.stop(),console.error(`Process ${n} not found`),globalThis.process.exit(1);return}r.tree?await c.kill(r.signal,{tree:!0}):await c.kill(r.signal),o.stop(),r.json?e({pid:Number.parseInt(n,10),signal:r.signal,...r.tree===!0?{tree:!0}:{},killed:!0}):console.log(r.tree?`Sent ${r.signal} to process tree ${n}`:`Sent ${r.signal} to process ${n}`)}),t.command(`logs`).description(`Stream buffered and live process logs until the process exits`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).option(`--stdout-only`,`Only show stdout`).option(`--stderr-only`,`Only show stderr`).action(async(e,t,n)=>{let{context:r,client:i}=G(n),a=await q(i,r,e);a=await J(a);let o=await a.process.get(Number.parseInt(t,10));if(!o){console.error(`Process ${t} not found`),globalThis.process.exit(1);return}for await(let e of o.logs())n.stdoutOnly&&e.type!==`stdout`||n.stderrOnly&&e.type!==`stderr`||(n.json?console.log(JSON.stringify(e)):e.type===`stdout`?globalThis.process.stdout.write(e.data):globalThis.process.stderr.write(e.data))}),t}const zu=[`python`,`node`,`typescript`,`bash`];function Bu(e){switch(de(e).toLowerCase()){case`.py`:return`python`;case`.js`:case`.mjs`:case`.cjs`:return`node`;case`.ts`:case`.tsx`:return`typescript`;case`.sh`:case`.bash`:return`bash`;default:return}}async function Vu(e){if(e===`-`){let e=[];for await(let t of process.stdin)e.push(typeof t==`string`?Buffer.from(t):t);return Buffer.concat(e).toString(`utf8`)}return await L(he(e),`utf8`)}async function Hu(e,t,n=Vu){let r=t?zu.find(e=>e===t)??(()=>{throw Error(`unknown --lang ${t}: must be one of ${zu.join(`, `)}`)})():void 0;if(!e||e===`-`){if(!r)throw Error(`reading from stdin requires --lang. Example: tangle run <id> -l python -`);return{language:r,source:await n(`-`)}}let i=Bu(e);return{language:r??i??(()=>{throw Error(`cannot infer language from "${e}". Pass it explicitly: tangle run <id> -l <python|node|typescript|bash> ${e}`)})(),source:await n(e)}}function Uu(e){return M(Ve(),`tangle-run-images`,e)}function Wu(){return new N(`run`).description(`Run code in a persistent kernel inside a sandbox. Variables persist across calls in the same --session.`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`[file]`,`Path to source file. Language is inferred from extension. Use - for stdin (requires --lang).`).option(`-l, --lang <lang>`,`Force language: ${zu.join(` | `)}. Required for stdin.`).option(`-s, --session <id>`,`Session id for kernel scoping`).option(`-t, --timeout <ms>`,`Per-call timeout in ms (0 disables)`,`60000`).option(`--save-images <dir>`,`Write image results into this directory (default: $TMPDIR/tangle-run-images/<sandbox>/).`).option(`--no-save-images`,`Don't write image results to disk; print summary only`).action(async(t,n,r)=>{let{language:i,source:a}=await Hu(n,r.lang),{context:o,client:s}=G(r),c=await q(s,o,t);c=await J(c);let l=f(`Running ${i} (${a.length}b)…`);r.json||l.start();let u=await c.runCode(i,a,{sessionId:r.session,timeoutMs:Number.parseInt(r.timeout,10)});if(l.stop(),r.json){e(u),u.exitCode!==0&&process.exit(u.exitCode);return}u.stdout&&process.stdout.write(u.stdout),u.stderr&&process.stderr.write(u.stderr);let d=0;for(let e of u.results)if(e.type===`image`)if(r.saveImages!==!1){let n=typeof r.saveImages==`string`?r.saveImages:Uu(t);Fe(n,{recursive:!0});let i=`${n}/${Date.now()}-${d}.${e.format}`;ze(i,Buffer.from(e.data,`base64`)),process.stderr.write(j.green(`✓ image → ${i}\n`)),d++}else process.stderr.write(j.gray(`[image: ${e.format}, ${e.data.length}b base64]\n`));else if(e.type===`dataframe`){let t=e.columns.map(e=>`${e.name}:${e.dtype}`).join(` | `);process.stderr.write(j.gray(`[dataframe ${e.rows.length}×${e.columns.length}${e.truncated?` (truncated)`:``}]\n`)),process.stderr.write(`${t}\n`);for(let t of e.rows.slice(0,20))process.stderr.write(`${t.map(e=>String(e)).join(` | `)}\n`);e.rows.length>20&&process.stderr.write(j.gray(`… ${e.rows.length-20} more rows\n`))}else e.type===`json`?(process.stderr.write(j.gray(`[json] `)),process.stderr.write(`${JSON.stringify(e.value,null,2)}\n`)):e.type===`html`?process.stderr.write(j.gray(`[html ${e.value.length}b]\n`)):e.type===`error`?(process.stderr.write(j.red(`✗ ${e.name}: ${e.message}\n`)),e.traceback&&process.stderr.write(`${e.traceback}\n`)):e.type===`text`&&process.stderr.write(`${e.value}\n`);u.error&&(process.stderr.write(j.red(`\n✗ ${u.error.name}: ${u.error.message}\n`)),u.error.traceback&&process.stderr.write(`${u.error.traceback}\n`)),u.exitCode!==0&&process.exit(u.exitCode)})}function Gu(t){t.command(`network <id-or-name>`).description(`Show runtime network state (exposed ports) for a sandbox. Outbound policy is the sandbox's egress policy.`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Updating network configuration...`);a.start();let o=await q(i,r,t);a.stop();let s=await o.network.getConfig();n.json?e(s):(l(`Network Configuration:`),s.ports&&s.ports.length>0?l(` Exposed Ports: ${s.ports.join(`, `)}`):l(` No exposed ports`))}),t.command(`expose <id-or-name>`).description(`Expose a port and get a public URL`).option(`-p, --port <port>`,`Port to expose`,`8000`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=Number.parseInt(n.port,10);if(Number.isNaN(o)||o<1||o>65535)throw Error(`Port must be a number between 1 and 65535`);let s=f(`Exposing port ${o}...`);s.start();let c=await(await q(a,i,t)).network.exposePort(o);s.stop(),n.json?e({port:o,url:c}):(r(`Port ${o} exposed.`),l(` URL: ${c}`))}),t.command(`urls <id-or-name>`).description(`List exposed port URLs for a sandbox`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching exposed URLs...`);a.start();let o=await(await q(i,r,t)).network.listUrls();if(a.stop(),n.json)e(o);else{let e=Object.entries(o);if(e.length===0)l(`No ports exposed.`);else{l(`Exposed Ports:`);for(let[t,n]of e)l(` ${t}: ${n}`)}}})}function Ku(){let e=new N(`sandbox`).description(`Manage sandboxes`);return Jo(e),qo(e),Lo(e),Gu(e),e}function qu(){return new N(`search`).description(`Search for text patterns in sandbox files (ripgrep)`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pattern>`,`Search pattern (regex)`).option(`-g, --glob <pattern>`,`File glob filter (e.g. '**/*.ts')`).option(`-n, --max-results <count>`,`Max results to return`).option(`-i, --ignore-case`,`Case-insensitive search`).action(async(e,t,n)=>{let{context:r,client:i}=G(n),a=f(`Searching...`);n.json||a.start();let o=await q(i,r,e),s=0,c=n.maxResults?Number.parseInt(n.maxResults,10):void 0,l={};n.glob&&(l.glob=n.glob),n.ignoreCase&&(l.ignoreCase=!0),c&&(l.maxResults=c);for await(let e of o.search(t,l))if(s===0&&a.stop(),s++,n.json?console.log(JSON.stringify(e)):console.log(`${e.path}:${e.line}:${e.column??0}: ${e.text}`),c&&s>=c)break;a.stop(),s===0&&!n.json&&console.log(`No matches found`)})}function Ju(){let t=new N(`secret`).description(`Manage secrets`);return t.command(`create`).description(`Create a new secret`).argument(`<name>`,`Secret name (e.g., HF_TOKEN, AWS_ACCESS_KEY)`).argument(`[value]`,`Secret value`).option(`--value-stdin`,`Read secret value from stdin`).action(async(t,n,i)=>{let a=await G(i).client.secrets.create(t,await Yu({value:n,valueStdin:i.valueStdin,prompt:`Enter value for secret '${t}': `}));i.json?e(a):(r(`Secret created: ${a.name}`),l(`Use --secret ${a.name} when creating a sandbox to select it for delivery.`))}),t.command(`list`).description(`List all secrets`).action(async t=>{let n=await G(t).client.secrets.list();t.json?e(n):n.length===0?(l(`No secrets found.`),l(`Use 'tangle secret create <name> [value]' to create one.`)):i([`Name`,`Created At`,`Updated At`],n.map(e=>[e.name,e.createdAt.toLocaleString(),e.updatedAt.toLocaleString()]))}),t.command(`delete`).description(`Delete a secret`).argument(`<name>`,`Secret name`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=G(n).client;if(!n.force&&!await ur(`Are you sure you want to delete secret '${t}'? This cannot be undone. (y/N) `,`--force`)){l(`Cancelled.`);return}await i.secrets.delete(t),n.json?e({success:!0,deleted:t}):r(`Secret deleted: ${t}`)}),t}async function Yu(e){if(e.value!==void 0&&e.valueStdin)throw Error(`Provide either a secret value argument or --value-stdin, not both`);let t=e.value??(e.valueStdin?await fr():await lr(e.prompt));if(!t.length)throw Error(e.valueStdin?`Secret value from stdin cannot be empty`:`Secret value cannot be empty`);return t}function Xu(){let e=new N(`skill`).description(`Print paths to shipped skill documentation`);return e.command(`path`).description(`Print the absolute path to the SKILL.md shipped with this CLI`).action(()=>{let e=ce.dirname(yt(import.meta.url)),t=ce.resolve(e,`..`,`SKILL.md`);console.log(t)}),e}function Zu(){let n=new N(`snapshot`).description(`Manage snapshots`);return n.command(`create <sandbox-id-or-name>`).description(`Create a snapshot of a sandbox`).option(`--tags <tags...>`,`Tags for the snapshot`).option(`--no-wait`,`Return once the snapshot is accepted and print the operation to poll`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=f(`Creating snapshot...`);o.start();let s=await q(a,i,t);if(n.wait===!1){let e=await s.snapshot({tags:n.tags,wait:!1});o.stop(),Ro(e.info,!!n.json);return}let c=await s.snapshot({tags:n.tags});o.stop(),n.json?e(c):(r(`Snapshot created: ${c.snapshotId}`),console.log(`Size: ${Qu(c.sizeBytes??0)}`))}),n.command(`list <sandbox-id-or-name>`).description(`List snapshots for a sandbox`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching snapshots...`);o.start();let s=await(await q(a,i,n)).listSnapshots();o.stop(),r.json?e(s):t(s.map(e=>({...e,size:Qu(e.sizeBytes??0)})),[{key:`snapshotId`,header:`ID`,width:24},{key:`createdAt`,header:`Created`,width:16},{key:`size`,header:`Size`,width:12},{key:`sandboxId`,header:`Sandbox`,width:20}])}),n.command(`restore <sandbox-id> <snapshot-id>`).description(`Create a new sandbox from a snapshot`).option(`--billing-owner <userId>`,`Platform user that pays for the restored sandbox. The API accepts this only from a first-party service key that is listed as a billing delegate, and refuses such a key that names no payer.`).action(async(t,n,i)=>{let{client:a}=G(i),o=f(`Restoring from snapshot...`);o.start();let s=await a.create({fromSnapshot:n,fromSandboxId:t,...i.billingOwner?{billingOwnerId:i.billingOwner}:{}});await s.waitFor(`running`,{timeoutMs:12e4}),o.stop(),i.json?e({sandboxId:s.id,restoredFrom:n,status:s.status}):(r(`New sandbox created: ${s.id}`),console.log(`Source snapshot: ${n}`))}),n.command(`revert <sandbox-id-or-name> <snapshot-id>`).description(`Revert an existing sandbox to a snapshot`).action(async(t,n,i)=>{let{context:a,client:o}=G(i),s=f(`Reverting sandbox to snapshot...`);s.start();let c=await q(o,a,t),l=await c.revertToSnapshot(n);await c.refresh(),s.stop(),i.json?e({sandboxId:c.id,snapshotId:l.snapshotId,status:c.status}):(r(`Sandbox reverted: ${c.id}`),console.log(`Source snapshot: ${l.snapshotId}`))}),n.command(`delete <sandbox-id-or-name> <snapshot-id>`).description(`Delete a sandbox snapshot`).action(async(t,n,i)=>{let{context:a,client:o}=G(i),s=f(`Deleting snapshot...`);s.start();let c=await(await q(o,a,t)).deleteSnapshot(n);s.stop(),i.json?e({success:!0,sandboxId:t,snapshotId:n,outcome:c.outcome}):c.outcome===`already_absent`?r(`Snapshot already gone: ${n}`):r(`Snapshot deleted: ${n}`)}),n}function Qu(e){if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`,`TB`],r=Math.floor(Math.log(e)/Math.log(t));return`${Number.parseFloat((e/t**r).toFixed(1))} ${n[r]}`}const $u=()=>import(`./device-i0PzYisd.mjs`);function ed(){let e=new N(`solve`).description(`Participate in Tangle Solve competitions`);e.command(`clone <competition>`).description(`Clone the pinned competition repository`).argument(`[directory]`,`Destination directory`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async(e,t,n)=>(await import(`./clone-CWY8dI5d.mjs`)).cloneCompetition(e,t,n)),e.command(`run [competition]`).description(`Run the competition checker and record its evidence`).option(`--directory <path>`,`Competition directory (defaults to the current directory)`).action(async(e,t)=>(await import(`./run-BSXC2ytE.mjs`)).runCompetition(e,t)),e.command(`submit [competition]`).description(`Submit checker evidence through the device account and Tempo`).option(`--directory <path>`,`Competition directory (defaults to the current directory)`).option(`--pr-url <url>`,`GitHub pull request containing the submission`).option(`--model <name>`,`Model used to produce the submission`).option(`--note <text>`,`Short note shown with the accepted submission`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async(e,t)=>(await import(`./submit-D2jvFJtX.mjs`)).submitCompetition(e,t)),e.command(`account`).description(`Show the local Solve signing account`).option(`--create`,`Create the account if it does not exist`).action(async e=>(await import(`./account-BaGFNxyq.mjs`)).showSolveAccount(e));let t=e.command(`device`).description(`List and revoke the Solve devices bound to your account`);return t.command(`list`).description(`List your devices and whether each may submit jobs on Tempo`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async e=>(await $u()).listSolveDevices(e)),t.command(`revoke <address>`).description(`Permanently revoke a device; the local device is revoked with its own key`).option(`--reason <text>`,`Why the device is revoked (shown to the account)`).option(`--yes`,`Confirm the permanent revocation without a prompt`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async(e,t)=>(await $u()).revokeSolveDevice(e,t)),e}function td(e,t){return`tangle ssh-proxy ${e.replace(/\/+$/,``)}/v1/sandboxes/${t}/runtime/ssh`}function nd(e){return/^[A-Za-z0-9_/:=@%+.,-]+$/.test(e)?e:`'${e.replace(/'/g,`'"'"'`)}'`}function rd(e){return`'${e.replace(/'/g,`''`)}'`}function id(e){return e===`win32`?`NUL`:`/dev/null`}function ad(e,t){return t===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN=${rd(`<token>`)}; ssh ${e.map(rd).join(` `)}`:`TANGLE_SSH_PROXY_AUTH_TOKEN=${nd(`<token>`)} ssh ${e.map(nd).join(` `)}`}function od(e){return e.connection!==void 0&&!e.connection.ssh}function sd(){d(`SSH is not enabled for this sandbox.`),l(`Create a sandbox with --ssh to enable SSH access.`),process.exit(1)}function cd(e,t=[],n=process.platform){let r=id(n);return[`-o`,`ProxyCommand=${e.proxyCommand}`,`-o`,`StrictHostKeyChecking=no`,`-o`,`UserKnownHostsFile=${r}`,`-o`,`GlobalKnownHostsFile=${r}`,`-o`,`LogLevel=ERROR`,`-o`,`ServerAliveInterval=15`,`-o`,`ServerAliveCountMax=4`,`-o`,`TCPKeepAlive=yes`,`${e.username}@localhost`,`-p`,String(e.port),...t]}function ld(){return new N(`ssh`).description(`Open SSH session to a sandbox`).argument(`<ref>`,`Sandbox ID or name`).argument(`[sshArgs...]`,`Extra args passed through to ssh`).option(`-i, --identity-file <path>`,`Private key file to pass to ssh`).option(`--print`,`Print SSH command instead of connecting`).allowUnknownOption(!0).action(async(e,t,n)=>{let{context:r,client:i}=G(n),a=f(`Getting SSH credentials...`);a.start();let o=await q(i,r,e);if(od(o)){a.stop(),sd();return}o=await J(o);let s=await o.ssh();if(a.stop(),!s){sd();return}let c={...s,proxyCommand:td(r.baseUrl,o.id)};if(!r.apiKey)throw Error(`SSH proxy requires API key auth. Set TANGLE_API_KEY or pass --api-key.`);let u=cd(c,[...n.identityFile?[`-i`,n.identityFile,`-o`,`IdentitiesOnly=yes`]:[],...t]);if(n.print){console.log(ad(u,process.platform));return}l(`Connecting via tunnel...`);let p=We(`ssh`,u,{stdio:`inherit`,env:{...process.env,TANGLE_SSH_PROXY_AUTH_TOKEN:r.apiKey}});p.on(`error`,e=>{e.code===`ENOENT`&&(d(`SSH client not found. Please install OpenSSH.`),process.exit(1)),H(e)}),p.on(`exit`,e=>{process.exit(e??0)})})}function ud(){let t=new N(`ssh-keys`).description(`Manage SSH keys`);return t.command(`list`).description(`List SSH keys`).action(async t=>{let n=f(`Fetching SSH keys...`);try{n.start();let r=await W(U(t)).sshKeys.list();n.stop(),t.json?e({sshKeys:r}):r.length===0?l(`No SSH keys found.`):i([`Name`,`Type`,`Fingerprint`,`Created`],r.map(e=>[e.name,e.keyType,e.fingerprint,e.createdAt.toLocaleString()]))}catch(e){n.stop(),H(e)}}),t.command(`add`).description(`Add SSH key`).argument(`<name>`,`SSH key name`).requiredOption(`--key-file <path>`,`Public key file path`).action(async(t,n)=>{let i=f(`Adding SSH key...`);try{let a=Ie(n.keyFile,`utf8`).trim();i.start();let o=await W(U(n)).sshKeys.create(t,a);i.stop(),n.json?e({sshKey:o}):r(`Added SSH key ${o.name} (${o.fingerprint})`)}catch(e){i.stop(),H(e)}}),t.command(`delete`).description(`Delete SSH key`).argument(`<name>`,`SSH key name or ID`).action(async(e,t)=>{let n=f(`Deleting SSH key...`);try{n.start(),await W(U(t)).sshKeys.delete(e),n.stop(),r(`Deleted SSH key ${e}`)}catch(e){n.stop(),H(e)}}),t}function dd(e,t=1){process.stderr.write(`${e}\n`),process.exit(t)}function fd(){return new N(`ssh-proxy`).description(`SSH proxy helper that pipes stdin/stdout to WebSocket`).argument(`<runtime-url>`,`Runtime WebSocket URL`).action(async e=>{let t=process.env.TANGLE_SSH_PROXY_AUTH_TOKEN;t||dd(`TANGLE_SSH_PROXY_AUTH_TOKEN not set`);let n=new URL(e.replace(/^http/,`ws`)),{default:r}=await import(`ws`),i=new r(n,{headers:{Authorization:`Bearer ${t}`},perMessageDeflate:!1}),a;function o(){a&&=(clearInterval(a),void 0)}i.on(`open`,()=>{a=setInterval(()=>{i.readyState===r.OPEN&&i.ping()},15e3),a.unref?.(),process.stdin.on(`data`,e=>{i.readyState===r.OPEN&&i.send(e,{binary:!0,compress:!1})}),process.stdin.on(`end`,()=>i.close(1e3))}),i.on(`message`,e=>{let t=Buffer.isBuffer(e)?e:Array.isArray(e)?Buffer.concat(e):Buffer.from(e);process.stdout.write(t)}),i.on(`error`,e=>{o(),dd(`WebSocket error: ${e.message}`)}),i.on(`close`,e=>{o(),process.exit(e===1e3?0:1)}),process.stdin.on(`error`,()=>i.close())})}function pd(){let n=new N(`team`).description(`Manage teams`);return $(n,`list`).description(`List teams for the current account`).action(async n=>{let r=U(n),i=W(r),a=n.json?null:f(`Fetching teams...`);a?.start();let o=await i.teams.list();if(a?.stop(),n.json){e({teams:o,activeTeamId:r.activeTeamId??null});return}t(o.map(e=>({active:e.id===r.activeTeamId,id:e.id,name:e.name,role:e.currentUserRole,members:e.memberCount})),[{key:`active`,header:`Active`,width:8},{key:`id`,header:`ID`,width:38},{key:`name`,header:`Name`,width:24},{key:`role`,header:`Role`,width:10},{key:`members`,header:`Members`,width:10}])}),$(n,`create <name>`).description(`Create a team`).option(`--org-id <id>`,`External organization id`).option(`--no-switch`,`Do not set the new team as active`).action(async(t,n)=>{let i=U(n),a=W(i),o=n.json?null:f(`Creating team...`);o?.start();let s=await a.teams.create({name:t,orgId:n.orgId});if(n.switch&&Ho(s,i.profile),o?.stop(),n.json){e({team:s,active:!!n.switch});return}r(`Team created: ${zo(s)}`),n.switch&&r(`Active team set to ${s.name}`)}),$(n,`switch <team>`).description(`Set the active team for the current profile`).action(async(t,n)=>{let i=U(n),a=await Bo(W(i),t);if(Ho(a,i.profile),n.json){e({team:a,activeTeamId:a.id});return}r(`Active team set to ${zo(a)}`)}),n.command(`current`).description(`Show the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(t=>{let n=En(t.profile);if(t.json){e(n.activeTeamId?n:{activeTeamId:null});return}if(!n.activeTeamId){console.log(`No active team.`);return}s({ID:n.activeTeamId,Name:n.activeTeamName})}),n.command(`clear`).description(`Clear the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(t=>{if(Uo(t.profile),t.json){e({activeTeamId:null});return}r(`Active team cleared.`)}),$(n,`members [team]`).description(`List team members`).action(async(n,r)=>{let i=U(r),a=W(i),o=await Vo(a,n,i.profile),s=await a.teams.listMembers(o.id);if(r.json){e({team:o,members:s});return}t(s,[{key:`id`,header:`ID`,width:36},{key:`customerEmail`,header:`Email`,width:28},{key:`role`,header:`Role`,width:10},{key:`status`,header:`Status`,width:10},{key:`joinedAt`,header:`Joined`,width:16}])}),$(n,`update-member <member-id>`).description(`Update a team member role`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).requiredOption(`--role <role>`,`Role: admin, member, viewer`).action(async(t,n)=>{let i=U(n),a=W(i),o=await Vo(a,n.team,i.profile),c=md(n.role),l=await a.teams.updateMember(o.id,t,{role:c});if(n.json){e({team:o,member:l});return}r(`Member updated: ${l.customerEmail}`),s({Team:o.name,Role:l.role,Status:l.status})}),$(n,`invite <email>`).description(`Invite a user to a team`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--role <role>`,`Role: admin, member, viewer`,`member`).option(`--ttl-hours <hours>`,`Invitation lifetime in hours`).action(async(t,n)=>{let i=U(n),a=W(i),o=await Vo(a,n.team,i.profile),c=md(n.role),l=await a.teams.invite(o.id,{email:t,role:c,ttlHours:n.ttlHours?Number.parseInt(n.ttlHours,10):void 0});if(n.json){e({team:o,invitation:l});return}r(`Invitation created for ${l.email}`),s({Team:o.name,Role:l.role,Expires:l.expiresAt,"Invitation ID":l.id}),r(`Re-run with --json to retrieve the invitation token for sharing.`)}),$(n,`leave [team]`).description(`Leave a team as the current user`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=U(n),a=W(i),o=await Vo(a,t,i.profile);if(!(!n.force&&!n.json&&!await ur(`Leave team '${o.name}'? (y/N) `,`--force`))){if(await a.teams.leave(o.id),i.activeTeamId===o.id&&Uo(i.profile),n.json){e({success:!0,teamId:o.id});return}r(`Left team: ${o.name}`)}}),$(n,`transfer <new-owner-customer-id> [team]`).description(`Transfer team ownership to another active member`).option(`--force`,`Skip confirmation prompt`).action(async(t,n,i)=>{let a=U(i),o=W(a),s=await Vo(o,n,a.profile);if(!(!i.force&&!i.json&&!await ur(`Transfer ownership of '${s.name}' to ${t}? This cannot be undone without the new owner's cooperation. (y/N) `,`--force`))){if(await o.teams.transferOwnership(s.id,t),i.json){e({success:!0,teamId:s.id,newOwnerCustomerId:t});return}r(`Ownership transferred for ${s.name}`)}}),n.addCommand(hd()),n.addCommand(gd()),$(n,`invitations [team]`).description(`List pending and historical team invitations`).action(async(n,r)=>{let i=U(r),a=W(i),o=await Vo(a,n,i.profile),s=await a.teams.listInvitations(o.id);if(r.json){e({team:o,invitations:s});return}t(s,[{key:`id`,header:`ID`,width:38},{key:`email`,header:`Email`,width:28},{key:`role`,header:`Role`,width:10},{key:`status`,header:`Status`,width:12},{key:`expiresAt`,header:`Expires`,width:16}])}),$(n,`accept <token>`).description(`Accept a team invitation`).option(`--no-switch`,`Do not set the accepted team as active`).action(async(t,n)=>{let i=U(n),a=W(i),o=await a.teams.acceptInvitation(t),s=n.switch===!1?null:await a.teams.get(o.teamId);if(s&&Ho(s,i.profile),n.json){e({member:o,activeTeamId:s?.id??null});return}r(`Invitation accepted for team ${o.teamId}`),s&&r(`Active team set to ${s.name}`)}),$(n,`revoke-invitation <invitation-id>`).description(`Revoke a pending team invitation`).action(async(t,n)=>{if(await W(U(n)).teams.revokeInvitation(t),n.json){e({success:!0,invitationId:t});return}r(`Invitation revoked: ${t}`)}),$(n,`remove-member <member-id>`).description(`Remove a member from a team`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).action(async(t,n)=>{let i=U(n),a=W(i),o=await Vo(a,n.team,i.profile);if(await a.teams.removeMember(o.id,t),n.json){e({success:!0,teamId:o.id,memberId:t});return}r(`Member removed: ${t}`)}),n}function md(e){if(e===`admin`||e===`member`||e===`viewer`)return e;throw Error(`Role must be one of: admin, member, viewer`)}function hd(){let n=new N(`secret`).description(`Manage team secrets`);return $(n,`list [team]`).description(`List team secret names`).action(async(n,r)=>{let i=U(r),a=W(i),o=await Vo(a,n,i.profile),s=await a.teams.listSecrets(o.id);if(r.json){e({team:o,secrets:s});return}t(s,[{key:`name`,header:`Name`,width:28},{key:`updatedAt`,header:`Updated`,width:24},{key:`updatedBy`,header:`Updated By`,width:28}])}),$(n,`set <name> [value]`).description(`Create or replace a team secret`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--value-stdin`,`Read secret value from stdin`).action(async(t,n,i)=>{let a=U(i),o=W(a),s=await Vo(o,i.team,a.profile),c=await Yu({value:n,valueStdin:i.valueStdin,prompt:`Enter value for team secret '${t}': `}),l=await o.teams.upsertSecret(s.id,t,c);if(i.json){e({team:s,secret:l});return}r(`Team secret saved: ${l.name}`)}),$(n,`delete <name>`).description(`Delete a team secret`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=U(n),a=W(i),o=await Vo(a,n.team,i.profile);if(!(!n.force&&!n.json&&!await ur(`Delete team secret '${t}' from '${o.name}'? (y/N) `,`--force`))){if(await a.teams.deleteSecret(o.id,t),n.json){e({success:!0,teamId:o.id,name:t});return}r(`Team secret deleted: ${t}`)}}),$(n,`reveal <name>`).description(`Reveal a team secret value`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).action(async(t,n)=>{let r=U(n),i=W(r),a=await Vo(i,n.team,r.profile),o=await i.teams.revealSecret(a.id,t);if(n.json){e({teamId:a.id,...o});return}console.log(o.value)}),n}function gd(){let n=new N(`templates`).description(`Manage team golden-path templates`);return $(n,`list [team]`).description(`List a team's golden-path templates`).action(async(n,r)=>{let i=U(r),a=W(i),o=await Vo(a,n,i.profile),s=await a.teams.listTemplates(o.id);if(r.json){e({team:o,templates:s});return}if(s.length===0){console.log(`No templates yet for ${o.name}.`);return}t(s.map(e=>({id:e.id,name:e.name,environment:e.environment,snapshot:`${e.snapshotId.slice(0,12)}…`,updated:e.updatedAt})),[{key:`id`,header:`ID`,width:38},{key:`name`,header:`Name`,width:28},{key:`environment`,header:`Env`,width:14},{key:`snapshot`,header:`Snapshot`,width:16},{key:`updated`,header:`Updated`,width:24}])}),$(n,`create <name> <snapshot-id>`).description(`Create a golden-path template from a snapshot`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`-d, --description <description>`,`Human-readable description shown in the dashboard`).option(`-e, --environment <environment>`,`Default environment to apply (defaults to 'universal')`).option(`--config <json>`,`Optional JSON config object merged into sandboxes created from this template`).action(async(t,n,i)=>{let a=U(i),o=W(a),s=await Vo(o,i.team,a.profile),c;if(i.config)try{let e=JSON.parse(i.config);if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`--config must be a JSON object`);c=e}catch(e){throw Error(`--config is not valid JSON: ${e instanceof Error?e.message:String(e)}`)}let l=await o.teams.createTemplate(s.id,{name:t,snapshotId:n,description:i.description,environment:i.environment,config:c});if(i.json){e({team:s,template:l});return}r(`Team template created: ${l.name} (${l.id})`)}),$(n,`delete <template-id>`).description(`Delete a team golden-path template`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=U(n),a=W(i),o=await Vo(a,n.team,i.profile);if(!(!n.force&&!n.json&&!await ur(`Delete template '${t}' from '${o.name}'? (y/N) `,`--force`))){if(await a.teams.deleteTemplate(o.id,t),n.json){e({success:!0,teamId:o.id,templateId:t});return}r(`Team template deleted: ${t}`)}}),n}function $(e,t){return e.command(t).option(`--profile <profile>`,`Credential profile`)}async function _d(t,n,i){let a=new AbortController,o=()=>a.abort();try{let i=W(U({...t,timeout:void 0}));process.once(`SIGINT`,o),process.once(`SIGTERM`,o);let s=await n(i,{...t.timeout===void 0?{}:{timeoutMs:Number(t.timeout)*1e3},resumeJobId:t.resumeJob,signal:a.signal,onProgress:e=>{process.stderr.write(`Publication ${e.id}: ${e.status}\n`)}}).finally(()=>{process.off(`SIGINT`,o),process.off(`SIGTERM`,o)});t.json?e(s):r(`template`in s?`Published template: ${s.template.slug}`:`Published template version: ${s.version.id}`)}catch(e){if(e instanceof w&&e.status!==401&&e.job&&[`pending`,`scanning`,`ready`].includes(e.job.status)){let t=[`tangle`,`template`,...i,`--resume-job`,e.job.id].map(ut).join(` `);Object.assign(e,{fix:{command:t}})}H(e,t.json)}}function vd(){let n=new N(`template`).description(`Manage published public templates`);return n.command(`list`).option(`-q, --query <query>`,`Search query`).option(`--tag <tag>`,`Filter by tag`).option(`--featured`,`Show featured templates only`).action(async n=>{let r=W(U(n)),i=n.featured?await r.publicTemplates.featured():await r.publicTemplates.list({query:n.query,tag:n.tag});if(n.json){e({templates:i});return}t(i,[{key:`slug`,header:`Slug`,width:28},{key:`name`,header:`Name`,width:28},{key:`forkCount`,header:`Forks`,width:8},{key:`sandboxCount`,header:`Sandboxes`,width:12},{key:`updatedAt`,header:`Updated`,width:24}])}),n.command(`get <id-or-slug>`).action(async(t,n)=>{let r=await W(U(n)).publicTemplates.get(t);if(n.json){e({template:r});return}e(r)}),n.command(`versions <id-or-slug>`).action(async(n,r)=>{let i=await W(U(r)).publicTemplates.versions(n);if(r.json){e({versions:i});return}t(i.map(e=>({...e})),[{key:`id`,header:`Version ID`,width:38},{key:`versionNumber`,header:`Version`,width:8},{key:`createdAt`,header:`Created`,width:24}])}),n.command(`publish <name> <snapshot-id> <sandbox-id>`).option(`--timeout <seconds>`,`Maximum wait for publication`).option(`--resume-job <id>`,`Resume an accepted publication for this snapshot`).option(`--slug <slug>`,`Stable public slug`).option(`-d, --description <description>`,`Template description`).option(`--readme <markdown>`,`README markdown`).option(`--tags <tags...>`,`Template tags`).option(`--release-notes <text>`,`Release notes`).option(`--team-id <id>`,`Publish under a team`).option(`--forked-from <id>`,`Fork source template id`).action((e,t,n,r)=>_d(r,async(i,a)=>({template:await i.publicTemplates.publish({name:e,slug:r.slug,description:r.description,snapshotId:t,sourceSandboxId:n,readmeMarkdown:r.readme,tags:r.tags,releaseNotes:r.releaseNotes,teamId:r.teamId,forkedFromTemplateId:r.forkedFrom},a)}),[`publish`,e,t,n])),n.command(`publish-version <id-or-slug> <snapshot-id> <sandbox-id>`).option(`--timeout <seconds>`,`Maximum wait for publication`).option(`--resume-job <id>`,`Resume an accepted publication for this snapshot`).option(`--readme <markdown>`,`README markdown`).option(`--tags <tags...>`,`Template tags`).option(`--release-notes <text>`,`Release notes`).action((e,t,n,r)=>_d(r,async(i,a)=>({version:await i.publicTemplates.publishVersion(e,{snapshotId:t,sourceSandboxId:n,readmeMarkdown:r.readme,tags:r.tags,releaseNotes:r.releaseNotes},a)}),[`publish-version`,e,t,n])),n}function yd(){let t=new N(`traces`).description(`Read hosted agent traces, spans, and eval-runs from Tangle Intelligence`);return t.command(`list`).description(`List trace summaries (one row per trace), newest first`).option(`--from <iso>`,`ISO-8601 lower bound on received time (inclusive)`).option(`--to <iso>`,`ISO-8601 upper bound on received time (inclusive)`).option(`--model <model>`,`Exact model match (any span carried this model)`).option(`--run <runId>`,`Exact run id match`).option(`--status <status>`,`ERROR | OK`).option(`-q, --query <text>`,`Substring over span name`).option(`--cursor <cursor>`,`Opaque pagination cursor from a prior page`).option(`--limit <count>`,`Page size (clamped server-side to [1, 200])`).action(async t=>{try{let n={from:t.from,to:t.to,model:t.model,runId:t.run,status:t.status===void 0?void 0:Ad(t.status),q:t.query,cursor:t.cursor,limit:t.limit===void 0?void 0:Fd(t.limit)},r=xd(t),i=t.json?null:f(`Fetching traces...`);i?.start();let a=await r.listTraces(n);if(i?.stop(),t.json)return e(a);wd(a.items),Od(a.nextCursor)}catch(e){Cd(e,t)}}),t.command(`get <traceId>`).description(`Show one trace's spans. Streams NDJSON to stdout with --ndjson.`).option(`--ndjson`,`Stream the full span set as NDJSON to stdout`).option(`--cursor <cursor>`,`Opaque pagination cursor from a prior page`).option(`--limit <count>`,`Spans per page`).action(async(t,n)=>{try{let r=xd(n);if(n.ndjson){await Sd(r,t);return}let i=n.json?null:f(`Fetching trace spans...`);i?.start();let a=await r.getTraceSpans(t,{cursor:n.cursor,limit:n.limit===void 0?void 0:Fd(n.limit)});if(i?.stop(),n.json)return e(a);Td(a.items),a.truncated&&s({Spans:`${a.items.length} of ${a.total} (truncated)`}),Od(a.nextCursor)}catch(e){Cd(e,n)}}),t.addCommand(bd()),t}function bd(){let t=new N(`runs`).description(`Read eval-runs pivoted off the trace surface`);return t.command(`list`).description(`List eval-runs, newest first`).option(`--status <status>`,`Run status filter`).option(`--gate <decision>`,`Promotion-gate decision filter`).option(`--label <key:value>`,`Match over the run's labels`).option(`--from <iso>`,`ISO-8601 lower bound on received time`).option(`--to <iso>`,`ISO-8601 upper bound on received time`).option(`-q, --query <text>`,`Substring over run dir`).option(`--cursor <cursor>`,`Opaque pagination cursor from a prior page`).option(`--limit <count>`,`Page size`).action(async t=>{try{let n={status:t.status===void 0?void 0:Md(t.status),gate:t.gate===void 0?void 0:Pd(t.gate),label:t.label,from:t.from,to:t.to,q:t.query,cursor:t.cursor,limit:t.limit===void 0?void 0:Fd(t.limit)},r=xd(t),i=t.json?null:f(`Fetching runs...`);i?.start();let a=await r.listRuns(n);if(i?.stop(),t.json)return e(a);Ed(a.items),Od(a.nextCursor)}catch(e){Cd(e,t)}}),t.command(`get <runId>`).description(`Show a single eval-run`).action(async(t,n)=>{try{let r=xd(n),i=n.json?null:f(`Fetching run...`);i?.start();let a=await r.getRun(t);if(i?.stop(),n.json)return e(a);Dd(a)}catch(e){Cd(e,n)}}),t}function xd(e){let t=gn(e.apiKey);if(!t)throw Error(`No API key found. Set TANGLE_API_KEY or run: tangle auth login`);return wt({apiKey:t,baseUrl:e.baseUrl??process.env.TANGLE_INTELLIGENCE_BASE_URL})}async function Sd(e,t){let n=(await e.exportTraceSpansNdjson(t)).getReader();try{for(;;){let{value:e,done:t}=await n.read();if(t)break;e&&process.stdout.write(Buffer.from(e))}}finally{n.releaseLock()}}function Cd(e,t){return H(e,t.json===!0)}function wd(e){t(e.map(e=>({traceId:e.traceId,root:e.rootName??`-`,model:e.model??`-`,spans:e.spanCount,errors:e.errorCount,durationMs:e.durationMs,cost:kd(e.costUsd)})),[{key:`traceId`,header:`Trace`,width:36},{key:`root`,header:`Root`,width:24},{key:`model`,header:`Model`,width:22},{key:`spans`,header:`Spans`,width:8},{key:`errors`,header:`Errors`,width:8},{key:`durationMs`,header:`Duration(ms)`,width:14},{key:`cost`,header:`Cost`,width:10}])}function Td(e){t(e.map(e=>({spanId:e.id,name:e.name,model:e.model??`-`,status:e.statusCode??`-`,cost:e.costUsd===null?`-`:`$${e.costUsd}`})),[{key:`spanId`,header:`Span`,width:40},{key:`name`,header:`Name`,width:28},{key:`model`,header:`Model`,width:22},{key:`status`,header:`Status`,width:10},{key:`cost`,header:`Cost`,width:12}])}function Ed(e){t(e.map(e=>({runId:e.id,status:e.status,gate:e.gateDecision??`-`,cost:e.totalCostUsd===null?`-`:`$${e.totalCostUsd}`,receivedAt:e.receivedAt})),[{key:`runId`,header:`Run`,width:24},{key:`status`,header:`Status`,width:22},{key:`gate`,header:`Gate`,width:18},{key:`cost`,header:`Cost`,width:12},{key:`receivedAt`,header:`Received`,width:18}])}function Dd(e){s({Run:e.id,Status:e.status,Gate:e.gateDecision??void 0,"Run Dir":e.runDir??void 0,Cost:e.totalCostUsd===null?void 0:`$${e.totalCostUsd}`,Duration:e.totalDurationMs===null?void 0:`${e.totalDurationMs}ms`,"Holdout Lift":e.holdoutLift??void 0,Received:e.receivedAt})}function Od(e){e&&s({"Next page":`--cursor ${e}`})}function kd(e){return e===null?`-`:`$${e.toFixed(4)}`}function Ad(e){if(e===`ERROR`||e===`OK`)return e;throw Error(`--status must be ERROR or OK`)}const jd=[`started`,`baseline-complete`,`generation-complete`,`gate-decided`,`finished`,`errored`];function Md(e){let t=jd.find(t=>t===e);if(t)return t;throw Error(`--status must be one of ${jd.join(`, `)}`)}const Nd=[`ship`,`hold`,`need_more_work`,`model_ceiling`,`arch_ceiling`];function Pd(e){let t=Nd.find(t=>t===e);if(t)return t;throw Error(`--gate must be one of ${Nd.join(`, `)}`)}function Fd(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}const Id=`@tangle-network/sandbox-cli`,Ld=`curl -fsSL https://sandbox.tangle.tools/install.sh | sh`;function Rd(e){let t=M(process.env.TANGLE_CLI_HOME||M(F(),`.local/share/tangle-cli`),`node_modules`,Id);if(Pe(t)&&Le(t)===e)return`tangle update`;if(e.includes(`${ge}.pnpm${ge}`))return`pnpm add -g ${Id}@latest`;if(e.includes(`${ge}node_modules${ge}`))return`npm install -g ${Id}@latest`}function zd(e){let t=`${process.env.TANGLE_NPM_REGISTRY??`https://registry.npmjs.org`}/${Id.replace(`/`,`%2F`)}/latest`;return new Promise(n=>{let r=(t.startsWith(`https:`)?Et:Tt).get(t,e=>{let t=``;e.on(`data`,e=>{t+=e}),e.on(`end`,()=>{let r;try{r=JSON.parse(t).version}catch{}let i=typeof r==`string`&&/^\d+\.\d+\.\d+$/.test(r);n(e.statusCode===200&&i?r:void 0)})});r.on(`error`,()=>n(void 0)),setTimeout(()=>{r.destroy(),n(void 0)},e).unref()})}const Bd=(e,t)=>e.localeCompare(t,`en`,{numeric:!0})>0;async function Vd(e,t){let n=Rd(e);if(!n||!process.stderr.isTTY||process.env.CI)return;let r=M(Wt,`update-check.json`),i=String(Math.floor(Date.now()/864e5));try{if(Pe(r)&&Ie(r,`utf8`)===i)return;Fe(Wt,{mode:448,recursive:!0}),ze(r,i)}catch{return}let a=await zd(1e3);a&&Bd(a,t)&&console.error(`tangle ${t} is installed; ${a} is latest. Run: ${n}`)}function Hd(e,t){return new N(`update`).description(`Install the latest published CLI`).action(async()=>{let n=Rd(e);if(n!==`tangle update`)throw new B(`UPDATE_ELSEWHERE`,`install.sh did not install this tangle`,n?`a package manager owns it`:`it runs from source`,n??`git pull, then rebuild the checkout`);let r=await zd(1e4);if(!r)throw new B(`NETWORK_UNAVAILABLE`,`the npm registry gave no version`,`no published version was read`,`tangle update`);if(!Bd(r,t))return console.log(`tangle ${t} is already current`);try{Ue(`bash`,[`-c`,`set -o pipefail; ${Ld}`],{stdio:[`ignore`,`ignore`,`inherit`]})}catch{throw new B(`UPDATE_INSTALL_FAILED`,`install.sh failed`,`its error is above`,Ld)}let i=JSON.parse(Ie(M(e,`package.json`),`utf8`));console.log(`tangle ${t} -> ${i.version}`)})}function Ud(){return new N(`usage`).description(`Show account usage and billing information`).action(async t=>{let{client:n}=G(t),r=t.json?null:f(`Fetching usage...`);r?.start();let[i,a]=await Promise.all([n.usage(),n.subscription().catch(()=>null)]);r?.stop(),t.json?e({...i,subscription:a}):(console.log(),console.log(`Account Usage`),console.log(`─`.repeat(40)),s({"Active Sandboxes":i.activeSandboxes,"Total Sandboxes":i.totalSandboxes,"Compute Minutes":Wd(i.computeMinutes),"GPU Seconds":i.gpuSeconds,"GPU Spend":Gd(i.gpuCostUsd)}),a&&(console.log(),console.log(`Subscription`),console.log(`─`.repeat(40)),s({Plan:a.plan,Status:a.status,"Credits Available":Gd(a.creditsAvailableUsd),"Credits Used":Gd(a.creditsUsedUsd),"Monthly Balance":Gd(a.monthlyBalanceUsd)})),console.log(),console.log(`Billing Period`),console.log(`─`.repeat(40)),s({Start:i.periodStart.toLocaleDateString(),End:i.periodEnd.toLocaleDateString()}),console.log())})}function Wd(e){if(e===void 0)return`-`;if(e<60)return`${e} min`;let t=Math.floor(e/60),n=e%60;return n===0?`${t} hr`:`${t} hr ${n} min`}function Gd(e){return e<0?`-$${(-e).toFixed(2)}`:`$${e.toFixed(2)}`}function Kd(){return new N(`use`).description(`Set or show the active sandbox (used when a command omits the id)`).argument(`[id]`,`Sandbox id to make active`).option(`--clear`,`Clear the active sandbox`).action((e,t)=>{if(t.clear){cn(),l(`Cleared the active sandbox.`);return}if(e){sn(e),l(`Active sandbox set to ${e}. Commands now default to it; override with --box or TANGLE_SANDBOX.`);return}let n=on();l(n?`Active sandbox: ${n}`:"No active sandbox. Set one with `tangle use <id>`.")})}function qd(e){t(e,[{key:`id`,header:`ID`},{key:`nodeId`,header:`Node`},{key:`name`,header:`Name`},{key:`contentType`,header:`Content Type`},{key:`byteSize`,header:`Bytes`},{key:`createdAt`,header:`Created`}])}function Jd(t){t.command(`artifacts`).description(`List a run's artifact metadata (never the bytes)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.listArtifacts(t,n);if(r.json)return e(i);qd(i.artifacts)}),t.command(`artifact-download`).description(`Download one run artifact's bytes to a file`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).argument(`<artifactId>`,`Artifact ID`).option(`--out <file>`,`Destination file (defaults to the artifact ID)`).action(async(t,n,r,i)=>{let a=await(await X(i)).workflows.downloadArtifact(t,n,r),o=i.out??r;try{ze(o,a.bytes)}catch(e){throw Error(`Could not write artifact to "${o}": ${e instanceof Error?e.message:String(e)}`)}if(i.json)return e({file:o,contentType:a.contentType,bytes:a.bytes.length});l(`Wrote ${o} (${a.bytes.length} bytes, ${a.contentType}).`)})}function Yd(e){t(e.map(e=>({id:e.id,run:e.runId,title:e.title,options:e.options.join(`, `),requested:e.requestedAt,expires:e.expiresAt??``})),[{key:`id`,header:`ID`},{key:`run`,header:`Run`},{key:`title`,header:`Title`},{key:`options`,header:`Options`},{key:`requested`,header:`Requested`},{key:`expires`,header:`Expires`}])}function Xd(t){t.command(`decisions`).description(`List a workflow's pending human decisions`).argument(`<id>`,`Workflow ID`).action(async(t,n)=>{let r=(await(await X(n)).workflows.listPendingDecisions()).decisions.filter(e=>e.workflowId===t);if(n.json)return e({decisions:r});Yd(r)}),t.command(`decision-resolve`).description(`Answer the decision a run is parked on and resume it`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).requiredOption(`--choice <choice>`,`The option to resolve with (one of the decision's options)`).action(async(t,n,r)=>{let i=await X(r),a=await i.workflows.getRunDecision(t,n),o=await i.workflows.resolveRunDecision(t,n,{decisionId:a.id,choice:r.choice});if(r.json)return e(o);if(o.resumed){l(`Resolved decision ${o.decisionId} with "${o.choice}" — run ${o.runId} resumed.`);return}l(`Resolved decision ${o.decisionId} with "${o.choice}", but run ${o.runId} had already finished — nothing to resume.`)})}function Zd(e){try{return Ie(e,`utf8`)}catch(t){throw Error(`Could not read workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function Qd(e){t(e.map(e=>({id:e.id,name:e.name,enabled:e.enabled?`yes`:`no`,issues:e.validationErrors.length,updated:e.updatedAt})),[{key:`id`,header:`ID`},{key:`name`,header:`Name`},{key:`enabled`,header:`Enabled`},{key:`issues`,header:`Issues`},{key:`updated`,header:`Updated`}])}function $d(e){let n=e.workflows.filter(e=>e.failed>0).length,r=e.workflows.filter(e=>e.failed===0&&e.waiting>0).length,i=e.workflows.filter(e=>e.failed===0&&e.waiting===0&&e.runsInWindow>0).length;l(`${n} failing · ${r} waiting · ${i} healthy · ${e.workflows.length} total over ${e.window}`),t(e.workflows.map(e=>({id:e.id,name:e.name,enabled:e.enabled?`yes`:`no`,runs:e.runsInWindow,failed:e.failed,waiting:e.waiting,success:e.successRate===null?`—`:`${Math.round(e.successRate*100)}%`,lastRun:e.lastRunStatus??`—`,lastRunAt:e.lastRunAt??`—`})),[{key:`id`,header:`ID`},{key:`name`,header:`Name`},{key:`enabled`,header:`Enabled`},{key:`runs`,header:`Runs`},{key:`failed`,header:`Failed`},{key:`waiting`,header:`Waiting`},{key:`success`,header:`Success`},{key:`lastRun`,header:`Last Run`},{key:`lastRunAt`,header:`Last Run At`}])}function ef(e){if(s({ID:e.id,Name:e.name,Description:e.description??``,Enabled:e.enabled?`yes`:`no`,Actions:e.actions.length}),e.triggers&&e.triggers.length>0&&(l(`Triggers`),tf(e.triggers)),e.validationErrors.length>0){l(`Validation issues`);for(let t of e.validationErrors)console.log(` ${t.path}: ${t.message}`)}}function tf(e){t(e.map(e=>({id:e.id,kind:e.kind,enabled:e.enabled?`yes`:`no`,detail:e.kind===`schedule`?`${e.cron??``} (${e.timezone??``})`:`${e.provider??``}:${e.eventFilter?.event??``}${e.eventFilter?.action?`.${e.eventFilter.action}`:``}`})),[{key:`id`,header:`ID`},{key:`kind`,header:`Kind`},{key:`enabled`,header:`Enabled`},{key:`detail`,header:`Detail`}])}function nf(t){t.command(`list`).description(`List your workflows`).action(async t=>{let n=await(await X(t)).workflows.list();if(t.json)return e(n);Qd(n)}),t.command(`fleet`).description(`Fleet overview: every workflow's run tallies over a trailing window, failing-first`).option(`--window <window>`,`Trailing window: 24h, 7d, or 30d`,`7d`).action(async t=>{let n=await(await X(t)).workflows.fleetInsights({window:t.window});if(t.json)return e(n);$d(n)}),t.command(`get`).description(`Show a workflow's definition and compiled triggers`).argument(`<id>`,`Workflow ID`).option(`--yaml`,`Print only the raw definition YAML (the export path — pipe to a file)`).action(async(t,n)=>{let r=await(await X(n)).workflows.get(t);if(n.yaml){if(r.definitionYaml===null)throw Error(`Workflow ${r.id} has no stored definition YAML to export`);process.stdout.write(r.definitionYaml.endsWith(`
174
- `)?r.definitionYaml:`${r.definitionYaml}\n`);return}if(n.json)return e(r);ef(r)}),t.command(`create`).description(`Create a workflow from a YAML file`).argument(`<file>`,`Path to the workflow YAML`).action(async(t,n)=>{let r=Zd(t),i=await(await X(n)).workflows.create(r);if(n.json)return e(i);l(`Created workflow ${i.id} (${i.name}).`),ef(i)}),t.command(`apply`).description(`Create or update a workflow idempotently, matched by the definition's name`).argument(`<file>`,`Path to the workflow YAML`).action(async(t,n)=>{let r=Zd(t),i=await X(n),a=await i.workflows.validate(r,{structural:!0});if(!a.valid){if(process.exitCode=1,n.json)return e(a);l(`Invalid workflow:`);for(let e of a.errors)console.log(` ${e.path}: ${e.message}`);return}let o=(await i.workflows.list()).find(e=>e.name===a.name);if(o){let t=await i.workflows.update(o.id,r);if(n.json)return e({action:`updated`,workflow:t});l(`Updated workflow ${t.id} (${t.name}) — matched by name.`),ef(t);return}let s=await i.workflows.create(r);if(n.json)return e({action:`created`,workflow:s});l(`Created workflow ${s.id} (${s.name}).`),ef(s)}),t.command(`update`).description(`Replace a workflow's definition from a YAML file`).argument(`<id>`,`Workflow ID`).argument(`<file>`,`Path to the workflow YAML`).option(`--note <note>`,`Revision note recorded on the appended revision (why this change)`).action(async(t,n,r)=>{let i=Zd(n),a=await(await X(r)).workflows.update(t,i,{...r.note===void 0?{}:{note:r.note}});if(r.json)return e(a);l(`Updated workflow ${a.id} (${a.name}).`),ef(a)}),t.command(`delete`).description(`Delete a workflow and its triggers`).argument(`<id>`,`Workflow ID`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{if(!n.force&&!await ur(`Delete workflow ${t}? `,`--force`)){l(`Delete cancelled.`);return}if(await(await X(n)).workflows.delete(t),n.json)return e({deleted:!0,id:t});l(`Deleted workflow ${t}.`)}),t.command(`validate`).description(`Validate a workflow YAML file without saving it`).argument(`<file>`,`Path to the workflow YAML`).option(`--structural`,`CI mode: compile + capability checks only, no connection resolution — the verdict is the same regardless of connected providers`).action(async(t,n)=>{let r=Zd(t),i=await(await X(n)).workflows.validate(r,{...n.structural?{structural:!0}:{}});if(n.json)return e(i);if(i.valid)l(`Valid: ${i.name} (${i.actionCount} action(s), ${i.triggerCount} trigger(s)).`);else{l(`Invalid workflow:`);for(let e of i.errors)console.log(` ${e.path}: ${e.message}`);process.exitCode=1}}),t.command(`schema`).description(`Print the JSON Schema for the workflow YAML`).action(async t=>{e(await(await X(t)).workflows.schema())})}async function rf(t,n,r){let i=await(await X(r)).workflows.setEnabled(t,n);if(r.json)return e(i);l(`${n?`Enabled`:`Disabled`} workflow ${i.id}.`),ef(i)}function af(e,t){try{return JSON.parse(e)}catch{throw Error(`Invalid ${t}: not valid JSON`)}}function of(e,t){try{ze(e,t,`utf8`)}catch(t){throw Error(`Could not write workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function sf(e){t(e.map(e=>({id:e.id,name:e.name,category:e.category,providers:e.providers.join(`, `),summary:e.summary})),[{key:`id`,header:`ID`},{key:`name`,header:`Name`},{key:`category`,header:`Category`},{key:`providers`,header:`Providers`},{key:`summary`,header:`Summary`}])}function cf(e,t){let n=e.kind===`github_app`,r=n?`${e.provider} (App installation)`:e.provider,i=e.connectUrl?` — ${n?`install`:`connect`}: ${e.connectUrl}`:``,a=e.prerequisite;return`${r}${i}${a&&t.some(e=>e.provider===a.provider&&e.kind===a.kind&&!e.connected)?` (after connecting ${a.provider})`:``}`}function lf(t){t.command(`enable`).description(`Enable a workflow so its triggers and manual runs fire`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await rf(e,!0,t)}),t.command(`disable`).description(`Disable a workflow (pause its triggers and manual runs)`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await rf(e,!1,t)}),t.command(`templates`).description(`List the curated starter workflow templates`).action(async t=>{let n=await(await X(t)).workflows.listTemplates();if(t.json)return e(n);sf(n)}),t.command(`init`).description(`Create a workflow from a gallery template and print (or save) its YAML`).argument(`<template-id>`,"Template ID from `workflows templates`").option(`--param <key=value>`,`Template parameter value. Repeatable.`,Oc,[]).option(`--file <out>`,`Write the instantiated workflow YAML to this file instead of stdout`).action(async(t,n)=>{let r=kc(n.param,`param`)??{},i=await(await X(n)).workflows.instantiateTemplate(t,r);if(n.json)return e(i);if(!i.created){l(`Template ${t} needs provider connections before it can run:`);for(let e of i.connectionRequirements)console.log(` ${e.connected?`✓`:`✗`} ${cf(e,i.connectionRequirements)}`);process.exitCode=1;return}let{workflow:a}=i;if(a.definitionYaml===null)throw Error(`Workflow ${a.id} was created but the server returned no definition YAML`);if(l(`Created workflow ${a.id} (${a.name}).`),n.file){of(n.file,a.definitionYaml),l(`Wrote ${n.file}.`);return}process.stdout.write(a.definitionYaml.endsWith(`
175
- `)?a.definitionYaml:`${a.definitionYaml}\n`)})}function uf(e){t(e,[{key:`key`,header:`Key`},{key:`version`,header:`Version`},{key:`updatedAt`,header:`Updated`}])}function df(t){s({Key:t.key,Version:t.version,Updated:t.updatedAt}),l(`Value`),e(t.value)}function ff(t){let n=t.command(`kv`).description(`Read and write a workflow's cross-run KV state`);n.command(`list`).description(`List every KV entry of a workflow`).argument(`<id>`,`Workflow ID`).action(async(t,n)=>{let r=await(await X(n)).workflows.listKv(t);if(n.json)return e(r);uf(r.entries)}),n.command(`get`).description(`Show one KV entry (value and version)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.getKv(t,n);if(r.json)return e(i);df(i)}),n.command(`set`).description(`Write a KV entry from a JSON value`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).argument(`<json>`,`Value as JSON (e.g. '{"cursor":123}' or '"abc"')`).option(`--cas <version>`,`Compare-and-swap: write only if the stored version still equals this`).action(async(t,n,r,i)=>{let a=af(r,`<json>`),o=i.cas===void 0?void 0:ha(i.cas,`--cas`),s=await X(i),c=o===void 0?await s.workflows.putKv(t,n,a):await s.workflows.casKv(t,n,o,a);if(i.json)return e(c);df(c)}),n.command(`delete`).description(`Delete a KV entry (idempotent)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.deleteKv(t,n);if(r.json)return e(i);l(i.deleted?`Deleted KV entry "${n}" of workflow ${t}.`:`No KV entry "${n}" on workflow ${t}.`)})}function pf(e){t(e.map(e=>({rev:e.rev,created:e.createdAt,by:e.createdBy,source:e.source,note:e.note??``})),[{key:`rev`,header:`Rev`},{key:`created`,header:`Created`},{key:`by`,header:`Created By`},{key:`source`,header:`Source`},{key:`note`,header:`Note`}])}function mf(t){t.command(`revisions`).description(`List a workflow's definition revision history (newest first)`).argument(`<id>`,`Workflow ID`).action(async(t,n)=>{let r=await(await X(n)).workflows.listRevisions(t);if(n.json)return e(r);pf(r)}),t.command(`revision`).description(`Show one revision's metadata and definition YAML`).argument(`<id>`,`Workflow ID`).argument(`<rev>`,`Revision number`).action(async(t,n,r)=>{let i=ha(n,`<rev>`),a=await(await X(r)).workflows.getRevision(t,i);if(r.json)return e(a);s({Revision:a.rev,Created:a.createdAt,"Created by":a.createdBy,Source:a.source,Note:a.note??``}),process.stdout.write(a.yaml.endsWith(`
176
- `)?a.yaml:`${a.yaml}\n`)}),t.command(`rollback`).description(`Restore a prior revision's definition as a NEW head revision (re-validated)`).argument(`<id>`,`Workflow ID`).argument(`<rev>`,`Revision number to restore`).action(async(t,n,r)=>{let i=ha(n,`<rev>`),a=await(await X(r)).workflows.rollback(t,i);if(r.json)return e(a);l(`Rolled back workflow ${a.id} to rev ${i}.`),ef(a)})}function hf(){let e=new N(`workflows`).description(`Create and manage Tangle workflows`);return nf(e),Pc(e),lf(e),mf(e),ff(e),Jd(e),Xd(e),e}function gf(e){for(let[t,n]of Object.entries(e.optsWithGlobals()))e.getOptionValue(t)===void 0&&n!==void 0&&e.setOptionValue(t,n)}const _f=_(import.meta.url),vf=_f(`../package.json`),yf=ue(_f.resolve(`../package.json`)),bf=vf.version??`0.0.0`;function xf(){let e=new N,t=Hd(yf,bf);e.name(`tangle`).description(`CLI for Tangle Sandbox operations`).version(bf).option(`--json`,`Output JSON where supported, including errors`).option(`--api-key <key>`,`API key (or set TANGLE_API_KEY)`).option(`--base-url <url>`,`API base URL`),e.hook(`preAction`,async(e,n)=>{gf(n);let r=n.opts(),i=r.json===!0||r.ndjson===!0;a(i),n!==t&&!i&&await Vd(yf,bf)}),e.addCommand(qr()),e.addCommand(Ku()),e.addCommand(Kd()),e.addCommand(Ju()),e.addCommand(bu()),e.addCommand(Au()),e.addCommand(ju()),e.addCommand(yo()),e.addCommand(ld()),e.addCommand(ud()),e.addCommand(fd()),e.addCommand(Dr()),e.addCommand(Zu()),e.addCommand(fs()),e.addCommand(Ud()),e.addCommand(pd()),e.addCommand(vd()),e.addCommand(ni()),e.addCommand(pi()),e.addCommand(Ru()),e.addCommand(ps()),e.addCommand(gs()),e.addCommand(eu()),e.addCommand(bl()),e.addCommand(hf()),e.addCommand(eo()),e.addCommand(qu()),e.addCommand(ed()),e.addCommand(Xu()),e.addCommand(mi()),e.addCommand(Iu()),e.addCommand(tu()),e.addCommand(qa()),e.addCommand(Ja()),e.addCommand(Wu()),e.addCommand(Mu()),e.addCommand(yd()),e.addCommand(Ls()),e.addCommand(t);function n(e){e.configureHelp({showGlobalOptions:!0}),e.configureOutput({writeErr:()=>{}}),e.exitOverride(t=>{t.exitCode===0&&process.exit(0),H(t,e.optsWithGlobals().json===!0)});for(let t of e.commands)n(t)}return n(e),e}const Sf=xf();Sf.parseAsync(process.argv).catch(e=>{H(e,Sf.opts().json===!0)});export{wn as _,nc as a,Qs as c,Ns as d,qe as f,Xt as g,en as h,cc as i,Ks as l,_n as m,Xl as n,rc as o,ur as p,X as r,oc as s,Q as t,Gs as u,B as v,H as y};
173
+ <script>${a(r)}<\/script></body></html>`,c=M(await pt(M(Ve(),`tangle-graph-`)),`${o}.html`);return await z(c,s,{mode:384}),c}function ml(t,n,r){t.command(`show <name-or-file>`).description(`Draw a graph file: labelled nodes, routes, loops and stops`).option(`--open`,`Write one offline page and open it in the browser`).action(async(t,i)=>{let a=await R(n(t,process.cwd())),{graphShape:o}=await import(`./graph-view-DOQKwuvP.mjs`),s=o(a,await L(a,`utf8`));if(i.json)return e(s);if(!i.open)return console.log(fl(s));let c=await pl(s,r);l(await Fr(bt(c).href)?`Opened ${c}`:`Open ${c}`)})}async function hl(e){if(!mn(e.apiKey)){if(e.json||e.dryRun||!process.stdin.isTTY)return;await Wr({baseUrl:e.sandboxBaseUrl,signal:e.signal})}return K(e)}async function gl(t,n,r){let i=zl(n.parameter),a=r??await hl(n);if(!a)throw new B(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured`,`tangle auth login`);let o=await a.connections.start(t,{cli:!0,connectionParameters:i,...n.scope?.length?{requestedScopes:n.scope}:{}});return n.json?(e(Vl(o)),o):(Bl(o,n.browser===!1?!1:await Fr(o.redirectUrl),n.wait),o)}async function _l(e,t,n,r){let i=async()=>{n.signal?.throwIfAborted();let{connections:i}=await e.connections.list(),a=i.filter(e=>e.status===`active`&&e.providerId.toLowerCase()===t.trim().toLowerCase());return a.length?Xe(a,r===void 0?t:`${t}:${r}`):void 0},a=await i();if(a||n.json||n.dryRun||!process.stdin.isTTY)return a;let o=await gl(t,{...n,wait:!0},e);for(;!a&&Date.now()<Date.parse(o.expiresAt);)await et(1e3,void 0,{signal:n.signal}),a=await i();return a}function vl(){let e=new N(`hub`).description(`Discover and run Tangle Hub tools`);return yl(e),bl(e),xl(e),Sl(e),Cl(e),e}function yl(t){t.command(`connect`).description(`Connect a provider account`).argument(`provider`,`Provider to connect`).option(`--no-browser`,`Print the authorization URL instead of opening it`).option(`--key-env <name>`,`Connect an API-key provider using this environment variable; never prints the key`).option(`--metadata <json>`,`Provider setup metadata for API-key connections`).option(`--scope <scope>`,`Request an OAuth scope; repeatable, must stay within the host's grant`,(e,t)=>[...t,e],[]).option(`--parameter <key=value>`,`Provider-specific OAuth value. Repeatable.`,(e,t)=>[...t,e],[]).action(async(t,n)=>{if(n.keyEnv){if(n.scope?.length)throw Error(`--scope applies to OAuth connections, not --key-env.`);let r=process.env[n.keyEnv];if(!r?.trim())throw Error(`Environment variable '${n.keyEnv}' is empty or unavailable.`);let i=await hl(n);if(!i)throw new B(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured`,`tangle auth login`);let a;if(n.metadata!==void 0)try{a=JSON.parse(n.metadata)}catch{throw Error(`--metadata must be valid JSON.`)}let o=await i.connections.connectApiKey(t,r,a);n.json?e(o):l(`Connected ${o.connection.providerId} as ${o.connection.id}.`);return}if(n.metadata!==void 0)throw Error(`--metadata requires --key-env.`);await gl(t,n)});let n=new N(`connections`).description(`List Hub provider connections`).action(async t=>{let n=await(await K(t)).connections.list();t.json?e(n):Rl(n.connections)});n.command(`revoke <connection-id>`).description(`Revoke a Hub provider connection`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let r=await K(n),i=await Nn(r,t);if(!n.force&&!await cr(`Revoke Hub connection ${i}? `,`--force`)){l(`Revoke cancelled.`);return}let a=await r.connections.revoke(i);if(n.json){e(a);return}l(`Revoked Hub connection ${a.connection.id}.`)}),t.addCommand(n)}function bl(n){n.command(`providers [provider]`).description(`Show provider setup and action catalog; use hub events for trigger readiness`).action(async(n,r)=>{let i=await(await K(r)).connections.providers(),a=i.providers.filter(e=>!n||e.providerId===n.toLowerCase());if(n&&!a.length)throw Error(`Provider '${n}' is absent from this deployment's catalog.`);if(r.json)return e({...i,providers:a});t(a,[{key:`providerId`,header:`Provider`},{key:`authKind`,header:`Auth`},{key:`configured`,header:`Connect configured`},{key:`actionCount`,header:`Catalog actions`}])}),n.command(`events [provider]`).description(`Discover deployed trigger events and ingress readiness separately from callable tools`).action(async(n,r)=>{let i=await K(r),[a,o]=await Promise.all([i.connections.providers(),i.workflows.catalogs()]),s=[...new Set([...a.providers.map(e=>e.providerId),...o.providerEventProviders])];if(n&&!s.includes(n.toLowerCase()))throw Error(`Provider '${n}' is absent from this deployment's catalog.`);let c=s.filter(e=>!n||e===n.toLowerCase()).map(e=>({provider:e,supported:o.providerEventProviders.includes(e),ingressConfigured:a.providers.find(t=>t.providerId===e)?.eventIngressConfigured??null,catalog:o.triggerEvents[e]??null}));if(r.json)return e({providers:c});t(c.map(e=>({...e,ingress:e.ingressConfigured===null?`unknown`:e.ingressConfigured?`ready`:`setup required`,events:e.catalog?.events.map(e=>e.id).join(`, `)??`no published vocabulary`})),[{key:`provider`,header:`Provider`},{key:`supported`,header:`Event source supported`},{key:`ingress`,header:`Ingress`},{key:`events`,header:`Events`}])})}function xl(t){let n=new N(`permissions`).description(`Manage Hub action permissions`);n.command(`list`).description(`List Hub permissions for a connection`).requiredOption(`--connection <ref>`,`Hub connection id, or provider[:account]`).action(async t=>{if(!t.connection)throw Error(`--connection is required.`);let n=await K(t),r=await Nn(n,t.connection),i=await n.permissions.list(r);t.json?e(i):Nl(i.policies)}),n.command(`set`).description(`Set Hub permission for one action`).requiredOption(`--connection <ref>`,`Hub connection id, or provider[:account]`).requiredOption(`--action <path>`,`Executor action path`).requiredOption(`--decision <allow|ask|deny>`,`Permission decision`).action(async t=>{if(!t.connection)throw Error(`--connection is required.`);if(!t.action)throw Error(`--action is required.`);let n=Pl(t.decision),r=await K(t),i=await Nn(r,t.connection),a=await r.permissions.set({connectionId:i,actionPath:t.action,decision:n});t.json?e(a):Nl([a.policy])}),n.command(`revert-writes`).description("Revoke a bulk `--allow-writes` grant for a connection (deletes only the auto-granted write rows; manual permissions are untouched)").requiredOption(`--connection <ref>`,`Hub connection id, or provider[:account]`).action(async t=>{if(!t.connection)throw Error(`--connection is required.`);let n=await K(t),r=await Nn(n,t.connection),i=await n.permissions.revertWrites(r);if(t.json){e(i);return}l(`Reverted ${i.reverted} write permission${i.reverted===1?``:`s`} for connection ${i.connectionId}.`)}),t.addCommand(n),t.addCommand(Tl())}function Sl(t){let n=new N(`tools`).description(`Discover Hub tools`);n.command(`sources`).description(`List Hub tool sources`).action(async t=>{let n=await(await K(t)).tools.sources();t.json?e(n):Fl(n.sources)}),n.command(`describe`).description(`Describe a Hub tool`).argument(`path`,`Executor tool path`).action(async(t,n)=>{let r=await(await K(n)).tools.describe(t);n.json?e(r):Il(r.tool)}),n.command(`search`).description(`Search Hub tools`).argument(`<query...>`,`Search query`).option(`--provider <provider>`,`Filter by provider/source ID`).action(async(t,n)=>{let r=await(await K(n)).tools.search(t.join(` `),{provider:n.provider});n.json?e(r):Ml(r.tools)}),t.addCommand(n),t.addCommand(wl(`call`)),t.addCommand(wl(`exec`))}function Cl(t){t.command(`resume`).description(`Resolve a Hub approval created by a paused execution`).argument(`approval-id`,`Hub approval ID from HUB_APPROVAL_REQUIRED`).option(`--accept`,`Approve the execution approval`).option(`--decline`,`Deny the execution approval`).option(`--cancel`,`Unsupported for approval-backed Hub resume`).action(async(e,t)=>{if(Dl(e),t.cancel)throw Error(`Hub approval resume does not support --cancel. Use --decline to deny the approval.`);if(t.accept&&t.decline)throw Error(`Choose only one of --accept or --decline.`);if(!t.accept&&!t.decline)throw Error(`Choose --accept to approve or --decline to deny the Hub approval.`);let n=await K(t);kl(t.decline?await n.approvals.deny(e):await n.approvals.approve(e),t.json===!0)}),t.command(`status`).description(`Show Hub auth and connection status`).action(async t=>{let n=await(await K(t)).status();t.json?e(n):Hl(n)})}function wl(t){return new N(t).description(`Execute a Hub tool`).argument(`<args...>`,`Tool path tokens followed by JSON input`).option(`--connection <ref>`,`Hub connection id, or provider[:account]`).option(`--auto-approve`,`Approve a HUB_APPROVAL_REQUIRED execution and retry once`).option(`--approve`,`Alias for --auto-approve`).option(`--no-hub-key`,`Do not auto-mint a platform Hub key; use the stored credential as-is`).action(async(t,n)=>{let{args:r,approve:i}=El(t,n),{path:a,input:o}=jl(r),s=await K(n),c=n.connection?await Nn(s,n.connection):void 0;e((await s.tools.invoke(a,o,{connectionId:c,approve:i})).result)})}function Tl(){let t=new N(`approvals`).description(`List and resolve Hub execution approvals`);t.command(`list`).description(`List pending Hub execution approvals`).action(async t=>{let n=await(await K(t)).approvals.list();t.json?e(n):Ol(n.approvals)});for(let e of[`approve`,`deny`])t.command(e).description(`${e===`approve`?`Approve`:`Deny`} a pending Hub execution approval`).argument(`approval-id`,`Hub approval ID`).action(async(t,n)=>{Dl(t),kl(await(await K(n)).approvals[e](t),n.json===!0)});return t}function El(e,t){let n=t.autoApprove;return{args:e.filter(e=>e!==`--approve`&&e!==`--auto-approve`),approve:t.approve===!0||n===!0||e.includes(`--approve`)||e.includes(`--auto-approve`)}}function Dl(e){if(!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`Hub approval ID must contain only letters, numbers, underscores, and dashes.`)}function Ol(e){t(e,[{key:`id`,header:`ID`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`connectionId`,header:`Connection`},{key:`status`,header:`Status`},{key:`expiresAt`,header:`Expires`}])}function kl(t,n){if(n){e(Al(t));return}l(`Hub approval ${t.approval.id} ${t.approval.status}.`),t.capabilityToken&&l("Capability token minted. Re-run the original command with `--approve` to execute automatically.")}function Al(e){return{approval:e.approval,...e.capabilityToken?{capabilityToken:{tokenId:e.capabilityToken.tokenId,expiresAt:e.capabilityToken.expiresAt}}:{}}}function jl(e){if(e.length<2)throw Error(`Usage: tangle hub call <path> <json-input>`);let t=e[e.length-1];try{return{path:e.slice(0,-1).join(`.`),input:JSON.parse(t)}}catch{throw Error(`Hub call input must be valid JSON.`)}}function Ml(e){t(e.map(e=>({...e,provider:e.providerId??e.requiredConnectionProviderId,connection:Ll(e)})),[{key:`path`,header:`Path`},{key:`provider`,header:`Provider`},{key:`title`,header:`Title`},{key:`description`,header:`Description`},{key:`connection`,header:`Connection`},{key:`policyState`,header:`Policy`}])}function Nl(e){t(e,[{key:`connectionId`,header:`Connection`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`decision`,header:`Decision`},{key:`updatedAt`,header:`Updated`}])}function Pl(e){if(e===`allow`||e===`ask`||e===`deny`)return e;throw Error(`--decision must be one of: allow, ask, deny.`)}function Fl(e){t(e,[{key:`sourceId`,header:`Source`},{key:`displayName`,header:`Provider`},{key:`toolCount`,header:`Tools`},{key:`connectionStatus`,header:`Connection`},{key:`health`,header:`Health`},{key:`configured`,header:`Configured`}])}function Il(e){s({Path:e.path,Provider:e.providerId??e.requiredConnectionProviderId,Title:e.title,Description:e.description,Connection:Ll(e),Policy:e.policyState}),e.inputSchema!==void 0&&(l(`Input schema`),console.log(JSON.stringify(e.inputSchema,null,2))),e.outputSchema!==void 0&&(l(`Output schema`),console.log(JSON.stringify(e.outputSchema,null,2)))}function Ll(e){if(e.connectionRequired===!1)return`not required`;if(e.connectionStatus)return e.connectionStatus}function Rl(e){t(e.map(e=>({...e,account:e.accountDisplay??e.displayName,scopes:e.scopes.join(`, `)})),[{key:`id`,header:`ID`},{key:`providerId`,header:`Provider`},{key:`account`,header:`Account`},{key:`scopes`,header:`Scopes`},{key:`status`,header:`Status`},{key:`health`,header:`Health`},{key:`lastUsedAt`,header:`Last Used`}])}function zl(e){if(!e||e.length===0)return;let t={};for(let n of e){let e=n.indexOf(`=`);if(e<=0||e===n.length-1)throw Error(`Invalid --parameter "${n}": expected key=value (for example subdomain=acme)`);let r=n.slice(0,e);if(Object.hasOwn(t,r))throw Error(`Duplicate --parameter key "${r}".`);t[r]=n.slice(e+1)}return t}function Bl(e,t,n=!1){t?l(`Opened browser to connect ${e.provider}.`):(l(`Open this URL to connect ${e.provider}:`),console.log(e.redirectUrl)),l(n?`Finish authorization in the browser; this run resumes when connected.`:"Finish authorization in the browser, then rerun `tangle hub status`.")}function Vl(e){return{provider:e.provider,redirectUrl:e.redirectUrl,expiresAt:e.expiresAt,scopes:e.scopes,cli:e.cli}}function Hl(e){let{principal:t,connections:n}=e;l(`Hub status`),s({Principal:t.kind,"User ID":t.userId,"API Key ID":t.apiKeyId,"Sandbox ID":t.sandboxId,"Connected Providers":n.connectedProviderCount,"Unhealthy Providers":n.unhealthyProviderCount}),n.unhealthyProviderCount>0&&l(`Some providers require reconnect.`)}const Ul=v(import.meta.url);if(!Ul)throw Error(`Tangle CLI package metadata was not found`);const Wl=ue(Ul),Q=e=>ve(`sha256`).update(e).digest(`hex`);function Gl(e,t){if(/[\\/]/.test(e)||/\.(yaml|yml|json)$/.test(e))return he(t,e);let n=t;for(;!Pe(M(n,`.git`))&&ue(n)!==n;)n=ue(n);Pe(M(n,`.git`))||(n=t);let r=[`yaml`,`yml`,`json`].flatMap(e=>[`graph.${e}`,e]),i=[n,F()].flatMap(t=>r.map(n=>M(t,`.tangle/graphs/${e}.${n}`))),a=i.find(Pe);if(a)return a;throw new B(`GRAPH_NOT_FOUND`,`Graph '${e}' was not found`,`Looked in ${i.join(`, `)}`,`tangle graph --help`)}async function Kl(e,t){return gs(e.signal,async n=>{let r=e.runId??be(),i,a=new Set,{graphNativeRedaction:o}=await import(`./graph-native-BOIC8WzU.mjs`),s=o();try{let o=M(F(),`.tangle`,`runs`,r);await ft(o,{recursive:!0,mode:448});let c=await R(M(F(),`.tangle`)),l=await R(e.cwd??process.cwd()),u=[`runs`,`graph-registry`,`graphs`].some(e=>Is(l,M(c,e))||Is(M(c,e),l))?M(F(),`.tangle`,`workspaces`,r):l;await ft(u,{recursive:!0,mode:448});let d;return await t({runId:r,runDir:o,cwd:u,bridge:t=>d??=(async()=>{n.throwIfAborted();let r=ye(32).toString(`hex`),{loadConfig:c,startServer:l}=await import(`cli-bridge`),d=M(Wl,`dist`,`stdio.mjs`),f={...process.env,BRIDGE_HOST:`127.0.0.1`,BRIDGE_BEARER:r,BRIDGE_DATA_DIR:M(o,`bridge`),BRIDGE_BACKENDS:sc,BRIDGE_JAIL_MODE:`fs-jail`,BRIDGE_JAIL_FALLBACK:`deny`,BRIDGE_JAIL_NETWORK:`relay`,BRIDGE_SUBSCRIPTIONS_ONLY:`1`};e.relayAllow?f.BRIDGE_JAIL_RELAY_ALLOW=e.relayAllow:delete f.BRIDGE_JAIL_RELAY_ALLOW;let p=c(f);t&&p.jailReadablePaths.push(d),i=await l({cwd:u,config:{...p,port:0},handleSignals:!1,quiet:!0,onRunRedaction:s.observe,mcpSecrets:{async get(t){let n=e.mcpSecretEnv,r=n&&Object.hasOwn(n,t)?n[t]:void 0,i=r===void 0?void 0:process.env[r];return i&&a.add(i),i}},hub:t?{client:t,hash:hs,serverForGrant:e=>{if(a.add(e),!i)throw Error(`Hub host is not ready`);return{transport:`stdio`,command:process.execPath,args:[{kind:`public`,value:d}],env:{TANGLE_HUB_MCP_ENDPOINT:{kind:`public`,value:`${i.url}/hub/mcp/grants/${e}`}}}}}:void 0});let{graphNativeCapture:m}=await import(`./graph-native-BOIC8WzU.mjs`);return{harnessTranscript:m({bridgeUrl:i.url,bridgeBearer:r,cwd:u,privateMcpSecrets:()=>[...a],redact:s.redact}),backend:`bridge`,bridgeUrl:i.url,bridgeBearer:r,cwd:u}})(),signal:n})}catch(t){throw t instanceof Error&&Object.assign(t,{runId:e.errorRunId??r}),t}finally{try{await i?.close()}finally{s.close(),a.clear()}}},e.fix??`tangle graph --help`)}function ql(e,t){return[`tangle graph run`,ut(e),...t.dryRun?[`--dry-run`]:[],...t.cloud?[`--cloud`]:[],...t.deploy?[`--deploy`,ut(t.deploy)]:[],...t.workflow?[`--workflow`,ut(t.workflow)]:[],...t.resume?[`--resume`,ut(t.resume)]:[],...t.seat?[`--seat`,ut(t.seat)]:[],...t.seatAccount?[`--seat-account`,ut(t.seatAccount)]:[],...t.seatCommand?[`--seat-command`,ut(t.seatCommand)]:[],...t.param.flatMap(e=>[`--param`,ut(e)])].join(` `)}async function Jl(e,t,n={}){let r=n,i=ql(e,t);return await gs(r.signal,async n=>{n.throwIfAborted();let a=Cs(t.mcpSecret);if(t.resume&&!t.resume.startsWith(`wfrun_`)&&(t.workflow||t.deploy)&&Y(`A local run cannot move to a cloud deployment`),t.deploy&&!t.cloud&&!t.workflow&&!t.resume?.startsWith(`wfrun_`))throw new B(`GRAPH_DEPLOY_INVALID`,`Deployment settings require cloud placement`,`Use --cloud to bind cloud triggers and settings`,`tangle graph run --help`);let o=await R(Gl(e,r.cwd??process.cwd())),s=r.source??await L(o,`utf8`),c=t.resume&&!t.resume.startsWith(`wfrun_`)?await tc(t.resume):void 0,l=r.taskWorkspace??(t.taskWorkspace?await Js(t.taskWorkspace):void 0)??c?.taskWorkspace;if(c&&(l?Ws(l):null)!==(c.taskWorkspace?Ws(c.taskWorkspace):null)&&Y(`The recorded task workspace snapshot changed`),l&&(t.cloud||t.workflow||t.resume?.startsWith(`wfrun_`)))throw Error(`Local private task workspace artifacts cannot be dispatched to a cloud backend`);let u=c?.runId??r.runId??be(),d=l&&!r.taskWorkspace?await Xs(l,{runId:u,resumeCwd:c?.cwd,signal:n,validationOnly:t.dryRun===!0&&!c&&!r.runId}):void 0;d&&(r={...r,runId:u,cwd:d.cwd,taskWorkspace:l});try{if(!t.resume&&(t.cloud||t.workflow)||t.resume?.startsWith(`wfrun_`))return Rc(o,s,t,n);let e=await Ns(),l=Q(s),u=Object.entries(Dc(t.param,`param`)??{}),d=Object.fromEntries(u.filter(([e])=>!e.startsWith(`gate.`))),f=Object.fromEntries(u.filter(([e])=>e.startsWith(`gate.`)).map(([e,t])=>[e.slice(5),t])),p=qe.parse(t.mcpPolicy??c?.mcpPolicy??{}),m=e.graphRegistry(M(F(),`.tangle`,`graph-registry`)),h;if(c){await R(c.cwd)!==c.cwd&&Y(`The recorded workspace identity changed`),c.file!==o&&Y(`The recorded graph source path changed`);let n=await e.loadGraph(m,c.graphDigest);n||Y(`The recorded executable graph is unavailable`),h=e.validateStoredGraph(n),ac(c,t,l,d,f)}let g={apiKey:t.apiKey,sandboxBaseUrl:t.baseUrl,signal:n,json:t.json,dryRun:t.dryRun&&!r.connectNeeds},_,v=()=>_??=hl(g),y=new Map,b=(e,{account:t})=>{let n=e.trim().toLowerCase(),r=JSON.stringify([n,t?.toLowerCase()]),i=y.get(r)??(async()=>{let e=await v(),r=e&&await _l(e,n,g,t);return r?{connectionId:r,capabilities:[`*`]}:void 0})();return y.set(r,i),i},x=async i=>{if(n.throwIfAborted(),c&&h)return _s(h,c.gateChoices??{}),{graph:h,params:c.params};let a=await e.loadGraphFile(o,{source:s,seat:t.seat??(r.defaultSeat===void 0?Qt().seat:r.defaultSeat??void 0),resolveSeat:cc(i,n),resolveNeed:b,params:d,...r.trigger?{trigger:r.trigger}:{},cwd:i,signal:n});if(n.throwIfAborted(),_s(a.graph,f),r.graphDigest&&a.graph.digest!==r.graphDigest)throw new B(`GRAPH_CHANGED`,`The validated graph changed before execution`,`Its compiled graph digest no longer matches validation`,`tangle graph run --help`);return a},S=r.cwd??process.cwd(),C=await x(c?.cwd??S),w=Je(p,!0),T=[];for(let e of C.graph.nodes){let t=Ae(e.profile,w);if(!t.ok)throw new B(`GRAPH_MCP_POLICY_REQUIRED`,`A graph profile exceeds its host policy`,`${e.id}: ${t.issues.filter(e=>e.level===`error`).map(e=>`${e.code}: ${e.message}`).join(`; `)}`,`tangle graph run --mcp-policy <policy.json> --help`);for(let t of Object.values(e.profile.mcp??{}))t.enabled!==!1&&t.url&&T.push(new URL(t.url).hostname)}let ee=[dc(C.graph),...T].filter(Boolean).join(`,`)||void 0;if(t.dryRun)return C;let E=fc(C.graph.nodes)?mc(t):void 0,D=c?.runId??r.runId??be(),O=c?.cwd??(r.taskWorkspace?S:await e.graphWorkspace(C.graph,{cwd:S,runId:D}));return await Kl({...r,runId:D,cwd:O,signal:n,fix:i,relayAllow:ee,mcpSecretEnv:a},i=>Yl(i,{kernel:e,registry:m,loaded:C,gateChoices:f,file:o,source:s,sourceDigest:l,context:r,options:t,prior:c,mcpPolicy:p,getHub:v,seatSource:E,signal:n}))}finally{await d?.release()}},i)}async function Yl({runId:e,runDir:t,cwd:n,bridge:r},{kernel:i,registry:a,loaded:o,gateChoices:s,file:c,source:u,sourceDigest:d,context:f,options:p,prior:m,mcpPolicy:h,getHub:g,seatSource:_,signal:v}){let{superviseGraphPursuit:y,readSettleRecord:b}=await import(`@tangle-network/agent-runtime/durable`),x=await i.recordStoredGraphRun(a,o.graph),S=m??{version:1,runId:e,cwd:n,file:c,graphDigest:x.digest,sourceDigest:d,source:u,params:o.params,...f.trigger?{trigger:f.trigger}:{},...Object.keys(s).length?{gateChoices:s}:{},startedAt:new Date().toISOString(),...p.seat===void 0?{}:{seat:p.seat},mcpPolicy:h,...f.taskWorkspace&&{taskWorkspace:f.taskWorkspace}};m||await nc(t,S);let C=m?await b(t):void 0;if(C&&C.tree.root!==e&&Y(`The settlement names another run`),C?.kind===`no-winner`&&Y(`The local run is terminal: ${C.reason}`),C)return{runId:e,graphDigest:x.digest,sourceDigest:d,...js(C),replayed:!0};let w=i.graphFromStored(x,{trigger:S.trigger}),T=x.nodes.some(e=>e.profile.connections?.length),ee=T?await g():void 0;if(T&&!ee)throw new B(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured for this local graph`,`tangle auth login`);let E=await r(ee),D=i.createPrivateCasArtifactPort(M(t,`artifacts`),e),O=await bs(o.params.knowledge,t,D,v),k=_?gc(E,_,v):void 0,A=S.startedAt;l(`Run ${e} · ${le(c)} · ${n}`);let te=await Xl(t);l(`Viewer ${te.url}`);let ne=new AbortController,re=await y(w,{pursuitId:x.digest,runDir:t,runId:e,backend:E,checkArtifacts:D,...O?{resolveSupervisorTools:O}:{},...w.entry===void 0?{driverBackend:E}:{},...x.gates?.length?{decideGate:vs(S.gateChoices??{},{json:p.json,signal:AbortSignal.any([v,ne.signal])})}:{},resume:!!m,signal:v,...S.trigger?{trigger:S.trigger}:{},...k?{selectSeat:k,coordination:{authentication:!0}}:{},profileSecurity:Je(S.mcpPolicy,T)}).finally(async()=>{ne.abort(),await te.close()}),ie={runId:e,graphDigest:x.digest,sourceDigest:d,...js(re.result.result)},ae=re.result.result,{tokens:oe,tokensKnown:se,iterations:j,ms:ce}=ae.spentTotal;if(await i.recordStoredGraphRun(a,x,{graphDigest:x.digest,evidence:[{kind:`authored-graph`,url:`urn:sha256:${x.digest}`},{kind:`authored-yaml`,url:`urn:sha256:${d}`}],taskDigest:i.taskShapeDigest({graph:le(c),params:o.params,trigger:S.trigger??null,taskWorkspace:S.taskWorkspace?Ws(S.taskWorkspace):null}),startedAt:A,finishedAt:new Date().toISOString(),outcome:ae.kind===`no-winner`?{kind:`no-winner`,reason:ae.reason}:{kind:`delivered`,summary:ie.text},cost:{iterations:j,ms:ce,...se===!1?{}:{tokens:oe.input+oe.output},...ie.costUsd===null?{}:{usd:ie.costUsd}},traversals:re.result.ledger.length,exhaustedEdges:re.result.exhaustedEdges,source:{kind:`tangle-cli-graph`,id:e}}),ae.kind===`no-winner`)throw Object.assign(new B(`GRAPH_RUN_FAILED`,`Graph '${le(c)}' finished without a result`,re.result.stopped?.reason||re.result.ledger.filter(e=>e.outcome===`unpropagated`&&e.reason).pop()?.reason||ae.reason,`tangle graph inspect ${e}`),{runId:e,runtimeFailures:[...ae.tree.nodes.filter(e=>e.failure).map(e=>({node:e.label,failure:e.failure})),...ae.reason===`driver-failed`&&ae.error.failure?[{node:`root`,failure:ae.error.failure}]:[]]});return ie}async function Xl(e){let{serveTopWeb:t}=await import(`@tangle-network/agent-runtime/tui`),{readGraphSessions:n}=await import(`./graph-native-BOIC8WzU.mjs`);return t({roots:[e],assets:M(Wl,`dist`,`graph-viewer`),readSessions:n})}async function Zl(t,n){if(n.artifacts||n.artifact)return wc(t,n);if(t.startsWith(`wfrun_`)){let r=await X(n),i=await r.workflows.getRun(t);if(n.json)return e(i);for(let e of i.runtime?.checks??[])l(`${e.node} ${e.status} · exit ${e.exitCode??`none`} · pass ${e.pass??`none`}\n${e.reason??e.tail}`);return l(`Run ${t} · ${r.baseUrl}/app/workflows/${encodeURIComponent(i.workflowId)}/runs/${encodeURIComponent(t)}`)}let r=M(F(),`.tangle`,`runs`,t);if(!/^[a-f0-9-]{36}$/i.test(t)||!Pe(r))throw new B(`RUN_NOT_FOUND`,`Run '${t}' was not found`,`Use a run ID printed by tangle graph run`,`tangle graph inspect --help`);let{loadTopSnapshot:i}=await import(`@tangle-network/agent-runtime/tui`);if(n.json)return e(await i(process.cwd(),{runDir:r}));l(`Run ${t} · ${(await Xl(r)).url}`)}function Ql(){let t=new N(`graph`).description(`Build and run portable agent graphs`);return ul(t),Zs(t),Lc(t,Gl),Bc(t,Gl),Cc(t),nl(t),ml(t,Gl,Wl),t.command(`inspect <run>`).description(`Inspect a live or retained graph run`).option(`--artifacts`,`List complete retained check files and capture gaps`).option(`--artifact <node/path>`,`Download one retained check file by node/path or digest`).option(`--out <file>`,`Save artifact bytes to a new private file`).action(Zl),t.command(`run <name-or-file>`).description(`Run a saved graph over native subscriptions`).option(`--cloud`,`Run through Tangle's durable cloud workflow owner`).option(`--deploy <file>`,`Cloud deployment settings, including triggers and parameter defaults`).option(`--workflow <id>`,`Run this existing cloud deployment at its exact source and revision`).option(`--resume <run>`,`Resume this run's saved graph and durable execution`).option(`--seat <seat>`,`Use harness/model@effort for every node`).addOption(Ss()).option(`--mcp-policy <file>`,`Host-owned JSON policy: allowLocalMcp and allowedMcpHosts; captured for resume`).option(`--seat-account <account>`,`Account id for an all-eligible authored seat`).option(`--seat-command <program>`,`Executable that prints the account id; the harness is its first argument`).option(`--seat-credential <credential>`,`Credential name passed to the seat command after the harness`).option(`--param <key=value>`,`Graph parameter or gate.<id>=<choice>; repeatable`,(e,t)=>[...t,e],[]).option(`--task-workspace <file>`,`Seed a private run copy from an exact local workspace capture`).option(`--dry-run`,`Validate and print the graph without starting agents`).action(async(t,n)=>{let r={...n,mcpPolicy:n.mcpPolicy===void 0?void 0:await ws(n.mcpPolicy)},i=await Jl(t,r);r.json||r.dryRun?e(i):`status`in i?(l(`${i.status} · ${i.runId}`),i.text&&console.log(i.text)):`viewerUrl`in i&&l(`Run ${i.runId} · ${i.viewerUrl}`)}),t}function $l(){let n=new N(`intelligence`).description(`Create and inspect trace intelligence reports`);return n.command(`connect [agent]`).alias(`connect-agent`).description(`Connect local agent CLIs to Tangle Intelligence`).option(`--endpoint <url>`,`OTLP endpoint base`,mi).option(`--workspace <path>`,`Workspace to write hook files into`,`.`).option(`--service-name <name>`,`OTel service.name label`).option(`--environment <name>`,`OTel deployment.environment label`,`local`).option(`--dry-run`,`Print planned writes without changing files`).option(`--hook-command <command>`,`Command native hooks should run`,`tangle intelligence hook`).option(`--no-smoke`,`Skip the install smoke trace`).action(async(t,n)=>{let r=t??`local`;yi(r);let i=tu(n.apiKey),a=await wi({selection:r,workspace:n.workspace,apiKey:i,endpoint:n.endpoint,serviceName:n.serviceName??xi(n.workspace),environment:n.environment,smoke:n.smoke,dryRun:!!n.dryRun,hookCommand:n.hookCommand}),o={configPath:a.configPath,agents:a.agents,nativeAgents:a.nativeAgents,manual:a.manual,written:a.written,smokeTraceId:a.smokeTraceId};if(n.json){e(o);return}s({Config:a.configPath,Agents:a.agents.join(`, `),"Native Hooks":a.nativeAgents.join(`, `)||void 0,"Manual Setup":a.manual.length?a.manual.map(e=>`${e.label}: ${e.reason}`).join(` `):void 0,Files:a.written.join(`, `),"Smoke Trace":a.smokeTraceId})}),n.command(`doctor`).description(`Check whether your agent traces carry CONTENT or are metadata-only`).option(`--endpoint <url>`,`OTLP endpoint base`,mi).action(async t=>{let n=Ci(),r=await ki({endpoint:t.endpoint===`https://intelligence.tangle.tools/v1/otlp`?n?.endpoint??`https://intelligence.tangle.tools/v1/otlp`:t.endpoint,apiKey:tu(t.apiKey??n?.apiKey)});t.json?e(r):eu(r),r.contentSeen||(process.exitCode=1)}),n.command(`hook`).description(`Emit one local agent hook event to Tangle Intelligence`).requiredOption(`--agent <agent>`,`Agent surface`).requiredOption(`--event <event>`,`Hook event name`).option(`--payload <json>`,`Hook payload JSON`).option(`--endpoint <url>`,`OTLP endpoint base`).option(`--service-name <name>`,`OTel service.name label`).option(`--environment <name>`,`OTel deployment.environment label`).option(`--session-id <id>`,`Session id override`).option(`--dry-run`,`Build the OTLP request without sending it`).option(`--non-blocking`,`Do not fail the parent agent process`).action(async t=>{try{let n=nu(t.agent),r=Ci(),i={agent:n,event:t.event,endpoint:t.endpoint??r?.endpoint??`https://intelligence.tangle.tools/v1/otlp`,apiKey:tu(t.apiKey??r?.apiKey),serviceName:t.serviceName??r?.serviceName??xi(process.cwd()),environment:t.environment??r?.environment??`local`,sessionId:t.sessionId,payload:t.payload===void 0?await iu():ru(t.payload)};if(t.dryRun){let r=Ei(i);if(t.json){e(r);return}s({Trace:r.traceId,Agent:n,Event:t.event});return}let a=await Di(i);if(t.json){e({traceId:a});return}s({Trace:a,Agent:n,Event:t.event})}catch(n){if(t.nonBlocking){let r=n instanceof Error?n.message:String(n);t.json?e({ok:!1,error:r}):console.error(`Tangle Intelligence hook skipped: ${r}`);return}H(n)}}),n.command(`sandbox <sandbox-id>`).description(`Create an intelligence report for one sandbox`).option(`--mode <mode>`,`deterministic | agentic`,`deterministic`).option(`--max-usd <amount>`,`Maximum customer charge for agentic analysis`).option(`--metadata <json>`,`Metadata JSON object`).action(async(e,t)=>{await au({type:`sandbox`,id:e},t)}),n.command(`fleet <fleet-id>`).description(`Create an intelligence report for a sandbox fleet`).option(`--mode <mode>`,`deterministic | agentic`,`deterministic`).option(`--max-usd <amount>`,`Maximum customer charge for agentic analysis`).option(`--metadata <json>`,`Metadata JSON object`).action(async(e,t)=>{await au({type:`fleet`,id:e},t)}),n.command(`create`).description(`Create a trace intelligence report`).requiredOption(`--subject-type <type>`,`sandbox | fleet`).requiredOption(`--subject-id <id>`,`Subject identifier`).option(`--mode <mode>`,`deterministic | agentic`,`deterministic`).option(`--max-usd <amount>`,`Maximum customer charge for agentic analysis`).option(`--metadata <json>`,`Metadata JSON object`).action(async e=>{await au({type:su(e.subjectType),id:e.subjectId},e)}),n.command(`get <job-id>`).description(`Get an intelligence report`).action(async(t,n)=>{let{client:r}=G(n),i=n.json?null:f(`Fetching intelligence report...`);i?.start();let a=await r.intelligence.getReport(t);if(i?.stop(),n.json){e(a);return}ou(a)}),n.command(`list`).description(`List intelligence reports`).option(`--subject-type <type>`,`sandbox | fleet`).option(`--subject-id <id>`,`Subject identifier`).option(`--limit <count>`,`Maximum reports to return`).action(async n=>{let{client:r}=G(n),i=n.json?null:f(`Fetching intelligence reports...`);i?.start();let a=await r.intelligence.listReports({subjectType:n.subjectType===void 0?void 0:su(n.subjectType),subjectId:n.subjectId,limit:n.limit===void 0?void 0:uu(n.limit)});if(i?.stop(),n.json){e(a);return}t(a.map(e=>({jobId:e.jobId,subject:`${e.subject.type}:${e.subject.id}`,mode:e.mode,status:e.status,cost:`$${e.billing.costUsd.toFixed(2)}`,updatedAt:e.updatedAt})),[{key:`jobId`,header:`Job`,width:20},{key:`subject`,header:`Subject`,width:28},{key:`mode`,header:`Mode`,width:15},{key:`status`,header:`Status`,width:14},{key:`cost`,header:`Cost`,width:10},{key:`updatedAt`,header:`Updated`,width:18}])}),n}function eu(e){s({Status:e.contentSeen?`content flowing`:e.tracesSeen?`metadata-only — a content gate is missing`:`no traces yet`,"Traces seen":e.tracesSeen?`yes`:`no`,"Content seen":e.contentSeen?`yes`:`no`,"Last seen":e.lastSeenAt??`never`,Window:`${e.windowDays}d`});let n=Object.entries(e.byAgent);n.length>0&&(console.log(),t(n.map(([e,t])=>({agent:e,traces:t.tracesSeen?`yes`:`no`,content:t.contentSeen?`yes`:`no`})),[{key:`agent`,header:`Agent`,width:18},{key:`traces`,header:`Traces`,width:10},{key:`content`,header:`Content`,width:10}]))}function tu(e){let t=e??process.env.TANGLE_INTELLIGENCE_API_KEY??process.env.TANGLE_API_KEY;if(!t)throw Error(`--api-key, TANGLE_INTELLIGENCE_API_KEY, or TANGLE_API_KEY is required`);return t}function nu(e){if(bi(e))return e;throw Error(`agent must be a known Tangle Intelligence agent surface`)}function ru(e){try{return JSON.parse(e)}catch(e){throw Error(`--payload must be JSON: ${e instanceof Error?e.message:String(e)}`)}}async function iu(){if(process.stdin.isTTY)return;let e=``;for await(let t of process.stdin)if(e+=typeof t==`string`?t:t.toString(`utf8`),e.length>65536)throw Error(`hook payload exceeds 65536 bytes`);let t=e.trim();if(t)try{return JSON.parse(t)}catch{return{body:t.slice(0,4096)}}}async function au(t,n){let r=cu(n.mode),i=du(n.metadata),a=n.maxUsd===void 0?void 0:lu(n.maxUsd);if(r===`agentic`&&a===void 0)throw Error(`Agentic intelligence reports require --max-usd`);let{client:o}=G(n),s=n.json?null:f(`Creating intelligence report...`);s?.start();let c=await o.intelligence.createReport({subject:t,mode:r,...a===void 0?{}:{budget:{billTo:`customer`,maxUsd:a}},...i===void 0?{}:{metadata:i}});if(s?.stop(),n.json){e(c);return}ou(c)}function ou(t){s({Job:t.jobId,Subject:`${t.subject.type}:${t.subject.id}`,Mode:t.mode,Status:t.status,"Billed To":t.billing.billedTo,Cost:`$${t.billing.costUsd.toFixed(2)}`,Budget:t.billing.budgetMaxUsd===void 0?void 0:`$${t.billing.budgetMaxUsd.toFixed(2)}`,Updated:t.updatedAt}),t.result!==null&&(console.log(),e(t.result))}function su(e){if(e===`sandbox`||e===`fleet`)return e;throw Error(`subject type must be sandbox or fleet`)}function cu(e){if(e===`deterministic`||e===`agentic`)return e;throw Error(`mode must be deterministic or agentic`)}function lu(e){let t=Number(e);if(!Number.isFinite(t)||t<0)throw Error(`--max-usd must be a non-negative number`);return t}function uu(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}function du(e){if(e===void 0)return;let t=JSON.parse(e);if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`--metadata must be a JSON object`);return t}const fu=[`router`,`sandbox`,`blueprint-agent`,`evals`,`agent-builder`];async function pu(e,t){let n=await Kn({...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.platformUrl===void 0?{}:{baseUrl:e.platformUrl},...e.baseUrl===void 0?{}:{sandboxBaseUrl:e.baseUrl}});if(!t||!n.minted)return n;throw Error("This command needs a key you minted yourself. A browser login is exchanged for a short-lived key the platform will not accept for key management. Set TANGLE_API_KEY, run `tangle auth login --api-key sk-tan-…`, or mint the key in the web console. `tangle keys list` works from the login alone.")}async function mu(e,t,n={}){let r=new Headers(n.headers);n.body&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`);let i=await qn(e,t,{...n,headers:r});if(n.expected!==void 0&&i.status!==n.expected)throw Error(await hu(i,t));return i}async function hu(e,t){let n=await e.text().catch(()=>``),r;try{let e=JSON.parse(n),t=typeof e?.error==`string`?e.error:e?.error?.message;typeof t==`string`&&t.trim()&&(r=t)}catch{}if(r)return`${r} (HTTP ${e.status})`;let i=n?`: ${n.slice(0,400)}`:``;return`Platform request to ${t} returned ${e.status}${i}`}const gu=[`ID`,`Prefix`,`Name`,`Product`,`Created`,`Last used`,`Expires`];function _u(e){return[e.id,e.keyPrefix??``,e.name,e.product??`all`,e.createdAt,e.lastUsedAt??`—`,e.expiresAt??`—`]}function vu(){let t=new N(`keys`).description(`Manage sk-tan-* API keys on id.tangle.tools`);return t.command(`list`).description(`List your active API keys`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async t=>{let n=await pu(t,!1),r=n.baseUrl,a=await(await mu(n,`${r}/v1/keys`,{expected:200})).json();if(t.json){e(a);return}i(gu,a.data.map(_u))}),t.command(`create`).description(`Create a new API key`).argument(`<name>`,`Human-readable name for the key`).option(`--product <product>`,`Restrict the key to one product (${fu.join(`|`)}). Omit for all products.`).option(`--budget-usd <amount>`,`Hard budget cap in USD`).option(`--rpm-limit <limit>`,`Requests-per-minute cap`).option(`--expires-in-days <days>`,`Expire the key after N days (integer)`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async(t,n)=>{if(n.product!==void 0&&!fu.includes(n.product))throw Error(`Invalid --product. Expected one of ${fu.join(`, `)}`);let i=await pu(n,!0),a=i.baseUrl,o=n.expiresInDays===void 0?void 0:new Date(Date.now()+Number.parseInt(n.expiresInDays,10)*24*60*60*1e3).toISOString(),s=f(`Creating API key...`);s.start();let c=await mu(i,`${a}/v1/keys`,{method:`POST`,expected:201,body:JSON.stringify({name:t,product:n.product,budgetUsd:n.budgetUsd?Number.parseFloat(n.budgetUsd):void 0,rpmLimit:n.rpmLimit?Number.parseInt(n.rpmLimit,10):void 0,expiresAt:o})});s.stop();let u=await c.json();if(n.json){e(u);return}r(`API key created: ${u.data.prefix}…`),l(`Copy this key now — it will never be shown again:\n${u.data.key}`)}),t.command(`revoke`).description(`Revoke an API key`).argument(`<keyId>`,"Key ID (from `tcloud keys list`)").option(`--yes`,`Skip the confirmation prompt`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async(t,n)=>{let i=await pu(n,!0),a=i.baseUrl;if(!n.yes&&!await cr(`Revoke key ${t}? Any service still using it will start to fail.`,`--yes`)){l(`Aborted.`);return}let o=await(await mu(i,`${a}/v1/keys/${encodeURIComponent(t)}`,{method:`DELETE`,expected:200})).json();if(n.json){e(o);return}r(`Revoked ${t}`)}),t}function yu(e){if(nn().token)throw Error(`A line relay cannot manage numbers or attachments. Use your owner CLI outside the agent box.`);return W(U(e))}function bu(e){if(!e.yes)throw Error(`Review the selected line and use --yes to authorize this change. Attaching enables metered agent work.`)}function xu(e){if(e===`imessage`||e===`whatsapp`||e===`email`||e===`sms`||e===`voice`||e===`telegram`)return e;throw Error(`--transport must be imessage, whatsapp, email, sms, voice, or telegram`)}function Su(e){return e().catch(H)}async function Cu(e){let t=await mt(e,`r`);try{if(!(await t.stat()).isFile())throw Error(`Attachment input must be a regular JSON file`);let e=Buffer.alloc(131073),n=0;for(;n<e.length;){let{bytesRead:r}=await t.read(e,n,e.length-n,null);if(r===0)break;n+=r}if(n===e.length)throw Error(`Attachment JSON exceeds 128 KiB`);let r;try{r=JSON.parse(e.subarray(0,n).toString(`utf8`))}catch{throw Error(`Attachment file is not valid JSON`)}if(!r||typeof r!=`object`||Array.isArray(r))throw Error(`Attachment JSON must be an object`);if(Object.hasOwn(r,`number`))throw Error(`Use the line ID argument, not a number field in the attachment file`);return r}finally{await t.close()}}function wu(t){t.command(`providers`).description(`List provider transports supported by this Hub deployment`).action(t=>Su(async()=>{e(await yu(t).lines.providers())})),t.command(`list`).description(`List owned lines, optionally for a saved agent profile or sandbox`).option(`--profile-id <id>`,`Stored profile ID`).option(`--sandbox <id>`,`Existing sandbox ID`).action(t=>Su(async()=>{e(await yu(t).lines.list({profileId:t.profileId,sandboxId:t.sandbox}))})),t.command(`get`).argument(`<line-id>`).description(`Inspect a line and its current attachment`).action((t,n)=>Su(async()=>{e(await yu(n).lines.get(t))})),t.command(`numbers`).argument(`<connection-id>`).description(`Discover owned provider numbers; this does not purchase or reserve a number`).option(`--transport <transport>`,`imessage, whatsapp, or sms`,`imessage`).action((t,n)=>Su(async()=>{let r=xu(n.transport);if(r===`email`)throw Error(`Email uses an owned mailbox, not phone inventory`);if(r===`voice`)throw Error(`Voice numbers are listed by ph0ny; provide the owned number ID to lines connect`);if(r===`telegram`)throw Error(`Telegram uses an owned bot, not phone inventory`);e(await yu(n).lines.numbers(t,r))})),t.command(`connect`).argument(`<connection-id>`).description(`Bind an owned number or identity through Hub; no provider rental is purchased`).option(`--transport <transport>`,`imessage, whatsapp, sms, email, voice, or telegram`,`imessage`).option(`--number-id <id>`,`Exact owned provider number ID; required for voice, SMS, WhatsApp and Linq iMessage`).option(`--address <email>`,`Owned mailbox on a verified email domain`).requiredOption(`--reference <reference>`,`Stable client reference; keep it unchanged on retry`).option(`--label <label>`,`Line display name`).option(`--yes`,`Authorize provider webhook configuration and line binding`).action((t,n)=>Su(async()=>{bu(n);let r=xu(n.transport);if(r!==`email`&&n.address)throw Error(`--address is email-only`);if((r===`email`||r===`telegram`)&&n.numberId)throw Error(`${r} does not take --number-id`);let i={connectionId:t,label:n.label,clientReference:n.reference},a;if(r===`email`)a={...i,transport:r,address:n.address};else if(r===`telegram`)a={...i,transport:r};else if(r===`imessage`)a={...i,transport:r,phoneNumberId:n.numberId};else{if(!n.numberId)throw Error(`${r} requires --number-id`);a={...i,transport:r,phoneNumberId:n.numberId}}e(await yu(n).lines.fromConnection(a))})),t.command(`attach`).argument(`<line-id>`).description(`Attach a saved agent to any sandbox, or use an isolated on-demand member instance`).option(`--file <path>`,`Reviewed native attachment JSON (exclusive with quick-setup flags)`).option(`--profile-id <id>`,`Owner-scoped saved profile; each turn pins its source revision`).option(`--member <address>`,`The one allowed sender: E.164 phone or email`).option(`--sandbox <id>`,`Use an existing sandbox instead of an on-demand instance`).option(`--instance-prefix <prefix>`,`Stable instance namespace; defaults to profile:<profile-id>:`).option(`--tools <mode>`,`chat denies tools; act applies the profile's tools and permissions`).option(`--turns-per-day <count>`,`Per-member daily turn ceiling (default 30)`).option(`--yes`,`Authorize agent execution and spend against your key limits`).action((t,n)=>Su(async()=>{bu(n);let r=yu(n),i;if(n.file){if(n.profileId||n.member||n.sandbox||n.instancePrefix||n.tools||n.turnsPerDay)throw Error(`Choose --file or quick-setup flags, not both`);i=await Cu(n.file)}else{if(!n.profileId||!n.member)throw Error(`Provide --profile-id and --member, or --file`);if(n.sandbox&&n.instancePrefix)throw Error(`Choose --sandbox or --instance-prefix`);let e=n.tools??`chat`,t=Number(n.turnsPerDay??`30`);if(e!==`chat`&&e!==`act`)throw Error(`--tools must be chat or act`);if(!Number.isSafeInteger(t)||t<1||t>1e4)throw Error(`--turns-per-day must be 1–10000`);if(e===`act`&&n.sandbox)throw Error(`Acting tools require an isolated on-demand instance; omit --sandbox`);i={mode:`personal`,members:[{address:n.member,role:`owner`}],unknownSenders:`reject`,roles:{owner:{context:`own`,tools:e}},respond:{kind:`agent`,profileId:n.profileId,...e===`act`?{rolePolicy:{version:1,roles:{owner:{kind:`general`}},members:{}}}:{}},limits:{turnsPerMemberPerDay:t},...n.sandbox?{sandboxId:n.sandbox}:{instance:{keyPrefix:n.instancePrefix??`profile:${n.profileId}:`,create:{ownerContext:`isolated`,...e===`act`?{egressPolicy:{mode:`strict`,allowDomains:[new URL(xn()).hostname],includeImplicitDomains:!1}}:{}}}}}}if(typeof i.sandboxId==`string`==(i.instance!==void 0))throw Error(`Attachment requires exactly one of sandboxId and instance`);let{sandboxId:a,instance:o,...s}=i,c;if(a){let e=await r.get(a);if(!e)throw Error(`Sandbox not found`);c=await e.lines.attach({...s,number:t})}else{if(!o)throw Error(`Attachment requires an instance`);c=await r.lines.attach({...s,number:t,instance:o})}e(c)}));for(let n of[`detach`,`release`])t.command(n).argument(`<line-id>`).description(n===`detach`?`Stop dispatch; preserve history and provider rental`:`Retire a detached Hub line; does not cancel provider rental`).option(`--yes`,`Authorize this change`).action((t,r)=>Su(async()=>{bu(r),e({[n]:await yu(r).lines[n](t)})}));t.command(`threads`).argument(`<line-id>`).description(`List this line's separate participant threads`).action((t,n)=>Su(async()=>{e(await yu(n).lines.threads(t).list())})),t.command(`messages`).argument(`<line-id>`).argument(`<thread-id>`).description(`Read one authorized participant thread`).action((t,n,r)=>Su(async()=>{e(await yu(r).lines.threads(t).messages(n))}))}async function Tu(e){let{token:t,baseUrl:n}=nn();if(t===void 0)return K(e);if(!t.startsWith(`lrc_`)||!n)throw Error(`The line box needs TANGLE_LINE_TOKEN and TANGLE_HUB_URL`);if(e.apiKey||e.baseUrl&&new URL(e.baseUrl).origin!==new URL(n).origin)throw Error(`A line token cannot be sent to another Hub or combined with an API key`);return new Ge({baseUrl:n,authHeaders:()=>({Authorization:`Bearer ${t}`})})}async function Eu(e,t){if(t)return t;if(!nn().token)throw Error(`Provide --line <line-id>`);return(await e.lines.context()).line.id}function Du(e){return e().catch(H)}function Ou(){return new N(`context`).description(`Show live line identity, members, consent, reminders and quotas`).action(t=>Du(async()=>{e(await(await Tu(t)).lines.context())}))}function ku(){let t=new N(`lines`).description(`Connect, manage, message and schedule on a Hub line`);return t.command(`members`).description(`List names, roles and consent on this line`).option(`--line <line-id>`,`Line ID; inferred in a line box`).action(t=>Du(async()=>{let n=await Tu(t);e(await n.lines.members.list(await Eu(n,t.line)))})),t.command(`send`).description(`Send to a consenting member through Hub`).argument(`<to-member>`,`Exact member ID for an owner; name, ID, or self in a line box`).argument(`<text>`,`Message text`).option(`--line <line-id>`,`Line ID; inferred in a line box`).option(`--on-behalf-of <member>`,`Verified sender for a member relay`).option(`--not-before <iso-time>`,`Delay delivery until this ISO time`).option(`--idempotency-key <key>`,`Stable key for a retry`).action((t,n,r)=>Du(async()=>{let i=await Tu(r),a=await Eu(i,r.line);if(!nn().token){if(r.onBehalfOf)throw Error(`--on-behalf-of is only available inside a line box`);if(!r.idempotencyKey)throw Error(`Owner sends require --idempotency-key so a retry keeps the same message`);if(!(await i.lines.members.list(a)).some(e=>e.id===t))throw Error(`Owner sends require an exact member ID from tangle lines members`);e(await i.lines.send(a,{memberId:t,text:n,idempotencyKey:r.idempotencyKey,...r.notBefore?{notBefore:r.notBefore}:{}}));return}e(await i.lines.send(a,{toMember:t,text:n,...r.onBehalfOf?{onBehalfOf:r.onBehalfOf}:{},...r.notBefore?{notBefore:r.notBefore}:{},...r.idempotencyKey?{idempotencyKey:r.idempotencyKey}:{}}))})),t.command(`remind`).description(`Wake the agent at a future time to write your reminder`).argument(`<text>`,`What to remember`).requiredOption(`--at <iso-time>`,`Future ISO time`).option(`--line <line-id>`,`Line ID; inferred in a line box`).option(`--idempotency-key <key>`,`Stable key for a retry`).action((t,n)=>Du(async()=>{if(!n.at)throw Error(`--at is required`);let r=await Tu(n),i=n.idempotencyKey??ve(`sha256`).update(JSON.stringify([t,n.at])).digest(`hex`).slice(0,32);e(await r.lines.remind(await Eu(r,n.line),{text:t,notBefore:n.at,idempotencyKey:i}))})),wu(t),t}function Au(){let e=new N(`mcp`).description(`Model Context Protocol bridge commands.`);return e.command(`serve <id-or-name>`).description(`Run a local MCP server (stdio) backed by the given sandbox (ID or name). Pipe its stdio from an MCP client config to expose sandbox tools.`).option(`-s, --session <id>`,`Session id for kernel scoping`,`mcp-local`).option(`--name <name>`,`MCP server name reported to clients`,`tangle-sandbox`).action(async(e,t)=>{let n=U({apiKey:t.apiKey,baseUrl:t.baseUrl}),r=await q(W(n),n,e),i;try{i=(await import(`@modelcontextprotocol/sdk/server/stdio.js`)).StdioServerTransport}catch{throw Error("`@modelcontextprotocol/sdk` is not installed in this environment. Install it with: pnpm add -g @modelcontextprotocol/sdk (or as a dev dep in the project running this command).")}let{connect:a,close:o}=await(await import(`@tangle-network/sandbox/agent`)).createMcpServer(r,{sessionId:t.session,name:t.name});await a(new i),process.stdin.resume(),process.stdin.on(`end`,()=>{o().finally(()=>process.exit(0))});for(let e of[`SIGINT`,`SIGTERM`])process.on(e,()=>{o().finally(()=>process.exit(0))})}),e}async function ju(e,t){if(t.self&&e)throw Error(`Use --self or an explicit sandbox, not both`);if(!t.self&&!e)throw Error(`Specify a sandbox id/name or --self`);let n=qt(),r=t.baseUrl||n.tangleBaseUrl||n.sandboxBaseUrl,i=n.hubUrl;if(t.self&&!r&&i&&new URL(i).origin!==`https://id.tangle.tools`)throw Error(`This deployment must set SANDBOX_BASE_URL or pass --base-url for self preview access`);let a=t.self?t.apiKey??pn():t.apiKey;if(t.self&&!a)throw Error(`Self preview access requires the injected sandbox runtime credential; it never reads saved owner credentials`);let o=U({apiKey:a,baseUrl:r}),s=W(o);return t.self?Ct(s):q(s,o,e)}async function Mu(e,t,n){let r=f(e);t||r.start();try{return await n()}finally{r.stop()}}function Nu(e){return e}function Pu(){let t=new N(`preview`).description(`Manage sandbox preview links`);return Nu(t.command(`start`).description(`Start/reuse a managed development server and publish its ready preview`).argument(`[id-or-name]`,`Sandbox ID or name`).option(`--self`,`Use only the sandbox bound to the runtime credential`).option(`--cwd <directory>`,`Project directory in the selected workspace`).option(`--session <session-id>`,`Select the agent's session workspace`).option(`--name <name>`,`App/service label`)).action(async(t,n)=>{let i=await ju(t,n),a=await Mu(`Starting managed preview...`,n.json,()=>xt(i,{cwd:n.cwd,sessionId:n.session,name:n.name}));n.json?e(a):(r(`Preview ready: ${a.url}`),console.log(`Preview ID: ${a.previewId}`))}),Nu(t.command(`list`).alias(`ls`).description(`List active preview links for a sandbox`).argument(`[id-or-name]`,`Sandbox ID or name`).option(`--self`,`Use only the sandbox bound to the runtime credential`)).action(async(t,n)=>{let r=await ju(t,n),a=await Mu(`Fetching preview links...`,n.json,()=>r.previewLinks.list());n.json?e(a):a.length===0?console.log(`No preview links found`):i([`App`,`Preview ID`,`Port`,`URL`,`Status`],a.map(e=>[Fu(e.metadata),e.previewId.slice(0,12),String(e.port),e.url,e.status]))}),Nu(t.command(`publish`).description(`Publish one existing HTTP service; never starts or replaces a process`).argument(`[id-or-name]`,`Sandbox ID or name`).option(`--self`,`Use only the sandbox bound to the runtime credential`).requiredOption(`--port <port>`,`Existing service port`).option(`--name <name>`,`App/service label`)).action(async(t,n)=>{if(!n.port||!/^\d+$/.test(n.port))throw Error(`An integer service port is required`);let i=await ju(t,n),a=await Mu(`Publishing service...`,n.json,()=>St(i,{port:Number(n.port),name:n.name}));n.json?e(a):r(`Preview ready: ${a.url}`)}),Nu(t.command(`create`).description(`Create a preview link for a port`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<port>`,`Port number to preview`)).action(async(t,n,i)=>{if(!/^\d+$/.test(n)||Number(n)<1||Number(n)>65535)throw Error(`Port must be an integer between 1 and 65535`);let a=await ju(t,i),o=await Mu(`Creating preview for port ${n}...`,i.json,()=>a.previewLinks.create(Number(n)));i.json?e(o):(r(`Preview created: ${o.url}`),console.log(`Preview ID: ${o.previewId}`))}),Nu(t.command(`remove`).alias(`rm`).description(`Remove a preview link`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<preview-id>`,`Preview link ID (from 'preview list')`)).action(async(t,n,i)=>{let a=await ju(t,i);await Mu(`Removing preview...`,i.json,()=>a.previewLinks.remove(n)),i.json?e({success:!0,previewId:n}):r(`Preview removed: ${n}`)}),t}function Fu(e){let t=e?.app;if(!t||typeof t!=`object`)return``;let n=`name`in t?t.name:void 0,r=`cwd`in t?t.cwd:void 0;return typeof n==`string`?n:typeof r==`string`?r:``}function Iu(){let t=new N(`process`).description(`Manage processes in a sandbox`);return t.command(`spawn`).description(`Spawn a process without blocking (returns PID)`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<command>`,`Command to execute`).option(`--cwd <dir>`,`Working directory`).option(`--env <vars...>`,`Environment variables (KEY=VALUE)`).option(`-t, --timeout <ms>`,`Timeout in milliseconds`).option(`--blocking`,`Wait for completion (default: false)`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=fo(r.env??[],`--env`,`env`),s=f(`Spawning: ${n}`);r.json||s.start();let c=await q(a,i,t);if(c=await J(c),r.blocking){let t=await c.exec(n,{cwd:r.cwd,env:Object.keys(o).length>0?o:void 0,timeoutMs:r.timeout?Number.parseInt(r.timeout,10):void 0});s.stop(),r.json?e(t):(t.stdout&&globalThis.process.stdout.write(t.stdout),t.stderr&&globalThis.process.stderr.write(t.stderr),t.exitCode!==0&&globalThis.process.exit(t.exitCode))}else{let i=await c.process.spawn(n,{cwd:r.cwd,env:Object.keys(o).length>0?o:void 0,timeoutMs:r.timeout?Number.parseInt(r.timeout,10):void 0});s.stop(),r.json?e({pid:i.pid,command:i.command}):(console.log(`Process started with PID: ${i.pid}`),console.log(`Use 'tangle process logs ${t} ${i.pid}' to view output`))}}),t.command(`list`).alias(`ls`).description(`List all processes in a sandbox`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--running`,`Show only running processes`).action(async(t,n)=>{let{context:r,client:a}=G(n),o=f(`Fetching processes...`);n.json||o.start();let s=await q(a,r,t);s=await J(s);let c=await s.process.list();n.running&&(c=c.filter(e=>e.running)),o.stop(),n.json?e(c):c.length===0?console.log(`No processes found`):i([`PID`,`Command`,`Status`,`Exit Code`,`Started`],c.map(e=>[String(e.pid),e.command.length>40?`${e.command.slice(0,37)}...`:e.command,e.running?`running`:`exited`,String(e.exitCode),e.startedAt.toLocaleString()]))}),t.command(`get`).description(`Get detailed info about a process`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching process info...`);r.json||o.start();let s=await q(a,i,t);s=await J(s);let c=await s.process.get(Number.parseInt(n,10));if(o.stop(),!c){console.error(`Process ${n} not found`),globalThis.process.exit(1);return}let l=await c.status();r.json?e(l):(console.log(`PID: ${l.pid}`),console.log(`Command: ${l.command}`),console.log(`CWD: ${l.cwd||`(default)`}`),console.log(`Status: ${l.running?`running`:`exited`}`),console.log(`Exit Code: ${l.exitCode}`),l.exitSignal&&console.log(`Signal: ${l.exitSignal}`),console.log(`Started: ${l.startedAt.toLocaleString()}`),l.exitedAt&&console.log(`Exited: ${l.exitedAt.toLocaleString()}`))}),t.command(`kill`).description(`Kill a process`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).option(`-s, --signal <signal>`,`Signal to send (SIGTERM, SIGKILL, etc.)`,`SIGTERM`).option(`--tree`,`Also kill descendants of the tracked process`).action(async(t,n,r)=>{let{context:i,client:a}=G(r),o=f(`Sending ${r.signal} to PID ${n}...`);r.json||o.start();let s=await q(a,i,t);s=await J(s);let c=await s.process.get(Number.parseInt(n,10));if(!c){o.stop(),console.error(`Process ${n} not found`),globalThis.process.exit(1);return}r.tree?await c.kill(r.signal,{tree:!0}):await c.kill(r.signal),o.stop(),r.json?e({pid:Number.parseInt(n,10),signal:r.signal,...r.tree===!0?{tree:!0}:{},killed:!0}):console.log(r.tree?`Sent ${r.signal} to process tree ${n}`:`Sent ${r.signal} to process ${n}`)}),t.command(`logs`).description(`Stream buffered and live process logs until the process exits`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).option(`--stdout-only`,`Only show stdout`).option(`--stderr-only`,`Only show stderr`).action(async(e,t,n)=>{let{context:r,client:i}=G(n),a=await q(i,r,e);a=await J(a);let o=await a.process.get(Number.parseInt(t,10));if(!o){console.error(`Process ${t} not found`),globalThis.process.exit(1);return}for await(let e of o.logs())n.stdoutOnly&&e.type!==`stdout`||n.stderrOnly&&e.type!==`stderr`||(n.json?console.log(JSON.stringify(e)):e.type===`stdout`?globalThis.process.stdout.write(e.data):globalThis.process.stderr.write(e.data))}),t}const Lu=[`python`,`node`,`typescript`,`bash`];function Ru(e){switch(de(e).toLowerCase()){case`.py`:return`python`;case`.js`:case`.mjs`:case`.cjs`:return`node`;case`.ts`:case`.tsx`:return`typescript`;case`.sh`:case`.bash`:return`bash`;default:return}}async function zu(e){if(e===`-`){let e=[];for await(let t of process.stdin)e.push(typeof t==`string`?Buffer.from(t):t);return Buffer.concat(e).toString(`utf8`)}return await L(he(e),`utf8`)}async function Bu(e,t,n=zu){let r=t?Lu.find(e=>e===t)??(()=>{throw Error(`unknown --lang ${t}: must be one of ${Lu.join(`, `)}`)})():void 0;if(!e||e===`-`){if(!r)throw Error(`reading from stdin requires --lang. Example: tangle run <id> -l python -`);return{language:r,source:await n(`-`)}}let i=Ru(e);return{language:r??i??(()=>{throw Error(`cannot infer language from "${e}". Pass it explicitly: tangle run <id> -l <python|node|typescript|bash> ${e}`)})(),source:await n(e)}}function Vu(e){return M(Ve(),`tangle-run-images`,e)}function Hu(){return new N(`run`).description(`Run code in a persistent kernel inside a sandbox. Variables persist across calls in the same --session.`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`[file]`,`Path to source file. Language is inferred from extension. Use - for stdin (requires --lang).`).option(`-l, --lang <lang>`,`Force language: ${Lu.join(` | `)}. Required for stdin.`).option(`-s, --session <id>`,`Session id for kernel scoping`).option(`-t, --timeout <ms>`,`Per-call timeout in ms (0 disables)`,`60000`).option(`--save-images <dir>`,`Write image results into this directory (default: $TMPDIR/tangle-run-images/<sandbox>/).`).option(`--no-save-images`,`Don't write image results to disk; print summary only`).action(async(t,n,r)=>{let{language:i,source:a}=await Bu(n,r.lang),{context:o,client:s}=G(r),c=await q(s,o,t);c=await J(c);let l=f(`Running ${i} (${a.length}b)…`);r.json||l.start();let u=await c.runCode(i,a,{sessionId:r.session,timeoutMs:Number.parseInt(r.timeout,10)});if(l.stop(),r.json){e(u),u.exitCode!==0&&process.exit(u.exitCode);return}u.stdout&&process.stdout.write(u.stdout),u.stderr&&process.stderr.write(u.stderr);let d=0;for(let e of u.results)if(e.type===`image`)if(r.saveImages!==!1){let n=typeof r.saveImages==`string`?r.saveImages:Vu(t);Fe(n,{recursive:!0});let i=`${n}/${Date.now()}-${d}.${e.format}`;ze(i,Buffer.from(e.data,`base64`)),process.stderr.write(j.green(`✓ image → ${i}\n`)),d++}else process.stderr.write(j.gray(`[image: ${e.format}, ${e.data.length}b base64]\n`));else if(e.type===`dataframe`){let t=e.columns.map(e=>`${e.name}:${e.dtype}`).join(` | `);process.stderr.write(j.gray(`[dataframe ${e.rows.length}×${e.columns.length}${e.truncated?` (truncated)`:``}]\n`)),process.stderr.write(`${t}\n`);for(let t of e.rows.slice(0,20))process.stderr.write(`${t.map(e=>String(e)).join(` | `)}\n`);e.rows.length>20&&process.stderr.write(j.gray(`… ${e.rows.length-20} more rows\n`))}else e.type===`json`?(process.stderr.write(j.gray(`[json] `)),process.stderr.write(`${JSON.stringify(e.value,null,2)}\n`)):e.type===`html`?process.stderr.write(j.gray(`[html ${e.value.length}b]\n`)):e.type===`error`?(process.stderr.write(j.red(`✗ ${e.name}: ${e.message}\n`)),e.traceback&&process.stderr.write(`${e.traceback}\n`)):e.type===`text`&&process.stderr.write(`${e.value}\n`);u.error&&(process.stderr.write(j.red(`\n✗ ${u.error.name}: ${u.error.message}\n`)),u.error.traceback&&process.stderr.write(`${u.error.traceback}\n`)),u.exitCode!==0&&process.exit(u.exitCode)})}function Uu(t){t.command(`network <id-or-name>`).description(`Show runtime network state (exposed ports) for a sandbox. Outbound policy is the sandbox's egress policy.`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Updating network configuration...`);a.start();let o=await q(i,r,t);a.stop();let s=await o.network.getConfig();n.json?e(s):(l(`Network Configuration:`),s.ports&&s.ports.length>0?l(` Exposed Ports: ${s.ports.join(`, `)}`):l(` No exposed ports`))}),t.command(`expose <id-or-name>`).description(`Expose a port and get a public URL`).option(`-p, --port <port>`,`Port to expose`,`8000`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=Number.parseInt(n.port,10);if(Number.isNaN(o)||o<1||o>65535)throw Error(`Port must be a number between 1 and 65535`);let s=f(`Exposing port ${o}...`);s.start();let c=await(await q(a,i,t)).network.exposePort(o);s.stop(),n.json?e({port:o,url:c}):(r(`Port ${o} exposed.`),l(` URL: ${c}`))}),t.command(`urls <id-or-name>`).description(`List exposed port URLs for a sandbox`).action(async(t,n)=>{let{context:r,client:i}=G(n),a=f(`Fetching exposed URLs...`);a.start();let o=await(await q(i,r,t)).network.listUrls();if(a.stop(),n.json)e(o);else{let e=Object.entries(o);if(e.length===0)l(`No ports exposed.`);else{l(`Exposed Ports:`);for(let[t,n]of e)l(` ${t}: ${n}`)}}})}function Wu(){let e=new N(`sandbox`).description(`Manage sandboxes`);return Ko(e),Go(e),Fo(e),Uu(e),e}function Gu(){return new N(`search`).description(`Search for text patterns in sandbox files (ripgrep)`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pattern>`,`Search pattern (regex)`).option(`-g, --glob <pattern>`,`File glob filter (e.g. '**/*.ts')`).option(`-n, --max-results <count>`,`Max results to return`).option(`-i, --ignore-case`,`Case-insensitive search`).action(async(e,t,n)=>{let{context:r,client:i}=G(n),a=f(`Searching...`);n.json||a.start();let o=await q(i,r,e),s=0,c=n.maxResults?Number.parseInt(n.maxResults,10):void 0,l={};n.glob&&(l.glob=n.glob),n.ignoreCase&&(l.ignoreCase=!0),c&&(l.maxResults=c);for await(let e of o.search(t,l))if(s===0&&a.stop(),s++,n.json?console.log(JSON.stringify(e)):console.log(`${e.path}:${e.line}:${e.column??0}: ${e.text}`),c&&s>=c)break;a.stop(),s===0&&!n.json&&console.log(`No matches found`)})}function Ku(){let t=new N(`secret`).description(`Manage secrets`);return t.command(`create`).description(`Create a new secret`).argument(`<name>`,`Secret name (e.g., HF_TOKEN, AWS_ACCESS_KEY)`).argument(`[value]`,`Secret value`).option(`--value-stdin`,`Read secret value from stdin`).action(async(t,n,i)=>{let a=await G(i).client.secrets.create(t,await qu({value:n,valueStdin:i.valueStdin,prompt:`Enter value for secret '${t}': `}));i.json?e(a):(r(`Secret created: ${a.name}`),l(`Use --secret ${a.name} when creating a sandbox to select it for delivery.`))}),t.command(`list`).description(`List all secrets`).action(async t=>{let n=await G(t).client.secrets.list();t.json?e(n):n.length===0?(l(`No secrets found.`),l(`Use 'tangle secret create <name> [value]' to create one.`)):i([`Name`,`Created At`,`Updated At`],n.map(e=>[e.name,e.createdAt.toLocaleString(),e.updatedAt.toLocaleString()]))}),t.command(`delete`).description(`Delete a secret`).argument(`<name>`,`Secret name`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=G(n).client;if(!n.force&&!await cr(`Are you sure you want to delete secret '${t}'? This cannot be undone. (y/N) `,`--force`)){l(`Cancelled.`);return}await i.secrets.delete(t),n.json?e({success:!0,deleted:t}):r(`Secret deleted: ${t}`)}),t}async function qu(e){if(e.value!==void 0&&e.valueStdin)throw Error(`Provide either a secret value argument or --value-stdin, not both`);let t=e.value??(e.valueStdin?await ur():await sr(e.prompt));if(!t.length)throw Error(e.valueStdin?`Secret value from stdin cannot be empty`:`Secret value cannot be empty`);return t}function Ju(){let e=new N(`skill`).description(`Print paths to shipped skill documentation`);return e.command(`path`).description(`Print the absolute path to the SKILL.md shipped with this CLI`).action(()=>{let e=ce.dirname(yt(import.meta.url)),t=ce.resolve(e,`..`,`SKILL.md`);console.log(t)}),e}function Yu(){let n=new N(`snapshot`).description(`Manage snapshots`);return n.command(`create <sandbox-id-or-name>`).description(`Create a snapshot of a sandbox`).option(`--tags <tags...>`,`Tags for the snapshot`).option(`--no-wait`,`Return once the snapshot is accepted and print the operation to poll`).action(async(t,n)=>{let{context:i,client:a}=G(n),o=f(`Creating snapshot...`);o.start();let s=await q(a,i,t);if(n.wait===!1){let e=await s.snapshot({tags:n.tags,wait:!1});o.stop(),Io(e.info,!!n.json);return}let c=await s.snapshot({tags:n.tags});o.stop(),n.json?e(c):(r(`Snapshot created: ${c.snapshotId}`),console.log(`Size: ${Xu(c.sizeBytes??0)}`))}),n.command(`list <sandbox-id-or-name>`).description(`List snapshots for a sandbox`).action(async(n,r)=>{let{context:i,client:a}=G(r),o=f(`Fetching snapshots...`);o.start();let s=await(await q(a,i,n)).listSnapshots();o.stop(),r.json?e(s):t(s.map(e=>({...e,size:Xu(e.sizeBytes??0)})),[{key:`snapshotId`,header:`ID`,width:24},{key:`createdAt`,header:`Created`,width:16},{key:`size`,header:`Size`,width:12},{key:`sandboxId`,header:`Sandbox`,width:20}])}),n.command(`restore <sandbox-id> <snapshot-id>`).description(`Create a new sandbox from a snapshot`).option(`--billing-owner <userId>`,`Platform user that pays for the restored sandbox. The API accepts this only from a first-party service key that is listed as a billing delegate, and refuses such a key that names no payer.`).action(async(t,n,i)=>{let{client:a}=G(i),o=f(`Restoring from snapshot...`);o.start();let s=await a.create({fromSnapshot:n,fromSandboxId:t,...i.billingOwner?{billingOwnerId:i.billingOwner}:{}});await s.waitFor(`running`,{timeoutMs:12e4}),o.stop(),i.json?e({sandboxId:s.id,restoredFrom:n,status:s.status}):(r(`New sandbox created: ${s.id}`),console.log(`Source snapshot: ${n}`))}),n.command(`revert <sandbox-id-or-name> <snapshot-id>`).description(`Revert an existing sandbox to a snapshot`).action(async(t,n,i)=>{let{context:a,client:o}=G(i),s=f(`Reverting sandbox to snapshot...`);s.start();let c=await q(o,a,t),l=await c.revertToSnapshot(n);await c.refresh(),s.stop(),i.json?e({sandboxId:c.id,snapshotId:l.snapshotId,status:c.status}):(r(`Sandbox reverted: ${c.id}`),console.log(`Source snapshot: ${l.snapshotId}`))}),n.command(`delete <sandbox-id-or-name> <snapshot-id>`).description(`Delete a sandbox snapshot`).action(async(t,n,i)=>{let{context:a,client:o}=G(i),s=f(`Deleting snapshot...`);s.start();let c=await(await q(o,a,t)).deleteSnapshot(n);s.stop(),i.json?e({success:!0,sandboxId:t,snapshotId:n,outcome:c.outcome}):c.outcome===`already_absent`?r(`Snapshot already gone: ${n}`):r(`Snapshot deleted: ${n}`)}),n}function Xu(e){if(e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`,`TB`],r=Math.floor(Math.log(e)/Math.log(t));return`${Number.parseFloat((e/t**r).toFixed(1))} ${n[r]}`}const Zu=()=>import(`./device-i0PzYisd.mjs`);function Qu(){let e=new N(`solve`).description(`Participate in Tangle Solve competitions`);e.command(`clone <competition>`).description(`Clone the pinned competition repository`).argument(`[directory]`,`Destination directory`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async(e,t,n)=>(await import(`./clone-CWY8dI5d.mjs`)).cloneCompetition(e,t,n)),e.command(`run [competition]`).description(`Run the competition checker and record its evidence`).option(`--directory <path>`,`Competition directory (defaults to the current directory)`).action(async(e,t)=>(await import(`./run-BSXC2ytE.mjs`)).runCompetition(e,t)),e.command(`submit [competition]`).description(`Submit checker evidence through the device account and Tempo`).option(`--directory <path>`,`Competition directory (defaults to the current directory)`).option(`--pr-url <url>`,`GitHub pull request containing the submission`).option(`--model <name>`,`Model used to produce the submission`).option(`--note <text>`,`Short note shown with the accepted submission`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async(e,t)=>(await import(`./submit-D2jvFJtX.mjs`)).submitCompetition(e,t)),e.command(`account`).description(`Show the local Solve signing account`).option(`--create`,`Create the account if it does not exist`).action(async e=>(await import(`./account-BaGFNxyq.mjs`)).showSolveAccount(e));let t=e.command(`device`).description(`List and revoke the Solve devices bound to your account`);return t.command(`list`).description(`List your devices and whether each may submit jobs on Tempo`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async e=>(await Zu()).listSolveDevices(e)),t.command(`revoke <address>`).description(`Permanently revoke a device; the local device is revoked with its own key`).option(`--reason <text>`,`Why the device is revoked (shown to the account)`).option(`--yes`,`Confirm the permanent revocation without a prompt`).option(`--api-url <url>`,`Solve API base URL`).option(`--profile <name>`,`Tangle profile`,`solve`).action(async(e,t)=>(await Zu()).revokeSolveDevice(e,t)),e}function $u(e,t){return`tangle ssh-proxy ${e.replace(/\/+$/,``)}/v1/sandboxes/${t}/runtime/ssh`}function ed(e){return/^[A-Za-z0-9_/:=@%+.,-]+$/.test(e)?e:`'${e.replace(/'/g,`'"'"'`)}'`}function td(e){return`'${e.replace(/'/g,`''`)}'`}function nd(e){return e===`win32`?`NUL`:`/dev/null`}function rd(e,t){return t===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN=${td(`<token>`)}; ssh ${e.map(td).join(` `)}`:`TANGLE_SSH_PROXY_AUTH_TOKEN=${ed(`<token>`)} ssh ${e.map(ed).join(` `)}`}function id(e){return e.connection!==void 0&&!e.connection.ssh}function ad(){d(`SSH is not enabled for this sandbox.`),l(`Create a sandbox with --ssh to enable SSH access.`),process.exit(1)}function od(e,t=[],n=process.platform){let r=nd(n);return[`-o`,`ProxyCommand=${e.proxyCommand}`,`-o`,`StrictHostKeyChecking=no`,`-o`,`UserKnownHostsFile=${r}`,`-o`,`GlobalKnownHostsFile=${r}`,`-o`,`LogLevel=ERROR`,`-o`,`ServerAliveInterval=15`,`-o`,`ServerAliveCountMax=4`,`-o`,`TCPKeepAlive=yes`,`${e.username}@localhost`,`-p`,String(e.port),...t]}function sd(){return new N(`ssh`).description(`Open SSH session to a sandbox`).argument(`<ref>`,`Sandbox ID or name`).argument(`[sshArgs...]`,`Extra args passed through to ssh`).option(`-i, --identity-file <path>`,`Private key file to pass to ssh`).option(`--print`,`Print SSH command instead of connecting`).allowUnknownOption(!0).action(async(e,t,n)=>{let{context:r,client:i}=G(n),a=f(`Getting SSH credentials...`);a.start();let o=await q(i,r,e);if(id(o)){a.stop(),ad();return}o=await J(o);let s=await o.ssh();if(a.stop(),!s){ad();return}let c={...s,proxyCommand:$u(r.baseUrl,o.id)};if(!r.apiKey)throw Error(`SSH proxy requires API key auth. Set TANGLE_API_KEY or pass --api-key.`);let u=od(c,[...n.identityFile?[`-i`,n.identityFile,`-o`,`IdentitiesOnly=yes`]:[],...t]);if(n.print){console.log(rd(u,process.platform));return}l(`Connecting via tunnel...`);let p=We(`ssh`,u,{stdio:`inherit`,env:{...process.env,TANGLE_SSH_PROXY_AUTH_TOKEN:r.apiKey}});p.on(`error`,e=>{e.code===`ENOENT`&&(d(`SSH client not found. Please install OpenSSH.`),process.exit(1)),H(e)}),p.on(`exit`,e=>{process.exit(e??0)})})}function cd(){let t=new N(`ssh-keys`).description(`Manage SSH keys`);return t.command(`list`).description(`List SSH keys`).action(async t=>{let n=f(`Fetching SSH keys...`);try{n.start();let r=await W(U(t)).sshKeys.list();n.stop(),t.json?e({sshKeys:r}):r.length===0?l(`No SSH keys found.`):i([`Name`,`Type`,`Fingerprint`,`Created`],r.map(e=>[e.name,e.keyType,e.fingerprint,e.createdAt.toLocaleString()]))}catch(e){n.stop(),H(e)}}),t.command(`add`).description(`Add SSH key`).argument(`<name>`,`SSH key name`).requiredOption(`--key-file <path>`,`Public key file path`).action(async(t,n)=>{let i=f(`Adding SSH key...`);try{let a=Ie(n.keyFile,`utf8`).trim();i.start();let o=await W(U(n)).sshKeys.create(t,a);i.stop(),n.json?e({sshKey:o}):r(`Added SSH key ${o.name} (${o.fingerprint})`)}catch(e){i.stop(),H(e)}}),t.command(`delete`).description(`Delete SSH key`).argument(`<name>`,`SSH key name or ID`).action(async(e,t)=>{let n=f(`Deleting SSH key...`);try{n.start(),await W(U(t)).sshKeys.delete(e),n.stop(),r(`Deleted SSH key ${e}`)}catch(e){n.stop(),H(e)}}),t}function ld(e,t=1){process.stderr.write(`${e}\n`),process.exit(t)}function ud(){return new N(`ssh-proxy`).description(`SSH proxy helper that pipes stdin/stdout to WebSocket`).argument(`<runtime-url>`,`Runtime WebSocket URL`).action(async e=>{let t=process.env.TANGLE_SSH_PROXY_AUTH_TOKEN;t||ld(`TANGLE_SSH_PROXY_AUTH_TOKEN not set`);let n=new URL(e.replace(/^http/,`ws`)),{default:r}=await import(`ws`),i=new r(n,{headers:{Authorization:`Bearer ${t}`},perMessageDeflate:!1}),a;function o(){a&&=(clearInterval(a),void 0)}i.on(`open`,()=>{a=setInterval(()=>{i.readyState===r.OPEN&&i.ping()},15e3),a.unref?.(),process.stdin.on(`data`,e=>{i.readyState===r.OPEN&&i.send(e,{binary:!0,compress:!1})}),process.stdin.on(`end`,()=>i.close(1e3))}),i.on(`message`,e=>{let t=Buffer.isBuffer(e)?e:Array.isArray(e)?Buffer.concat(e):Buffer.from(e);process.stdout.write(t)}),i.on(`error`,e=>{o(),ld(`WebSocket error: ${e.message}`)}),i.on(`close`,e=>{o(),process.exit(e===1e3?0:1)}),process.stdin.on(`error`,()=>i.close())})}function dd(){let n=new N(`team`).description(`Manage teams`);return $(n,`list`).description(`List teams for the current account`).action(async n=>{let r=U(n),i=W(r),a=n.json?null:f(`Fetching teams...`);a?.start();let o=await i.teams.list();if(a?.stop(),n.json){e({teams:o,activeTeamId:r.activeTeamId??null});return}t(o.map(e=>({active:e.id===r.activeTeamId,id:e.id,name:e.name,role:e.currentUserRole,members:e.memberCount})),[{key:`active`,header:`Active`,width:8},{key:`id`,header:`ID`,width:38},{key:`name`,header:`Name`,width:24},{key:`role`,header:`Role`,width:10},{key:`members`,header:`Members`,width:10}])}),$(n,`create <name>`).description(`Create a team`).option(`--org-id <id>`,`External organization id`).option(`--no-switch`,`Do not set the new team as active`).action(async(t,n)=>{let i=U(n),a=W(i),o=n.json?null:f(`Creating team...`);o?.start();let s=await a.teams.create({name:t,orgId:n.orgId});if(n.switch&&Bo(s,i.profile),o?.stop(),n.json){e({team:s,active:!!n.switch});return}r(`Team created: ${Lo(s)}`),n.switch&&r(`Active team set to ${s.name}`)}),$(n,`switch <team>`).description(`Set the active team for the current profile`).action(async(t,n)=>{let i=U(n),a=await Ro(W(i),t);if(Bo(a,i.profile),n.json){e({team:a,activeTeamId:a.id});return}r(`Active team set to ${Lo(a)}`)}),n.command(`current`).description(`Show the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(t=>{let n=wn(t.profile);if(t.json){e(n.activeTeamId?n:{activeTeamId:null});return}if(!n.activeTeamId){console.log(`No active team.`);return}s({ID:n.activeTeamId,Name:n.activeTeamName})}),n.command(`clear`).description(`Clear the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(t=>{if(Vo(t.profile),t.json){e({activeTeamId:null});return}r(`Active team cleared.`)}),$(n,`members [team]`).description(`List team members`).action(async(n,r)=>{let i=U(r),a=W(i),o=await zo(a,n,i.profile),s=await a.teams.listMembers(o.id);if(r.json){e({team:o,members:s});return}t(s,[{key:`id`,header:`ID`,width:36},{key:`customerEmail`,header:`Email`,width:28},{key:`role`,header:`Role`,width:10},{key:`status`,header:`Status`,width:10},{key:`joinedAt`,header:`Joined`,width:16}])}),$(n,`update-member <member-id>`).description(`Update a team member role`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).requiredOption(`--role <role>`,`Role: admin, member, viewer`).action(async(t,n)=>{let i=U(n),a=W(i),o=await zo(a,n.team,i.profile),c=fd(n.role),l=await a.teams.updateMember(o.id,t,{role:c});if(n.json){e({team:o,member:l});return}r(`Member updated: ${l.customerEmail}`),s({Team:o.name,Role:l.role,Status:l.status})}),$(n,`invite <email>`).description(`Invite a user to a team`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--role <role>`,`Role: admin, member, viewer`,`member`).option(`--ttl-hours <hours>`,`Invitation lifetime in hours`).action(async(t,n)=>{let i=U(n),a=W(i),o=await zo(a,n.team,i.profile),c=fd(n.role),l=await a.teams.invite(o.id,{email:t,role:c,ttlHours:n.ttlHours?Number.parseInt(n.ttlHours,10):void 0});if(n.json){e({team:o,invitation:l});return}r(`Invitation created for ${l.email}`),s({Team:o.name,Role:l.role,Expires:l.expiresAt,"Invitation ID":l.id}),r(`Re-run with --json to retrieve the invitation token for sharing.`)}),$(n,`leave [team]`).description(`Leave a team as the current user`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=U(n),a=W(i),o=await zo(a,t,i.profile);if(!(!n.force&&!n.json&&!await cr(`Leave team '${o.name}'? (y/N) `,`--force`))){if(await a.teams.leave(o.id),i.activeTeamId===o.id&&Vo(i.profile),n.json){e({success:!0,teamId:o.id});return}r(`Left team: ${o.name}`)}}),$(n,`transfer <new-owner-customer-id> [team]`).description(`Transfer team ownership to another active member`).option(`--force`,`Skip confirmation prompt`).action(async(t,n,i)=>{let a=U(i),o=W(a),s=await zo(o,n,a.profile);if(!(!i.force&&!i.json&&!await cr(`Transfer ownership of '${s.name}' to ${t}? This cannot be undone without the new owner's cooperation. (y/N) `,`--force`))){if(await o.teams.transferOwnership(s.id,t),i.json){e({success:!0,teamId:s.id,newOwnerCustomerId:t});return}r(`Ownership transferred for ${s.name}`)}}),n.addCommand(pd()),n.addCommand(md()),$(n,`invitations [team]`).description(`List pending and historical team invitations`).action(async(n,r)=>{let i=U(r),a=W(i),o=await zo(a,n,i.profile),s=await a.teams.listInvitations(o.id);if(r.json){e({team:o,invitations:s});return}t(s,[{key:`id`,header:`ID`,width:38},{key:`email`,header:`Email`,width:28},{key:`role`,header:`Role`,width:10},{key:`status`,header:`Status`,width:12},{key:`expiresAt`,header:`Expires`,width:16}])}),$(n,`accept <token>`).description(`Accept a team invitation`).option(`--no-switch`,`Do not set the accepted team as active`).action(async(t,n)=>{let i=U(n),a=W(i),o=await a.teams.acceptInvitation(t),s=n.switch===!1?null:await a.teams.get(o.teamId);if(s&&Bo(s,i.profile),n.json){e({member:o,activeTeamId:s?.id??null});return}r(`Invitation accepted for team ${o.teamId}`),s&&r(`Active team set to ${s.name}`)}),$(n,`revoke-invitation <invitation-id>`).description(`Revoke a pending team invitation`).action(async(t,n)=>{if(await W(U(n)).teams.revokeInvitation(t),n.json){e({success:!0,invitationId:t});return}r(`Invitation revoked: ${t}`)}),$(n,`remove-member <member-id>`).description(`Remove a member from a team`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).action(async(t,n)=>{let i=U(n),a=W(i),o=await zo(a,n.team,i.profile);if(await a.teams.removeMember(o.id,t),n.json){e({success:!0,teamId:o.id,memberId:t});return}r(`Member removed: ${t}`)}),n}function fd(e){if(e===`admin`||e===`member`||e===`viewer`)return e;throw Error(`Role must be one of: admin, member, viewer`)}function pd(){let n=new N(`secret`).description(`Manage team secrets`);return $(n,`list [team]`).description(`List team secret names`).action(async(n,r)=>{let i=U(r),a=W(i),o=await zo(a,n,i.profile),s=await a.teams.listSecrets(o.id);if(r.json){e({team:o,secrets:s});return}t(s,[{key:`name`,header:`Name`,width:28},{key:`updatedAt`,header:`Updated`,width:24},{key:`updatedBy`,header:`Updated By`,width:28}])}),$(n,`set <name> [value]`).description(`Create or replace a team secret`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--value-stdin`,`Read secret value from stdin`).action(async(t,n,i)=>{let a=U(i),o=W(a),s=await zo(o,i.team,a.profile),c=await qu({value:n,valueStdin:i.valueStdin,prompt:`Enter value for team secret '${t}': `}),l=await o.teams.upsertSecret(s.id,t,c);if(i.json){e({team:s,secret:l});return}r(`Team secret saved: ${l.name}`)}),$(n,`delete <name>`).description(`Delete a team secret`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=U(n),a=W(i),o=await zo(a,n.team,i.profile);if(!(!n.force&&!n.json&&!await cr(`Delete team secret '${t}' from '${o.name}'? (y/N) `,`--force`))){if(await a.teams.deleteSecret(o.id,t),n.json){e({success:!0,teamId:o.id,name:t});return}r(`Team secret deleted: ${t}`)}}),$(n,`reveal <name>`).description(`Reveal a team secret value`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).action(async(t,n)=>{let r=U(n),i=W(r),a=await zo(i,n.team,r.profile),o=await i.teams.revealSecret(a.id,t);if(n.json){e({teamId:a.id,...o});return}console.log(o.value)}),n}function md(){let n=new N(`templates`).description(`Manage team golden-path templates`);return $(n,`list [team]`).description(`List a team's golden-path templates`).action(async(n,r)=>{let i=U(r),a=W(i),o=await zo(a,n,i.profile),s=await a.teams.listTemplates(o.id);if(r.json){e({team:o,templates:s});return}if(s.length===0){console.log(`No templates yet for ${o.name}.`);return}t(s.map(e=>({id:e.id,name:e.name,environment:e.environment,snapshot:`${e.snapshotId.slice(0,12)}…`,updated:e.updatedAt})),[{key:`id`,header:`ID`,width:38},{key:`name`,header:`Name`,width:28},{key:`environment`,header:`Env`,width:14},{key:`snapshot`,header:`Snapshot`,width:16},{key:`updated`,header:`Updated`,width:24}])}),$(n,`create <name> <snapshot-id>`).description(`Create a golden-path template from a snapshot`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`-d, --description <description>`,`Human-readable description shown in the dashboard`).option(`-e, --environment <environment>`,`Default environment to apply (defaults to 'universal')`).option(`--config <json>`,`Optional JSON config object merged into sandboxes created from this template`).action(async(t,n,i)=>{let a=U(i),o=W(a),s=await zo(o,i.team,a.profile),c;if(i.config)try{let e=JSON.parse(i.config);if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`--config must be a JSON object`);c=e}catch(e){throw Error(`--config is not valid JSON: ${e instanceof Error?e.message:String(e)}`)}let l=await o.teams.createTemplate(s.id,{name:t,snapshotId:n,description:i.description,environment:i.environment,config:c});if(i.json){e({team:s,template:l});return}r(`Team template created: ${l.name} (${l.id})`)}),$(n,`delete <template-id>`).description(`Delete a team golden-path template`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{let i=U(n),a=W(i),o=await zo(a,n.team,i.profile);if(!(!n.force&&!n.json&&!await cr(`Delete template '${t}' from '${o.name}'? (y/N) `,`--force`))){if(await a.teams.deleteTemplate(o.id,t),n.json){e({success:!0,teamId:o.id,templateId:t});return}r(`Team template deleted: ${t}`)}}),n}function $(e,t){return e.command(t).option(`--profile <profile>`,`Credential profile`)}async function hd(t,n,i){let a=new AbortController,o=()=>a.abort();try{let i=W(U({...t,timeout:void 0}));process.once(`SIGINT`,o),process.once(`SIGTERM`,o);let s=await n(i,{...t.timeout===void 0?{}:{timeoutMs:Number(t.timeout)*1e3},resumeJobId:t.resumeJob,signal:a.signal,onProgress:e=>{process.stderr.write(`Publication ${e.id}: ${e.status}\n`)}}).finally(()=>{process.off(`SIGINT`,o),process.off(`SIGTERM`,o)});t.json?e(s):r(`template`in s?`Published template: ${s.template.slug}`:`Published template version: ${s.version.id}`)}catch(e){if(e instanceof w&&e.status!==401&&e.job&&[`pending`,`scanning`,`ready`].includes(e.job.status)){let t=[`tangle`,`template`,...i,`--resume-job`,e.job.id].map(ut).join(` `);Object.assign(e,{fix:{command:t}})}H(e,t.json)}}function gd(){let n=new N(`template`).description(`Manage published public templates`);return n.command(`list`).option(`-q, --query <query>`,`Search query`).option(`--tag <tag>`,`Filter by tag`).option(`--featured`,`Show featured templates only`).action(async n=>{let r=W(U(n)),i=n.featured?await r.publicTemplates.featured():await r.publicTemplates.list({query:n.query,tag:n.tag});if(n.json){e({templates:i});return}t(i,[{key:`slug`,header:`Slug`,width:28},{key:`name`,header:`Name`,width:28},{key:`forkCount`,header:`Forks`,width:8},{key:`sandboxCount`,header:`Sandboxes`,width:12},{key:`updatedAt`,header:`Updated`,width:24}])}),n.command(`get <id-or-slug>`).action(async(t,n)=>{let r=await W(U(n)).publicTemplates.get(t);if(n.json){e({template:r});return}e(r)}),n.command(`versions <id-or-slug>`).action(async(n,r)=>{let i=await W(U(r)).publicTemplates.versions(n);if(r.json){e({versions:i});return}t(i.map(e=>({...e})),[{key:`id`,header:`Version ID`,width:38},{key:`versionNumber`,header:`Version`,width:8},{key:`createdAt`,header:`Created`,width:24}])}),n.command(`publish <name> <snapshot-id> <sandbox-id>`).option(`--timeout <seconds>`,`Maximum wait for publication`).option(`--resume-job <id>`,`Resume an accepted publication for this snapshot`).option(`--slug <slug>`,`Stable public slug`).option(`-d, --description <description>`,`Template description`).option(`--readme <markdown>`,`README markdown`).option(`--tags <tags...>`,`Template tags`).option(`--release-notes <text>`,`Release notes`).option(`--team-id <id>`,`Publish under a team`).option(`--forked-from <id>`,`Fork source template id`).action((e,t,n,r)=>hd(r,async(i,a)=>({template:await i.publicTemplates.publish({name:e,slug:r.slug,description:r.description,snapshotId:t,sourceSandboxId:n,readmeMarkdown:r.readme,tags:r.tags,releaseNotes:r.releaseNotes,teamId:r.teamId,forkedFromTemplateId:r.forkedFrom},a)}),[`publish`,e,t,n])),n.command(`publish-version <id-or-slug> <snapshot-id> <sandbox-id>`).option(`--timeout <seconds>`,`Maximum wait for publication`).option(`--resume-job <id>`,`Resume an accepted publication for this snapshot`).option(`--readme <markdown>`,`README markdown`).option(`--tags <tags...>`,`Template tags`).option(`--release-notes <text>`,`Release notes`).action((e,t,n,r)=>hd(r,async(i,a)=>({version:await i.publicTemplates.publishVersion(e,{snapshotId:t,sourceSandboxId:n,readmeMarkdown:r.readme,tags:r.tags,releaseNotes:r.releaseNotes},a)}),[`publish-version`,e,t,n])),n}function _d(){let t=new N(`traces`).description(`Read hosted agent traces, spans, and eval-runs from Tangle Intelligence`);return t.command(`list`).description(`List trace summaries (one row per trace), newest first`).option(`--from <iso>`,`ISO-8601 lower bound on received time (inclusive)`).option(`--to <iso>`,`ISO-8601 upper bound on received time (inclusive)`).option(`--model <model>`,`Exact model match (any span carried this model)`).option(`--run <runId>`,`Exact run id match`).option(`--status <status>`,`ERROR | OK`).option(`-q, --query <text>`,`Substring over span name`).option(`--cursor <cursor>`,`Opaque pagination cursor from a prior page`).option(`--limit <count>`,`Page size (clamped server-side to [1, 200])`).action(async t=>{try{let n={from:t.from,to:t.to,model:t.model,runId:t.run,status:t.status===void 0?void 0:Od(t.status),q:t.query,cursor:t.cursor,limit:t.limit===void 0?void 0:Nd(t.limit)},r=yd(t),i=t.json?null:f(`Fetching traces...`);i?.start();let a=await r.listTraces(n);if(i?.stop(),t.json)return e(a);Sd(a.items),Ed(a.nextCursor)}catch(e){xd(e,t)}}),t.command(`get <traceId>`).description(`Show one trace's spans. Streams NDJSON to stdout with --ndjson.`).option(`--ndjson`,`Stream the full span set as NDJSON to stdout`).option(`--cursor <cursor>`,`Opaque pagination cursor from a prior page`).option(`--limit <count>`,`Spans per page`).action(async(t,n)=>{try{let r=yd(n);if(n.ndjson){await bd(r,t);return}let i=n.json?null:f(`Fetching trace spans...`);i?.start();let a=await r.getTraceSpans(t,{cursor:n.cursor,limit:n.limit===void 0?void 0:Nd(n.limit)});if(i?.stop(),n.json)return e(a);Cd(a.items),a.truncated&&s({Spans:`${a.items.length} of ${a.total} (truncated)`}),Ed(a.nextCursor)}catch(e){xd(e,n)}}),t.addCommand(vd()),t}function vd(){let t=new N(`runs`).description(`Read eval-runs pivoted off the trace surface`);return t.command(`list`).description(`List eval-runs, newest first`).option(`--status <status>`,`Run status filter`).option(`--gate <decision>`,`Promotion-gate decision filter`).option(`--label <key:value>`,`Match over the run's labels`).option(`--from <iso>`,`ISO-8601 lower bound on received time`).option(`--to <iso>`,`ISO-8601 upper bound on received time`).option(`-q, --query <text>`,`Substring over run dir`).option(`--cursor <cursor>`,`Opaque pagination cursor from a prior page`).option(`--limit <count>`,`Page size`).action(async t=>{try{let n={status:t.status===void 0?void 0:Ad(t.status),gate:t.gate===void 0?void 0:Md(t.gate),label:t.label,from:t.from,to:t.to,q:t.query,cursor:t.cursor,limit:t.limit===void 0?void 0:Nd(t.limit)},r=yd(t),i=t.json?null:f(`Fetching runs...`);i?.start();let a=await r.listRuns(n);if(i?.stop(),t.json)return e(a);wd(a.items),Ed(a.nextCursor)}catch(e){xd(e,t)}}),t.command(`get <runId>`).description(`Show a single eval-run`).action(async(t,n)=>{try{let r=yd(n),i=n.json?null:f(`Fetching run...`);i?.start();let a=await r.getRun(t);if(i?.stop(),n.json)return e(a);Td(a)}catch(e){xd(e,n)}}),t}function yd(e){let t=mn(e.apiKey);if(!t)throw Error(`No API key found. Set TANGLE_API_KEY or run: tangle auth login`);return wt({apiKey:t,baseUrl:e.baseUrl??process.env.TANGLE_INTELLIGENCE_BASE_URL})}async function bd(e,t){let n=(await e.exportTraceSpansNdjson(t)).getReader();try{for(;;){let{value:e,done:t}=await n.read();if(t)break;e&&process.stdout.write(Buffer.from(e))}}finally{n.releaseLock()}}function xd(e,t){return H(e,t.json===!0)}function Sd(e){t(e.map(e=>({traceId:e.traceId,root:e.rootName??`-`,model:e.model??`-`,spans:e.spanCount,errors:e.errorCount,durationMs:e.durationMs,cost:Dd(e.costUsd)})),[{key:`traceId`,header:`Trace`,width:36},{key:`root`,header:`Root`,width:24},{key:`model`,header:`Model`,width:22},{key:`spans`,header:`Spans`,width:8},{key:`errors`,header:`Errors`,width:8},{key:`durationMs`,header:`Duration(ms)`,width:14},{key:`cost`,header:`Cost`,width:10}])}function Cd(e){t(e.map(e=>({spanId:e.id,name:e.name,model:e.model??`-`,status:e.statusCode??`-`,cost:e.costUsd===null?`-`:`$${e.costUsd}`})),[{key:`spanId`,header:`Span`,width:40},{key:`name`,header:`Name`,width:28},{key:`model`,header:`Model`,width:22},{key:`status`,header:`Status`,width:10},{key:`cost`,header:`Cost`,width:12}])}function wd(e){t(e.map(e=>({runId:e.id,status:e.status,gate:e.gateDecision??`-`,cost:e.totalCostUsd===null?`-`:`$${e.totalCostUsd}`,receivedAt:e.receivedAt})),[{key:`runId`,header:`Run`,width:24},{key:`status`,header:`Status`,width:22},{key:`gate`,header:`Gate`,width:18},{key:`cost`,header:`Cost`,width:12},{key:`receivedAt`,header:`Received`,width:18}])}function Td(e){s({Run:e.id,Status:e.status,Gate:e.gateDecision??void 0,"Run Dir":e.runDir??void 0,Cost:e.totalCostUsd===null?void 0:`$${e.totalCostUsd}`,Duration:e.totalDurationMs===null?void 0:`${e.totalDurationMs}ms`,"Holdout Lift":e.holdoutLift??void 0,Received:e.receivedAt})}function Ed(e){e&&s({"Next page":`--cursor ${e}`})}function Dd(e){return e===null?`-`:`$${e.toFixed(4)}`}function Od(e){if(e===`ERROR`||e===`OK`)return e;throw Error(`--status must be ERROR or OK`)}const kd=[`started`,`baseline-complete`,`generation-complete`,`gate-decided`,`finished`,`errored`];function Ad(e){let t=kd.find(t=>t===e);if(t)return t;throw Error(`--status must be one of ${kd.join(`, `)}`)}const jd=[`ship`,`hold`,`need_more_work`,`model_ceiling`,`arch_ceiling`];function Md(e){let t=jd.find(t=>t===e);if(t)return t;throw Error(`--gate must be one of ${jd.join(`, `)}`)}function Nd(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}const Pd=`@tangle-network/sandbox-cli`,Fd=`curl -fsSL https://sandbox.tangle.tools/install.sh | sh`,Id=/^\d+\.\d+\.\d+$/;function Ld(e){let t=M(process.env.TANGLE_CLI_HOME||M(F(),`.local/share/tangle-cli`),`node_modules`,Pd);if(Pe(t)&&Le(t)===e)return`tangle update`;if(e.endsWith(M(`lib`,`node_modules`,Pd)))return`npm install -g ${Pd}@latest`;if(e.includes(M(`pnpm`,`global`,``)))return`pnpm add -g ${Pd}@latest`;if(e.includes(`${ge}node_modules${ge}`))return``}const Rd=()=>`${process.env.TANGLE_NPM_REGISTRY??`https://registry.npmjs.org`}/${Pd.replace(`/`,`%2F`)}/latest`,zd=`const fs = require("node:fs");
174
+ const [file, url] = process.argv.slice(1);
175
+ const record = (latest) => {
176
+ const state = JSON.parse(fs.readFileSync(file, "utf8"));
177
+ fs.writeFileSync(file, JSON.stringify({ ...state, latest }));
178
+ };
179
+ fetch(url, { signal: AbortSignal.timeout(30000) })
180
+ .then((r) => r.json()).then((b) => b.version, () => null)
181
+ .then((v) => record(${Id}.test(v) ? v : null), () => {});`,Bd=(e,t)=>e.localeCompare(t,`en`,{numeric:!0})>0;function Vd(e,t){let n=Ld(e);if(n===void 0||!process.stderr.isTTY||process.env.CI)return;let r=M(Ht,`update-check.json`),i=Math.floor(Date.now()/864e5);try{let e=Pe(r)?JSON.parse(Ie(r,`utf8`)):{},a=e.checked!==i,o=Id.test(e.latest)&&Bd(e.latest,t);if(!a&&(!o||e.shown===i))return;Fe(Ht,{mode:448,recursive:!0});let s={...e,checked:i,shown:o?i:e.shown};ze(r,JSON.stringify(s)),a&&We(process.execPath,[`-e`,zd,r,Rd()],{detached:!0,stdio:`ignore`}).unref(),o&&e.shown!==i&&console.error(`tangle ${t} is installed; ${e.latest} is latest.${n&&` Run: ${n}`}`)}catch{}}function Hd(e,t){return new N(`update`).description(`Install the latest published CLI`).action(async()=>{let n=Ld(e);if(n!==`tangle update`)throw new B(`UPDATE_ELSEWHERE`,`install.sh did not install this tangle`,n===void 0?`it runs from source`:`another tool owns it`,n||Fd);let r=(await fetch(Rd(),{signal:AbortSignal.timeout(1e4)}).then(e=>e.json()).catch(()=>({}))).version??``;if(!Id.test(r))throw new B(`NETWORK_UNAVAILABLE`,`the npm registry gave no version`,`no published version was read`,`tangle update`);if(!Bd(r,t))return console.log(`tangle ${t} is already current`);try{Ue(`bash`,[`-c`,`set -o pipefail; ${Fd}`],{stdio:[`ignore`,`ignore`,`inherit`]})}catch{throw new B(`UPDATE_INSTALL_FAILED`,`install.sh failed`,`its error is above`,Fd)}let i=JSON.parse(Ie(M(e,`package.json`),`utf8`));console.log(`tangle ${t} -> ${i.version}`)})}function Ud(){return new N(`usage`).description(`Show account usage and billing information`).action(async t=>{let{client:n}=G(t),r=t.json?null:f(`Fetching usage...`);r?.start();let[i,a]=await Promise.all([n.usage(),n.subscription().catch(()=>null)]);r?.stop(),t.json?e({...i,subscription:a}):(console.log(),console.log(`Account Usage`),console.log(`─`.repeat(40)),s({"Active Sandboxes":i.activeSandboxes,"Total Sandboxes":i.totalSandboxes,"Compute Minutes":Wd(i.computeMinutes),"GPU Seconds":i.gpuSeconds,"GPU Spend":Gd(i.gpuCostUsd)}),a&&(console.log(),console.log(`Subscription`),console.log(`─`.repeat(40)),s({Plan:a.plan,Status:a.status,"Credits Available":Gd(a.creditsAvailableUsd),"Credits Used":Gd(a.creditsUsedUsd),"Monthly Balance":Gd(a.monthlyBalanceUsd)})),console.log(),console.log(`Billing Period`),console.log(`─`.repeat(40)),s({Start:i.periodStart.toLocaleDateString(),End:i.periodEnd.toLocaleDateString()}),console.log())})}function Wd(e){if(e===void 0)return`-`;if(e<60)return`${e} min`;let t=Math.floor(e/60),n=e%60;return n===0?`${t} hr`:`${t} hr ${n} min`}function Gd(e){return e<0?`-$${(-e).toFixed(2)}`:`$${e.toFixed(2)}`}function Kd(){return new N(`use`).description(`Set or show the active sandbox (used when a command omits the id)`).argument(`[id]`,`Sandbox id to make active`).option(`--clear`,`Clear the active sandbox`).action((e,t)=>{if(t.clear){on(),l(`Cleared the active sandbox.`);return}if(e){an(e),l(`Active sandbox set to ${e}. Commands now default to it; override with --box or TANGLE_SANDBOX.`);return}let n=rn();l(n?`Active sandbox: ${n}`:"No active sandbox. Set one with `tangle use <id>`.")})}function qd(e){t(e,[{key:`id`,header:`ID`},{key:`nodeId`,header:`Node`},{key:`name`,header:`Name`},{key:`contentType`,header:`Content Type`},{key:`byteSize`,header:`Bytes`},{key:`createdAt`,header:`Created`}])}function Jd(t){t.command(`artifacts`).description(`List a run's artifact metadata (never the bytes)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.listArtifacts(t,n);if(r.json)return e(i);qd(i.artifacts)}),t.command(`artifact-download`).description(`Download one run artifact's bytes to a file`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).argument(`<artifactId>`,`Artifact ID`).option(`--out <file>`,`Destination file (defaults to the artifact ID)`).action(async(t,n,r,i)=>{let a=await(await X(i)).workflows.downloadArtifact(t,n,r),o=i.out??r;try{ze(o,a.bytes)}catch(e){throw Error(`Could not write artifact to "${o}": ${e instanceof Error?e.message:String(e)}`)}if(i.json)return e({file:o,contentType:a.contentType,bytes:a.bytes.length});l(`Wrote ${o} (${a.bytes.length} bytes, ${a.contentType}).`)})}function Yd(e){t(e.map(e=>({id:e.id,run:e.runId,title:e.title,options:e.options.join(`, `),requested:e.requestedAt,expires:e.expiresAt??``})),[{key:`id`,header:`ID`},{key:`run`,header:`Run`},{key:`title`,header:`Title`},{key:`options`,header:`Options`},{key:`requested`,header:`Requested`},{key:`expires`,header:`Expires`}])}function Xd(t){t.command(`decisions`).description(`List a workflow's pending human decisions`).argument(`<id>`,`Workflow ID`).action(async(t,n)=>{let r=(await(await X(n)).workflows.listPendingDecisions()).decisions.filter(e=>e.workflowId===t);if(n.json)return e({decisions:r});Yd(r)}),t.command(`decision-resolve`).description(`Answer the decision a run is parked on and resume it`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).requiredOption(`--choice <choice>`,`The option to resolve with (one of the decision's options)`).action(async(t,n,r)=>{let i=await X(r),a=await i.workflows.getRunDecision(t,n),o=await i.workflows.resolveRunDecision(t,n,{decisionId:a.id,choice:r.choice});if(r.json)return e(o);if(o.resumed){l(`Resolved decision ${o.decisionId} with "${o.choice}" — run ${o.runId} resumed.`);return}l(`Resolved decision ${o.decisionId} with "${o.choice}", but run ${o.runId} had already finished — nothing to resume.`)})}function Zd(e){try{return Ie(e,`utf8`)}catch(t){throw Error(`Could not read workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function Qd(e){t(e.map(e=>({id:e.id,name:e.name,enabled:e.enabled?`yes`:`no`,issues:e.validationErrors.length,updated:e.updatedAt})),[{key:`id`,header:`ID`},{key:`name`,header:`Name`},{key:`enabled`,header:`Enabled`},{key:`issues`,header:`Issues`},{key:`updated`,header:`Updated`}])}function $d(e){let n=e.workflows.filter(e=>e.failed>0).length,r=e.workflows.filter(e=>e.failed===0&&e.waiting>0).length,i=e.workflows.filter(e=>e.failed===0&&e.waiting===0&&e.runsInWindow>0).length;l(`${n} failing · ${r} waiting · ${i} healthy · ${e.workflows.length} total over ${e.window}`),t(e.workflows.map(e=>({id:e.id,name:e.name,enabled:e.enabled?`yes`:`no`,runs:e.runsInWindow,failed:e.failed,waiting:e.waiting,success:e.successRate===null?`—`:`${Math.round(e.successRate*100)}%`,lastRun:e.lastRunStatus??`—`,lastRunAt:e.lastRunAt??`—`})),[{key:`id`,header:`ID`},{key:`name`,header:`Name`},{key:`enabled`,header:`Enabled`},{key:`runs`,header:`Runs`},{key:`failed`,header:`Failed`},{key:`waiting`,header:`Waiting`},{key:`success`,header:`Success`},{key:`lastRun`,header:`Last Run`},{key:`lastRunAt`,header:`Last Run At`}])}function ef(e){if(s({ID:e.id,Name:e.name,Description:e.description??``,Enabled:e.enabled?`yes`:`no`,Actions:e.actions.length}),e.triggers&&e.triggers.length>0&&(l(`Triggers`),tf(e.triggers)),e.validationErrors.length>0){l(`Validation issues`);for(let t of e.validationErrors)console.log(` ${t.path}: ${t.message}`)}}function tf(e){t(e.map(e=>({id:e.id,kind:e.kind,enabled:e.enabled?`yes`:`no`,detail:e.kind===`schedule`?`${e.cron??``} (${e.timezone??``})`:`${e.provider??``}:${e.eventFilter?.event??``}${e.eventFilter?.action?`.${e.eventFilter.action}`:``}`})),[{key:`id`,header:`ID`},{key:`kind`,header:`Kind`},{key:`enabled`,header:`Enabled`},{key:`detail`,header:`Detail`}])}function nf(t){t.command(`list`).description(`List your workflows`).action(async t=>{let n=await(await X(t)).workflows.list();if(t.json)return e(n);Qd(n)}),t.command(`fleet`).description(`Fleet overview: every workflow's run tallies over a trailing window, failing-first`).option(`--window <window>`,`Trailing window: 24h, 7d, or 30d`,`7d`).action(async t=>{let n=await(await X(t)).workflows.fleetInsights({window:t.window});if(t.json)return e(n);$d(n)}),t.command(`get`).description(`Show a workflow's definition and compiled triggers`).argument(`<id>`,`Workflow ID`).option(`--yaml`,`Print only the raw definition YAML (the export path — pipe to a file)`).action(async(t,n)=>{let r=await(await X(n)).workflows.get(t);if(n.yaml){if(r.definitionYaml===null)throw Error(`Workflow ${r.id} has no stored definition YAML to export`);process.stdout.write(r.definitionYaml.endsWith(`
182
+ `)?r.definitionYaml:`${r.definitionYaml}\n`);return}if(n.json)return e(r);ef(r)}),t.command(`create`).description(`Create a workflow from a YAML file`).argument(`<file>`,`Path to the workflow YAML`).action(async(t,n)=>{let r=Zd(t),i=await(await X(n)).workflows.create(r);if(n.json)return e(i);l(`Created workflow ${i.id} (${i.name}).`),ef(i)}),t.command(`apply`).description(`Create or update a workflow idempotently, matched by the definition's name`).argument(`<file>`,`Path to the workflow YAML`).action(async(t,n)=>{let r=Zd(t),i=await X(n),a=await i.workflows.validate(r,{structural:!0});if(!a.valid){if(process.exitCode=1,n.json)return e(a);l(`Invalid workflow:`);for(let e of a.errors)console.log(` ${e.path}: ${e.message}`);return}let o=(await i.workflows.list()).find(e=>e.name===a.name);if(o){let t=await i.workflows.update(o.id,r);if(n.json)return e({action:`updated`,workflow:t});l(`Updated workflow ${t.id} (${t.name}) — matched by name.`),ef(t);return}let s=await i.workflows.create(r);if(n.json)return e({action:`created`,workflow:s});l(`Created workflow ${s.id} (${s.name}).`),ef(s)}),t.command(`update`).description(`Replace a workflow's definition from a YAML file`).argument(`<id>`,`Workflow ID`).argument(`<file>`,`Path to the workflow YAML`).option(`--note <note>`,`Revision note recorded on the appended revision (why this change)`).action(async(t,n,r)=>{let i=Zd(n),a=await(await X(r)).workflows.update(t,i,{...r.note===void 0?{}:{note:r.note}});if(r.json)return e(a);l(`Updated workflow ${a.id} (${a.name}).`),ef(a)}),t.command(`delete`).description(`Delete a workflow and its triggers`).argument(`<id>`,`Workflow ID`).option(`--force`,`Skip confirmation prompt`).action(async(t,n)=>{if(!n.force&&!await cr(`Delete workflow ${t}? `,`--force`)){l(`Delete cancelled.`);return}if(await(await X(n)).workflows.delete(t),n.json)return e({deleted:!0,id:t});l(`Deleted workflow ${t}.`)}),t.command(`validate`).description(`Validate a workflow YAML file without saving it`).argument(`<file>`,`Path to the workflow YAML`).option(`--structural`,`CI mode: compile + capability checks only, no connection resolution — the verdict is the same regardless of connected providers`).action(async(t,n)=>{let r=Zd(t),i=await(await X(n)).workflows.validate(r,{...n.structural?{structural:!0}:{}});if(n.json)return e(i);if(i.valid)l(`Valid: ${i.name} (${i.actionCount} action(s), ${i.triggerCount} trigger(s)).`);else{l(`Invalid workflow:`);for(let e of i.errors)console.log(` ${e.path}: ${e.message}`);process.exitCode=1}}),t.command(`schema`).description(`Print the JSON Schema for the workflow YAML`).action(async t=>{e(await(await X(t)).workflows.schema())})}async function rf(t,n,r){let i=await(await X(r)).workflows.setEnabled(t,n);if(r.json)return e(i);l(`${n?`Enabled`:`Disabled`} workflow ${i.id}.`),ef(i)}function af(e,t){try{return JSON.parse(e)}catch{throw Error(`Invalid ${t}: not valid JSON`)}}function of(e,t){try{ze(e,t,`utf8`)}catch(t){throw Error(`Could not write workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function sf(e){t(e.map(e=>({id:e.id,name:e.name,category:e.category,providers:e.providers.join(`, `),summary:e.summary})),[{key:`id`,header:`ID`},{key:`name`,header:`Name`},{key:`category`,header:`Category`},{key:`providers`,header:`Providers`},{key:`summary`,header:`Summary`}])}function cf(e,t){let n=e.kind===`github_app`,r=n?`${e.provider} (App installation)`:e.provider,i=e.connectUrl?` — ${n?`install`:`connect`}: ${e.connectUrl}`:``,a=e.prerequisite;return`${r}${i}${a&&t.some(e=>e.provider===a.provider&&e.kind===a.kind&&!e.connected)?` (after connecting ${a.provider})`:``}`}function lf(t){t.command(`enable`).description(`Enable a workflow so its triggers and manual runs fire`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await rf(e,!0,t)}),t.command(`disable`).description(`Disable a workflow (pause its triggers and manual runs)`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await rf(e,!1,t)}),t.command(`templates`).description(`List the curated starter workflow templates`).action(async t=>{let n=await(await X(t)).workflows.listTemplates();if(t.json)return e(n);sf(n)}),t.command(`init`).description(`Create a workflow from a gallery template and print (or save) its YAML`).argument(`<template-id>`,"Template ID from `workflows templates`").option(`--param <key=value>`,`Template parameter value. Repeatable.`,Ec,[]).option(`--file <out>`,`Write the instantiated workflow YAML to this file instead of stdout`).action(async(t,n)=>{let r=Dc(n.param,`param`)??{},i=await(await X(n)).workflows.instantiateTemplate(t,r);if(n.json)return e(i);if(!i.created){l(`Template ${t} needs provider connections before it can run:`);for(let e of i.connectionRequirements)console.log(` ${e.connected?`✓`:`✗`} ${cf(e,i.connectionRequirements)}`);process.exitCode=1;return}let{workflow:a}=i;if(a.definitionYaml===null)throw Error(`Workflow ${a.id} was created but the server returned no definition YAML`);if(l(`Created workflow ${a.id} (${a.name}).`),n.file){of(n.file,a.definitionYaml),l(`Wrote ${n.file}.`);return}process.stdout.write(a.definitionYaml.endsWith(`
183
+ `)?a.definitionYaml:`${a.definitionYaml}\n`)})}function uf(e){t(e,[{key:`key`,header:`Key`},{key:`version`,header:`Version`},{key:`updatedAt`,header:`Updated`}])}function df(t){s({Key:t.key,Version:t.version,Updated:t.updatedAt}),l(`Value`),e(t.value)}function ff(t){let n=t.command(`kv`).description(`Read and write a workflow's cross-run KV state`);n.command(`list`).description(`List every KV entry of a workflow`).argument(`<id>`,`Workflow ID`).action(async(t,n)=>{let r=await(await X(n)).workflows.listKv(t);if(n.json)return e(r);uf(r.entries)}),n.command(`get`).description(`Show one KV entry (value and version)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.getKv(t,n);if(r.json)return e(i);df(i)}),n.command(`set`).description(`Write a KV entry from a JSON value`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).argument(`<json>`,`Value as JSON (e.g. '{"cursor":123}' or '"abc"')`).option(`--cas <version>`,`Compare-and-swap: write only if the stored version still equals this`).action(async(t,n,r,i)=>{let a=af(r,`<json>`),o=i.cas===void 0?void 0:pa(i.cas,`--cas`),s=await X(i),c=o===void 0?await s.workflows.putKv(t,n,a):await s.workflows.casKv(t,n,o,a);if(i.json)return e(c);df(c)}),n.command(`delete`).description(`Delete a KV entry (idempotent)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(t,n,r)=>{let i=await(await X(r)).workflows.deleteKv(t,n);if(r.json)return e(i);l(i.deleted?`Deleted KV entry "${n}" of workflow ${t}.`:`No KV entry "${n}" on workflow ${t}.`)})}function pf(e){t(e.map(e=>({rev:e.rev,created:e.createdAt,by:e.createdBy,source:e.source,note:e.note??``})),[{key:`rev`,header:`Rev`},{key:`created`,header:`Created`},{key:`by`,header:`Created By`},{key:`source`,header:`Source`},{key:`note`,header:`Note`}])}function mf(t){t.command(`revisions`).description(`List a workflow's definition revision history (newest first)`).argument(`<id>`,`Workflow ID`).action(async(t,n)=>{let r=await(await X(n)).workflows.listRevisions(t);if(n.json)return e(r);pf(r)}),t.command(`revision`).description(`Show one revision's metadata and definition YAML`).argument(`<id>`,`Workflow ID`).argument(`<rev>`,`Revision number`).action(async(t,n,r)=>{let i=pa(n,`<rev>`),a=await(await X(r)).workflows.getRevision(t,i);if(r.json)return e(a);s({Revision:a.rev,Created:a.createdAt,"Created by":a.createdBy,Source:a.source,Note:a.note??``}),process.stdout.write(a.yaml.endsWith(`
184
+ `)?a.yaml:`${a.yaml}\n`)}),t.command(`rollback`).description(`Restore a prior revision's definition as a NEW head revision (re-validated)`).argument(`<id>`,`Workflow ID`).argument(`<rev>`,`Revision number to restore`).action(async(t,n,r)=>{let i=pa(n,`<rev>`),a=await(await X(r)).workflows.rollback(t,i);if(r.json)return e(a);l(`Rolled back workflow ${a.id} to rev ${i}.`),ef(a)})}function hf(){let e=new N(`workflows`).description(`Create and manage Tangle workflows`);return nf(e),Mc(e),lf(e),mf(e),ff(e),Jd(e),Xd(e),e}function gf(e){for(let[t,n]of Object.entries(e.optsWithGlobals()))e.getOptionValue(t)===void 0&&n!==void 0&&e.setOptionValue(t,n)}const _f=_(import.meta.url),vf=_f(`../package.json`),yf=ue(_f.resolve(`../package.json`)),bf=vf.version??`0.0.0`;function xf(){let e=new N,t=Hd(yf,bf);e.name(`tangle`).description(`CLI for Tangle Sandbox operations`).version(bf).option(`--json`,`Output JSON where supported, including errors`).option(`--api-key <key>`,`API key (or set TANGLE_API_KEY)`).option(`--base-url <url>`,`API base URL`),e.hook(`preAction`,(e,n)=>{gf(n);let r=n.opts(),i=r.json===!0||r.ndjson===!0;a(i),n!==t&&!i&&Vd(yf,bf)}),e.addCommand(Gr()),e.addCommand(Wu()),e.addCommand(Kd()),e.addCommand(Ku()),e.addCommand(vu()),e.addCommand(Ou()),e.addCommand(ku()),e.addCommand(_o()),e.addCommand(sd()),e.addCommand(cd()),e.addCommand(ud()),e.addCommand(Tr()),e.addCommand(Yu()),e.addCommand(us()),e.addCommand(Ud()),e.addCommand(dd()),e.addCommand(gd()),e.addCommand(ei()),e.addCommand(di()),e.addCommand(Iu()),e.addCommand(ds()),e.addCommand(ms()),e.addCommand(Ql()),e.addCommand(vl()),e.addCommand(hf()),e.addCommand(Qa()),e.addCommand(Gu()),e.addCommand(Qu()),e.addCommand(Ju()),e.addCommand(fi()),e.addCommand(Pu()),e.addCommand($l()),e.addCommand(Ga()),e.addCommand(Ka()),e.addCommand(Hu()),e.addCommand(Au()),e.addCommand(_d()),e.addCommand(Fs()),e.addCommand(t);function n(e){e.configureHelp({showGlobalOptions:!0}),e.configureOutput({writeErr:()=>{}}),e.exitOverride(t=>{t.exitCode===0&&process.exit(0),H(t,e.optsWithGlobals().json===!0)});for(let t of e.commands)n(t)}return n(e),e}const Sf=xf();Sf.parseAsync(process.argv).catch(e=>{H(e,Sf.opts().json===!0)});export{Sn as _,ec as a,Xs as c,js as d,qe as f,Jt as g,Qt as h,oc as i,Ws as l,hn as m,Jl as n,tc as o,cr as p,X as r,ic as s,Q as t,Us as u,B as v,H as y};