@tangle-network/sandbox-cli 0.22.103 → 0.22.104

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,7 +1,5 @@
1
- import{createRequire as e,findPackageJSON as t}from"node:module";import"dotenv/config";import{ALL_BACKEND_TYPES as n,AuthError as r,NetworkError as i,NotFoundError as a,PublicTemplatePublishError as o,QuotaError as s,SANDBOX_RUNTIMES as c,Sandbox as l,ServerError as u,StateError as d,TimeoutError as f,ValidationError as p,createAgentRunOutcomeTracker as m,createConfidentialSandbox as h,generateAttestationNonce as g,parseBackendType as _,parseSSEStream as v,validateBatchRunRequest as y}from"@tangle-network/sandbox";import b from"chalk";import ee from"ora";import{Command as x,Option as S}from"commander";import{createHash as C,randomBytes as te,randomUUID as w}from"node:crypto";import{ProxySecretsSchema as T,REASONING_EFFORTS as E,agentInteractiveSessionRunRef as D,agentProfileSchema as O,canonicalAgentProfileDigest as ne,canonicalCandidateDigest as re,modelProvider as ie,parseSeatSpec as ae}from"@tangle-network/agent-interface";import*as k from"node:fs";import{chmodSync as oe,constants as se,existsSync as ce,mkdirSync as le,readFileSync as ue,renameSync as de,writeFileSync as fe}from"node:fs";import*as A from"node:path";import{basename as pe,dirname as me,extname as he,isAbsolute as ge,join as j,relative as _e,resolve as ve,sep as ye}from"node:path";import*as be from"node:os";import{homedir as M,tmpdir as xe}from"node:os";import{execFile as Se,execFileSync as Ce,spawn as we}from"node:child_process";import{lockSync as Te}from"proper-lockfile";import{HubClient as Ee}from"@tangle-network/hub-sdk";import{createInterface as De}from"node:readline";import{Writable as Oe}from"node:stream";import{buffer as ke}from"node:stream/consumers";import{setTimeout as Ae}from"node:timers/promises";import{CONTENT_COMPLETION_KEY as je,CONTENT_PROMPT_KEY as Me,CONTENT_TOOL_ARGS_KEY as Ne,CONTENT_TOOL_NAME_KEY as Pe,CONTENT_TOOL_RESULT_KEY as Fe,TANGLE_SUBJECT_KEY as Ie,asContentField as Le,asContentString as Re}from"@tangle-network/agent-core/telemetry";import{z as N}from"zod";import{execCli as ze,shellQuote as Be}from"@tangle-network/sdk-cli-runner";import*as P from"node:fs/promises";import{mkdir as Ve,mkdtemp as He,open as Ue,readFile as We,realpath as Ge,rm as Ke,writeFile as qe}from"node:fs/promises";import{listLocalModels as Je,loadConfig as Ye}from"cli-bridge";import{promisify as Xe,stripVTControlCharacters as Ze}from"node:util";import{createCliBridgeProvider as Qe}from"@tangle-network/agent-provider-cli-bridge";import{gunzipSync as $e}from"node:zlib";import{SearchEnvironmentFault as et}from"@tangle-network/agent-runtime";import{fileURLToPath as tt,pathToFileURL as nt}from"node:url";import{parseDocument as rt}from"yaml";import{createMcpServer as it}from"@tangle-network/sandbox/agent";import{ensureAgentPreview as at,publishAgentPreview as ot,resolveSelfSandbox as st}from"@tangle-network/sandbox/preview";import{generatePrivateKey as ct,privateKeyToAccount as lt}from"viem/accounts";import{createPublicClient as ut,createWalletClient as dt,decodeAbiParameters as ft,decodeEventLog as pt,encodeAbiParameters as mt,getAddress as ht,http as gt,isAddress as _t,keccak256 as vt,parseAbi as yt,parseAbiItem as bt,parseAbiParameters as xt,stringToHex as St,toHex as Ct}from"viem";import{tempoModerato as wt}from"viem/chains";import{Actions as Tt,withRelay as Et}from"viem/tempo";import Dt from"ws";import{createIntelligenceClient as Ot}from"@tangle-network/sandbox/intelligence";let kt=!1;function At(e){kt=e}function jt(...e){kt?console.error(...e):console.log(...e)}function Mt(e){return e==null?b.dim(`-`):typeof e==`boolean`?e?b.green(`yes`):b.red(`no`):e instanceof Date?Pt(e):typeof e==`string`&&Nt(e)?Pt(new Date(e)):String(e)}function Nt(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function Pt(e){let t=Date.now()-e.getTime();if(t<6e4)return`just now`;if(t<36e5)return`${Math.floor(t/6e4)} min ago`;if(t<864e5){let e=Math.floor(t/36e5);return`${e} hour${e>1?`s`:``} ago`}let n=Math.floor(t/864e5);return`${n} day${n>1?`s`:``} ago`}function Ft(e){switch(e){case`running`:return b.green(e);case`pending`:case`provisioning`:return b.yellow(e);case`stopped`:return b.gray(e);case`failed`:case`deleted`:return b.red(e);default:return e}}function F(e,t){let n=t.map(t=>{let n=t.header.length,r=Math.max(...e.map(e=>Mt(e[t.key]).length));return t.width??Math.max(n,r)+2}),r=e.map(e=>t.map(t=>t.key===`status`?Ft(String(e[t.key])):Mt(e[t.key])));Ht(t.map(e=>e.header),r,n)}function I(e){console.log(JSON.stringify(e,null,2))}function L(e){jt(b.green(`✓`),e)}function It(e){console.error(b.red(`✗`),e)}function Lt(e){jt(b.yellow(`!`),e)}function R(e){jt(b.blue(`→`),e)}const Rt=new Set;function z(e){let t=ee({text:e,color:`cyan`,isSilent:kt});return Rt.add(t),t}function zt(){for(let e of Rt)e.isSpinning&&e.stop();Rt.clear()}function B(e,t=0){let n=` `.repeat(t);for(let[t,r]of Object.entries(e))r!=null&&console.log(`${n}${b.dim(`${t}:`)} ${Mt(r)}`)}function Bt(e){let t=`${e.cpuCores} vCPU / ${e.memoryMB} MB / ${e.diskGB} GB`;return e.pool?`${t} (pool: ${e.pool})`:t}function Vt(e){if(console.log(),console.log(b.bold(`Sandbox Details`)),console.log(b.dim(`─`.repeat(40))),B({ID:e.id,Name:e.name,Status:Ft(e.status),Resources:e.resources?Bt(e.resources):void 0,Created:e.createdAt,Expires:e.expiresAt}),e.connection){if(console.log(),console.log(b.bold(`Connection`)),console.log(b.dim(`─`.repeat(40))),e.connection.ssh){let{ssh:t}=e.connection,n=process.platform===`win32`?`NUL`:`/dev/null`,r=`ssh -o ProxyCommand="${t.proxyCommand}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=${n} -o GlobalKnownHostsFile=${n} -o LogLevel=ERROR -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -o TCPKeepAlive=yes ${t.username}@localhost -p ${t.port}`;B({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&B({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&B({"API URL":e.connection.runtimeUrl})}console.log()}function Ht(e,t,n){if(t.length===0){console.log(b.dim(`No items found.`));return}let r=n??e.map((e,n)=>{let r=Math.max(...t.map(e=>String(e[n]??``).length));return Math.max(e.length,r)+2});console.log(e.map((e,t)=>b.bold(e.padEnd(r[t]))).join(``));for(let e of t)console.log(e.map((e,t)=>String(e??``).padEnd(r[t])).join(``))}var V=class extends Error{constructor(e,t,n,r){super(t),this.code=e,this.cause=n,this.fix=r,this.name=`ActionableCliError`}};const Ut=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`]),Wt=new Set([`GRAPH_INVALID`,`STEP_REF`,`PROFILE_INVALID`,`UNKNOWN_HARNESS`,`HUB_TOOL_UNKNOWN`,`TRIGGER_INVALID`,`WORKFLOW_INPUT_FILE_INVALID`,`VALIDATION_ERROR`]),Gt=new Set([`UNKNOWN_COMMAND`,`GRAPH_PARAM_MISSING`,`GRAPH_PARAM_UNKNOWN`,`SEAT_SYNTAX`,`HUB_PROVIDER_UNKNOWN`,`USAGE_INVALID`]),Kt=new Set([`SUBSCRIPTION_REQUIRED`,`MODEL_NOT_FOUND`,`MODEL_PROVIDER_MISMATCH`,`MCP_BLOCKED`,`CLOUD_SEAT_UNSUPPORTED`,`SCHEDULE_AUTHORITY`]);function qt(e){return typeof e==`object`&&e?e:{}}function H(e){return typeof e==`string`&&e.length>0?e:void 0}function Jt(e){let t=H(e);return t&&/^[a-z0-9][a-z0-9_-]*$/i.test(t)?t:void 0}function Yt(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=H(qt(n).code);(e||r)&&(t=r?`${r}${e?`: ${e}`:``}`:e)}return t}function Xt(e){return e.code===`credential-refused`&&e.owner===`caller`&&e.providerCode===`subscription_required`?qt(e.remediation):{}}function Zt(e){let t=qt(e),n=Array.isArray(t.runtimeFailures)?t.runtimeFailures.map(qt):[],c=n.find(e=>H(Xt(qt(e.failure)).fix))??n[0],l=qt(c?.failure??t.runtimeFailure),u=Xt(l),m=qt(t.details),h=Jt(t.provider??m.provider??m.providerId),g=qt(t.fix??m.fix),_=H(t.code)??`CLI_ERROR`,v=H(t.message)??String(e),y=H(l.cause)??H(t.cause)??H(m.reason)??v,b=`tangle --help`,ee=typeof m.providerRetryable==`boolean`?m.providerRetryable:typeof t.retryable==`boolean`?t.retryable:null;if(e instanceof r||_===`HUB_UNAUTHENTICATED`||t.status===401)_=`AUTH_EXPIRED`,v=`Authentication failed`,b=`tangle auth login`;else if(t.status===403&&v.startsWith(`Sandbox runtime creden`))_=`SANDBOX_CREDENTIAL_REFUSED`,v=`This sandbox's own TANGLE_API_KEY may call Hub endpoints only`,b=`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(_))_=[`HUB_CONNECTION_MISSING`,`CONNECTION_REQUIRED`].includes(_)?`HUB_NOT_CONNECTED`:`HUB_RECONNECT`,b=h?`tangle hub connect ${h}`:`tangle hub connections --json`;else if(_===`HUB_APPROVAL_REQUIRED`){let e=Jt(qt(m.approval).id);b=e?`tangle hub approvals approve ${e}`:`tangle hub approvals list --json`}else _===`HUB_PROVIDER_REJECTED`?(b=`tangle hub status --json`,m.providerRetryable===!1&&(y+=`. Change the request before retrying`)):_===`provider_quota_exhausted`||_===`SEAT_LIMIT`?(_=`SEAT_LIMIT`,b=`tangle auth status`,ee=!0):e instanceof s?b=`tangle usage --json`:e instanceof i?(_=`NETWORK_UNAVAILABLE`,v=`Network error: ${v}`,y=Yt(e.cause)??`No response arrived`,b=`tangle auth status --json`):e instanceof f?(_=`TIMEOUT`,b=`tangle sandbox list --json`):e instanceof p?(_=`VALIDATION_ERROR`,v=`Invalid input`):e instanceof a||e instanceof d?b=`tangle sandbox list --json`:_===`commander.unknownCommand`?(_=`UNKNOWN_COMMAND`,b=v.includes(`'graph'`)?`npm install -g @tangle-network/sandbox-cli@latest`:`tangle --help`):_.startsWith(`commander.`)?_=`USAGE_INVALID`:(_===`ENOENT`||_===`EACCES`)&&(_=`INPUT_UNAVAILABLE`);e instanceof V&&(b=e.fix,ee=!1),H(u.fix)&&(_=u.cause===`not_authenticated`?`SEAT_NOT_LOGGED_IN`:`SUBSCRIPTION_REQUIRED`),e instanceof o&&b===`tangle --help`&&(b=`tangle template publish --help`),b=H(u.fix)??H(g.command)??(_===`HUB_NOT_CONNECTED`?void 0:H(t.fixCommand))??b,Ut.has(_)&&b===`tangle --help`&&(b=`tangle auth login`);let x=qt(t.subject??m.subject??{node:c?.node??t.node,seat:t.seat??u.harness}),S=e instanceof i||e instanceof Error&&`batchCustody`in e?t.batchCustody:void 0;S&&(y=`Batch acceptance: ${S.acceptance}; retirement receipt ${S.cleanup?.mode===`release`&&S.cleanup.isComplete?`proved`:`unproved`}.`,ee=!1,b=`tangle batch run --help`);let C=H(t.resumeAt??m.resumeAt??m.resetAt);return{code:_,...S?{batchCustody:S}:{},catalogCode:H(t.catalogCode),message:H(t.nextStep)&&H(t.message),nextStep:H(t.nextStep),subject:{...H(x.node)?{node:String(x.node)}:{},...H(x.seat)?{seat:String(x.seat)}:{}},what:v,cause:y,fix:{command:b,...Array.isArray(g.alternatives)&&g.alternatives.every(e=>typeof e==`string`)?{alternatives:g.alternatives}:{},...g.edit===void 0?{}:{edit:g.edit},...H(g.url)?{url:String(g.url)}:{}},retryable:ee,...C&&Number.isFinite(Date.parse(C))?{resumeAt:C}:{},...H(t.runId)?{runId:String(t.runId)}:{},...H(t.requestId)?{requestId:String(t.requestId)}:{},...typeof t.status==`number`?{status:t.status}:{},...H(l.code)&&H(l.owner)?{runtimeFailure:{code:String(l.code),owner:String(l.owner),cause:typeof l.cause==`string`?l.cause:y,...H(l.providerCode)?{providerCode:String(l.providerCode)}:{},...typeof l.providerStatus==`number`?{providerStatus:l.providerStatus}:{},...typeof l.retryAfterMs==`number`?{retryAfterMs:l.retryAfterMs}:{},...Object.keys(u).length?{remediation:u}:{}}}:{},...e instanceof o&&e.job?{job:e.job}:{}}}function Qt(e){let t=[e.subject.node&&`node ${e.subject.node}`,e.subject.seat].filter(Boolean).join(` · `);return`✗ ${`${t?`${t}: `:``}${e.what}${e.status?` (HTTP ${e.status})`:``}`}${e.cause===e.what?``:` — ${e.cause}`}${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 $t(e){return Qt(Zt(e))}function U(e,t=!1){zt();let n=Zt(e);t?I({ok:!1,error:n}):console.error(b.red(Qt(n)));let r=1;Ut.has(n.code)?r=77:Wt.has(n.code)?r=65:Gt.has(n.code)?r=64:Kt.has(n.code)?r=78:[`SEAT_LIMIT`,`RATE_LIMITED`].includes(n.code)?r=75:[`HARNESS_NOT_INSTALLED`,`MCP_UNREACHABLE`,`NETWORK_UNAVAILABLE`].includes(n.code)?r=69:n.code===`RUN_STOPPED`&&(r=130),process.exit(r)}function en(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:pe(a)}}let t;try{t=ue(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:pe(e),content:t}}function tn(e){let t=(e.skills??[]).map(en),n=(e.tools??[]).map(en),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 nn(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 an(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await an(e):ue(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw new V(`PROFILE_INVALID`,`Profile '${e}' is invalid`,`Expected a JSON AgentProfile`,`tangle agent profile create --name my-agent --json`)}return rn(n,e)}function rn(e,t){let n=O.safeParse(e);if(!n.success)throw new V(`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 an(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function on(e){let t=e.profileSource?await nn(e.profileSource):void 0,n=tn(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const sn=A.join(be.homedir(),`.tangle`),cn=A.join(sn,`credentials.json`),ln=`tangle-sandbox-cli`,un=new Int32Array(new SharedArrayBuffer(4));var dn=class extends Error{constructor(e,t){super(`Credentials file at ${e} is corrupted and cannot be parsed. Inspect or remove it manually before retrying — refusing to overwrite it automatically.`),this.filePath=e,this.name=`CredentialsFileCorruptedError`,t&&(this.cause=t)}},fn=class extends Error{constructor(e){super(`Credential storage preflight failed: ${e}`),this.name=`CredentialStorageProbeError`}},pn=class extends Error{constructor(e){super(`Credential storage is busy. Wait a moment and retry.`),this.name=`CredentialsFileLockedError`,e&&(this.cause=e)}};function mn(e){let t=yn(e);if(t)return{value:t,source:`keychain`};let n=Sn(e);return n?{value:n,source:`file`}:{source:`none`}}function hn(e,t){return bn(e,t)?(wn(e),`keychain`):(Cn(e,t),`file`)}function gn(){let e=`credential-write-probe:${process.pid}:${w()}`,t=w();if(bn(e,t)){let n=yn(e);if(!xn(e))throw new fn(`the OS keychain accepted a test credential but the CLI could not remove it`);if(n!==t)throw new fn(`the OS keychain accepted a test credential but the CLI could not read it back`);return`keychain`}return On(e),`file`}function _n(e){xn(e),wn(e)}function vn(e,t){let n=process.platform;if(n!==`darwin`&&n!==`linux`)return;let r=n===`darwin`?`security`:`secret-tool`;try{return Ce(r,e[n],{encoding:`utf8`,input:t,stdio:[t===void 0?`ignore`:`pipe`,`pipe`,`ignore`],timeout:n===`linux`?1e4:void 0}).trim()}catch{return}}function yn(e){let t=An(e);return vn({darwin:[`find-generic-password`,`-s`,ln,`-a`,t,`-w`],linux:[`lookup`,`service`,ln,`account`,t]})}function bn(e,t){let n=An(e),r=[`add-generic-password`,`-U`,`-s`,ln,`-a`],i=[`store`,`--label=Tangle Sandbox CLI`,`service`];return vn({darwin:[...r,n,`-w`,t],linux:[...i,ln,`account`,n]},process.platform===`linux`?t:void 0)!==void 0}function xn(e){let t=An(e);return vn({darwin:[`delete-generic-password`,`-s`,ln,`-a`,t],linux:[`clear`,`service`,ln,`account`,t]})!==void 0}function Sn(e){return En()[e]}function Cn(e,t){Tn(()=>{let n=En();n[e]=t,Dn(n)})}function wn(e){return Tn(()=>{let t;try{t=En()}catch(e){if(e instanceof dn)return!1;throw e}return e in t?(delete t[e],Dn(t),Sn(e)===void 0):!0})}function Tn(e){kn();let t=Date.now()+2e3,n,r;for(;!n;)try{n=Te(cn,{realpath:!1,stale:5e3})}catch(e){if(r=e instanceof Error?e:void 0,!e||typeof e!=`object`||!(`code`in e)||e.code!==`ELOCKED`)throw e;if(Date.now()>=t)throw new pn(r);Atomics.wait(un,0,0,20)}try{return e()}finally{n()}}function En(){let e;try{e=k.readFileSync(cn,`utf8`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))throw new dn(cn);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof dn?e:new dn(cn,e instanceof Error?e:void 0)}}function Dn(e){if(kn(),Object.keys(e).length===0){k.existsSync(cn)&&k.unlinkSync(cn);return}let t=`${cn}.${process.pid}.tmp`;k.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),k.renameSync(t,cn)}function On(e){let t=w(),n=!1,r;try{if(Cn(e,t),n=!0,Sn(e)!==t)throw new fn(`the credentials file did not return the value just written`)}catch(e){r=e}finally{if(n)try{!wn(e)&&!r&&(r=new fn(`the credentials file accepted a test credential but the CLI could not remove it`))}catch(e){r??=e}}if(r)throw r}function kn(){if(!k.existsSync(sn)){k.mkdirSync(sn,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(k.statSync(sn).mode&511)!=448&&k.chmodSync(sn,448)}catch{}}function An(e){return`profile:${e}`}const jn=A.join(be.homedir(),`.tangle`),Mn=A.join(jn,`config.json`),Nn=`https://id.tangle.tools`,Pn=`https://solve.tangle.tools/api/solve`,Fn=`default`;function In(){return{tangleBaseUrl:process.env.TANGLE_BASE_URL,sandboxBaseUrl:process.env.SANDBOX_BASE_URL,hubUrl:process.env.TANGLE_HUB_URL}}function Ln(e,t){let n=Un(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 Fn;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 Rn(){k.existsSync(jn)||k.mkdirSync(jn,{mode:448,recursive:!0})}function zn(e,t){Rn();let n=`${e}.${process.pid}.tmp`;k.writeFileSync(n,t,{mode:384}),k.renameSync(n,e)}function Bn(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function Vn(){try{if(k.existsSync(Mn))return JSON.parse(k.readFileSync(Mn,`utf-8`))}catch{}return{}}function Hn(e){let t=gr(Vn(),e);zn(Mn,`${JSON.stringify(t,null,2)}\n`)}function Un(e){return _r(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||Vn().activeProfile||Fn)}function Wn(e){Hn({activeProfile:_r(e)})}function Gn(){return{token:process.env.TANGLE_LINE_TOKEN,baseUrl:process.env.TANGLE_HUB_URL}}function Kn(){return process.env.TANGLE_SANDBOX||Vn().currentSandbox||void 0}function qn(e){Hn({currentSandbox:e})}function Jn(){let e=Vn();delete e.currentSandbox,zn(Mn,`${JSON.stringify(e,null,2)}\n`)}function Yn(){let e=Vn().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=te(4).toString(`hex`),r=`${t?`${t}-`:`device-`}${n}`;return Hn({deviceId:r}),r}function Xn(e){let t=e||Kn();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 Zn(){let e=Vn(),t=Un(),n=new Set([Fn,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(_r(e.activeProfile)),[...n].map(e=>{let n=mn(e).source;return{name:e,active:e===t,hasApiKey:n!==`none`,baseUrl:or(void 0,e),apiKeySource:n}}).sort((e,t)=>e.name.localeCompare(t.name))}function Qn(e){let t=Un(e);return{name:t,active:t===Un(),baseUrl:or(void 0,t),credentialSource:mn(t).source}}function $n(e,t){let n=_r(e),r=Vn(),i=hr(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=hn(n,t.apiKey)),Hn({profiles:Object.keys(l).length>0?l:{}}),u}function er(e){let t=Un(e),n={...Vn().profiles??{}},r=n[t];if(r){let e={...r};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}Hn({profiles:n}),_n(t)}function tr(){let e=process.env.TANGLE_API_KEY_FILE;if(e){let t=k.readFileSync(e,`utf8`).trim();if(!t.startsWith(`sk-tan-`))throw Error(`Invalid sandbox credential file`);return t}return process.env.TANGLE_API_KEY}function nr(e,t){let n=Ln(`sandbox`,t);return e||tr()||mn(n).value}function rr(e,t){return e||(process.env.TANGLE_SOLVE_API_KEY?process.env.TANGLE_SOLVE_API_KEY:mn(Ln(`solve`,t)).value)}function ir(e,t){let n=Ln(`sandbox`,t);return e?`flag`:process.env.TANGLE_API_KEY_FILE||process.env.TANGLE_API_KEY?`env`:mn(n).source}function ar(e,t){return e?`flag`:process.env.TANGLE_SOLVE_API_KEY?`env`:mn(Ln(`solve`,t)).source}function or(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=Un(t),i=Vn(),a=hr(r,i);return a.baseUrl?a.baseUrl:(r===Fn||r===`sandbox`)&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function sr(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function cr(e){return e?.trim().replace(/\/+$/,``)||void 0}function lr(e){return cr(e?.flag)??cr(sr(cr(process.env.TANGLE_HUB_URL)))??cr(process.env.TANGLE_PLATFORM_URL)??cr(e?.cachedPlatformUrl?.())??Nn}function ur(e){let t=cr(e)??cr(process.env.TANGLE_SOLVE_API_URL);if(t&&t!==Pn)throw Error(`Solve credentials may only be sent to ${Pn}`);return Pn}function dr(e){let t=cr(e);if(t&&t!==Nn)throw Error(`Solve credentials may only be sent to ${Nn}`);return Nn}function W(e){let t=Ln(`sandbox`,e.profile),n=nr(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===Fn?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:or(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...fr(t)}}function fr(e){let t=Vn(),n=hr(Un(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function pr(e,t){$n(Un(t),{activeTeamId:e.id,activeTeamName:e.name})}function mr(e){let t=Un(e),n=Vn(),r={...n.profiles??{}},i={baseUrl:hr(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],Hn({profiles:r})}function hr(e,t=Vn()){let n=_r(e);return{...n===Fn?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[Fn]?.activeTeamId,activeTeamName:t.profiles?.[Fn]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function gr(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 _r(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 vr=null,yr=null;function G(e){if(!e&&vr)return vr;let t=e??W({});return(!vr||!yr||yr.apiKey!==t.apiKey||yr.baseUrl!==t.baseUrl||yr.timeout!==t.timeout)&&(vr=new l({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),yr=t),vr}function br(){vr=null,yr=null}function K(e){let t=W({apiKey:e.apiKey,baseUrl:e.baseUrl});return{context:t,client:G(t)}}async function xr(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 Sr(r,n)}function Sr(e,t){let n=t.trim();if(n.length===0)throw Error(`Connection reference is empty.`);let r=e.find(e=>e.id===n);if(r)return r.id;let i=n.indexOf(`:`),a=(i===-1?n:n.slice(0,i)).trim().toLowerCase(),o=i===-1?null:n.slice(i+1).trim(),s=e.filter(e=>e.status!==`revoked`&&e.providerId.toLowerCase()===a);if(o&&o.length>0){let e=o.toLowerCase();s=s.filter(t=>(t.accountDisplay??``).toLowerCase()===e||t.displayName.toLowerCase()===e)}if(s.length===1)return s[0].id;throw s.length===0?Error(`No hub connection matches "${t}". List your connections with \`tangle hub connections\`.`):Error(Cr(t,s))}function Cr(e,t){let n=t.map(e=>`- ${e.id} (provider: ${e.providerId}, account: ${e.accountDisplay??e.displayName})`).join(`
2
- `);return`Hub connection reference is ambiguous: "${e}" matches ${t.length} connections. Use a connection id or provider:account instead.
3
- `+n}function wr(e,t){return[...t,e]}async function Tr(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:`${Sr(r,e.ref)}:${e.tail}`)}function Er(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 Dr(e,t){return C(`sha256`).update(`${e}\0${t}`).digest(`hex`).slice(0,32)}function Or(e){return`${e}:hub`}function kr(e){let{value:t}=mn(Or(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 Ar(e,t){try{hn(Or(e),JSON.stringify(t))}catch{}}async function jr(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 Mr=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=Dr(t,n);let a=kr(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 jr(this.sandboxBaseUrl,this.sessionToken,this.deviceId,this.signal),sessionFingerprint:this.fingerprint};return this.cache=t,Ar(this.profile,t),t}};function Nr(e){if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function Pr(e,t){return lr({flag:e.baseUrl,...e.useCachedPlatformUrl?{cachedPlatformUrl:()=>kr(t)?.platformUrl}:{}})}function Fr(e,t){let n=Ln(`sandbox`,e.profile),r=nr(e.apiKey,n),i=ir(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:Pr(e,n)}:{kind:`managed`,profile:n,sandboxBaseUrl:or(e.sandboxBaseUrl,n),sessionToken:o,deviceId:Yn(),baseUrlOverride:e.baseUrl}}async function Ir(e={}){let t=Fr(e,e.hubKey===!1||Nr(process.env.TANGLE_SKIP_HUB_KEY));if(t.kind===`static`)return{token:t.apiKey,baseUrl:t.baseUrl,minted:!1};let n=new Mr(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 Lr(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 Rr(e={}){let t;try{t=await Ir(e)}catch(e){return{reachable:!1,reason:e instanceof Error?e.message:String(e),refused:!0}}try{let e=await Lr(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 zr(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=Fr(e,e.hubKey===!1||Nr(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 Ee({baseUrl:r.baseUrl,fetch:n,authHeaders:()=>({Authorization:`Bearer ${t?tr():r.apiKey}`})})}let i=new Mr(r.profile,r.sandboxBaseUrl,r.sessionToken,r.deviceId,e.signal),a=await i.ensure();return new Ee({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 Br(e={}){return zr(e)}function q(e={}){return zr({...e,useCachedPlatformUrl:!0,allowHubCapabilityToken:!0})}function Vr(e,t){return`Sandbox name is ambiguous: ${e}. Use a sandbox id instead.\n${t.map(e=>`- ${e.id} (status: ${e.status}, created: ${e.createdAt.toISOString()})`).join(`
4
- `)}`}function Hr(e){return e.activeTeamId?`team:${e.activeTeamId}`:void 0}async function J(e,t,n,r={}){if(!r.nameOnly){let t=await e.get(n);if(t)return t;if(Wr(n))throw Error(`Sandbox not found: ${n}`)}let i=(await e.list({scope:Hr(t)})).filter(e=>e.name?.toLowerCase()===n.toLowerCase());if(i.length===0)throw Error(`Sandbox not found: ${n}`);if(i.length>1)throw Error(Vr(n,i));return i[0]}const Ur=/^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 Wr(e){return Ur.test(e)}async function Gr(e,t,n,r={}){try{return(await(await J(e,t,n,{nameOnly:r.name})).delete()).outcome}catch(e){if(!(e instanceof Error&&e.message===`Sandbox not found: ${n}`)||r.name||!r.retryCleanup&&!Wr(n))throw e}let i=await e.fetch(`/v1/sandboxes/${encodeURIComponent(n)}`,{method:`DELETE`});if(i.ok){let e=await i.json().catch(()=>({}));return e.outcome===`destroyed`||e.outcome===`already_absent`?e.outcome:`unknown`}let a=(await i.text()).trim();throw Error(`Sandbox cleanup failed for ${n} (HTTP ${i.status})${a?`: ${a}`:``}`)}async function Y(e,t){if(e.status!==`stopped`)return e;let n=t?.resumeTimeoutMs??12e4;R(`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 Kr=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function qr(e,t,n){switch(e){case`anthropic`:return`// pnpm add @anthropic-ai/sdk @tangle-network/sandbox
1
+ import{createRequire as e,findPackageJSON as t}from"node:module";import"dotenv/config";import{ALL_BACKEND_TYPES as n,AuthError as r,NetworkError as i,NotFoundError as a,PublicTemplatePublishError as o,QuotaError as s,SANDBOX_RUNTIMES as c,Sandbox as l,ServerError as u,StateError as d,TimeoutError as f,ValidationError as p,createAgentRunOutcomeTracker as m,createConfidentialSandbox as h,generateAttestationNonce as g,parseBackendType as _,parseSSEStream as v,validateBatchRunRequest as y}from"@tangle-network/sandbox";import b from"chalk";import x from"ora";import{Command as S,Option as C}from"commander";import{createHash as w,randomBytes as T,randomUUID as E}from"node:crypto";import{ProxySecretsSchema as D,REASONING_EFFORTS as O,agentCandidateArtifactRefSchema as k,agentCandidateWorkspaceSnapshotEvidenceSchema as ee,agentInteractiveSessionRunRef as te,agentProfileSchema as ne,canonicalAgentProfileDigest as re,canonicalCandidateDigest as A,modelProvider as ie,parseSeatSpec as ae,validateAgentProfileSecurity as oe}from"@tangle-network/agent-interface";import*as se from"node:fs";import{chmodSync as ce,constants as le,existsSync as ue,mkdirSync as de,readFileSync as fe,renameSync as pe,writeFileSync as me}from"node:fs";import*as j from"node:path";import{basename as he,dirname as ge,extname as _e,isAbsolute as ve,join as M,relative as ye,resolve as be,sep as xe}from"node:path";import*as Se from"node:os";import{homedir as N,tmpdir as Ce}from"node:os";import{execFile as we,execFileSync as Te,spawn as Ee}from"node:child_process";import{lockSync as De}from"proper-lockfile";import{HubClient as Oe,graphMcpPolicySchema as ke,graphMcpPolicySchema as Ae,graphProfileSecurity as je,resolveConnectionReferenceFrom as Me,resolveConnectionReferenceFrom as Ne}from"@tangle-network/hub-sdk";import{createInterface as Pe}from"node:readline";import{Writable as Fe}from"node:stream";import{buffer as Ie}from"node:stream/consumers";import{setTimeout as Le}from"node:timers/promises";import{CONTENT_COMPLETION_KEY as Re,CONTENT_PROMPT_KEY as ze,CONTENT_TOOL_ARGS_KEY as Be,CONTENT_TOOL_NAME_KEY as Ve,CONTENT_TOOL_RESULT_KEY as He,TANGLE_SUBJECT_KEY as Ue,asContentField as We,asContentString as Ge}from"@tangle-network/agent-core/telemetry";import{z as P}from"zod";import{execCli as Ke,shellQuote as qe}from"@tangle-network/sdk-cli-runner";import*as Je from"node:fs/promises";import Ye,{lstat as Xe,mkdir as Ze,mkdtemp as Qe,open as $e,readFile as F,readdir as et,realpath as I,rename as tt,rm as nt,writeFile as L}from"node:fs/promises";import{KnowledgeImprovementCandidateRefSchema as rt,assertKnowledgeRetrievalMatchesVisibilityArtifact as it,createKnowledgeTools as at,createRunScopedStores as ot,decodeKnowledgeVisibilitySnapshot as st,encodeKnowledgeVisibilitySnapshot as ct,hashKnowledgeBase as lt,loadSourceRegistry as ut,parseKnowledgeWriteBlocks as dt,promoteKnowledgeCandidate as ft,restoreKnowledgeCandidateBaseline as pt,verifyKnowledgeRetrievalReceipt as mt}from"@tangle-network/agent-knowledge";import{acquireSingleRunLock as ht,incumbent as gt,parseSearchLedgerLine as _t,replaySearchLedgerText as vt,uniform as yt}from"@tangle-network/agent-eval/campaign";import{captureAgentWorkspaceSnapshot as bt,materializeAgentWorkspaceSnapshot as xt}from"@tangle-network/agent-runtime/candidate-execution";import{createBudgetPool as St,createPrivateCasArtifactPort as Ct,readGraphStrings as wt,setGraphStrings as Tt}from"@tangle-network/agent-runtime/kernel";import{listLocalModels as Et,loadConfig as Dt}from"cli-bridge";import{promisify as Ot,stripVTControlCharacters as kt}from"node:util";import{createCliBridgeProvider as At}from"@tangle-network/agent-provider-cli-bridge";import{parse as jt,parseDocument as Mt}from"yaml";import{SearchEnvironmentFault as Nt,improve as Pt,officialGepa as Ft,reflectiveProfileProposer as It,searchMethod as Lt,subscriptionLane as Rt}from"@tangle-network/agent-runtime";import{readSettleRecord as zt,runEvidence as Bt}from"@tangle-network/agent-runtime/durable";import{runtimeRunRolloutLines as Vt}from"@tangle-network/agent-eval/supervisor-run";import{paretoFrontier as Ht}from"@tangle-network/agent-eval";import{gunzipSync as Ut}from"node:zlib";import{fileURLToPath as Wt,pathToFileURL as Gt}from"node:url";import{createMcpServer as Kt}from"@tangle-network/sandbox/agent";import{ensureAgentPreview as qt,publishAgentPreview as Jt,resolveSelfSandbox as Yt}from"@tangle-network/sandbox/preview";import{generatePrivateKey as Xt,privateKeyToAccount as Zt}from"viem/accounts";import{createPublicClient as Qt,createWalletClient as $t,decodeAbiParameters as en,decodeEventLog as tn,encodeAbiParameters as nn,getAddress as rn,http as an,isAddress as on,keccak256 as sn,parseAbi as cn,parseAbiItem as ln,parseAbiParameters as un,stringToHex as dn,toHex as fn}from"viem";import{tempoModerato as pn}from"viem/chains";import{Actions as mn,withRelay as hn}from"viem/tempo";import gn from"ws";import{createIntelligenceClient as _n}from"@tangle-network/sandbox/intelligence";let vn=!1;function yn(e){vn=e}function bn(...e){vn?console.error(...e):console.log(...e)}function xn(e){return e==null?b.dim(`-`):typeof e==`boolean`?e?b.green(`yes`):b.red(`no`):e instanceof Date?Cn(e):typeof e==`string`&&Sn(e)?Cn(new Date(e)):String(e)}function Sn(e){return/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(e)}function Cn(e){let t=Date.now()-e.getTime();if(t<6e4)return`just now`;if(t<36e5)return`${Math.floor(t/6e4)} min ago`;if(t<864e5){let e=Math.floor(t/36e5);return`${e} hour${e>1?`s`:``} ago`}let n=Math.floor(t/864e5);return`${n} day${n>1?`s`:``} ago`}function wn(e){switch(e){case`running`:return b.green(e);case`pending`:case`provisioning`:return b.yellow(e);case`stopped`:return b.gray(e);case`failed`:case`deleted`:return b.red(e);default:return e}}function R(e,t){let n=t.map(t=>{let n=t.header.length,r=Math.max(...e.map(e=>xn(e[t.key]).length));return t.width??Math.max(n,r)+2}),r=e.map(e=>t.map(t=>t.key===`status`?wn(String(e[t.key])):xn(e[t.key])));jn(t.map(e=>e.header),r,n)}function z(e){console.log(JSON.stringify(e,null,2))}function B(e){bn(b.green(`✓`),e)}function Tn(e){console.error(b.red(`✗`),e)}function En(e){bn(b.yellow(`!`),e)}function V(e){bn(b.blue(`→`),e)}const Dn=new Set;function H(e){let t=x({text:e,color:`cyan`,isSilent:vn});return Dn.add(t),t}function On(){for(let e of Dn)e.isSpinning&&e.stop();Dn.clear()}function U(e,t=0){let n=` `.repeat(t);for(let[t,r]of Object.entries(e))r!=null&&console.log(`${n}${b.dim(`${t}:`)} ${xn(r)}`)}function kn(e){let t=`${e.cpuCores} vCPU / ${e.memoryMB} MB / ${e.diskGB} GB`;return e.pool?`${t} (pool: ${e.pool})`:t}function An(e){if(console.log(),console.log(b.bold(`Sandbox Details`)),console.log(b.dim(`─`.repeat(40))),U({ID:e.id,Name:e.name,Status:wn(e.status),Resources:e.resources?kn(e.resources):void 0,Created:e.createdAt,Expires:e.expiresAt}),e.connection){if(console.log(),console.log(b.bold(`Connection`)),console.log(b.dim(`─`.repeat(40))),e.connection.ssh){let{ssh:t}=e.connection,n=process.platform===`win32`?`NUL`:`/dev/null`,r=`ssh -o ProxyCommand="${t.proxyCommand}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=${n} -o GlobalKnownHostsFile=${n} -o LogLevel=ERROR -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -o TCPKeepAlive=yes ${t.username}@localhost -p ${t.port}`;U({SSH:process.platform===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN='<token>'; ${r}`:`TANGLE_SSH_PROXY_AUTH_TOKEN='<token>' ${r}`})}e.connection.webTerminalUrl&&U({"Web Terminal":e.connection.webTerminalUrl}),e.connection.runtimeUrl&&U({"API URL":e.connection.runtimeUrl})}console.log()}function jn(e,t,n){if(t.length===0){console.log(b.dim(`No items found.`));return}let r=n??e.map((e,n)=>{let r=Math.max(...t.map(e=>String(e[n]??``).length));return Math.max(e.length,r)+2});console.log(e.map((e,t)=>b.bold(e.padEnd(r[t]))).join(``));for(let e of t)console.log(e.map((e,t)=>String(e??``).padEnd(r[t])).join(``))}var W=class extends Error{constructor(e,t,n,r){super(t),this.code=e,this.cause=n,this.fix=r,this.name=`ActionableCliError`}};const Mn=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`]),Nn=new Set([`GRAPH_INVALID`,`STEP_REF`,`PROFILE_INVALID`,`UNKNOWN_HARNESS`,`HUB_TOOL_UNKNOWN`,`TRIGGER_INVALID`,`WORKFLOW_INPUT_FILE_INVALID`,`VALIDATION_ERROR`]),Pn=new Set([`UNKNOWN_COMMAND`,`GRAPH_PARAM_MISSING`,`GRAPH_PARAM_UNKNOWN`,`SEAT_SYNTAX`,`HUB_PROVIDER_UNKNOWN`,`USAGE_INVALID`]),Fn=new Set([`SUBSCRIPTION_REQUIRED`,`MODEL_NOT_FOUND`,`MODEL_PROVIDER_MISMATCH`,`MCP_BLOCKED`,`CLOUD_SEAT_UNSUPPORTED`,`SCHEDULE_AUTHORITY`]);function In(e){return typeof e==`object`&&e?e:{}}function Ln(e){return typeof e==`string`&&e.length>0?e:void 0}function Rn(e){let t=Ln(e);return t&&/^[a-z0-9][a-z0-9_-]*$/i.test(t)?t:void 0}function zn(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=Ln(In(n).code);(e||r)&&(t=r?`${r}${e?`: ${e}`:``}`:e)}return t}function Bn(e){return e.code===`credential-refused`&&e.owner===`caller`&&e.providerCode===`subscription_required`?In(e.remediation):{}}function Vn(e){let t=In(e),n=Array.isArray(t.runtimeFailures)?t.runtimeFailures.map(In):[],c=n.find(e=>Ln(Bn(In(e.failure)).fix))??n[0],l=In(c?.failure??t.runtimeFailure),u=Bn(l),m=In(t.details),h=Rn(t.provider??m.provider??m.providerId),g=In(t.fix??m.fix),_=Ln(t.code)??`CLI_ERROR`,v=Ln(t.message)??String(e),y=Ln(l.cause)??Ln(t.cause)??Ln(m.reason)??v,b=`tangle --help`,x=typeof m.providerRetryable==`boolean`?m.providerRetryable:typeof t.retryable==`boolean`?t.retryable:null;if(e instanceof r||_===`HUB_UNAUTHENTICATED`||t.status===401)_=`AUTH_EXPIRED`,v=`Authentication failed`,b=`tangle auth login`;else if(t.status===403&&v.startsWith(`Sandbox runtime creden`))_=`SANDBOX_CREDENTIAL_REFUSED`,v=`This sandbox's own TANGLE_API_KEY may call Hub endpoints only`,b=`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(_))_=[`HUB_CONNECTION_MISSING`,`CONNECTION_REQUIRED`].includes(_)?`HUB_NOT_CONNECTED`:`HUB_RECONNECT`,b=h?`tangle hub connect ${h}`:`tangle hub connections --json`;else if(_===`HUB_APPROVAL_REQUIRED`){let e=Rn(In(m.approval).id);b=e?`tangle hub approvals approve ${e}`:`tangle hub approvals list --json`}else _===`HUB_PROVIDER_REJECTED`?(b=`tangle hub status --json`,m.providerRetryable===!1&&(y+=`. Change the request before retrying`)):_===`provider_quota_exhausted`||_===`SEAT_LIMIT`?(_=`SEAT_LIMIT`,b=`tangle auth status`,x=!0):e instanceof s?b=`tangle usage --json`:e instanceof i?(_=`NETWORK_UNAVAILABLE`,v=`Network error: ${v}`,y=zn(e.cause)??`No response arrived`,b=`tangle auth status --json`):e instanceof f?(_=`TIMEOUT`,b=`tangle sandbox list --json`):e instanceof p?(_=`VALIDATION_ERROR`,v=`Invalid input`):e instanceof a||e instanceof d?b=`tangle sandbox list --json`:_===`commander.unknownCommand`?(_=`UNKNOWN_COMMAND`,b=v.includes(`'graph'`)?`npm install -g @tangle-network/sandbox-cli@latest`:`tangle --help`):_.startsWith(`commander.`)?_=`USAGE_INVALID`:(_===`ENOENT`||_===`EACCES`)&&(_=`INPUT_UNAVAILABLE`);e instanceof W&&(b=e.fix,x=!1),Ln(u.fix)&&(_=u.cause===`not_authenticated`?`SEAT_NOT_LOGGED_IN`:`SUBSCRIPTION_REQUIRED`),e instanceof o&&b===`tangle --help`&&(b=`tangle template publish --help`),b=Ln(u.fix)??Ln(g.command)??(_===`HUB_NOT_CONNECTED`?void 0:Ln(t.fixCommand))??b,Mn.has(_)&&b===`tangle --help`&&(b=`tangle auth login`);let S=In(t.subject??m.subject??{node:c?.node??t.node,seat:t.seat??u.harness}),C=e instanceof i||e instanceof Error&&`batchCustody`in e?t.batchCustody:void 0;C&&(y=`Batch acceptance: ${C.acceptance}; retirement receipt ${C.cleanup?.mode===`release`&&C.cleanup.isComplete?`proved`:`unproved`}.`,x=!1,b=`tangle batch run --help`);let w=Ln(t.resumeAt??m.resumeAt??m.resetAt);return{code:_,...C?{batchCustody:C}:{},catalogCode:Ln(t.catalogCode),message:Ln(t.nextStep)&&Ln(t.message),nextStep:Ln(t.nextStep),subject:{...Ln(S.node)?{node:String(S.node)}:{},...Ln(S.seat)?{seat:String(S.seat)}:{}},what:v,cause:y,fix:{command:b,...Array.isArray(g.alternatives)&&g.alternatives.every(e=>typeof e==`string`)?{alternatives:g.alternatives}:{},...g.edit===void 0?{}:{edit:g.edit},...Ln(g.url)?{url:String(g.url)}:{}},retryable:x,...w&&Number.isFinite(Date.parse(w))?{resumeAt:w}:{},...Ln(t.runId)?{runId:String(t.runId)}:{},...Ln(t.requestId)?{requestId:String(t.requestId)}:{},...typeof t.status==`number`?{status:t.status}:{},...Ln(l.code)&&Ln(l.owner)?{runtimeFailure:{code:String(l.code),owner:String(l.owner),cause:typeof l.cause==`string`?l.cause:y,...Ln(l.providerCode)?{providerCode:String(l.providerCode)}:{},...typeof l.providerStatus==`number`?{providerStatus:l.providerStatus}:{},...typeof l.retryAfterMs==`number`?{retryAfterMs:l.retryAfterMs}:{},...Object.keys(u).length?{remediation:u}:{}}}:{},...e instanceof o&&e.job?{job:e.job}:{}}}function Hn(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 Un(e){return Hn(Vn(e))}function G(e,t=!1){On();let n=Vn(e);t?z({ok:!1,error:n}):console.error(b.red(Hn(n)));let r=1;Mn.has(n.code)?r=77:Nn.has(n.code)?r=65:Pn.has(n.code)?r=64:Fn.has(n.code)?r=78:[`SEAT_LIMIT`,`RATE_LIMITED`].includes(n.code)?r=75:[`HARNESS_NOT_INSTALLED`,`MCP_UNREACHABLE`,`NETWORK_UNAVAILABLE`].includes(n.code)?r=69:n.code===`RUN_STOPPED`&&(r=130),process.exit(r)}function Wn(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:he(a)}}let t;try{t=fe(e,`utf8`)}catch{throw Error(`cannot read skill/tool "${e}": not a readable file and not a github: ref`)}return{kind:`inline`,name:he(e),content:t}}function Gn(e){let t=(e.skills??[]).map(Wn),n=(e.tools??[]).map(Wn),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 Kn(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 Jn(`https://raw.githubusercontent.com/${i[0]}/${i[1]}/${a}/${i.slice(2).join(`/`)}`)}else t=/^https?:\/\//.test(e)?await Jn(e):fe(e,`utf8`);let n;try{n=JSON.parse(t)}catch{throw new W(`PROFILE_INVALID`,`Profile '${e}' is invalid`,`Expected a JSON AgentProfile`,`tangle agent profile create --name my-agent --json`)}return qn(n,e)}function qn(e,t){let n=ne.safeParse(e);if(!n.success)throw new W(`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 Jn(e){let t=await fetch(e);if(!t.ok)throw Error(`failed to fetch ${e} (${t.status})`);return t.text()}async function Yn(e){let t=e.profileSource?await Kn(e.profileSource):void 0,n=Gn(e);return t?n?{...t,...n,...n.resources?{resources:{...t.resources,...n.resources}}:{}}:t:n}const Xn=j.join(Se.homedir(),`.tangle`),Zn=j.join(Xn,`credentials.json`),Qn=`tangle-sandbox-cli`,$n=new Int32Array(new SharedArrayBuffer(4));var er=class extends Error{constructor(e,t){super(`Credentials file at ${e} is corrupted and cannot be parsed. Inspect or remove it manually before retrying — refusing to overwrite it automatically.`),this.filePath=e,this.name=`CredentialsFileCorruptedError`,t&&(this.cause=t)}},tr=class extends Error{constructor(e){super(`Credential storage preflight failed: ${e}`),this.name=`CredentialStorageProbeError`}},nr=class extends Error{constructor(e){super(`Credential storage is busy. Wait a moment and retry.`),this.name=`CredentialsFileLockedError`,e&&(this.cause=e)}};function rr(e){let t=cr(e);if(t)return{value:t,source:`keychain`};let n=dr(e);return n?{value:n,source:`file`}:{source:`none`}}function ir(e,t){return lr(e,t)?(pr(e),`keychain`):(fr(e,t),`file`)}function ar(){let e=`credential-write-probe:${process.pid}:${E()}`,t=E();if(lr(e,t)){let n=cr(e);if(!ur(e))throw new tr(`the OS keychain accepted a test credential but the CLI could not remove it`);if(n!==t)throw new tr(`the OS keychain accepted a test credential but the CLI could not read it back`);return`keychain`}return _r(e),`file`}function or(e){ur(e),pr(e)}function sr(e,t){let n=process.platform;if(n!==`darwin`&&n!==`linux`)return;let r=n===`darwin`?`security`:`secret-tool`;try{return Te(r,e[n],{encoding:`utf8`,input:t,stdio:[t===void 0?`ignore`:`pipe`,`pipe`,`ignore`],timeout:n===`linux`?1e4:void 0}).trim()}catch{return}}function cr(e){let t=yr(e);return sr({darwin:[`find-generic-password`,`-s`,Qn,`-a`,t,`-w`],linux:[`lookup`,`service`,Qn,`account`,t]})}function lr(e,t){let n=yr(e),r=[`add-generic-password`,`-U`,`-s`,Qn,`-a`],i=[`store`,`--label=Tangle Sandbox CLI`,`service`];return sr({darwin:[...r,n,`-w`,t],linux:[...i,Qn,`account`,n]},process.platform===`linux`?t:void 0)!==void 0}function ur(e){let t=yr(e);return sr({darwin:[`delete-generic-password`,`-s`,Qn,`-a`,t],linux:[`clear`,`service`,Qn,`account`,t]})!==void 0}function dr(e){return hr()[e]}function fr(e,t){mr(()=>{let n=hr();n[e]=t,gr(n)})}function pr(e){return mr(()=>{let t;try{t=hr()}catch(e){if(e instanceof er)return!1;throw e}return e in t?(delete t[e],gr(t),dr(e)===void 0):!0})}function mr(e){vr();let t=Date.now()+2e3,n,r;for(;!n;)try{n=De(Zn,{realpath:!1,stale:5e3})}catch(e){if(r=e instanceof Error?e:void 0,!e||typeof e!=`object`||!(`code`in e)||e.code!==`ELOCKED`)throw e;if(Date.now()>=t)throw new nr(r);Atomics.wait($n,0,0,20)}try{return e()}finally{n()}}function hr(){let e;try{e=se.readFileSync(Zn,`utf8`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{};throw e}try{let t=JSON.parse(e);if(typeof t!=`object`||!t||Array.isArray(t))throw new er(Zn);let n={};for(let[e,r]of Object.entries(t))typeof r==`string`&&(n[e]=r);return n}catch(e){throw e instanceof er?e:new er(Zn,e instanceof Error?e:void 0)}}function gr(e){if(vr(),Object.keys(e).length===0){se.existsSync(Zn)&&se.unlinkSync(Zn);return}let t=`${Zn}.${process.pid}.tmp`;se.writeFileSync(t,`${JSON.stringify(e,null,2)}\n`,{mode:384}),se.renameSync(t,Zn)}function _r(e){let t=E(),n=!1,r;try{if(fr(e,t),n=!0,dr(e)!==t)throw new tr(`the credentials file did not return the value just written`)}catch(e){r=e}finally{if(n)try{!pr(e)&&!r&&(r=new tr(`the credentials file accepted a test credential but the CLI could not remove it`))}catch(e){r??=e}}if(r)throw r}function vr(){if(!se.existsSync(Xn)){se.mkdirSync(Xn,{mode:448,recursive:!0});return}if(process.platform!==`win32`)try{(se.statSync(Xn).mode&511)!=448&&se.chmodSync(Xn,448)}catch{}}function yr(e){return`profile:${e}`}const br=j.join(Se.homedir(),`.tangle`),xr=j.join(br,`config.json`),Sr=`https://id.tangle.tools`,Cr=`https://solve.tangle.tools/api/solve`,wr=`default`;function Tr(){return{tangleBaseUrl:process.env.TANGLE_BASE_URL,sandboxBaseUrl:process.env.SANDBOX_BASE_URL,hubUrl:process.env.TANGLE_HUB_URL}}function Er(e,t){let n=Mr(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 wr;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 Dr(){se.existsSync(br)||se.mkdirSync(br,{mode:448,recursive:!0})}function Or(e,t){Dr();let n=`${e}.${process.pid}.tmp`;se.writeFileSync(n,t,{mode:384}),se.renameSync(n,e)}function kr(e){return e.startsWith(`sk_`)||e.startsWith(`sk-tan-`)}function Ar(){try{if(se.existsSync(xr))return JSON.parse(se.readFileSync(xr,`utf-8`))}catch{}return{}}function jr(e){let t=ai(Ar(),e);Or(xr,`${JSON.stringify(t,null,2)}\n`)}function Mr(e){return oi(e||process.env.TANGLE_PROFILE||process.env.SANDBOX_PROFILE||Ar().activeProfile||wr)}function Nr(e){jr({activeProfile:oi(e)})}function Pr(){return{token:process.env.TANGLE_LINE_TOKEN,baseUrl:process.env.TANGLE_HUB_URL}}function Fr(){return process.env.TANGLE_SANDBOX||Ar().currentSandbox||void 0}function Ir(e){jr({currentSandbox:e})}function Lr(){let e=Ar();delete e.currentSandbox,Or(xr,`${JSON.stringify(e,null,2)}\n`)}function Rr(){let e=Ar().deviceId;if(e&&/^[A-Za-z0-9_.-]{1,64}$/.test(e))return e;let t=Se.hostname().replace(/[^A-Za-z0-9_.-]/g,`-`).replace(/^-+|-+$/g,``).slice(0,32),n=T(4).toString(`hex`),r=`${t?`${t}-`:`device-`}${n}`;return jr({deviceId:r}),r}function zr(e){let t=e||Fr();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 Br(){let e=Ar(),t=Mr(),n=new Set([wr,...Object.keys(e.profiles??{})]);return e.activeProfile&&n.add(oi(e.activeProfile)),[...n].map(e=>{let n=rr(e).source;return{name:e,active:e===t,hasApiKey:n!==`none`,baseUrl:Yr(void 0,e),apiKeySource:n}}).sort((e,t)=>e.name.localeCompare(t.name))}function Vr(e){let t=Mr(e);return{name:t,active:t===Mr(),baseUrl:Yr(void 0,t),credentialSource:rr(t).source}}function Hr(e,t){let n=oi(e),r=Ar(),i=ii(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=ir(n,t.apiKey)),jr({profiles:Object.keys(l).length>0?l:{}}),u}function Ur(e){let t=Mr(e),n={...Ar().profiles??{}},r=n[t];if(r){let e={...r};e.baseUrl||e.activeTeamId||e.activeTeamName?n[t]=e:delete n[t]}jr({profiles:n}),or(t)}function Wr(){let e=process.env.TANGLE_API_KEY_FILE;if(e){let t=se.readFileSync(e,`utf8`).trim();if(!t.startsWith(`sk-tan-`))throw Error(`Invalid sandbox credential file`);return t}return process.env.TANGLE_API_KEY}function Gr(e,t){let n=Er(`sandbox`,t);return e||Wr()||rr(n).value}function Kr(e,t){return e||(process.env.TANGLE_SOLVE_API_KEY?process.env.TANGLE_SOLVE_API_KEY:rr(Er(`solve`,t)).value)}function qr(e,t){let n=Er(`sandbox`,t);return e?`flag`:process.env.TANGLE_API_KEY_FILE||process.env.TANGLE_API_KEY?`env`:rr(n).source}function Jr(e,t){return e?`flag`:process.env.TANGLE_SOLVE_API_KEY?`env`:rr(Er(`solve`,t)).source}function Yr(e,t){if(e)return e;let n=process.env.TANGLE_BASE_URL||process.env.SANDBOX_BASE_URL;if(n)return n;let r=Mr(t),i=Ar(),a=ii(r,i);return a.baseUrl?a.baseUrl:(r===wr||r===`sandbox`)&&i.baseUrl?i.baseUrl:`https://sandbox.tangle.tools`}function Xr(e){if(e)return e.replace(/\/v1\/hub\/?$/,``)}function Zr(e){return e?.trim().replace(/\/+$/,``)||void 0}function Qr(e){return Zr(e?.flag)??Zr(Xr(Zr(process.env.TANGLE_HUB_URL)))??Zr(process.env.TANGLE_PLATFORM_URL)??Zr(e?.cachedPlatformUrl?.())??Sr}function $r(e){let t=Zr(e)??Zr(process.env.TANGLE_SOLVE_API_URL);if(t&&t!==Cr)throw Error(`Solve credentials may only be sent to ${Cr}`);return Cr}function ei(e){let t=Zr(e);if(t&&t!==Sr)throw Error(`Solve credentials may only be sent to ${Sr}`);return Sr}function K(e){let t=Er(`sandbox`,e.profile),n=Gr(e.apiKey,t);if(!n)throw Error(`No API key found for profile '${t}'. Set TANGLE_API_KEY or run: tangle auth login${t===wr?``:` --profile ${t}`}`);return{apiKey:n,baseUrl:Yr(e.baseUrl,t),timeout:e.timeout??3e4,profile:t,...ti(t)}}function ti(e){let t=Ar(),n=ii(Mr(e),t);return{activeTeamId:n.activeTeamId,activeTeamName:n.activeTeamName}}function ni(e,t){Hr(Mr(t),{activeTeamId:e.id,activeTeamName:e.name})}function ri(e){let t=Mr(e),n=Ar(),r={...n.profiles??{}},i={baseUrl:ii(t,n).baseUrl};i.baseUrl?r[t]=i:delete r[t],jr({profiles:r})}function ii(e,t=Ar()){let n=oi(e);return{...n===wr?{baseUrl:t.baseUrl,activeTeamId:t.profiles?.[wr]?.activeTeamId,activeTeamName:t.profiles?.[wr]?.activeTeamName}:{},...t.profiles?.[n]??{}}}function ai(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 oi(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 si=null,ci=null;function q(e){if(!e&&si)return si;let t=e??K({});return(!si||!ci||ci.apiKey!==t.apiKey||ci.baseUrl!==t.baseUrl||ci.timeout!==t.timeout)&&(si=new l({apiKey:t.apiKey,baseUrl:t.baseUrl,timeoutMs:t.timeout}),ci=t),si}function li(){si=null,ci=null}function J(e){let t=K({apiKey:e.apiKey,baseUrl:e.baseUrl});return{context:t,client:q(t)}}async function ui(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 Me(r,n)}function di(e,t){return[...t,e]}async function fi(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:`${Ne(r,e.ref)}:${e.tail}`)}function pi(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 mi(e,t){return w(`sha256`).update(`${e}\0${t}`).digest(`hex`).slice(0,32)}function hi(e){return`${e}:hub`}function gi(e){let{value:t}=rr(hi(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 _i(e,t){try{ir(hi(e),JSON.stringify(t))}catch{}}async function vi(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 yi=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=mi(t,n);let a=gi(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 vi(this.sandboxBaseUrl,this.sessionToken,this.deviceId,this.signal),sessionFingerprint:this.fingerprint};return this.cache=t,_i(this.profile,t),t}};function bi(e){if(!e)return!1;let t=e.trim().toLowerCase();return t===`1`||t===`true`||t===`yes`}function xi(e,t){return Qr({flag:e.baseUrl,...e.useCachedPlatformUrl?{cachedPlatformUrl:()=>gi(t)?.platformUrl}:{}})}function Si(e,t){let n=Er(`sandbox`,e.profile),r=Gr(e.apiKey,n),i=qr(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:xi(e,n)}:{kind:`managed`,profile:n,sandboxBaseUrl:Yr(e.sandboxBaseUrl,n),sessionToken:o,deviceId:Rr(),baseUrlOverride:e.baseUrl}}async function Ci(e={}){let t=Si(e,e.hubKey===!1||bi(process.env.TANGLE_SKIP_HUB_KEY));if(t.kind===`static`)return{token:t.apiKey,baseUrl:t.baseUrl,minted:!1};let n=new yi(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 wi(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 Ti(e={}){let t;try{t=await Ci(e)}catch(e){return{reachable:!1,reason:e instanceof Error?e.message:String(e),refused:!0}}try{let e=await wi(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 Ei(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=Si(e,e.hubKey===!1||bi(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 Oe({baseUrl:r.baseUrl,fetch:n,authHeaders:()=>({Authorization:`Bearer ${t?Wr():r.apiKey}`})})}let i=new yi(r.profile,r.sandboxBaseUrl,r.sessionToken,r.deviceId,e.signal),a=await i.ensure();return new Oe({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 Di(e={}){return Ei(e)}function Oi(e={}){return Ei({...e,useCachedPlatformUrl:!0,allowHubCapabilityToken:!0})}function ki(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 Ai(e){return e.activeTeamId?`team:${e.activeTeamId}`:void 0}async function Y(e,t,n,r={}){if(!r.nameOnly){let t=await e.get(n);if(t)return t;if(Mi(n))throw Error(`Sandbox not found: ${n}`)}let i=(await e.list({scope:Ai(t)})).filter(e=>e.name?.toLowerCase()===n.toLowerCase());if(i.length===0)throw Error(`Sandbox not found: ${n}`);if(i.length>1)throw Error(ki(n,i));return i[0]}const ji=/^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 Mi(e){return ji.test(e)}async function Ni(e,t,n,r={}){try{return(await(await Y(e,t,n,{nameOnly:r.name})).delete()).outcome}catch(e){if(!(e instanceof Error&&e.message===`Sandbox not found: ${n}`)||r.name||!r.retryCleanup&&!Mi(n))throw e}let i=await e.fetch(`/v1/sandboxes/${encodeURIComponent(n)}`,{method:`DELETE`});if(i.ok){let e=await i.json().catch(()=>({}));return e.outcome===`destroyed`||e.outcome===`already_absent`?e.outcome:`unknown`}let a=(await i.text()).trim();throw Error(`Sandbox cleanup failed for ${n} (HTTP ${i.status})${a?`: ${a}`:``}`)}async function X(e,t){if(e.status!==`stopped`)return e;let n=t?.resumeTimeoutMs??12e4;V(`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 Pi=[`anthropic`,`openai`,`vercel-ai`,`mastra`,`mcp-local`,`claude-desktop`,`cursor`,`zed`];function Fi(e,t,n){switch(e){case`anthropic`:return`// pnpm add @anthropic-ai/sdk @tangle-network/sandbox
5
3
  import Anthropic from "@anthropic-ai/sdk";
6
4
  import { Sandbox } from "@tangle-network/sandbox";
7
5
  import { anthropicTools } from "@tangle-network/sandbox/agent";
@@ -121,37 +119,40 @@ await connect(new StdioServerTransport());`;case`claude-desktop`:return`// Add t
121
119
  }
122
120
  }
123
121
  }
124
- }`}}function Jr(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 Yr(){return new x(`connect`).description(`Print a copy-paste SDK integration snippet for one of: ${Kr.join(`, `)} (to stream a local agent's telemetry to Intelligence, see 'tangle connect')`).argument(`<framework>`,Kr.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)=>{Kr.includes(e)||(console.error(b.red(`unknown framework: ${e}`),`\nsupported: ${Kr.join(`, `)}`),process.exit(2));let n=e;process.stdout.write(b.cyan(`# ${Jr(n)}\n\n`)),process.stdout.write(`${qr(n,t.sandbox,t.session)}\n`)})}async function Xr(e,t=!1,n){n?.throwIfAborted();let r=t?new Oe({write(e,t,n){n()}}):process.stderr,i=De({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(`
125
- `)}}async function Zr(e){let t=await Xr(e,!0);if(t===void 0)throw Error(`No answer on stdin.`);return t}async function Qr(e,t){let n=await Xr(e);if(n===void 0)throw process.stderr.write(`
126
- `),Error(t?`No answer on stdin. Pass ${t} to skip the confirmation.`:`No answer on stdin.`);return[`y`,`yes`].includes(n.toLowerCase())}async function $r(e,t,n){let r=await Xr(`${e}${t?` [${t}]`:``}: `,!1,n);if(r===void 0)throw Error(`No answer on stdin.`);return r||t||``}async function ei(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 ke(process.stdin)).toString(`utf8`).replace(/\r?\n$/,``)}function ti(){let e=new x(`profile`).description(`Create, inspect, and validate portable agent profiles`);return e.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(e,t)=>{let n=t.name,r=t.description,i=t.harness,a=t.model,o=t.systemPrompt,s=t.skills??[],c=t.tools??[];if(!n&&process.stdin.isTTY&&(n=await $r(`Profile name`,`my-agent`),r=await $r(`Description (optional)`)||void 0,i=await $r(`Harness`,`claude-code`)||void 0,a=await $r(`Model (optional, provider/model)`)||void 0,o=await $r(`System prompt (optional)`)||void 0,s=await ni(`Skill ref (local path or github:..., blank to finish)`),c=await ni(`Tool ref (blank to finish)`)),!n)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 l=tn({model:a,systemPrompt:o,skills:s,tools:c}),u=rn({...n?{name:n}:{},...r?{description:r}:{},...l??{},...i?{harness:i}:{}},`new profile`);if(t.json){I(u);return}let d=e??`agent-profile.json`;fe(d,`${JSON.stringify(u,null,2)}\n`),R(`Wrote ${d}`),R(`Run it: tangle agent prompt <box> --profile ${d}${i?` --harness ${i}`:``}`)}),e.command(`show <source>`).description(`Load and print a profile (local path, https URL, or github:owner/repo/path[@ref])`).action(async e=>{try{I(await nn(e))}catch(e){U(e,!0)}}),e.command(`validate <source>`).description(`Validate a profile against the canonical AgentProfile schema`).action(async(e,t)=>{let n=await nn(e),r=typeof n.name==`string`?n.name:`(unnamed)`;t.json?I({ok:!0,name:r}):R(`Profile valid: "${r}"`)}),e}async function ni(e){let t=[];for(;;){let n=await $r(e);if(!n)break;t.push(n)}return t}function ri(e){return(process.env.TANGLE_SANDBOX_WEB_URL?.trim()||e).replace(/\/+$/,``)}function ii(e,t){if(process.exitCode=1,e.status===`blocked_on_approval`){console.error(b.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(b.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(b.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(b.yellow(`⚠ Agent is awaiting a plan decision.`)),console.error(`Approve or reject the pending plan before continuing.`);return}console.error(b.red(`✗ ${e.error&&e.error.length>0?e.error:t}`))}function ai(e){let t=e.part;if(t?.type===`text`)return t.text??t.content??void 0}function oi(e){return e.finalText??e.response??e.output??e.content??e.text??void 0}function si(e){if(!e.result.success){ii(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(b.green(`✓ Done`),b.dim(`(${r.join(`, `)})`))}async function ci(e,t,n=!0){let r=``,i,a=m(),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=ai(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=oi(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 li(e){let t=Er(e??[]);if(t.length!==0)return{profile:{connections:t}}}function ui(e,t,n,r,i,a){let o={...r??{},harness:n,...i?{model:{...r?.model??{},default:i}}:{}},s={profile:o,requestedProfileDigest:ne(o),initialPrompt:a};return{...s,run:D({provider:`tangle-sandbox`,environmentId:e,sessionId:t,executionId:`interactive-execution-${t}`},s)}}async function di(e){let t=Er(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 q({hubKey:e.hubKey});for(let r of t){let t=await n.permissions.allowWrites(r.connectionId);e.json||R(`Allowed ${t.writeActions} write action${t.writeActions===1?``:`s`} for connection ${r.connectionId} (${t.granted} newly granted).`)}e.json||R(`Revert anytime: ${t.map(e=>`tangle hub permissions revert-writes --connection ${e.connectionId}`).join(` · `)}`)}async function fi(e){!e.connection||e.connection.length===0||(e.connection=await Tr(e.connection,()=>q({hubKey:e.hubKey})))}async function pi(e,t){let n=process.stdin,r=process.stdout,i=null,a=!1,o=!1,s,c=new Promise(e=>{s=e}),l=()=>{try{n.setRawMode(!1)}catch{}n.pause()},u=()=>{a||(a=!0,l(),n.off(`data`,p),process.off(`SIGWINCH`,f),process.off(`SIGINT`,d),process.off(`SIGTERM`,d),process.off(`exit`,l),s())},d=e=>{(i?.close()??Promise.resolve()).finally(()=>{u(),process.exit(e===`SIGTERM`?143:130)})},f=()=>{i?.isOpen&&i.resize(r.columns||80,r.rows||24)},p=e=>{if(!i)return;let t=e.indexOf(29);if(t===-1){i.write(e);return}t>0&&i.write(e.subarray(0,t)),i.close().finally(u)};if(i=await e.attach({cols:r.columns||80,rows:r.rows||24,handlers:{onData:e=>{r.write(Buffer.from(e.buffer,e.byteOffset,e.byteLength))},onExit:e=>{o=!0;let t=e.exitCode===void 0?``:` (code ${e.exitCode})`;r.write(`\r\n[interactive session exited${t}]\r\n`),i?.close().finally(u)},onError:e=>{r.write(`\r\n[terminal stream error: ${e.message}]\r\n`)},onClose:()=>u()}}),n.setRawMode(!0),n.resume(),n.on(`data`,p),process.on(`SIGWINCH`,f),process.on(`SIGINT`,d),process.on(`SIGTERM`,d),process.on(`exit`,l),await c,console.log(),o){R(`Interactive session ended.`);return}R(`Detached — the session keeps running.`),B({"Watch & drive":t})}function mi(){let e=new x(`agent`).description(`Interact with AI agent`);return e.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>`.",wr,[]).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(e,t,n)=>{let r=t===void 0?e:t,i=t===void 0?Xn(n.box):e,{context:a,client:o}=K(n),s=await on({profileSource:n.profile,systemPrompt:n.systemPrompt,skills:n.skills,tools:n.tools});await fi(n);let c=li(n.connection);n.allowWrites&&await di(n);let l=s||c?{...s,...c?.profile}:void 0,u=n.harness,d=l||u||n.model?{...u?{type:u}:{},...l?{profile:l}:{},...n.model?{model:{model:n.model}}:{}}:void 0,f=await J(o,a,i);if(f=await Y(f),n.interactive){let e=n.session??`int-${w()}`,t=u??(await f.backend.status()).type,i=ui(f.id,e,t,l,n.model,r),o=f.session(e).interactive(),s=z(`Starting interactive ${t} session...`);s.start();let c;try{c=await o.start(i)}finally{s.stop()}let d=c.ref.preparationReceipt.harness,p=c.state===`running`?c.streamUrl:void 0,m=`${ri(a.baseUrl)}/dashboard/sandbox/${encodeURIComponent(f.id)}?interactive=${encodeURIComponent(c.ref.run.sessionId)}`;if(n.json){I({state:c.state,sessionId:c.ref.run.sessionId,harness:d,...p?{streamUrl:p}:{},webUrl:m});return}if(R(`Interactive ${d} session ${c.state}.`),console.log(),B({...c.state===`running`?{"Watch & drive":m}:{},Session:c.ref.run.sessionId}),console.log(),c.state===`exited`){R(`The initial prompt completed with reason: ${c.reason}.`);return}R(`Open the link to watch the agent and type to take over.`),process.stdin.isTTY===!0&&process.stdout.isTTY===!0&&(console.log(),R(`Attaching to the live session — press Ctrl-] to detach.`),await pi(o,m));return}if(n.stream){n.json||(R(`Streaming response...`),console.log());let e=Date.now(),t=await ci(f.streamPrompt(r,{sessionId:n.session,timeoutMs:Number.parseInt(n.timeout,10),...d?{backend:d}:{}}),e,!n.json);n.json?(I({...t.outcome.result,...t.response?{response:t.response}:{},...t.outcome.tokenUsage?{tokenUsage:t.outcome.tokenUsage}:{},durationMs:Date.now()-e}),t.outcome.result.success||(process.exitCode=1)):(t.printed>0&&console.log(),si(t.outcome))}else{let e=z(`Processing prompt...`);e.start();let t=await f.prompt(r,{sessionId:n.session,timeoutMs:Number.parseInt(n.timeout,10),...d?{backend:d}:{}});e.stop(),n.json?(I(t),t.success===!1&&(process.exitCode=1)):t.success===!1?ii(t,`Agent prompt failed`):(console.log(t.response),console.log(),B({Duration:`${t.durationMs}ms`,"Input Tokens":t.usage?.inputTokens,"Output Tokens":t.usage?.outputTokens}))}}),e.addCommand(Yr()),e.addCommand(ti()),e}async function hi(e){let t=e.timeoutMs??1e4,n=e.baseUrl.replace(/\/$/,``),a=`${n}/v1/account/me`;try{let n=await fetch(a,{headers:{Accept:`application/json`,Authorization:`Bearer ${e.apiKey}`},signal:AbortSignal.timeout(t)});if(!n.ok){let e=await _i(n);throw n.status===401||n.status===403?new r(e||`Invalid API key`):n.status>=500?new u(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 r||e instanceof u||e instanceof f?e:e instanceof Error&&e.name===`AbortError`?new f(`Timed out validating credentials against ${n}`,{timeoutMs:t}):e instanceof Error&&!(e instanceof TypeError)?e:new i(`Failed to reach ${n}`,{cause:gi(e)})}}function gi(e){return e instanceof Error?e:void 0}async function _i(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 vi(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}function yi(e){if(!xi(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 bi(e){e.signal?.throwIfAborted();let t=e.timeoutMs??12e4,n=e.baseUrl.replace(/\/$/,``),r=await import(`node:http`),i=te(32).toString(`hex`),a=null,o=null,s=new Promise((e,t)=>{a=e,o=t}),c=r.createServer((e,t)=>{try{let n=yi({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(Ti(`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(Ti(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(Ti(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(Ti(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 wi(o.toString());e.onLoginUrl?.({loginUrl:o.toString(),browserOpened:l});let u=await Ci({baseUrl:n,grantToken:await Si(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 xi(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 Si(e,t,n){let r=new AbortController;try{return await Promise.race([e,Ae(t,void 0,{signal:AbortSignal.any([r.signal,...n?[n]:[]])}).then(()=>{throw new f(`Timed out waiting for browser login to complete`,{timeoutMs:t})})])}finally{r.abort()}}async function Ci(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 i(`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 wi(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 Ti(e){return`<!doctype html>
122
+ }`}}function Ii(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 Li(){return new S(`connect`).description(`Print a copy-paste SDK integration snippet for one of: ${Pi.join(`, `)} (to stream a local agent's telemetry to Intelligence, see 'tangle connect')`).argument(`<framework>`,Pi.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)=>{Pi.includes(e)||(console.error(b.red(`unknown framework: ${e}`),`\nsupported: ${Pi.join(`, `)}`),process.exit(2));let n=e;process.stdout.write(b.cyan(`# ${Ii(n)}\n\n`)),process.stdout.write(`${Fi(n,t.sandbox,t.session)}\n`)})}async function Ri(e,t=!1,n){n?.throwIfAborted();let r=t?new Fe({write(e,t,n){n()}}):process.stderr,i=Pe({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 zi(e){let t=await Ri(e,!0);if(t===void 0)throw Error(`No answer on stdin.`);return t}async function Bi(e,t){let n=await Ri(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 Vi(e,t,n){let r=await Ri(`${e}${t?` [${t}]`:``}: `,!1,n);if(r===void 0)throw Error(`No answer on stdin.`);return r||t||``}async function Hi(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 Ie(process.stdin)).toString(`utf8`).replace(/\r?\n$/,``)}function Ui(){let e=new S(`profile`).description(`Create, inspect, and validate portable agent profiles`);return e.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(e,t)=>{let n=t.name,r=t.description,i=t.harness,a=t.model,o=t.systemPrompt,s=t.skills??[],c=t.tools??[];if(!n&&process.stdin.isTTY&&(n=await Vi(`Profile name`,`my-agent`),r=await Vi(`Description (optional)`)||void 0,i=await Vi(`Harness`,`claude-code`)||void 0,a=await Vi(`Model (optional, provider/model)`)||void 0,o=await Vi(`System prompt (optional)`)||void 0,s=await Wi(`Skill ref (local path or github:..., blank to finish)`),c=await Wi(`Tool ref (blank to finish)`)),!n)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 l=Gn({model:a,systemPrompt:o,skills:s,tools:c}),u=qn({...n?{name:n}:{},...r?{description:r}:{},...l??{},...i?{harness:i}:{}},`new profile`);if(t.json){z(u);return}let d=e??`agent-profile.json`;me(d,`${JSON.stringify(u,null,2)}\n`),V(`Wrote ${d}`),V(`Run it: tangle agent prompt <box> --profile ${d}${i?` --harness ${i}`:``}`)}),e.command(`show <source>`).description(`Load and print a profile (local path, https URL, or github:owner/repo/path[@ref])`).action(async e=>{try{z(await Kn(e))}catch(e){G(e,!0)}}),e.command(`validate <source>`).description(`Validate a profile against the canonical AgentProfile schema`).action(async(e,t)=>{let n=await Kn(e),r=typeof n.name==`string`?n.name:`(unnamed)`;t.json?z({ok:!0,name:r}):V(`Profile valid: "${r}"`)}),e}async function Wi(e){let t=[];for(;;){let n=await Vi(e);if(!n)break;t.push(n)}return t}function Gi(e){return(process.env.TANGLE_SANDBOX_WEB_URL?.trim()||e).replace(/\/+$/,``)}function Ki(e,t){if(process.exitCode=1,e.status===`blocked_on_approval`){console.error(b.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(b.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(b.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(b.yellow(`⚠ Agent is awaiting a plan decision.`)),console.error(`Approve or reject the pending plan before continuing.`);return}console.error(b.red(`✗ ${e.error&&e.error.length>0?e.error:t}`))}function qi(e){let t=e.part;if(t?.type===`text`)return t.text??t.content??void 0}function Ji(e){return e.finalText??e.response??e.output??e.content??e.text??void 0}function Yi(e){if(!e.result.success){Ki(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(b.green(`✓ Done`),b.dim(`(${r.join(`, `)})`))}async function Xi(e,t,n=!0){let r=``,i,a=m(),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=qi(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=Ji(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 Zi(e){let t=pi(e??[]);if(t.length!==0)return{profile:{connections:t}}}function Qi(e,t,n,r,i,a){let o={...r??{},harness:n,...i?{model:{...r?.model??{},default:i}}:{}},s={profile:o,requestedProfileDigest:re(o),initialPrompt:a};return{...s,run:te({provider:`tangle-sandbox`,environmentId:e,sessionId:t,executionId:`interactive-execution-${t}`},s)}}async function $i(e){let t=pi(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 Oi({hubKey:e.hubKey});for(let r of t){let t=await n.permissions.allowWrites(r.connectionId);e.json||V(`Allowed ${t.writeActions} write action${t.writeActions===1?``:`s`} for connection ${r.connectionId} (${t.granted} newly granted).`)}e.json||V(`Revert anytime: ${t.map(e=>`tangle hub permissions revert-writes --connection ${e.connectionId}`).join(` · `)}`)}async function ea(e){!e.connection||e.connection.length===0||(e.connection=await fi(e.connection,()=>Oi({hubKey:e.hubKey})))}async function ta(e,t){let n=process.stdin,r=process.stdout,i=null,a=!1,o=!1,s,c=new Promise(e=>{s=e}),l=()=>{try{n.setRawMode(!1)}catch{}n.pause()},u=()=>{a||(a=!0,l(),n.off(`data`,p),process.off(`SIGWINCH`,f),process.off(`SIGINT`,d),process.off(`SIGTERM`,d),process.off(`exit`,l),s())},d=e=>{(i?.close()??Promise.resolve()).finally(()=>{u(),process.exit(e===`SIGTERM`?143:130)})},f=()=>{i?.isOpen&&i.resize(r.columns||80,r.rows||24)},p=e=>{if(!i)return;let t=e.indexOf(29);if(t===-1){i.write(e);return}t>0&&i.write(e.subarray(0,t)),i.close().finally(u)};if(i=await e.attach({cols:r.columns||80,rows:r.rows||24,handlers:{onData:e=>{r.write(Buffer.from(e.buffer,e.byteOffset,e.byteLength))},onExit:e=>{o=!0;let t=e.exitCode===void 0?``:` (code ${e.exitCode})`;r.write(`\r\n[interactive session exited${t}]\r\n`),i?.close().finally(u)},onError:e=>{r.write(`\r\n[terminal stream error: ${e.message}]\r\n`)},onClose:()=>u()}}),n.setRawMode(!0),n.resume(),n.on(`data`,p),process.on(`SIGWINCH`,f),process.on(`SIGINT`,d),process.on(`SIGTERM`,d),process.on(`exit`,l),await c,console.log(),o){V(`Interactive session ended.`);return}V(`Detached — the session keeps running.`),U({"Watch & drive":t})}function na(){let e=new S(`agent`).description(`Interact with AI agent`);return e.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>`.",di,[]).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(e,t,n)=>{let r=t===void 0?e:t,i=t===void 0?zr(n.box):e,{context:a,client:o}=J(n),s=await Yn({profileSource:n.profile,systemPrompt:n.systemPrompt,skills:n.skills,tools:n.tools});await ea(n);let c=Zi(n.connection);n.allowWrites&&await $i(n);let l=s||c?{...s,...c?.profile}:void 0,u=n.harness,d=l||u||n.model?{...u?{type:u}:{},...l?{profile:l}:{},...n.model?{model:{model:n.model}}:{}}:void 0,f=await Y(o,a,i);if(f=await X(f),n.interactive){let e=n.session??`int-${E()}`,t=u??(await f.backend.status()).type,i=Qi(f.id,e,t,l,n.model,r),o=f.session(e).interactive(),s=H(`Starting interactive ${t} session...`);s.start();let c;try{c=await o.start(i)}finally{s.stop()}let d=c.ref.preparationReceipt.harness,p=c.state===`running`?c.streamUrl:void 0,m=`${Gi(a.baseUrl)}/dashboard/sandbox/${encodeURIComponent(f.id)}?interactive=${encodeURIComponent(c.ref.run.sessionId)}`;if(n.json){z({state:c.state,sessionId:c.ref.run.sessionId,harness:d,...p?{streamUrl:p}:{},webUrl:m});return}if(V(`Interactive ${d} session ${c.state}.`),console.log(),U({...c.state===`running`?{"Watch & drive":m}:{},Session:c.ref.run.sessionId}),console.log(),c.state===`exited`){V(`The initial prompt completed with reason: ${c.reason}.`);return}V(`Open the link to watch the agent and type to take over.`),process.stdin.isTTY===!0&&process.stdout.isTTY===!0&&(console.log(),V(`Attaching to the live session — press Ctrl-] to detach.`),await ta(o,m));return}if(n.stream){n.json||(V(`Streaming response...`),console.log());let e=Date.now(),t=await Xi(f.streamPrompt(r,{sessionId:n.session,timeoutMs:Number.parseInt(n.timeout,10),...d?{backend:d}:{}}),e,!n.json);n.json?(z({...t.outcome.result,...t.response?{response:t.response}:{},...t.outcome.tokenUsage?{tokenUsage:t.outcome.tokenUsage}:{},durationMs:Date.now()-e}),t.outcome.result.success||(process.exitCode=1)):(t.printed>0&&console.log(),Yi(t.outcome))}else{let e=H(`Processing prompt...`);e.start();let t=await f.prompt(r,{sessionId:n.session,timeoutMs:Number.parseInt(n.timeout,10),...d?{backend:d}:{}});e.stop(),n.json?(z(t),t.success===!1&&(process.exitCode=1)):t.success===!1?Ki(t,`Agent prompt failed`):(console.log(t.response),console.log(),U({Duration:`${t.durationMs}ms`,"Input Tokens":t.usage?.inputTokens,"Output Tokens":t.usage?.outputTokens}))}}),e.addCommand(Li()),e.addCommand(Ui()),e}async function ra(e){let t=e.timeoutMs??1e4,n=e.baseUrl.replace(/\/$/,``),a=`${n}/v1/account/me`;try{let n=await fetch(a,{headers:{Accept:`application/json`,Authorization:`Bearer ${e.apiKey}`},signal:AbortSignal.timeout(t)});if(!n.ok){let e=await aa(n);throw n.status===401||n.status===403?new r(e||`Invalid API key`):n.status>=500?new u(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 r||e instanceof u||e instanceof f?e:e instanceof Error&&e.name===`AbortError`?new f(`Timed out validating credentials against ${n}`,{timeoutMs:t}):e instanceof Error&&!(e instanceof TypeError)?e:new i(`Failed to reach ${n}`,{cause:ia(e)})}}function ia(e){return e instanceof Error?e:void 0}async function aa(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 oa(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`)}function sa(e){if(!la(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 ca(e){e.signal?.throwIfAborted();let t=e.timeoutMs??12e4,n=e.baseUrl.replace(/\/$/,``),r=await import(`node:http`),i=T(32).toString(`hex`),a=null,o=null,s=new Promise((e,t)=>{a=e,o=t}),c=r.createServer((e,t)=>{try{let n=sa({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(pa(`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(pa(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(pa(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(pa(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 fa(o.toString());e.onLoginUrl?.({loginUrl:o.toString(),browserOpened:l});let u=await da({baseUrl:n,grantToken:await ua(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 la(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 ua(e,t,n){let r=new AbortController;try{return await Promise.race([e,Le(t,void 0,{signal:AbortSignal.any([r.signal,...n?[n]:[]])}).then(()=>{throw new f(`Timed out waiting for browser login to complete`,{timeoutMs:t})})])}finally{r.abort()}}async function da(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 i(`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 fa(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 pa(e){return`<!doctype html>
127
125
  <html lang="en">
128
126
  <head>
129
127
  <meta charset="utf-8" />
130
128
  <title>Sandbox CLI Login</title>
131
129
  </head>
132
130
  <body>
133
- <p>${e?`Sandbox CLI login failed: ${vi(e)}`:`Sandbox CLI login complete. You can close this window.`}</p>
131
+ <p>${e?`Sandbox CLI login failed: ${oa(e)}`:`Sandbox CLI login complete. You can close this window.`}</p>
134
132
  </body>
135
- </html>`}const Ei=15*6e4,Di=`sandbox`;function Oi(e){return Number.isFinite(e)&&e>0?e:Ei}async function ki(e){let t=e.timeoutMs??Ei,n=Date.now(),r=await Ai({baseUrl:e.baseUrl,app:e.app??Di,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 f(`Timed out waiting for device authorization to complete`,{timeoutMs:t});let i=await ji({baseUrl:e.baseUrl,app:e.app??Di,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 Ai(e){let t=Oi(e.timeoutMs),n=e.app!==Di,r=await fetch(`${Mi(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 i(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),a=await r.json().catch(()=>null);if(!r.ok||!a?.success||!a.data?.device_code)throw Error(a?.error?.message||`Failed to start device login`);return a.data}async function ji(e){let t=Oi(e.timeoutMs),n=e.app!==Di,r=await fetch(`${Mi(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 i(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),a=await r.json().catch(()=>null);if(r.status===428&&a?.error?.code===`AUTHORIZATION_PENDING`)return{status:`pending`,intervalSeconds:typeof a.data?.interval==`number`&&a.data.interval>0?a.data.interval:5};if(!r.ok||!a?.success||!a.data?.api_key||!a.data.email)throw Error(a?.error?.message||`Failed to complete device authorization`);return{status:`approved`,data:{apiKey:a.data.api_key,email:a.data.email,name:a.data.name,tier:a.data.tier}}}function Mi(e){return e.replace(/\/$/,``)}async function Ni(e){let t=e.apiKey,n=Vi(e.app??`sandbox`),r=Hi(n,e.profile),i=Bi(e.provider),a=n===`solve`?dr(e.baseUrl):or(e.baseUrl,r),o=e.browser!==!1,s=(t,i)=>{Li({profile:r,apiKey:t,baseUrl:e.baseUrl?a:void 0,activate:n===`sandbox`}),br(),L(`Authenticated`),B({Profile:r,Email:i.email,Tier:i.tier,"Base URL":a}),R(Ri)};if(t&&!Bn(t)){It(`Invalid API key format. Keys should start with 'sk_' or 'sk-tan-'.`),process.exit(1);return}if(gn(),!t){let t=o&&n===`sandbox`,r=z(t?`Starting browser login...`:`Starting device login...`);r.start();let c;try{c=t?await bi({baseUrl:a,provider:i,signal:e.signal,onLoginUrl:({loginUrl:e,browserOpened:t})=>{r.stop(),R(t?`Browser login opened.`:`Open this URL to continue browser login:`),console.log(e)}}):await ki({baseUrl:a,app:n,provider:i,onInstructions:({userCode:e,verificationUrl:t,verificationUrlComplete:i})=>{r.stop(),R(`Complete login in a browser on any device:`),B({"Verification URL":t,"Verification URL (prefilled)":i,"Device Code":e}),n===`solve`&&o&&wi(i)}})}finally{r.stop()}s(c.apiKey,c);return}let c=z(`Validating credentials...`);c.start();let l=await hi({apiKey:t,baseUrl:a});c.stop(),s(t,l)}function Pi(){let e=new x(`auth`).description(`Manage authentication`);return e.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(Ni),e.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=Hi(Vi(e.app),e.profile);er(t),br(),L(`Logged out successfully.`),R(`Credentials removed for profile '${t}'.`)}),e.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 e=>{let t=Vi(e.app),n=Hi(t,e.profile),i=t===`solve`?rr(e.apiKey,n):nr(e.apiKey,n),a=t===`solve`?dr(e.baseUrl):or(e.baseUrl,n),o=t===`solve`?ar(e.apiKey,n):ir(e.apiKey,n);if(!i){if(e.json){I({authenticated:!1,reason:`missing_credentials`,profile:n,baseUrl:a,credentialSource:null});return}It(`Not authenticated`),R(`Run 'tangle auth login --profile ${n}' to authenticate.`),process.exit(1)}let s=e.json?null:z(`Checking credentials...`);s?.start();try{let r=await hi({apiKey:i,baseUrl:a}),c=t===`solve`?null:await Rr({...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.profile===void 0?{}:{profile:e.profile},sandboxBaseUrl:a});s?.stop();let l=c!==null&&!c.reachable&&c.refused,u=!l,d=c!==null&&!c.reachable&&!c.refused;if(e.json){I({authenticated:u,profile:n,baseUrl:a,credentialSource:o,account:r,...c?{sandbox:{authenticated:!0},platform:c}:{}}),u||process.exit(1);return}l?Lt(`Authenticated for sandbox only`):d?Lt(`Authenticated — the platform is unreachable right now`):L(`Authenticated`),B({Profile:n,Credentials:`configured`,"Base URL":a,Source:Ii(o),Email:r.email,Tier:r.tier,...c?{Platform:c.reachable?`reachable (${c.baseUrl})`:`UNREACHABLE — ${c.reason}`}:{}}),d&&R(`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.`),u||(R("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(t){s?.stop(),e.json&&(I({authenticated:!1,profile:n,baseUrl:a,credentialSource:o,error:t instanceof Error?t.message:String(t)}),process.exit(1)),t instanceof r?It(`Stored credentials are invalid.`):Lt(`Stored credentials found, but validation could not complete.`),B({Profile:n,Credentials:`configured`,"Base URL":a,Source:Ii(o),Error:t instanceof Error?t.message:String(t)}),process.exit(1)}}),e.addCommand(Fi()),e}function Fi(){let e=new x(`profiles`).description(`Manage CLI profiles`);return e.command(`list`).description(`List configured profiles`).action(e=>{let t=Zn();if(e.json){I(t);return}if(t.length===0){R(`No profiles found.`);return}Ht([`Profile`,`Active`,`Base URL`,`Credentials`,`Source`],t.map(e=>[e.name,e.active?`yes`:`no`,e.baseUrl,e.hasApiKey?`configured`:`none`,e.apiKeySource]))}),e.command(`use <name>`).description(`Set the active profile`).action(e=>{Wn(e);let t=Qn(e);L(`Active profile set to '${t.name}'.`),B({"Base URL":t.baseUrl,Credentials:t.credentialSource===`none`?`missing`:`configured`})}),e.command(`current`).description(`Show the active profile`).action(e=>{let t=Qn();if(e.json){I({name:t.name,active:t.active,baseUrl:t.baseUrl,credentialSource:t.credentialSource});return}B({Profile:t.name,"Base URL":t.baseUrl,Credentials:t.credentialSource===`none`?`missing`:`configured`,Source:Ii(t.credentialSource)})}),e}function Ii(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 Li(e){let t=$n(e.profile,{apiKey:e.apiKey,...e.baseUrl?{baseUrl:e.baseUrl}:{}});e.activate!==!1&&Wn(e.profile),Hn(e.baseUrl&&e.profile===`default`?{baseUrl:e.baseUrl}:{}),Ri=zi(e.profile,t)}let Ri=`Credentials updated.`;function zi(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 Bi(e){if(e===void 0||e===`github`||e===`google`||e===`microsoft`)return e;throw Error(`--provider must be one of: github, google, microsoft`)}function Vi(e){if(e===void 0||e===`sandbox`||e===`solve`)return e??`sandbox`;throw Error(`--app must be one of: sandbox, solve`)}function Hi(e,t){return Ln(e,t)}function Ui(){let e=new x(`backend`).description(`Manage sandbox AI agent backend`);return e.command(`status <sandboxId-or-name>`).description(`Get backend agent status`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching backend status...`);i.start();let a=await(await J(r,n,e)).backend.status();i.stop(),t.json?I(a):(R(`Backend Type: ${a.type}`),R(`Status: ${a.status}`),a.version&&R(`Version: ${a.version}`),a.error&&R(`Error: ${a.error}`),a.capabilities&&R(`Capabilities: ${JSON.stringify(a.capabilities)}`))}),e.command(`configure <sandboxId-or-name>`).description(`Update backend configuration`).option(`--model <model>`,`Model id (e.g. provider/model)`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Updating backend config...`);i.start();let a=await J(r,n,e),o=t.model?{model:t.model}:{};await a.backend.updateConfig(o),i.stop(),L(`Backend configuration updated`),t.json&&I(o)}),e.command(`mcp-status <sandboxId-or-name>`).description(`Get status of MCP servers`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching MCP status...`);i.start();let a=await(await J(r,n,e)).backend.getMcpStatus();if(i.stop(),t.json)I(a);else{let e=Object.entries(a);e.length===0?R(`No MCP servers configured`):F(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}])}}),e.command(`restart <sandboxId-or-name>`).description(`Restart the backend agent`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Restarting backend...`);i.start(),await(await J(r,n,e)).backend.restart(),i.stop(),L(`Backend restarted`)}),e}function Wi(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 Gi(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 Ki(e){let t=e.readFile??(e=>ue(e,`utf8`)),n=[];e.file&&n.push(...Gi(t(e.file)));for(let t of e.inline??[])n.push(Wi(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 qi=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function Ji(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 Yi(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(!qi.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 Xi(e,t){if(!e||e.length===0)throw Error(`No backends provided. Use --backend id=type or --request <file>.`);let n=e.map(Yi),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:Ji(t)}),n}function Zi(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`--request file is not valid JSON: ${e.message}`)}try{return y(t)}catch(e){throw Error(`--request file is not a valid batch request: ${e.message}`)}}function Qi(e,t,n){return n?`${e} [${t}]`:e}function $i(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 ea(){let e=new x(`batch`).description(`Run multiple agent tasks in parallel across sandboxes`);return e.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(e,t)=>{let n=new AbortController,r=!1,i=()=>{r||(r=!0,R(`Cancel requested — stopping stream...`),n.abort())};process.on(`SIGINT`,i),process.on(`SIGTERM`,i);try{let r;if(e.request){let n=[`tasks`,`task`,`backend`,`model`,`timeout`,`persistent`,`reuseKey`].filter(e=>t.getOptionValueSource(e)===`cli`);if(n.length>0){let e={reuseKey:`reuse-key`};throw Error(`--request cannot be combined with ${n.map(t=>`--${e[t]??t}`).join(`, `)}`)}r=Zi(ue(e.request,`utf8`))}else{let t=Ki({file:e.tasks,inline:e.task}),n=Xi(e.backend,e.model),i=Number(e.timeout);if(!Number.isInteger(i)||i<=0)throw Error(`--timeout must be a positive integer number of milliseconds`);let a=!!e.persistent;if(a&&!e.reuseKey)throw Error(`--persistent requires --reuse-key`);if(!a&&e.reuseKey)throw Error(`--reuse-key requires --persistent`);r=y({tasks:t,timeoutMs:i,backends:n,...a?{persistent:!0,reuseKey:e.reuseKey}:{persistent:!1}})}let{tasks:i,backends:a}=r,{client:o}=K(e),s={signal:n.signal,replayOnly:!!e.replayOnly,...e.idempotencyKey?{idempotencyKey:e.idempotencyKey}:{}},c;if(e.stream){let t=e.json?console.error:console.log;R(`Streaming batch of ${i.length} task(s)...`),t();let n=o.streamBatch(r,s),l=a.length>1;for(;;){let e=await n.next();if(e.done){c=e.value;break}let r=e.value;switch(r.type){case`batch.started`:{let e=r.data;R(`Batch started (${e.taskCount} tasks, ${e.backendCount} backends)`);break}case`task.started`:{let e=r.data;t(b.dim(`→ ${Qi(e.taskId,e.backendId,l)} started`));break}case`task.retry`:{let e=r.data;t(b.yellow(`↻ ${Qi(e.taskId,e.backendId,l)} retry ${e.attempt}: ${e.error}`));break}case`task.completed`:{let e=r.data;t(b.green(`✓ ${Qi(e.taskId,e.backendId,l)} completed in ${e.durationMs}ms`+(e.retries?` (${e.retries} retries)`:``)));break}case`task.failed`:{let e=r.data;t(b.red(`✗ ${Qi(e.taskId,e.backendId,l)} failed: ${e.error}`));break}}}t()}else R(`Running batch of ${i.length} task(s)...`),c=await o.runBatch(r,s),e.json||console.log();if(e.json)I(c);else if(B({"Total tasks":c.totalTasks,"Total backends":c.totalBackends,"Total executions":c.totalExecutions,Succeeded:c.totalSuccess,Failed:c.totalFailure,"Total retries":c.totalRetries,"Success rate":`${c.successRate.toFixed(1)}%`}),!e.stream&&c.results.length>0){let e=$i(c.results);console.log(),console.log(b.bold(`Task Results`)),console.log(b.dim(`─`.repeat(40)));for(let t of c.results){let n=t.success?b.green(`✓`):b.red(`✗`),r=t.success?t.usage.inputTokens+t.usage.outputTokens:0,i=r>0?` • ${r} tokens`:``;console.log(`${n} ${Qi(t.taskId,t.backendId,e.has(t.taskId))} ${b.dim(`(${t.durationMs}ms, ${t.retries} retries${i})`)}`),t.success||console.log(b.red(` ${t.error}`))}}c.totalFailure>0&&(process.exitCode=1)}catch(t){let n=t instanceof Error&&`batchCustody`in t?t.batchCustody:void 0;if(n?.acceptance===`accepted`&&!(n.cleanup?.mode===`release`&&n.cleanup.isComplete)&&R(`Batch accepted; retirement receipt unproved.`),r){console.log(),R(`Batch cancelled.`),e.json&&t instanceof Error&&`batchCustody`in t&&I({ok:!1,batchCustody:t.batchCustody}),process.exitCode=130;return}U(t,e.json)}finally{process.off(`SIGINT`,i),process.off(`SIGTERM`,i)}}),e}function ta(){let e=new x(`branch`).description(`Branch a running sandbox into copy-on-write children`);return e.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(e,t)=>{let n=Number.parseInt(t.count,10);if(!Number.isInteger(n)||n<1)throw Error(`--count must be an integer >= 1 (got ${t.count})`);let{context:r,client:i}=K(t),a=z(`Branching into ${n} child(ren)...`);a.start();let o=await J(i,r,e),s=await o.fork(n,{...t.idempotencyKey?{idempotencyKey:t.idempotencyKey}:{}}),c=s.children;a.stop(),t.json?I({children:c.map(e=>({sandboxId:e.id})),requestedCount:s.requestedCount,materializedCount:s.materializedCount,complete:s.complete,...s.idempotency?{idempotency:s.idempotency}:{}}):(s.complete?L(`Branched ${c.length} child(ren) from ${o.id}`):Lt(`Branched ${s.materializedCount} of ${s.requestedCount} requested child(ren) from ${o.id}`),s.idempotency?.outcome===`replayed`&&R(`Replayed an earlier fan-out under this key; created none.`),F(c.map(e=>({sandboxId:e.id})),[{key:`sandboxId`,header:`Child Sandbox`,width:28}]))}),e}const na=[`codex`,`claude-code`,`nanoclaw`,`kimi-code`,`opencode`,`pi`,`openclaw`,`hermes`],ra=`https://intelligence.tangle.tools/v1/otlp`,ia=[`codex`,`claude-code`],aa=[`codex`,`claude-code`,`nanoclaw`],oa=[`SessionStart`,`UserPromptSubmit`,`PreToolUse`,`PostToolUse`,`Stop`],sa={codex:{kind:`native`,surface:`codex`,label:`Codex`,buildFiles:xa},"claude-code":{kind:`native`,surface:`claude-code`,label:`Claude Code`,buildFiles:Sa},nanoclaw:{kind:`native`,surface:`nanoclaw`,label:`NanoClaw`,buildFiles:Sa},"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 ca(e){let t=e.split(`,`).map(e=>e.trim()).filter(Boolean).flatMap(e=>ba(e));return t.length===0?[...ia]:Fa(t)}function la(e){return Object.hasOwn(sa,e)}function ua(e=process.cwd()){return pe(ve(e))||`agent-workspace`}function da(){return j(M(),`.tangle`,`intelligence.json`)}function fa(e=da()){if(!ce(e))return null;let t=Ma(e),n=Ia(t,`apiKey`),r=Ia(t,`endpoint`),i=Ia(t,`serviceName`),a=Ia(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 pa(e){let t=ve(e.workspace),n=da(),r=ca(e.selection),i=[],a=[],o=[],s={apiKey:e.apiKey,endpoint:ya(e.endpoint),serviceName:e.serviceName,environment:e.environment};e.dryRun||ka(n,s),o.push(n);for(let n of r){let r=sa[n];if(r.kind===`manual`){a.push({agent:r.surface,label:r.label,reason:r.reason});continue}i.push(r.surface);let s=t=>ma(e.hookCommand,r.surface,t);for(let n of r.buildFiles(s)){let r=j(t,n.relPath);if(e.dryRun){o.push(r);continue}ja(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 ga({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 ma(e,t,n){return`${e.trim()} --agent ${t} --event ${n} --non-blocking`}function ha(e){let t=BigInt(Date.now())*1000000n,n=Ra(16),r=Ra(8),i=e.sessionId??Ca(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`,...wa(e.payload)};return i&&(a[`session.id`]=i,a[`gen_ai.conversation.id`]=i,a[`tangle.sessionId`]=i),{body:{resourceSpans:[{resource:{attributes:[za(`service.name`,e.serviceName),za(`deployment.environment`,e.environment),za(`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])=>za(e,t)),status:{code:1}}]}]}]},traceId:n}}async function ga(e){let{body:t,traceId:n}=ha(e),r=await fetch(`${ya(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 _a(e){return ya(e).replace(/\/v1\/otlp$/,``).replace(/\/+$/,``)}async function va(e){let t=`${_a(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 ya(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 ba(e){switch(e){case`local`:case`both`:return[...ia];case`all`:return[...aa];case`claude`:return[`claude-code`];case`kimi`:return[`kimi-code`];default:if(la(e))return[e];throw Error(`agent must be one of: local, all, both, ${na.join(`, `)}`)}}function xa(e){let t=Object.fromEntries(oa.map(t=>[t,[{command:e(t),timeoutMs:3e3,blocking:!1,matcher:`*`}]]));return[{relPath:`.codex/hooks.json`,content:JSON.stringify({hooks:t},null,2)}]}function Sa(e){let t=Object.fromEntries(oa.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 Ca(e){return Ea(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 wa(e){let t={},n=Ta(e,[`tool.name`,`toolName`,`tool_name`,`tool`]),r=Ta(e,[`command`,`cmd`,`shell_command`,`shellCommand`]),i=Ta(e,[`tool.input`,`toolInput`,`tool_input`,`input`,`arguments`,`args`]),a=Ta(e,[`tool.output`,`toolOutput`,`tool_output`,`output`,`result`]),o=Ta(e,[`tool.exit_code`,`exitCode`,`exit_code`,`status`]),s=Ta(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 Ta(e,t){let n=Da(e,t);if(n===void 0)return null;if(typeof n==`string`)return Oa(n);if(typeof n==`number`||typeof n==`boolean`||typeof n==`bigint`)return String(n);try{return Oa(JSON.stringify(n))}catch{return null}}function Ea(e,t){let n=Da(e,t);return typeof n==`string`&&n.length>0?n:void 0}function Da(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 Oa(e){return e.length>4096?`${e.slice(0,4093)}...`:e}function ka(e,t){Aa(e,`${JSON.stringify(t,null,2)}\n`)}function Aa(e,t){le(me(e),{mode:448,recursive:!0});let n=`${e}.${process.pid}.tmp`;fe(n,t,{mode:384}),de(n,e)}function ja(e,t,n){le(me(e),{recursive:!0});let r=Na(Ma(e),t);fe(e,`${JSON.stringify(r,null,2)}\n`,{mode:n??420})}function Ma(e){if(!ce(e))return{};let t=JSON.parse(ue(e,`utf8`));if(!La(t))throw Error(`${e} must contain a JSON object`);return t}function Na(e,t){let n={...e};for(let[e,r]of Object.entries(t)){let t=n[e];La(t)&&La(r)?n[e]=Na(t,r):Array.isArray(t)&&Array.isArray(r)?n[e]=Pa([...t,...r]):n[e]=r}return n}function Pa(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 Fa(e){return[...new Set(e)]}function Ia(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function La(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&(Object.getPrototypeOf(e)===Object.prototype||Object.getPrototypeOf(e)===null)}function Ra(e){return te(e).toString(`hex`)}function za(e,t){return{key:e,value:{stringValue:t}}}const Ba=`tangle.opencode-exporter`,Va=16384;function Ha(e){return e.length<=Va?e:`${e.slice(0,Va-1)}…`}function Ua(e,t){return{key:e,value:{stringValue:t}}}function Wa(e){if(!e||typeof e!=`object`)return null;let t=e,n=Le(t.type);return n?{type:n,properties:t.properties&&typeof t.properties==`object`?t.properties:void 0}:null}function Ga(e,t){let n=[Ua(`event.name`,e),Ua(`gen_ai.system`,`opencode`),Ua(`service.name`,`opencode`)];return t&&(n.push(Ua(`session.id`,t)),n.push(Ua(`gen_ai.conversation.id`,t))),n}function Ka(e){if(!e)return null;let t=e.part,n=e.info;return Le(t?.sessionID)??Le(n?.sessionID)??Le(e.sessionID)??null}function qa(e,t){let n=Le(e.role)??Le(e.info?.role);if(n)return n.toLowerCase();let r=Le(e.messageID),i=t?.(r)??null;return i?i.toLowerCase():null}function Ja(e,t,n){let r=[],i=Ka(e.properties),a=(n,r)=>({timeUnixNano:t,severityNumber:9,severityText:`INFO`,...n===null?{}:{body:{stringValue:Ha(n)}},attributes:[...Ga(e.type,i),...r]});if(e.type===`message.part.updated`){let t=e.properties?.part;if(!t)return r;let i=Le(t.type);if(i===`text`||i===`reasoning`){let e=Le(t.text);if(e){let i=qa(t,n)===`user`?Me:je;r.push(a(e,[Ua(i,Ha(e))]))}return r}if(i===`tool`){let e=Le(t.tool),n=t.state,i=Re(n?.input),o=Re(n?.output),s=Le(n?.error)??(typeof n?.error==`object`&&n?.error!==null?Re(n.error):null);if(e||i){let t=[];e&&t.push(Ua(Pe,e)),i&&t.push(Ua(Ne,Ha(i))),r.push(a(null,t))}let c=o??s;if(c){let t=[Ua(Fe,Ha(c))];e&&t.push(Ua(Pe,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=Le(t.text)??(e.type===`session.next.text.delta`?Le(t.delta):null);return n&&r.push(a(n,[Ua(je,Ha(n))])),r}return r}function Ya(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()!==Ie)continue;let n=t.slice(e+1).trim();if(n.length>0)return n}return null}function Xa(e,t){if(e.length===0)return null;let n=[Ua(`service.name`,`opencode`),Ua(`gen_ai.system`,`opencode`),Ua(`telemetry.sdk.name`,Ba)];return t&&t.trim().length>0&&n.push(Ua(Ie,t.trim())),{resourceLogs:[{resource:{attributes:n},scopeLogs:[{scope:{name:Ba,version:`1.0.0`},logRecords:e}]}]}}function Za(e){return(e??process.env.OPENCODE_BASE_URL??`http://127.0.0.1:4096`).replace(/\/+$/,``)}async function Qa(e){let t=ya(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 $a=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 eo(){return(BigInt(Date.now())*1000000n).toString()}async function to(e){let t=Za(e.opencodeBaseUrl),n=e.nowUnixNano??eo,r=e.fetchImpl??fetch,i=e.subjectKey===void 0?Ya():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 v(a.body,{signal:e.signal})){o.eventsSeen++;let a=Wa(t.data);if(!a)continue;if(a.type===`message.updated`){let e=a.properties?.info,t=Le(e?.id),n=Le(e?.role);t&&n&&s.set(t,n);continue}let l=Ja(a,n(),c),u=Xa(l,i);u&&(await Qa({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 $a(e,o)}return o}function no(e,t){let n=Number(e);if(!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}const ro=[`claude-code`,`codex`,`opencode`,`openclaw`,`hermes`,`nanoclaw`],io={"claude-code":`Claude Code`,codex:`Codex`,opencode:`OpenCode`,openclaw:`OpenClaw`,hermes:`Hermes`,nanoclaw:`NanoClaw`};function ao(e){return ro.includes(e)}function oo(e){return ce(e)?ue(e,`utf8`):``}function so(e,t){le(me(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;fe(n,t,{mode:384}),oe(n,384),de(n,e)}const co=`# >>> tangle intelligence (claude-code) >>>`,lo=`# <<< tangle intelligence (claude-code) <<<`,uo={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 fo(e,t){return t===`env`?e:/\s/.test(e)?`"${e}"`:e}function po(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}=${fo(i.value,t)}${e}`)}return r.join(`
136
- `)}function mo(e){let t=ya(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=uo[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 po(a,i)}function ho(e){return[co,mo(e),lo].join(`
137
- `)}function go(e,t){let n=e.indexOf(co);if(n!==-1){let r=e.indexOf(lo,n);if(r===-1)throw Error(`shell rc has a '${co}' marker without its closing '${lo}' — 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?``:_o(e)}${t}\n`,changed:!0}}function _o(e){return e.endsWith(`
133
+ </html>`}const ma=15*6e4,ha=`sandbox`;function ga(e){return Number.isFinite(e)&&e>0?e:ma}async function _a(e){let t=e.timeoutMs??ma,n=Date.now(),r=await va({baseUrl:e.baseUrl,app:e.app??ha,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 f(`Timed out waiting for device authorization to complete`,{timeoutMs:t});let i=await ya({baseUrl:e.baseUrl,app:e.app??ha,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 va(e){let t=ga(e.timeoutMs),n=e.app!==ha,r=await fetch(`${ba(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 i(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),a=await r.json().catch(()=>null);if(!r.ok||!a?.success||!a.data?.device_code)throw Error(a?.error?.message||`Failed to start device login`);return a.data}async function ya(e){let t=ga(e.timeoutMs),n=e.app!==ha,r=await fetch(`${ba(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 i(`Failed to reach ${e.baseUrl}`,{cause:t instanceof Error?t:void 0})}),a=await r.json().catch(()=>null);if(r.status===428&&a?.error?.code===`AUTHORIZATION_PENDING`)return{status:`pending`,intervalSeconds:typeof a.data?.interval==`number`&&a.data.interval>0?a.data.interval:5};if(!r.ok||!a?.success||!a.data?.api_key||!a.data.email)throw Error(a?.error?.message||`Failed to complete device authorization`);return{status:`approved`,data:{apiKey:a.data.api_key,email:a.data.email,name:a.data.name,tier:a.data.tier}}}function ba(e){return e.replace(/\/$/,``)}async function xa(e){let t=e.apiKey,n=ka(e.app??`sandbox`),r=Aa(n,e.profile),i=Oa(e.provider),a=n===`solve`?ei(e.baseUrl):Yr(e.baseUrl,r),o=e.browser!==!1,s=(t,i)=>{Ta({profile:r,apiKey:t,baseUrl:e.baseUrl?a:void 0,activate:n===`sandbox`}),li(),B(`Authenticated`),U({Profile:r,Email:i.email,Tier:i.tier,"Base URL":a}),V(Ea)};if(t&&!kr(t)){Tn(`Invalid API key format. Keys should start with 'sk_' or 'sk-tan-'.`),process.exit(1);return}if(ar(),!t){let t=o&&n===`sandbox`,r=H(t?`Starting browser login...`:`Starting device login...`);r.start();let c;try{c=t?await ca({baseUrl:a,provider:i,signal:e.signal,onLoginUrl:({loginUrl:e,browserOpened:t})=>{r.stop(),V(t?`Browser login opened.`:`Open this URL to continue browser login:`),console.log(e)}}):await _a({baseUrl:a,app:n,provider:i,onInstructions:({userCode:e,verificationUrl:t,verificationUrlComplete:i})=>{r.stop(),V(`Complete login in a browser on any device:`),U({"Verification URL":t,"Verification URL (prefilled)":i,"Device Code":e}),n===`solve`&&o&&fa(i)}})}finally{r.stop()}s(c.apiKey,c);return}let c=H(`Validating credentials...`);c.start();let l=await ra({apiKey:t,baseUrl:a});c.stop(),s(t,l)}function Sa(){let e=new S(`auth`).description(`Manage authentication`);return e.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(xa),e.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=Aa(ka(e.app),e.profile);Ur(t),li(),B(`Logged out successfully.`),V(`Credentials removed for profile '${t}'.`)}),e.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 e=>{let t=ka(e.app),n=Aa(t,e.profile),i=t===`solve`?Kr(e.apiKey,n):Gr(e.apiKey,n),a=t===`solve`?ei(e.baseUrl):Yr(e.baseUrl,n),o=t===`solve`?Jr(e.apiKey,n):qr(e.apiKey,n);if(!i){if(e.json){z({authenticated:!1,reason:`missing_credentials`,profile:n,baseUrl:a,credentialSource:null});return}Tn(`Not authenticated`),V(`Run 'tangle auth login --profile ${n}' to authenticate.`),process.exit(1)}let s=e.json?null:H(`Checking credentials...`);s?.start();try{let r=await ra({apiKey:i,baseUrl:a}),c=t===`solve`?null:await Ti({...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.profile===void 0?{}:{profile:e.profile},sandboxBaseUrl:a});s?.stop();let l=c!==null&&!c.reachable&&c.refused,u=!l,d=c!==null&&!c.reachable&&!c.refused;if(e.json){z({authenticated:u,profile:n,baseUrl:a,credentialSource:o,account:r,...c?{sandbox:{authenticated:!0},platform:c}:{}}),u||process.exit(1);return}l?En(`Authenticated for sandbox only`):d?En(`Authenticated — the platform is unreachable right now`):B(`Authenticated`),U({Profile:n,Credentials:`configured`,"Base URL":a,Source:wa(o),Email:r.email,Tier:r.tier,...c?{Platform:c.reachable?`reachable (${c.baseUrl})`:`UNREACHABLE — ${c.reason}`}:{}}),d&&V(`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.`),u||(V("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(t){s?.stop(),e.json&&(z({authenticated:!1,profile:n,baseUrl:a,credentialSource:o,error:t instanceof Error?t.message:String(t)}),process.exit(1)),t instanceof r?Tn(`Stored credentials are invalid.`):En(`Stored credentials found, but validation could not complete.`),U({Profile:n,Credentials:`configured`,"Base URL":a,Source:wa(o),Error:t instanceof Error?t.message:String(t)}),process.exit(1)}}),e.addCommand(Ca()),e}function Ca(){let e=new S(`profiles`).description(`Manage CLI profiles`);return e.command(`list`).description(`List configured profiles`).action(e=>{let t=Br();if(e.json){z(t);return}if(t.length===0){V(`No profiles found.`);return}jn([`Profile`,`Active`,`Base URL`,`Credentials`,`Source`],t.map(e=>[e.name,e.active?`yes`:`no`,e.baseUrl,e.hasApiKey?`configured`:`none`,e.apiKeySource]))}),e.command(`use <name>`).description(`Set the active profile`).action(e=>{Nr(e);let t=Vr(e);B(`Active profile set to '${t.name}'.`),U({"Base URL":t.baseUrl,Credentials:t.credentialSource===`none`?`missing`:`configured`})}),e.command(`current`).description(`Show the active profile`).action(e=>{let t=Vr();if(e.json){z({name:t.name,active:t.active,baseUrl:t.baseUrl,credentialSource:t.credentialSource});return}U({Profile:t.name,"Base URL":t.baseUrl,Credentials:t.credentialSource===`none`?`missing`:`configured`,Source:wa(t.credentialSource)})}),e}function wa(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 Ta(e){let t=Hr(e.profile,{apiKey:e.apiKey,...e.baseUrl?{baseUrl:e.baseUrl}:{}});e.activate!==!1&&Nr(e.profile),jr(e.baseUrl&&e.profile===`default`?{baseUrl:e.baseUrl}:{}),Ea=Da(e.profile,t)}let Ea=`Credentials updated.`;function Da(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 Oa(e){if(e===void 0||e===`github`||e===`google`||e===`microsoft`)return e;throw Error(`--provider must be one of: github, google, microsoft`)}function ka(e){if(e===void 0||e===`sandbox`||e===`solve`)return e??`sandbox`;throw Error(`--app must be one of: sandbox, solve`)}function Aa(e,t){return Er(e,t)}function ja(){let e=new S(`backend`).description(`Manage sandbox AI agent backend`);return e.command(`status <sandboxId-or-name>`).description(`Get backend agent status`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching backend status...`);i.start();let a=await(await Y(r,n,e)).backend.status();i.stop(),t.json?z(a):(V(`Backend Type: ${a.type}`),V(`Status: ${a.status}`),a.version&&V(`Version: ${a.version}`),a.error&&V(`Error: ${a.error}`),a.capabilities&&V(`Capabilities: ${JSON.stringify(a.capabilities)}`))}),e.command(`configure <sandboxId-or-name>`).description(`Update backend configuration`).option(`--model <model>`,`Model id (e.g. provider/model)`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Updating backend config...`);i.start();let a=await Y(r,n,e),o=t.model?{model:t.model}:{};await a.backend.updateConfig(o),i.stop(),B(`Backend configuration updated`),t.json&&z(o)}),e.command(`mcp-status <sandboxId-or-name>`).description(`Get status of MCP servers`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching MCP status...`);i.start();let a=await(await Y(r,n,e)).backend.getMcpStatus();if(i.stop(),t.json)z(a);else{let e=Object.entries(a);e.length===0?V(`No MCP servers configured`):R(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}])}}),e.command(`restart <sandboxId-or-name>`).description(`Restart the backend agent`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Restarting backend...`);i.start(),await(await Y(r,n,e)).backend.restart(),i.stop(),B(`Backend restarted`)}),e}function Ma(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 Na(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 Pa(e){let t=e.readFile??(e=>fe(e,`utf8`)),n=[];e.file&&n.push(...Na(t(e.file)));for(let t of e.inline??[])n.push(Ma(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 Fa=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function Ia(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 La(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(!Fa.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 Ra(e,t){if(!e||e.length===0)throw Error(`No backends provided. Use --backend id=type or --request <file>.`);let n=e.map(La),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:Ia(t)}),n}function za(e){let t;try{t=JSON.parse(e)}catch(e){throw Error(`--request file is not valid JSON: ${e.message}`)}try{return y(t)}catch(e){throw Error(`--request file is not a valid batch request: ${e.message}`)}}function Ba(e,t,n){return n?`${e} [${t}]`:e}function Va(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 Ha(){let e=new S(`batch`).description(`Run multiple agent tasks in parallel across sandboxes`);return e.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(e,t)=>{let n=new AbortController,r=!1,i=()=>{r||(r=!0,V(`Cancel requested — stopping stream...`),n.abort())};process.on(`SIGINT`,i),process.on(`SIGTERM`,i);try{let r;if(e.request){let n=[`tasks`,`task`,`backend`,`model`,`timeout`,`persistent`,`reuseKey`].filter(e=>t.getOptionValueSource(e)===`cli`);if(n.length>0){let e={reuseKey:`reuse-key`};throw Error(`--request cannot be combined with ${n.map(t=>`--${e[t]??t}`).join(`, `)}`)}r=za(fe(e.request,`utf8`))}else{let t=Pa({file:e.tasks,inline:e.task}),n=Ra(e.backend,e.model),i=Number(e.timeout);if(!Number.isInteger(i)||i<=0)throw Error(`--timeout must be a positive integer number of milliseconds`);let a=!!e.persistent;if(a&&!e.reuseKey)throw Error(`--persistent requires --reuse-key`);if(!a&&e.reuseKey)throw Error(`--reuse-key requires --persistent`);r=y({tasks:t,timeoutMs:i,backends:n,...a?{persistent:!0,reuseKey:e.reuseKey}:{persistent:!1}})}let{tasks:i,backends:a}=r,{client:o}=J(e),s={signal:n.signal,replayOnly:!!e.replayOnly,...e.idempotencyKey?{idempotencyKey:e.idempotencyKey}:{}},c;if(e.stream){let t=e.json?console.error:console.log;V(`Streaming batch of ${i.length} task(s)...`),t();let n=o.streamBatch(r,s),l=a.length>1;for(;;){let e=await n.next();if(e.done){c=e.value;break}let r=e.value;switch(r.type){case`batch.started`:{let e=r.data;V(`Batch started (${e.taskCount} tasks, ${e.backendCount} backends)`);break}case`task.started`:{let e=r.data;t(b.dim(`→ ${Ba(e.taskId,e.backendId,l)} started`));break}case`task.retry`:{let e=r.data;t(b.yellow(`↻ ${Ba(e.taskId,e.backendId,l)} retry ${e.attempt}: ${e.error}`));break}case`task.completed`:{let e=r.data;t(b.green(`✓ ${Ba(e.taskId,e.backendId,l)} completed in ${e.durationMs}ms`+(e.retries?` (${e.retries} retries)`:``)));break}case`task.failed`:{let e=r.data;t(b.red(`✗ ${Ba(e.taskId,e.backendId,l)} failed: ${e.error}`));break}}}t()}else V(`Running batch of ${i.length} task(s)...`),c=await o.runBatch(r,s),e.json||console.log();if(e.json)z(c);else if(U({"Total tasks":c.totalTasks,"Total backends":c.totalBackends,"Total executions":c.totalExecutions,Succeeded:c.totalSuccess,Failed:c.totalFailure,"Total retries":c.totalRetries,"Success rate":`${c.successRate.toFixed(1)}%`}),!e.stream&&c.results.length>0){let e=Va(c.results);console.log(),console.log(b.bold(`Task Results`)),console.log(b.dim(`─`.repeat(40)));for(let t of c.results){let n=t.success?b.green(`✓`):b.red(`✗`),r=t.success?t.usage.inputTokens+t.usage.outputTokens:0,i=r>0?` • ${r} tokens`:``;console.log(`${n} ${Ba(t.taskId,t.backendId,e.has(t.taskId))} ${b.dim(`(${t.durationMs}ms, ${t.retries} retries${i})`)}`),t.success||console.log(b.red(` ${t.error}`))}}c.totalFailure>0&&(process.exitCode=1)}catch(t){let n=t instanceof Error&&`batchCustody`in t?t.batchCustody:void 0;if(n?.acceptance===`accepted`&&!(n.cleanup?.mode===`release`&&n.cleanup.isComplete)&&V(`Batch accepted; retirement receipt unproved.`),r){console.log(),V(`Batch cancelled.`),e.json&&t instanceof Error&&`batchCustody`in t&&z({ok:!1,batchCustody:t.batchCustody}),process.exitCode=130;return}G(t,e.json)}finally{process.off(`SIGINT`,i),process.off(`SIGTERM`,i)}}),e}function Ua(){let e=new S(`branch`).description(`Branch a running sandbox into copy-on-write children`);return e.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(e,t)=>{let n=Number.parseInt(t.count,10);if(!Number.isInteger(n)||n<1)throw Error(`--count must be an integer >= 1 (got ${t.count})`);let{context:r,client:i}=J(t),a=H(`Branching into ${n} child(ren)...`);a.start();let o=await Y(i,r,e),s=await o.fork(n,{...t.idempotencyKey?{idempotencyKey:t.idempotencyKey}:{}}),c=s.children;a.stop(),t.json?z({children:c.map(e=>({sandboxId:e.id})),requestedCount:s.requestedCount,materializedCount:s.materializedCount,complete:s.complete,...s.idempotency?{idempotency:s.idempotency}:{}}):(s.complete?B(`Branched ${c.length} child(ren) from ${o.id}`):En(`Branched ${s.materializedCount} of ${s.requestedCount} requested child(ren) from ${o.id}`),s.idempotency?.outcome===`replayed`&&V(`Replayed an earlier fan-out under this key; created none.`),R(c.map(e=>({sandboxId:e.id})),[{key:`sandboxId`,header:`Child Sandbox`,width:28}]))}),e}const Wa=[`codex`,`claude-code`,`nanoclaw`,`kimi-code`,`opencode`,`pi`,`openclaw`,`hermes`],Ga=`https://intelligence.tangle.tools/v1/otlp`,Ka=[`codex`,`claude-code`],qa=[`codex`,`claude-code`,`nanoclaw`],Ja=[`SessionStart`,`UserPromptSubmit`,`PreToolUse`,`PostToolUse`,`Stop`],Ya={codex:{kind:`native`,surface:`codex`,label:`Codex`,buildFiles:lo},"claude-code":{kind:`native`,surface:`claude-code`,label:`Claude Code`,buildFiles:uo},nanoclaw:{kind:`native`,surface:`nanoclaw`,label:`NanoClaw`,buildFiles:uo},"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 Xa(e){let t=e.split(`,`).map(e=>e.trim()).filter(Boolean).flatMap(e=>co(e));return t.length===0?[...Ka]:wo(t)}function Za(e){return Object.hasOwn(Ya,e)}function Qa(e=process.cwd()){return he(be(e))||`agent-workspace`}function $a(){return M(N(),`.tangle`,`intelligence.json`)}function eo(e=$a()){if(!ue(e))return null;let t=xo(e),n=To(t,`apiKey`),r=To(t,`endpoint`),i=To(t,`serviceName`),a=To(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 to(e){let t=be(e.workspace),n=$a(),r=Xa(e.selection),i=[],a=[],o=[],s={apiKey:e.apiKey,endpoint:so(e.endpoint),serviceName:e.serviceName,environment:e.environment};e.dryRun||vo(n,s),o.push(n);for(let n of r){let r=Ya[n];if(r.kind===`manual`){a.push({agent:r.surface,label:r.label,reason:r.reason});continue}i.push(r.surface);let s=t=>no(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}bo(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 io({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 no(e,t,n){return`${e.trim()} --agent ${t} --event ${n} --non-blocking`}function ro(e){let t=BigInt(Date.now())*1000000n,n=Do(16),r=Do(8),i=e.sessionId??fo(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`,...po(e.payload)};return i&&(a[`session.id`]=i,a[`gen_ai.conversation.id`]=i,a[`tangle.sessionId`]=i),{body:{resourceSpans:[{resource:{attributes:[Oo(`service.name`,e.serviceName),Oo(`deployment.environment`,e.environment),Oo(`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])=>Oo(e,t)),status:{code:1}}]}]}]},traceId:n}}async function io(e){let{body:t,traceId:n}=ro(e),r=await fetch(`${so(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 ao(e){return so(e).replace(/\/v1\/otlp$/,``).replace(/\/+$/,``)}async function oo(e){let t=`${ao(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 so(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 co(e){switch(e){case`local`:case`both`:return[...Ka];case`all`:return[...qa];case`claude`:return[`claude-code`];case`kimi`:return[`kimi-code`];default:if(Za(e))return[e];throw Error(`agent must be one of: local, all, both, ${Wa.join(`, `)}`)}}function lo(e){let t=Object.fromEntries(Ja.map(t=>[t,[{command:e(t),timeoutMs:3e3,blocking:!1,matcher:`*`}]]));return[{relPath:`.codex/hooks.json`,content:JSON.stringify({hooks:t},null,2)}]}function uo(e){let t=Object.fromEntries(Ja.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 fo(e){return ho(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 po(e){let t={},n=mo(e,[`tool.name`,`toolName`,`tool_name`,`tool`]),r=mo(e,[`command`,`cmd`,`shell_command`,`shellCommand`]),i=mo(e,[`tool.input`,`toolInput`,`tool_input`,`input`,`arguments`,`args`]),a=mo(e,[`tool.output`,`toolOutput`,`tool_output`,`output`,`result`]),o=mo(e,[`tool.exit_code`,`exitCode`,`exit_code`,`status`]),s=mo(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 mo(e,t){let n=go(e,t);if(n===void 0)return null;if(typeof n==`string`)return _o(n);if(typeof n==`number`||typeof n==`boolean`||typeof n==`bigint`)return String(n);try{return _o(JSON.stringify(n))}catch{return null}}function ho(e,t){let n=go(e,t);return typeof n==`string`&&n.length>0?n:void 0}function go(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 _o(e){return e.length>4096?`${e.slice(0,4093)}...`:e}function vo(e,t){yo(e,`${JSON.stringify(t,null,2)}\n`)}function yo(e,t){de(ge(e),{mode:448,recursive:!0});let n=`${e}.${process.pid}.tmp`;me(n,t,{mode:384}),pe(n,e)}function bo(e,t,n){de(ge(e),{recursive:!0});let r=So(xo(e),t);me(e,`${JSON.stringify(r,null,2)}\n`,{mode:n??420})}function xo(e){if(!ue(e))return{};let t=JSON.parse(fe(e,`utf8`));if(!Eo(t))throw Error(`${e} must contain a JSON object`);return t}function So(e,t){let n={...e};for(let[e,r]of Object.entries(t)){let t=n[e];Eo(t)&&Eo(r)?n[e]=So(t,r):Array.isArray(t)&&Array.isArray(r)?n[e]=Co([...t,...r]):n[e]=r}return n}function Co(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 wo(e){return[...new Set(e)]}function To(e,t){let n=e[t];return typeof n==`string`&&n.length>0?n:void 0}function Eo(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&(Object.getPrototypeOf(e)===Object.prototype||Object.getPrototypeOf(e)===null)}function Do(e){return T(e).toString(`hex`)}function Oo(e,t){return{key:e,value:{stringValue:t}}}const ko=`tangle.opencode-exporter`,Ao=16384;function jo(e){return e.length<=Ao?e:`${e.slice(0,Ao-1)}…`}function Mo(e,t){return{key:e,value:{stringValue:t}}}function No(e){if(!e||typeof e!=`object`)return null;let t=e,n=We(t.type);return n?{type:n,properties:t.properties&&typeof t.properties==`object`?t.properties:void 0}:null}function Po(e,t){let n=[Mo(`event.name`,e),Mo(`gen_ai.system`,`opencode`),Mo(`service.name`,`opencode`)];return t&&(n.push(Mo(`session.id`,t)),n.push(Mo(`gen_ai.conversation.id`,t))),n}function Fo(e){if(!e)return null;let t=e.part,n=e.info;return We(t?.sessionID)??We(n?.sessionID)??We(e.sessionID)??null}function Io(e,t){let n=We(e.role)??We(e.info?.role);if(n)return n.toLowerCase();let r=We(e.messageID),i=t?.(r)??null;return i?i.toLowerCase():null}function Lo(e,t,n){let r=[],i=Fo(e.properties),a=(n,r)=>({timeUnixNano:t,severityNumber:9,severityText:`INFO`,...n===null?{}:{body:{stringValue:jo(n)}},attributes:[...Po(e.type,i),...r]});if(e.type===`message.part.updated`){let t=e.properties?.part;if(!t)return r;let i=We(t.type);if(i===`text`||i===`reasoning`){let e=We(t.text);if(e){let i=Io(t,n)===`user`?ze:Re;r.push(a(e,[Mo(i,jo(e))]))}return r}if(i===`tool`){let e=We(t.tool),n=t.state,i=Ge(n?.input),o=Ge(n?.output),s=We(n?.error)??(typeof n?.error==`object`&&n?.error!==null?Ge(n.error):null);if(e||i){let t=[];e&&t.push(Mo(Ve,e)),i&&t.push(Mo(Be,jo(i))),r.push(a(null,t))}let c=o??s;if(c){let t=[Mo(He,jo(c))];e&&t.push(Mo(Ve,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=We(t.text)??(e.type===`session.next.text.delta`?We(t.delta):null);return n&&r.push(a(n,[Mo(Re,jo(n))])),r}return r}function Ro(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()!==Ue)continue;let n=t.slice(e+1).trim();if(n.length>0)return n}return null}function zo(e,t){if(e.length===0)return null;let n=[Mo(`service.name`,`opencode`),Mo(`gen_ai.system`,`opencode`),Mo(`telemetry.sdk.name`,ko)];return t&&t.trim().length>0&&n.push(Mo(Ue,t.trim())),{resourceLogs:[{resource:{attributes:n},scopeLogs:[{scope:{name:ko,version:`1.0.0`},logRecords:e}]}]}}function Bo(e){return(e??process.env.OPENCODE_BASE_URL??`http://127.0.0.1:4096`).replace(/\/+$/,``)}async function Vo(e){let t=so(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 Ho=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 Uo(){return(BigInt(Date.now())*1000000n).toString()}async function Wo(e){let t=Bo(e.opencodeBaseUrl),n=e.nowUnixNano??Uo,r=e.fetchImpl??fetch,i=e.subjectKey===void 0?Ro():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 v(a.body,{signal:e.signal})){o.eventsSeen++;let a=No(t.data);if(!a)continue;if(a.type===`message.updated`){let e=a.properties?.info,t=We(e?.id),n=We(e?.role);t&&n&&s.set(t,n);continue}let l=Lo(a,n(),c),u=zo(l,i);u&&(await Vo({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 Ho(e,o)}return o}function Go(e,t){let n=Number(e);if(!Number.isSafeInteger(n)||n<=0)throw Error(`${t} must be a positive integer`);return n}const Ko=[`claude-code`,`codex`,`opencode`,`openclaw`,`hermes`,`nanoclaw`],qo={"claude-code":`Claude Code`,codex:`Codex`,opencode:`OpenCode`,openclaw:`OpenClaw`,hermes:`Hermes`,nanoclaw:`NanoClaw`};function Jo(e){return Ko.includes(e)}function Yo(e){return ue(e)?fe(e,`utf8`):``}function Xo(e,t){de(ge(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;me(n,t,{mode:384}),ce(n,384),pe(n,e)}const Zo=`# >>> tangle intelligence (claude-code) >>>`,Qo=`# <<< tangle intelligence (claude-code) <<<`,$o={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 es(e,t){return t===`env`?e:/\s/.test(e)?`"${e}"`:e}function ts(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}=${es(i.value,t)}${e}`)}return r.join(`
134
+ `)}function ns(e){let t=so(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=$o[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 ts(a,i)}function rs(e){return[Zo,ns(e),Qo].join(`
135
+ `)}function is(e,t){let n=e.indexOf(Zo);if(n!==-1){let r=e.indexOf(Qo,n);if(r===-1)throw Error(`shell rc has a '${Zo}' marker without its closing '${Qo}' — 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?``:as(e)}${t}\n`,changed:!0}}function as(e){return e.endsWith(`
138
136
 
139
137
  `)?e:e.endsWith(`
140
- `)?`${e}\n`:`${e}\n\n`}function vo(){let e=process.env.SHELL??``;return e.includes(`zsh`)?j(M(),`.zshrc`):e.includes(`bash`)?j(M(),`.bashrc`):j(M(),`.zshrc`)}function yo(e){if(e===`shell`||e===`env`||e===`dockerfile`)return e;throw Error(`--format must be one of: shell, env, dockerfile (got '${e}')`)}function bo(e){if(e===`full`||e===`prompts`||e===`metadata`)return e;throw Error(`--content must be one of: full, prompts, metadata (got '${e}')`)}async function xo(e){let t=mo({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format});if(console.log(t),e.format!==`shell`){console.log(),R(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(),R(`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??vo(),r=process.stdin.isTTY?await $r(`Append this idempotent block to ${n}? (y/N)`,`n`):`n`;if(r.toLowerCase()!==`y`&&r.toLowerCase()!==`yes`){console.log(),R(`Not writing. To append later: tangle connect claude-code --rc ${n}`);return}let i=ho({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format}),{contents:a,changed:o}=go(oo(n),i);if(!o){console.log(),L(`Already present in ${n} — nothing to change.`);return}so(n,a),console.log(),L(`Wrote Tangle Intelligence env block to ${n}.`),R(`Reload your shell (e.g. 'source ${n}') before running the agent.`)}function So(e){let t=[],n={header:null,body:[]};for(let r of e.split(`
141
- `))Co(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 Co(e){let t=e.trim();return t.startsWith(`[`)&&t.endsWith(`]`)&&!t.includes(`=`)||t.startsWith(`[[`)&&t.endsWith(`]]`)}function wo(e){let t=[];for(let n of e)n.header!==null&&t.push(n.header),t.push(...n.body);return t.join(`
142
- `)}function To(e){return[{key:`environment`,line:`environment = "prod"`},{key:`log_user_prompt`,line:`log_user_prompt = true`},{key:`exporter`,line:`exporter = { otlp-http = { endpoint = "${ya(e.endpoint)}/v1/logs", protocol = "json", headers = { "Authorization" = "Bearer ${e.apiKey??"${TANGLE_API_KEY}"}" } } }`}]}function Eo(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 Do(e,t){let n=To(t),r=new Set(n.map(e=>e.key));if(e.trim()===``)return{contents:`${[`[otel]`,...n.map(e=>e.line)].join(`
143
- `)}\n`,changed:!0};let i=So(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&&!Oo(r)&&r.body.push(``),i.push(t);let a=ko(wo(i));return{contents:a,changed:a!==ko(e)}}let o=a.body.filter(e=>{let t=Eo(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=ko(wo(i));return{contents:c,changed:c!==ko(e)}}function Oo(e){return e.body.length>0&&e.body[e.body.length-1].trim()===``}function ko(e){return e.endsWith(`
144
- `)?e:`${e}\n`}function Ao(e){let t=j(M(),`.codex`,`config.toml`),{contents:n,changed:r}=Do(oo(t),{endpoint:e.endpoint,apiKey:e.apiKey});if(!e.write){console.log(n.trimEnd());return}if(!r){L(`${t} already has the Tangle [otel] block — nothing to change.`);return}so(t,n),L(`Merged the Tangle [otel] block into ${t}.`),R("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."),R(`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 jo(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`${io[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 Mo(e){let t=Date.now()+e.timeoutSeconds*1e3,n=3e3,r=Math.min(e.timeoutSeconds*1e3,1e4),i=z(`Checking whether content is flowing…`);i.start();let a;try{for(;;){try{a=await va({endpoint:e.endpoint,apiKey:e.apiKey,timeoutMs:r})}catch(e){if(Date.now()>=t)throw e;await Ae(n);continue}if(a.contentSeen||Date.now()>=t)break;await Ae(n)}}finally{i.stop()}if(!a)throw Error(`onboarding status check returned no result`);No(a,e.agent),a.contentSeen||(process.exitCode=1)}function No(e,t){if(e.contentSeen){L(`Content flowing — Tangle Intelligence can analyze this feed.`),B({"Last seen":e.lastSeenAt??`just now`,Window:`${e.windowDays}d`});return}if(e.tracesSeen){Lt(`Metadata-only — traces are arriving but carry no content. You missed a content gate.`);let n=t?[t]:Object.keys(e.byAgent).filter(ao),r=n.length>0?n:ro;for(let n of r){let r=e.byAgent[n];(t||!r||r.tracesSeen&&!r.contentSeen)&&R(jo(n))}return}Lt(`No traces yet for your tenant. Run your agent once on a real task, then re-run --verify.`),t&&R(jo(t))}function Po(e){let t=e??process.env.TANGLE_INTELLIGENCE_API_KEY??nr(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 Fo(){return new x(`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`,ra).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=ya(t.endpoint);if(t.run){if((e?Lo(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 Vo({endpoint:n,apiKey:Po(t.apiKey),opencodeUrl:t.opencodeUrl});return}if(t.verify){await Mo({endpoint:n,apiKey:Po(t.apiKey),agent:e?Lo(e):void 0,timeoutSeconds:no(t.timeout,`--timeout`)});return}let r=e?Lo(e):await Ro(),i=t.inlineKey?Po(t.apiKey):void 0;r===`claude-code`?await xo({endpoint:n,apiKey:i,projectKey:t.project,rcPath:t.rc,write:t.write!==!1,content:bo(t.content),format:yo(t.format)}):r===`codex`?Ao({endpoint:n,apiKey:i,projectKey:t.project,write:t.write!==!1}):r===`opencode`?zo({endpoint:n}):Bo(r,{endpoint:n}),console.log(),R(`Run your agent on a real task, then verify content is flowing: tangle connect ${r} --verify`)})}function Io(){return new x(`opencode-exporter`).description(`Export a running OpenCode's content to Tangle Intelligence (standalone shim)`).option(`--endpoint <url>`,`OTLP endpoint base`,ra).option(`--opencode-url <url>`,`OpenCode server base URL (or set OPENCODE_BASE_URL)`).action(async e=>{await Vo({endpoint:ya(e.endpoint),apiKey:Po(e.apiKey),opencodeUrl:e.opencodeUrl})})}function Lo(e){if(ao(e))return e;throw Error(`Unknown agent '${e}'. Choose one of: ${ro.join(`, `)}`)}async function Ro(){if(!process.stdin.isTTY)throw Error(`Specify an agent: tangle connect <${ro.join(`|`)}>`);console.log(`Which coding agent are you connecting?`),ro.forEach((e,t)=>{console.log(` ${t+1}) ${io[e]} (${e})`)});let e=await $r(`Enter a number or name`,`1`);return ro[Number.parseInt(e,10)-1]||Lo(e.trim())}function zo(e){let t=ya(e.endpoint);Lt(`OpenCode has no native OTel exporter, so a standalone install emits nothing without a shim.`),console.log(),B({"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(),R(`Start OpenCode in server mode ('opencode serve'), then in another terminal run: tangle connect opencode --run`),R(`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`),R(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting the exporter.`)}function Bo(e,t){let n=ya(t.endpoint),r=io[e];Lt(`${r} has no native OTel exporter, so a standalone install emits nothing without instrumentation.`),console.log(),B({"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(),R(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting ${r}.`),R(`Verify content is flowing: tangle connect ${e} --verify`)}async function Vo(e){let t=Za(e.opencodeUrl),n=new AbortController,r=()=>n.abort();process.on(`SIGINT`,r),process.on(`SIGTERM`,r),R(`Subscribing to OpenCode at ${t} — exporting content to Tangle.`),R(`Run OpenCode tasks now. Press Ctrl-C to stop.`),console.log();let i=0,a;try{a=await to({endpoint:e.endpoint,apiKey:e.apiKey,opencodeBaseUrl:t,signal:n.signal,onExport:({eventType:e,records:t})=>{i+=t,R(`exported ${t} record(s) from ${e} (total ${i})`)}})}catch(e){if(e instanceof $a){let{recordsExported:t,contentEventsExported:n}=e.partial;console.log(),Lt(`Exporter failed after exporting ${t} content record(s) from ${n} event(s): ${e.message}`)}throw e}finally{process.off(`SIGINT`,r),process.off(`SIGTERM`,r)}if(console.log(),a.contentEventsExported===0){Lt(`Saw ${a.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}L(`Exported ${a.recordsExported} content record(s) from ${a.contentEventsExported} event(s).`),R(`Verify it landed: tangle connect opencode --verify`)}function Ho(){let e=new x(`environments`).alias(`env`).description(`Manage sandbox environments`);return e.command(`list`).alias(`ls`).description(`List available environments`).action(async e=>{let{client:t}=K(e),n=z(`Fetching environments...`);e.json||n.start();let r=await t.environments.list();n.stop(),e.json?I(r):r.length===0?console.log(`No environments found`):Ht([`ID`,`Description`,`Version`,`Runtimes`],r.map(e=>[e.id,e.description??``,e.version,e.runtimes.join(`, `)]))}),e.command(`get`).description(`Get environment details`).argument(`<id>`,`Environment ID`).action(async(e,t)=>{let{client:n}=K(t),r=z(`Fetching environment...`);t.json||r.start();let i=await n.environments.get(e);if(r.stop(),!i){console.error(`Environment not found: ${e}`),process.exit(1);return}t.json?I(i):(console.log(`ID: ${i.id}`),console.log(`Description: ${i.description??`-`}`),console.log(`Version: ${i.version}`),console.log(`Runtimes: ${i.runtimes.join(`, `)}`),i.base&&console.log(`Base: ${i.base}`))}),e}const Uo=N.string().trim().toLowerCase().min(1).max(64).regex(/^[a-z][a-z0-9-]*$/),Wo=N.string().trim().toLowerCase().min(1).max(128).regex(/^[a-z0-9][a-z0-9._-]*$/),Go=N.object({kind:Wo,count:N.number().int().positive().default(1),vramGb:N.number().positive().optional()}).strict();N.object({command:N.string().min(1).max(8192),timeoutMs:N.number().int().positive().max(2147453647).optional(),env:N.record(N.string(),N.string()).optional(),cwd:N.string().min(1).max(2048).optional()}).strict(),N.object({refresh:N.enum([`true`,`false`]).optional(),acceleratorKind:Wo.optional(),acceleratorCount:N.coerce.number().pipe(Go.shape.count.unwrap()).optional(),acceleratorVramGb:N.coerce.number().positive().optional()}).strict(),N.object({maxSpendUsd:N.number().positive().max(1e4).optional(),maxLifetimeSeconds:N.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 Ko=N.object({provider:Uo.optional(),image:N.string().min(1).max(512).optional(),env:N.record(N.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),N.string()).optional(),diskGb:N.number().int().positive().optional(),volumeGb:N.number().int().nonnegative().optional(),volumeMountPath:N.string().startsWith(`/`).max(2048).optional(),region:N.string().min(1).max(128).optional(),manifest:N.record(N.string(),N.unknown()).optional(),command:N.array(N.string().max(8192)).min(1).max(256).optional(),ports:N.array(N.number().int().min(1).max(65535)).max(32).optional(),endpoint:N.object({port:N.number().int().min(1).max(65535),healthPath:N.string().regex(/^\/(?![/\\])/).refine(e=>![`\r`,`
145
- `,` `].some(t=>e.includes(t))).max(2048).optional()}).strict().optional(),allowSpot:N.boolean().optional(),maxHourlyUsd:N.number().positive().optional(),weights:N.object({manifestSha:N.string().regex(/^[a-f0-9]{64}$/),sizeBytes:N.number().int().positive().safe()}).strict().optional(),arms:N.array(N.unknown()).min(1).max(256).optional(),maxSpendUsd:N.number().positive().max(1e4),maxLifetimeSeconds:N.number().int().positive().max(1440*60),idleTimeoutSeconds:N.number().int().positive().optional()}).strict();Ko.extend({accelerator:Go});const qo=Go,Jo=Uo;N.object({...Ko.omit({env:!0}).shape,id:N.string(),projectRef:N.string(),ownerUserId:N.string(),productId:N.string().optional(),provider:Jo,providerLeaseId:N.string().optional(),providerInstanceType:N.string().optional(),endpointUrl:N.string().optional(),status:N.enum([`provisioning`,`ready`,`detaching`,`destroyed`,`failed`]),accelerator:qo,providerCostPerHourUsd:N.number().optional(),customerPricePerHourUsd:N.number().optional(),estimatedProviderCostUsd:N.number().optional(),estimatedCustomerCostUsd:N.number().optional(),providerSelection:N.object({strategy:N.enum([`explicit`,`cheapest`,`ranked`]),selectedProvider:Jo,requestedProvider:Jo.optional(),candidates:N.array(N.object({provider:Jo,accelerator:qo,providerInstanceType:N.string().optional(),region:N.string().optional(),pricingSource:N.enum([`live`,`configured`]).optional(),providerCostPerHourUsd:N.number(),customerPricePerHourUsd:N.number(),maxLifetimeSeconds:N.number(),estimatedProviderCostUsd:N.number(),estimatedCustomerCostUsd:N.number()})),rejected:N.array(N.object({provider:Jo,error:N.string()}))}).optional(),createdAt:N.string(),updatedAt:N.string(),readyAt:N.string().optional(),startedAt:N.string().optional(),lastUsedAt:N.string().optional(),destroyedAt:N.string().optional(),failure:N.string().optional(),billing:N.object({seconds:N.number(),providerCostUsd:N.number(),customerCostUsd:N.number(),providerCostPerHourUsd:N.number(),customerPricePerHourUsd:N.number(),startedAt:N.string(),stoppedAt:N.string()}).optional()});function Yo(e){return{kind:rs(e.kind),count:e.count?ns(e.count,`--accelerator-count`):1,...e.memory?{vramGb:as(e.memory,`--accelerator-memory`)}:{}}}function Xo(e,t,n){if(!t&&Object.values(e).some(Boolean))throw Error(n);return t?Qo(e,`--gpu-`):void 0}function Zo(e){return{...Qo(e,`--`),accelerator:Yo({kind:e.acceleratorKind,count:e.acceleratorCount,memory:e.acceleratorMemory})}}function Qo(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:is(n,`${t}provider`)}:{},...r?{image:r}:{},...i?{env:ts(i,`${t}env`,`env`)}:{},maxSpendUsd:as(a,`${t}max-spend-usd`),maxLifetimeSeconds:ns(o,`${t}max-lifetime`),...s?{idleTimeoutSeconds:ns(s,`${t}idle-timeout`)}:{}}}function $o(e){return e.length===1?e[0]:e.map(Be).join(` `)}function es(e){return{timeoutMs:e.timeout?ns(String(e.timeout),`--timeout`):void 0,env:e.env?ts(e.env,`--env`,`env`):void 0}}function ts(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 ns(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 rs(e){let t=Wo.safeParse(e);if(t.success)return t.data;throw Error(`--accelerator-kind must contain only letters, numbers, dots, underscores, or hyphens`)}function is(e,t){let n=Uo.safeParse(e);if(n.success)return n.data;throw Error(`${t} must start with a letter and contain only letters, numbers, or hyphens`)}function as(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 os(){return new x(`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(e,t,n)=>{try{let{context:r,client:i}=K(n),a=$o(t),o=ts(n.env??[],`--env`,`env`),s=z(`Executing: ${a}`);n.json||s.start();let c=await J(i,r,e);c=await Y(c);let l=await c.exec(a,{cwd:n.cwd,env:Object.keys(o).length>0?o:void 0,timeoutMs:Number.parseInt(n.timeout,10)});s.stop(),n.json?I(l):(l.stdout&&process.stdout.write(l.stdout),l.stderr&&process.stderr.write(l.stderr)),l.exitCode!==0&&(process.exitCode=l.exitCode)}catch(e){if(e instanceof i){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 U(Error(t,{cause:e}))}U(e)}})}function ss(e){e.command(`capabilities`).description(`List fleet drivers and their supported features`).action(async e=>{let{client:t}=K(e),n=z(`Fetching capabilities...`);n.start();let r=await t.fleets.capabilities();n.stop(),e.json?I(r):F(r.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}])}),e.command(`usage <fleet-id>`).description(`Show fleet usage and reliability insights`).action(async(e,t)=>{let{client:n}=K(t),r=z(`Fetching usage...`);r.start();let i=await n.fleets.usage(e);if(r.stop(),t.json)I(i);else if(B({"Fleet ID":i.usage.fleetId,Status:i.usage.status,Machines:i.usage.machineCount,Running:i.usage.runningMachines,Failed:i.usage.failedMachines,"Runtime (ms)":i.usage.meteredUsage?.runtimeMs,"Reliability score":i.insights.reliabilityScore,"Failure rate":i.insights.failureRate}),i.insights.recommendedActions.length>0){console.log(`
146
- Recommended actions:`);for(let e of i.insights.recommendedActions)console.log(` - ${e}`)}}),e.command(`cost <fleet-id>`).description(`Show the fleet's cost estimate`).action(async(e,t)=>{let{client:n}=K(t),r=z(`Estimating cost...`);r.start();let i=await n.fleets.cost(e);r.stop(),t.json?I(i):B({Plan:i.plan,Currency:i.currency,"Hourly (USD)":i.hourlyUsd,"Max lifetime (s)":i.maxLifetimeSeconds,"Estimated max lifetime (USD)":i.estimatedMaxLifetimeUsd,Machines:i.requestedResources.machines,"Total CPU":i.requestedResources.totalCpu,"Total memory (MB)":i.requestedResources.totalMemoryMb})})}function cs(e){return[...e.entries()].map(([e,t])=>({machineId:e,sandboxId:t.id,status:t.status}))}function ls(e){e.command(`list <fleet-id>`).description(`List the machines of one fleet (fleet id is required)`).option(`--status <status>`,`Filter machines by status`).action(async(e,t)=>{let{client:n}=K(t),r=z(`Fetching fleet...`);r.start();let i=await n.fleets.list({fleetId:e,status:t.status});r.stop();let a=cs(i.machines);t.json?I({fleetId:i.fleetId,machines:a}):F(a,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}])}),e.command(`get <fleet-id>`).description(`Show one fleet's manifest (server record)`).action(async(e,t)=>{let{client:n}=K(t),r=z(`Fetching manifest...`);r.start();let i=await n.fleets.manifest(e);r.stop(),t.json?I(i):(B({"Fleet ID":i.fleetId??i.id,Machines:i.machines.length,"Workspace mode":i.workspace?.mode,"Workspace status":i.workspace?.status,"Max lifetime (s)":i.policy?.maxLifetimeSeconds,"Max spend (USD)":i.policy?.maxSpendUsd,Created:i.createdAt,Updated:i.updatedAt}),F(i.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}]))}),e.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(e,t)=>{let{client:n}=K(t),r=z(`Deleting fleet...`);r.start(),await n.fleets.delete(e,{continueOnError:t.continueOnError}),r.stop(),t.json?I({success:!0,fleetId:e}):L(`Fleet deleted: ${e}`)}),e.command(`reap`).description(`TTL cleanup of all expired fleets (fleet-wide)`).option(`--dry-run`,`Report what would be reaped without deleting`).action(async e=>{let{client:t}=K(e),n=z(`Reaping expired fleets...`);n.start();let r=await t.fleets.reapExpired({dryRun:e.dryRun});n.stop(),e.json?I(r):(B({"Dry run":r.dryRun,Expired:r.expired,Deleted:r.deleted}),F(r.fleets,[{key:`fleetId`,header:`Fleet`,width:24},{key:`expiredAt`,header:`Expired`,width:18},{key:`deleted`,header:`Deleted`,width:10}]))}),e.command(`reconcile`).description(`Drop fleet records whose underlying sandboxes vanished`).option(`--dry-run`,`Report orphans without removing them`).action(async e=>{let{client:t}=K(e),n=z(`Reconciling fleets...`);n.start();let r=await t.fleets.reconcile({dryRun:e.dryRun});n.stop(),e.json?I(r):(B({"Dry run":r.dryRun,Checked:r.checked,Orphaned:r.orphaned,Removed:r.removed}),F(r.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 us(e,t){let n=await Ir({apiKey:t.apiKey,baseUrl:t.baseUrl??lr()}),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 ds(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 ei();if(t.length===0)throw Error(`${e.flagPrefix}-stdin received empty input on stdin`);return t}}function fs(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 ps(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 ms(e,t){let n={};return e.cpu!==void 0&&(n.cpuCores=ns(e.cpu,`--cpu`)),e.memory!==void 0&&(n.memoryMB=ns(e.memory,`--memory`)),e.disk!==void 0&&(n.diskGB=ns(e.disk,`--disk`)),t&&(n.accelerator=t),Object.keys(n).length>0?n:void 0}function hs(e){let t=e.split(`/`);return t.length>=2?{provider:t[0],model:t.slice(1).join(`/`)}:{model:e}}function gs(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]=_s(r.join(`=`))}return t}function _s(e){try{return JSON.parse(e)}catch{return e}}function vs(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`?ns(e.gitDepth,`--git-depth`):void 0,sparse:Array.isArray(e.gitSparse)?e.gitSparse:void 0,auth:t?{token:t}:void 0}}}function ys(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:bs(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 bs(e){if(e===`s3`||e===`gcs`||e===`r2`)return e;throw Error(`--storage-type must be one of s3, gcs, or r2`)}function xs(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=ue(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=T.parse(t);return n.length>0?n:void 0}function Ss(e){R(` Status: ${e.status}`),R(` Provider: ${e.provider}`),R(` GPU: ${e.accelerator.kind} x ${e.accelerator.count}`),e.customerPricePerHourUsd!==void 0&&R(` Customer price: $${e.customerPricePerHourUsd}/hr`),e.estimatedCustomerCostUsd!==void 0&&R(` Max estimate: $${e.estimatedCustomerCostUsd}`),e.billing&&(R(` Billed seconds: ${e.billing.seconds}`),R(` Customer cost: $${e.billing.customerCostUsd}`))}function Cs(e){e.result.stdout&&process.stdout.write(e.result.stdout),e.result.stderr&&process.stderr.write(e.result.stderr),R(`Exit code: ${e.result.exitCode}`)}function ws(e){let t=e.command(`gpu`).description(`Manage on-demand GPU leases for a sandbox`);t.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(e,t)=>{let{context:n,client:r}=K(t),i=z(`Checking GPU providers...`);i.start();let a=await(await J(r,n,e)).gpu.providers(t.acceleratorKind?{accelerator:Yo({kind:t.acceleratorKind,count:t.acceleratorCount,memory:t.acceleratorMemory})}:{});if(i.stop(),t.json){I(a);return}F(a.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 a.statuses){let t=e.state===`credential-invalid`?e.credential?.detail:e.estimateError;t&&R(`${e.provider}: ${t}`)}a.usable.length===0&&R(`No GPU provider is usable on this deployment: set the variables in Needs for one provider on the server.`)}),t.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(e,t)=>{let{context:n,client:r}=K(t),i=z(`Attaching GPU lease...`);i.start();let a=await(await J(r,n,e)).gpu.attach(Zo(t));i.stop(),t.json?I(a):(L(`GPU lease attached: ${a.id}`),Ss(a))}),t.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(e,t,n)=>{let r,i,a,o;try{let{context:a,client:o}=K(n),s=await J(o,a,e),c=z(`Attaching GPU lease...`);c.start(),r=await s.gpu.attach(Zo(n)),c.stop();let l=z(`Running GPU command...`);l.start(),i=await s.gpu.exec(r.id,{command:$o(t),...es(n),cwd:n.cwd}),l.stop(),n.json||Cs(i)}catch(e){a=e}finally{if(r)try{let{context:t,client:i}=K(n);r=await(await J(i,t,e)).gpu.detach(r.id)}catch(e){o=e}}if(a){U(a),o&&U(o);return}if(o){U(o);return}n.json?I({lease:r,result:i}):r&&L(`GPU lease detached: ${r.id}`);let s=i?.result.exitCode;s&&s!==0&&(process.exitCode=s)}),t.command(`list <id-or-name>`).description(`List GPU leases attached to a sandbox`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching GPU leases...`);i.start();let a=await(await J(r,n,e)).gpu.list();i.stop(),t.json?I(a):a.length===0?R(`No GPU leases attached.`):F(a.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}])}),t.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(e,t,n,r)=>{let{context:i,client:a}=K(r),o=z(`Running GPU command...`);o.start();let s=await(await J(a,i,e)).gpu.exec(t,{command:$o(n),...es(r),cwd:r.cwd});o.stop(),r.json?I(s):Cs(s)}),t.command(`detach <id-or-name> <lease-id>`).description(`Detach and destroy a GPU lease`).action(async(e,t,n)=>{let{context:r,client:i}=K(n),a=z(`Detaching GPU lease...`);a.start();let o=await(await J(i,r,e)).gpu.detach(t);a.stop(),n.json?I(o):(L(`GPU lease detached: ${o.id}`),Ss(o))})}function Ts(e,t){if(t){I(e);return}if(!e.id){e.kind===`snapshot`&&e.result?.snapshot?L(`Snapshot created: ${e.result.snapshot.snapshotId}`):L(`Sandbox ${e.sandboxId} stopped.`);return}L(`${e.kind===`snapshot`?`Snapshot`:`Stop`} of sandbox ${e.sandboxId} accepted.`),R(`Operation: ${e.id}`),R(`Status: ${e.statusUrl}`)}function Es(e){return`${e.name} (${e.id})`}async function Ds(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 Os(e,t,n){if(t)return Ds(e,t);let r=fr(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 ks(e,t){pr({id:e.id,name:e.name},t)}function As(e){mr(e)}async function js(e){if(e.explicitTeam&&e.personal)throw Error(`--team and --personal cannot be used together`);if(!e.personal)return e.explicitTeam?(await Ds(e.client,e.explicitTeam)).id:e.activeTeamId}async function Ms(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 Ds(e.client,e.explicitTeam)).id}`;if(e.activeTeamId)return`team:${e.activeTeamId}`}function Ns(e){if(!e)return e;let t={...e};for(let e of[`authToken`,`execToken`])t[e]!==void 0&&(t[e]=`[REDACTED]`);return t}function Ps(e){e.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(e,t)=>{let{context:n,client:r}=K(t),i=t.nonce===`auto`?g():t.nonce,a=z(`Fetching TEE attestation...`);a.start();let o=await(await J(r,n,e)).getTeeAttestation(i?{attestationNonce:i}:void 0);a.stop(),t.json?I(o):(L(`Attestation fetched for ${e}`),console.log(`TEE type: ${o.attestation.tee_type}`),console.log(`Evidence bytes: ${o.attestation.evidence.length}`),console.log(`Measurement bytes: ${o.attestation.measurement.length}`),console.log(`Timestamp: ${o.attestation.timestamp}`),o.attestationNonce&&console.log(`Nonce: ${o.attestationNonce}`))}),e.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 e=>{let{context:t,client:n}=K(e),r=z(`Fetching sandboxes...`);r.start();let i=await Ms({client:n,explicitTeam:e.team,personal:e.personal,allScopes:e.allScopes,activeTeamId:t.activeTeamId}),a=await n.list({status:e.status===`all`?void 0:e.status,limit:Number.parseInt(e.limit,10),scope:i});r.stop(),e.json?I(a):F(a.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}])}),e.command(`get <id-or-name>`).description(`Get sandbox details`).option(`--profile`,`Show the active agent profile provenance (name, hash, skills)`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching sandbox...`);i.start();let a=await J(r,n,e);if(i.stop(),t.profile){let e=a.getProfileProvenance?.();e?(R(`Agent profile provenance:`),R(` Base profile: ${e.base.name??`(inline)`} (${e.base.sha256.slice(0,12)}...)`),R(` Effective: ${e.effective.name??`(inline)`} (${e.effective.sha256.slice(0,12)}...)`),R(` Materialized: ${e.materializedAt}`),e.base.sha256!==e.effective.sha256&&R(` ⚠ Profile changed since creation (base ≠ effective)`)):R(`No profile materialized (bare sandbox). Create with --profile <name> to install one.`);return}t.json?I(a):Vt({id:a.id,name:a.name,status:a.status,resources:a.resources,createdAt:a.createdAt?.toISOString(),expiresAt:a.expiresAt?.toISOString(),connection:a.connection})}),e.command(`shapes`).description(`List the named sandbox sizes, the default, and this account's ceiling`).action(async e=>{let{client:t}=K(e),n=await t.shapes();if(e.json){I(n);return}let r=e=>e.cpuCores<=n.ceiling.cpuCores&&e.memoryMB<=n.ceiling.memoryMB&&e.diskGB<=n.ceiling.diskGB;F(n.presets.map(e=>({name:e.name===n.default?`${e.name} (default)`:e.name,cpu:e.cpuCores,memory:`${e.memoryMB} MB`,disk:`${e.diskGB} GB`,available:r(e)?`yes`:e.name===n.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}]),R(`Ceiling for this account: ${Bt(n.ceiling)}`)}),e.command(`delete <id-or-name>`).description(`Delete a sandbox`).option(`-f, --force`,`Skip confirmation`).option(`--name`,`Treat the reference as a sandbox name`).option(`--retry-cleanup`,`Retry server-side cleanup after the sandbox disappeared from get/list`).action(async(e,t)=>{if(!t.force&&!await Qr(`Delete sandbox ${e}? [y/N] `,`--force`)){R(`Cancelled.`);return}let{context:n,client:r}=K(t),i=z(`Deleting sandbox...`);i.start();let a=await Gr(r,n,e,{retryCleanup:t.retryCleanup,name:t.name});i.stop(),L(a===`already_absent`?`Sandbox ${e} was already gone.`:`Sandbox ${e} deleted.`)}),e.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:r}=K(t),i=z(`Stopping sandbox...`);i.start();let a=await J(r,n,e,{nameOnly:t.name});if(t.wait===!1){let e=await a.stop({wait:!1});i.stop(),Ts(e.info,!!t.json);return}await a.stop(),i.stop(),L(`Sandbox ${e} stopped.`)}),e.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 r=W({apiKey:t.apiKey,baseUrl:t.baseUrl,timeout:n}),i=G(r),a=z(`Resuming sandbox...`);a.start();let o=await J(i,r,e);await o.resume({timeoutMs:n}),t.wait&&(a.text=`Waiting for sandbox to start...`,await o.waitFor(`running`,{timeoutMs:n})),a.stop(),L(`Sandbox ${o.id} resumed.`)})}function Fs(e){e.command(`create`).description(`Create a new sandbox`).option(`-n, --name <name>`,`Sandbox name`).option(`-e, --environment <environment>`,Is).addOption(Ls()).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 S(`--driver <type>`,`Run on Tangle network operators instead of the platform's hosts (--tee needs it)`).choices([`tangle`])).option(`--backend <type>`,`Backend agent type (${n.join(`, `)})`).option(`--backend-model <model>`,`Model override (format: provider/model)`).addOption(new S(`--reasoning-effort <level>`,`Reasoning effort for the backend's model; overrides the profile's model.reasoningEffort`).choices(E)).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 e=>{let t=await ds({envVarName:e.gitTokenEnv,fromStdin:e.gitTokenStdin,flagPrefix:`--git-token`}),n=await ds({envVarName:e.storageSecretAccessKeyEnv,fromStdin:e.storageSecretAccessKeyStdin,flagPrefix:`--storage-secret-access-key`}),r=await ds({envVarName:e.backendApiKeyEnv,fromStdin:e.backendApiKeyStdin,flagPrefix:`--backend-api-key`}),i=fs({secret:e.cliAuth,backend:e.backend,apiKeyGiven:r!==void 0}),a;if(e.profileStdin){let e=await ei(`--profile-stdin`,`the AgentProfile JSON`);try{a=JSON.parse(e)}catch{U(Error(`--profile-stdin: the input is not valid JSON`));return}}else if(e.profile){let t=String(e.profile);if(t.startsWith(`.`)||t.startsWith(`/`)||t.endsWith(`.json`))try{a=JSON.parse(ue(t,`utf8`))}catch(e){U(Error(`--profile ${t}: ${e.message}`));return}else try{a=await us(t,e)}catch(e){U(Error(`--profile ${t}: ${e.message}`));return}}a=zs(a,e.reasoningEffort);let o=W({apiKey:e.apiKey,baseUrl:e.baseUrl,timeout:e.timeout?Number.parseInt(e.timeout,10):void 0}),s=G(o),c=z(`Creating sandbox...`);c.start();let l=await js({client:s,explicitTeam:e.team,personal:e.personal,activeTeamId:o.activeTeamId}),u=ts(e.env??[],`--env`,`env`),d=e.metadata?gs(e.metadata):void 0,f=vs(e,t),p=ys(e,n),m=e.acceleratorKind?Yo({kind:String(e.acceleratorKind),count:String(e.acceleratorCount),memory:typeof e.acceleratorMemory==`string`?e.acceleratorMemory:void 0}):void 0,g=Xo({provider:typeof e.gpuProvider==`string`?e.gpuProvider:void 0,image:typeof e.gpuWorkerImage==`string`?e.gpuWorkerImage:void 0,env:Array.isArray(e.gpuEnv)?e.gpuEnv:void 0,maxSpendUsd:typeof e.gpuMaxSpendUsd==`string`?e.gpuMaxSpendUsd:void 0,maxLifetime:typeof e.gpuMaxLifetime==`string`?e.gpuMaxLifetime:void 0,idleTimeout:typeof e.gpuIdleTimeout==`string`?e.gpuIdleTimeout:void 0},!!m,`Create-time GPU lease flags require --accelerator-kind`),v=e.driver?{type:`tangle`}:void 0,y=e.backend||e.backendModel||a?{...e.backend?{type:_(e.backend)}:{},...a?{profile:a}:{},model:e.backendModel||r||i?{...e.backendModel?hs(e.backendModel):{},apiKey:r,...i?{cliAuth:i}:{}}:void 0}:void 0,b=ps(e.secret),ee=i?[...new Set([...b??[],i.secretEnv])]:b,x=xs(e.proxySecret),S=ms(e,m),C=e.sshKeyFile??(e.ssh&&!e.sshKey&&!e.sshKeys?.length?[Rs()]:[]),te=[...e.sshKey?[e.sshKey]:[],...C.map(e=>ue(e,`utf8`).trim())],w={name:e.name,environment:e.environment,runtime:e.runtime,bare:e.bare||void 0,sshEnabled:e.ssh||!!e.sshKey||te.length>0||!!e.sshKeys?.length,sshPublicKeys:te.length>0?te:void 0,sshKeyIds:e.sshKeys,webTerminalEnabled:e.webTerminal,env:Object.keys(u).length>0?u:void 0,git:f,...S?{resources:S}:{},gpuLease:g,maxLifetimeSeconds:Number.parseInt(e.lifetime,10),idleTimeoutSeconds:Number.parseInt(e.idleTimeout,10),storage:p,fromSnapshot:e.fromSnapshot,publicTemplateId:e.publicTemplate,publicTemplateVersionId:e.publicTemplateVersion,teamId:l,...e.billingOwner?{billingOwnerId:e.billingOwner}:{},secrets:ee,...x?{proxySecrets:x}:{},metadata:d,driver:v,backend:y},T=e.tee?{tee:e.tee,sealed:e.sealed||void 0,attestationRefresh:e.attestationRefresh||e.attestationNonce===`auto`||void 0}:void 0,E=T?await h(s,{...w,confidential:T,attestationNonce:e.attestationNonce??(e.attestationRefresh?`auto`:void 0),requireAttestation:e.requireAttestation??!0}):void 0,D=E?.sandbox??await s.create(w);e.wait&&(c.text=`Waiting for sandbox to start...`,await D.waitFor(`running`,{timeoutMs:12e4}),await D.refresh()),c.stop(),e.json?I({id:D.id,name:D.name,status:D.status,resources:D.resources,createdAt:D.createdAt,expiresAt:D.expiresAt,connection:Ns(D.connection),teamId:l,gpuLease:D.gpuLease,confidential:T,attestation:E?.attestation,attestationNonce:E?.attestationNonce}):(L(`Sandbox created: ${D.id}`),Vt({id:D.id,name:D.name,status:D.status,resources:D.resources,createdAt:D.createdAt?.toISOString(),expiresAt:D.expiresAt?.toISOString(),connection:D.connection}),l&&console.log(`Team: ${l}`),D.gpuLease&&(console.log(`GPU lease: ${D.gpuLease.id}`),Ss(D.gpuLease)),T&&(console.log(`TEE: ${T.tee}`),console.log(`Attestation: ${E?.attestation?`present`:`not returned`}`),E?.attestationNonce&&console.log(`Attestation nonce: ${E.attestationNonce}`)))})}const Is="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 Ls(){return new S(`--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(c)}function Rs(){let e=[`id_ed25519`,`id_ecdsa`,`id_rsa`].map(e=>`${M()}/.ssh/${e}.pub`),t=e.find(e=>ce(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 zs(e,t){if(!t)return e;let n=e?.model??{};return{...e,model:{...n,reasoningEffort:t}}}function Bs(e){if(e.spec){let t=JSON.parse(ue(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=Us(e),n=Ws(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=Gs(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 Vs(e){let{base:t,machines:n}=Bs(e);return{...t,machines:n}}function Hs(e){let{base:t,machines:n}=Bs(e);return{...t,workers:n}}function Us(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=Yo({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 Ws(e,t){return Xo({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 Gs(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 Ks(e){e.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>`,Is).addOption(Ls()).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 e=>{let{client:t}=K(e),n=z(`Creating fleet...`);n.start();let r=e.coordinator?await t.fleets.createWithCoordinator(Hs(e)):await t.fleets.create(Vs(e));n.stop();let i=cs(r.machines);e.json?I({fleetId:r.fleetId,machines:i}):(L(`Fleet created: ${r.fleetId}`),F(i,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}]))})}function qs(e){e.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(e,t,n)=>{let{client:r}=K(n),i=z(`Dispatching command...`);i.start();let a=await(await r.fleets.list({fleetId:e})).dispatchExecDetailed(t,{machines:n.machine,cwd:n.cwd,timeoutMs:n.timeout?Number(n.timeout):void 0,maxConcurrent:n.maxConcurrent?Number(n.maxConcurrent):void 0});if(i.stop(),n.json)I(a);else{F(a.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 a.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}`)}}a.results.some(e=>e.ok===!1)&&(process.exitCode=1)}),e.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(e,t)=>{let n=/^\d+$/.test(t.agents)?Number(t.agents):JSON.parse(ue(t.agents,`utf8`));if(!Array.isArray(n)&&e===void 0)throw Error(`A prompt is required unless --agents names a file whose agents carry tasks`);let{client:r}=K(t);if(!!t.parentFleet!=!!t.parentAgent)throw Error(`--parent-fleet and --parent-agent go together`);let i=t.placement===`auto`||t.placement===`dedicated`?t.placement:{agentsPerSandbox:Number(t.placement)},a=t.maxSpendUsd?Number(t.maxSpendUsd):void 0,o=z(`Creating fleet...`);o.start();let s=Date.now(),c=await r.fleets.create({fleetId:t.fleetId,agents:n,placement:i,defaults:{...t.environment?{environment:t.environment}:{},...t.memory?{resources:{memoryMB:Number(t.memory)}}:{},...t.model?{backend:{type:`opencode`,model:{model:t.model}}}:{}},...a===void 0?{}:{budgetUsd:a},...t.parentFleet?{parent:{fleetId:t.parentFleet,agentId:t.parentAgent}}:{}}),l=Date.now()-s;o.stop(),t.json||L(`Fleet ${c.fleetId}: ${c.agents.length} agents on ${c.machines.size} sandboxes in ${l} ms`);let u=[],d;try{for await(let n of c.run(e,{timeoutMs:t.timeout?Number(t.timeout):void 0})){if(n.type===`agent.finished`&&!t.json){let e=n.result;console.log(`[${e.agentId}] ${e.harness??`default`}/${e.model??`default`} ${e.status} ${e.durationMs}ms ${e.costUsd===void 0?`no cost reported`:`$${e.costUsd.toFixed(5)}`} ${e.result?.response??e.error??``}`)}n.type===`fleet.finished`&&(u=n.results,d=n.spend)}}finally{t.keep||await c.delete({continueOnError:!0})}t.json?I({fleetId:c.fleetId,createMs:l,sandboxes:c.machines.size,results:u,spend:d,deleted:!t.keep}):B({fleetId:c.fleetId,completed:u.filter(e=>e.status===`completed`).length,agents:u.length,spend:JSON.stringify(d),deleted:!t.keep}),u.some(e=>e.status!==`completed`)&&(process.exitCode=1)}),e.command(`cancel <fleet-id>`).description(`Interrupt every agent of a fleet and cancel its child fleets; sandboxes keep running`).action(async(e,t)=>{let{client:n}=K(t),r=await(await n.fleets.list({fleetId:e})).cancel();t.json?I({fleetId:e,...r}):L(`Fleet ${e}: interrupted ${r.interrupted} agents, cancelled ${r.children} child fleets`)})}const Js=[`list`,`create`,`delete`,`exec`,`prompt`,`read`,`write`];function Ys(e){if(!(!e||e.length===0)){for(let t of e)if(!Js.includes(t))throw Error(`Invalid token action '${t}'. Allowed: ${Js.join(`, `)}`);return e}}function Xs(e){return e.length<=12?`****`:`${e.slice(0,6)}...${e.slice(-4)} (masked — use --json for full value)`}function Zs(e){e.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(e,t)=>{let{client:n}=K(t),r=z(`Minting fleet token...`);r.start();let i=await n.fleets.createToken(e,{actions:Ys(t.action),ttlMinutes:t.ttlMinutes?Number(t.ttlMinutes):void 0});r.stop(),t.json?I(i):(B({"Fleet ID":i.fleetId,Token:Xs(i.token),"Expires at":new Date(i.expiresAt).toISOString(),Actions:i.actions.join(`, `)}),console.log(`
147
- Re-run with --json to print the full token value.`))})}function Qs(){let e=new x(`workspace`).description(`Manage a fleet's shared workspace`);return e.command(`snapshot <fleet-id>`).description(`Snapshot the fleet's shared workspace`).action(async(e,t)=>{let{client:n}=K(t),r=z(`Creating workspace snapshot...`);r.start();let i=await n.fleets.createWorkspaceSnapshot(e);r.stop(),t.json?I(i):L(`Workspace snapshot created: ${i.snapshotId??i.id}`)}),e.command(`restore <fleet-id> <snapshot-id>`).description(`Restore the fleet's shared workspace from a snapshot`).action(async(e,t,n)=>{let{client:r}=K(n),i=z(`Restoring workspace...`);i.start();let a=await r.fleets.restoreWorkspaceSnapshot(e,t);i.stop(),n.json?I(a):L(`Workspace restored from ${a.snapshotId??t}`)}),e.command(`reconcile <fleet-id>`).description(`Re-mount the shared workspace on all fleet machines`).action(async(e,t)=>{let{client:n}=K(t),r=z(`Reconciling workspace...`);r.start();let i=await n.fleets.reconcileWorkspace(e);r.stop(),t.json?I(i):(B({"Fleet ID":i.fleetId,Checked:i.checked,"Orphaned mounts":i.orphanedMounts}),F(i.machines,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`mounted`,header:`Mounted`,width:10}]))}),e}function $s(){let e=new x(`fleet`).description(`Manage sandbox fleets`);return Ks(e),ls(e),e.addCommand(Qs()),qs(e),ss(e),Zs(e),e}function ec(){let e=new x(`fs`).description(`File system operations on sandboxes`);return e.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(e,t,n,r)=>{let{context:i,client:a}=K(r),o=await J(a,i,e);if(o=await Y(o),!k.existsSync(t))throw Error(`Local file not found: ${t}`);let s=k.statSync(t),c=Date.now();r.json||console.error(`Uploading ${t} to ${n}...`),await o.fs.upload(t,n,{onProgress:e=>{if(r.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesUploaded}/${e.totalBytes} bytes)`)}});let l=Date.now()-c;r.json||console.error(``),r.json?I({success:!0,localPath:t,remotePath:n,size:s.size,durationMs:l}):console.log(`✓ Uploaded ${s.size} bytes in ${l}ms`)}),e.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(e,t,n,r)=>{let{context:i,client:a}=K(r),o=await J(a,i,e);o=await Y(o);let s=Date.now();r.json||console.error(`Downloading ${t} to ${n}...`),await o.fs.download(t,n,{onProgress:e=>{if(r.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesDownloaded}/${e.totalBytes} bytes)`)}});let c=Date.now()-s,l=k.statSync(n);r.json||console.error(``),r.json?I({success:!0,remotePath:t,localPath:n,size:l.size,durationMs:c}):console.log(`✓ Downloaded ${l.size} bytes in ${c}ms`)}),e.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(e,t,n)=>{let{context:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a);let o=await a.fs.list(t,{all:n.all,long:n.long});if(n.json)I(o);else if(n.long)Ht([`Mode`,`Owner`,`Group`,`Size`,`Modified`,`Name`],o.map(e=>{let t=e.isDir?`d`:e.isSymlink?`l`:`-`,n=tc(e.permissions),r=e.isDir?`<DIR>`:nc(e.size),i=e.modTime.toLocaleDateString();return[t+n,e.owner,e.group,r,i,e.name]}));else{let e=o.map(e=>e.isDir?`${e.name}/`:e.name);console.log(e.join(` `))}}),e.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(e,t,n)=>{let{context:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a);let o=await a.fs.stat(t);n.json?I(o):(console.log(` File: ${o.name}`),console.log(` Path: ${o.path}`),console.log(` Size: ${nc(o.size)} (${o.size} bytes)`),console.log(` Type: ${o.isDir?`directory`:o.isSymlink?`symlink`:`file`}`),console.log(` Mode: ${tc(o.permissions)} (${o.permissions.toString(8)})`),console.log(` Owner: ${o.owner}`),console.log(` Group: ${o.group}`),console.log(` Modified: ${o.modTime.toISOString()}`),console.log(` Accessed: ${o.accessTime.toISOString()}`))}),e.command(`cat`).description(`Print file contents`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to file`).action(async(e,t,n)=>{let{context:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a);let o=await a.read(t);n.json?I({path:t,content:o}):console.log(o)}),e.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(e,t,n)=>{let{context:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a),await a.fs.delete(t,{recursive:n.recursive}),n.json?I({success:!0,path:t,deleted:!0}):console.log(`✓ Deleted: ${t}`)}),e.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(e,t,n)=>{let{context:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a),await a.fs.mkdir(t,{recursive:n.parents}),n.json?I({success:!0,path:t,created:!0}):console.log(`✓ Created: ${t}`)}),e.command(`exists`).description(`Check if a path exists`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to check`).action(async(e,t,n)=>{let{context:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a);let o=await a.fs.exists(t);n.json?I({path:t,exists:o}):(console.log(o?`exists`:`not found`),process.exit(+!o))}),e}function tc(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 nc(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 rc(){let e=new x(`git`).description(`Git operations in a sandbox workspace`);return e.command(`status`).description(`Show git repository status`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching status...`);t.json||i.start();let a=await J(r,n,e);a=await Y(a);let o=await a.git.status();if(i.stop(),t.json)I(o);else if(!o.isRepo)console.log(`No git repository in the sandbox workspace.`);else{if(console.log(`Branch: ${o.branch??`unknown`}`),console.log(`HEAD: ${o.head.slice(0,7)||`(no commits)`}`),console.log(`Dirty: ${o.isDirty?`yes`:`no`}`),o.ahead&&console.log(`Ahead: ${o.ahead}`),o.behind&&console.log(`Behind: ${o.behind}`),o.staged.length>0){console.log(`\nStaged (${o.staged.length}):`);for(let e of o.staged)console.log(` + ${e}`)}if(o.modified.length>0){console.log(`\nModified (${o.modified.length}):`);for(let e of o.modified)console.log(` M ${e}`)}if(o.untracked.length>0){console.log(`\nUntracked (${o.untracked.length}):`);for(let e of o.untracked)console.log(` ? ${e}`)}}}),e.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(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching log...`);t.json||i.start();let a=await J(r,n,e);a=await Y(a);let o=await a.git.log(Number.parseInt(t.limit,10));if(i.stop(),t.json)I(o);else if(o.length===0)console.log(`No commits found`);else for(let e of o)console.log(`${e.shortSha} ${e.message.split(`
148
- `)[0]} (${e.author}, ${e.date.toLocaleDateString()})`)}),e.command(`diff`).description(`Show diff`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--ref <ref>`,`Ref to diff against`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching diff...`);t.json||i.start();let a=await J(r,n,e);a=await Y(a);let o=await a.git.diff(t.ref);i.stop(),t.json?I(o):o.raw?console.log(o.raw):console.log(`${o.additions} additions, ${o.deletions} deletions across ${o.files.length} files`)}),e.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:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a),await a.git.add(t),L(`Staged: ${t.join(`, `)}`)}),e.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(e,t)=>{let{context:n,client:r}=K(t),i=await J(r,n,e);i=await Y(i);let a=await i.git.commit(t.message,{amend:t.amend});t.json?I(a):L(`Committed: ${a.shortSha} ${a.message}`)}),e.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:r}=K(t),i=z(`Pushing...`);i.start();let a=await J(r,n,e);a=await Y(a),await a.git.push({force:t.force}),i.stop(),L(`Pushed to remote`)}),e.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:r}=K(t),i=z(`Pulling...`);i.start();let a=await J(r,n,e);a=await Y(a),await a.git.pull({rebase:t.rebase}),i.stop(),L(`Pulled from remote`)}),e.command(`branches`).description(`List branches`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching branches...`);t.json||i.start();let a=await J(r,n,e);a=await Y(a);let o=await a.git.branches();i.stop(),t.json?I(o):o.length===0?console.log(`No branches found`):Ht([`Name`,`Current`,`Remote`],o.map(e=>[e.name,e.current?`* `:` `,e.upstream??`-`]))}),e.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:r,client:i}=K(n),a=await J(i,r,e);a=await Y(a),await a.git.checkout(t,{create:n.create}),L(`Checked out: ${t}${n.create?` (new)`:``}`)}),e}function ic(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 C(`sha256`).update(n).digest(`hex`).slice(0,t)}Object.freeze([`HS256`]),Object.freeze([`RS256`]);async function ac(e,t,n=`tangle --help`){let r=new AbortController,i=e??r.signal,a=()=>{r.abort(),process.stderr.write(`Stopping…
149
- `)};e||(process.once(`SIGINT`,a),process.once(`SIGTERM`,a));try{return i.throwIfAborted(),await t(i)}catch(e){if(!i.aborted||e instanceof V&&e.code===`RUN_STOPPED`)throw e;let t=new V(`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 oc(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 V(`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 sc(e,t){let n=t.signal;return async r=>{let i=Object.hasOwn(e,r.gate)?e[r.gate]:void 0,a=`--param ${Be(`gate.${r.gate}=<choice>`)}`,o=`${r.question} Choose one of: ${r.choices.join(`, `)}`,s=()=>new V(`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 $r(`${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 cc=N.string().regex(/^[a-f0-9]{64}$/),lc=N.strictObject({version:N.literal(1),runId:N.uuid(),file:N.string().refine(ge),cwd:N.string().refine(ge),sourceDigest:cc,graphDigest:cc,params:N.record(N.string(),N.unknown()),gateChoices:N.record(N.string(),N.string()).optional(),startedAt:N.iso.datetime(),seat:N.string().optional()});function X(e){throw new V(`GRAPH_RESUME_REFUSED`,`The graph run cannot be resumed`,e,`tangle graph run --help`)}async function uc(e){N.uuid().safeParse(e).success||X(`Use a recorded graph run ID`);let t;try{let n=j(await Ge(j(M(),`.tangle`)),`runs`,e);await Ge(n)!==n&&X(`The run directory redirects elsewhere`),t=await Ue(j(n,`input.json`),se.O_RDONLY|se.O_NOFOLLOW),(await t.stat()).isFile()||X(`The run input is not a regular file`);let r=lc.parse(JSON.parse(await t.readFile(`utf8`)));return(r.runId!==e||await Ge(r.cwd)!==r.cwd)&&X(`The recorded run or workspace identity changed`),r}catch(e){if(e instanceof V)throw e;return X(`The private recorded run input is missing or invalid`)}finally{await t?.close()}}async function dc(e,t){await qe(j(e,`input.json`),JSON.stringify(t),{flag:`wx`,mode:384,flush:!0})}function fc(e,t,n,r,i={}){e.sourceDigest!==n&&X(`The authored graph source changed`),t.cloud&&X(`A local run cannot move to cloud execution`),Object.entries(r).some(([t,n])=>!Object.hasOwn(e.params,t)||re(n)!==re(e.params[t]))&&X(`A recorded graph parameter changed`),Object.entries(i).some(([t,n])=>e.gateChoices?.[t]!==n)&&X(`A recorded gate choice changed`),t.seat!==void 0&&t.seat!==e.seat&&X(`The recorded graph seat override changed`)}const pc=`claude,codex,kimi,opencode,gemini,pi`;function mc(e,t){let n;return async(r,{node:i,lastCandidate:a})=>{t.throwIfAborted();let o;try{o=r===void 0?void 0:ae(r)}catch(e){throw e instanceof Error&&Object.assign(e,{node:i,seat:r,fixCommand:`tangle graph run --help`}),e}n??=Je({cwd:e,signal:t,config:Ye({...process.env,BRIDGE_BACKENDS:pc,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 V(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??ae(f.id).harness,m=o?.provider??f.provider,h=o?.model??f.id.slice(p.length+1);if(!m||!h)throw new V(`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 hc=Xe(Se);function gc(e,t,n=`tangle graph run --help`){throw new V(`SEAT_NONE_DETECTED`,e,t,n)}function _c(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 V(`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 vc(e){return e.some(e=>(e.profile?.seats?.length??0)>0)}function yc(e){let t=e?.trim();if(t)return/\s/u.test(t)&&gc(`A seat account, command, or credential must be a single token`,`The seat command is an executable path, not a shell line`),t}function bc(e){let t=yc(e.seatAccount),n=yc(e.seatCommand),r=yc(e.seatCredential);return r&&!n&&!t&&gc(`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}:{}}}function xc(e){if(e.seats===void 0)return e;let{seats:t,...n}=e;return n}async function Sc(e,t,n){if(e.account)return e.account;e.command||gc(`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 hc(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`;gc(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))&&gc(`The seat command did not print an account id`,`The command must print one account id and nothing else`),i}function Cc(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 Sc(t,a,n);return!o&&!t.account&&r.set(s,c),(!c||/\s/u.test(c)||i.resumeSeatId!==void 0&&i.resumeSeatId!==c)&&gc(`Node '${i.nodeId}' has no seat account`,`The authored seat, account flag, or seat command did not yield one`),{seat:c,backend:{backend:`provider`,provider:Qe({baseUrl:e.bridgeUrl,bearerToken:e.bridgeBearer}),defaults:{workspace:{cwd:{base:`host`,path:e.cwd}}},runtime:`cli`,outputFormat:`json`,destroyOnSettle:!0,requireTerminalEvent:!0,profileForCreate:xc}}}}function Z(e){return Br({signal:e.signal,...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.baseUrl===void 0?{}:{baseUrl:e.baseUrl}})}const wc=N.object({version:N.literal(1),type:N.enum([`state`,`ack`,`error`,`event`]),requestId:N.string().optional(),operationId:N.string().optional(),command:N.string().optional(),code:N.string().optional(),message:N.string().optional(),result:N.unknown().optional()}).passthrough(),Tc=N.object({state:N.object({runConfiguration:N.unknown()}),view:N.object({capabilities:N.record(N.string(),N.object({available:N.boolean(),reason:N.string().optional()}))})}),Ec=N.object({status:N.enum([`completed`,`failed`,`cancelled`]),analysis:N.object({id:N.string().min(1)}).passthrough(),source:N.object({runtimeRun:N.unknown()}).passthrough()}).passthrough(),Dc=`TANGLE_GRAPH_ANALYSIS_SOURCE`;async function Oc(e,t,n){if(!e.startsWith(`wfrun_`)){let t=j(await Ge(j(M(),`.tangle`)),`runs`,e);if(await Ge(t)!==t)throw new V(`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:N.object({runId:N.literal(e),runDir:N.literal(t)})}}let r={signal:n,...t.apiKey===void 0?{}:{apiKey:t.apiKey},...t.baseUrl===void 0?{}:{baseUrl:t.baseUrl}},i=await Z(r),a=N.object({id:N.literal(e),workflowId:N.string(),revUsed:N.number().int(),execution:N.object({kind:N.literal(`graph`),sourceSha:N.string(),authoredGraphDigest:N.string(),graphDigest:N.string()}),runtime:N.object({snapshot:N.object({supervisors:N.tuple([N.object({id:N.string()})])})})}).parse(await i.workflows.getRun(e,{signal:n})),o=a.runtime.snapshot.supervisors[0];if(!o)throw new V(`BRAID_RPC_FAILED`,`The cloud run has no retained Runtime root`,`Wait for execution evidence before analysis`,`tangle graph inspect ${e}`);let s=await Ir(r);if(new URL(s.baseUrl.replace(/\/+$/,``)).href!==new URL(i.baseUrl.replace(/\/+$/,``)).href)throw new V(`AUTH_REQUIRED`,`The analysis source origin changed`,`Use the same authenticated platform origin`,`tangle auth status --json`);return{source:`runtime:${e}@${Dc}`,env:{[Dc]:JSON.stringify({url:`${s.baseUrl.replace(/\/+$/,``)}/v1/workflows/runs/${encodeURIComponent(e)}`,headers:{Authorization:`Bearer ${s.token}`}})},schema:N.object({runId:N.literal(e),remoteEndpointEnv:N.literal(Dc),checkpoint:N.object({workflowId:N.literal(a.workflowId),runtimeRunId:N.literal(o.id),revUsed:N.literal(a.revUsed),sourceSha:N.literal(a.execution.sourceSha),authoredGraphDigest:N.literal(a.execution.authoredGraphDigest),graphDigest:N.literal(a.execution.graphDigest)})})}}async function kc(e,t){if(!e.startsWith(`wfrun_`)&&!N.uuid().safeParse(e).success)throw new V(`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 V(`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 V(`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)?ve(process.cwd(),n):n;return ac(t.signal,async n=>{let i=await Oc(e,t,n),a=i.source;return $l({signal:n,errorRunId:e},async n=>{let o=await n.bridge(),s=await He(j(n.runDir,`analysis-`)),c=j(s,`config.json`),l=j(s,`database.key`),u=j(s,`state.sqlite`),d=`connection-owned-graph-bridge`,f=new Date().toISOString();await qe(l,te(32),{mode:384,flag:`wx`}),await qe(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-${w()}`,h=`op-${w()}`,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}},ee={version:1,requestId:v,operationId:h,command:`shutdown`,params:{mode:`wait`}},x,S,C,T,E={transform:e=>{let t=wc.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 V(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`&&(x??=e),e.requestId===_&&e.type===`ack`&&(S??=e),e.requestId===v&&e.type===`ack`&&(C??=e)}},D=await ze({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},E,{stdin:[y,...t.dryRun?[]:[b],ee].map(e=>JSON.stringify(e)).join(`
138
+ `)?`${e}\n`:`${e}\n\n`}function os(){let e=process.env.SHELL??``;return e.includes(`zsh`)?M(N(),`.zshrc`):e.includes(`bash`)?M(N(),`.bashrc`):M(N(),`.zshrc`)}function ss(e){if(e===`shell`||e===`env`||e===`dockerfile`)return e;throw Error(`--format must be one of: shell, env, dockerfile (got '${e}')`)}function cs(e){if(e===`full`||e===`prompts`||e===`metadata`)return e;throw Error(`--content must be one of: full, prompts, metadata (got '${e}')`)}async function ls(e){let t=ns({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format});if(console.log(t),e.format!==`shell`){console.log(),V(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(),V(`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??os(),r=process.stdin.isTTY?await Vi(`Append this idempotent block to ${n}? (y/N)`,`n`):`n`;if(r.toLowerCase()!==`y`&&r.toLowerCase()!==`yes`){console.log(),V(`Not writing. To append later: tangle connect claude-code --rc ${n}`);return}let i=rs({endpoint:e.endpoint,apiKey:e.apiKey,projectKey:e.projectKey,content:e.content,format:e.format}),{contents:a,changed:o}=is(Yo(n),i);if(!o){console.log(),B(`Already present in ${n} — nothing to change.`);return}Xo(n,a),console.log(),B(`Wrote Tangle Intelligence env block to ${n}.`),V(`Reload your shell (e.g. 'source ${n}') before running the agent.`)}function us(e){let t=[],n={header:null,body:[]};for(let r of e.split(`
139
+ `))ds(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 ds(e){let t=e.trim();return t.startsWith(`[`)&&t.endsWith(`]`)&&!t.includes(`=`)||t.startsWith(`[[`)&&t.endsWith(`]]`)}function fs(e){let t=[];for(let n of e)n.header!==null&&t.push(n.header),t.push(...n.body);return t.join(`
140
+ `)}function ps(e){return[{key:`environment`,line:`environment = "prod"`},{key:`log_user_prompt`,line:`log_user_prompt = true`},{key:`exporter`,line:`exporter = { otlp-http = { endpoint = "${so(e.endpoint)}/v1/logs", protocol = "json", headers = { "Authorization" = "Bearer ${e.apiKey??"${TANGLE_API_KEY}"}" } } }`}]}function ms(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 hs(e,t){let n=ps(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=us(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&&!gs(r)&&r.body.push(``),i.push(t);let a=_s(fs(i));return{contents:a,changed:a!==_s(e)}}let o=a.body.filter(e=>{let t=ms(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=_s(fs(i));return{contents:c,changed:c!==_s(e)}}function gs(e){return e.body.length>0&&e.body[e.body.length-1].trim()===``}function _s(e){return e.endsWith(`
142
+ `)?e:`${e}\n`}function vs(e){let t=M(N(),`.codex`,`config.toml`),{contents:n,changed:r}=hs(Yo(t),{endpoint:e.endpoint,apiKey:e.apiKey});if(!e.write){console.log(n.trimEnd());return}if(!r){B(`${t} already has the Tangle [otel] block — nothing to change.`);return}Xo(t,n),B(`Merged the Tangle [otel] block into ${t}.`),V("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."),V(`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 ys(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`${qo[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 bs(e){let t=Date.now()+e.timeoutSeconds*1e3,n=3e3,r=Math.min(e.timeoutSeconds*1e3,1e4),i=H(`Checking whether content is flowing…`);i.start();let a;try{for(;;){try{a=await oo({endpoint:e.endpoint,apiKey:e.apiKey,timeoutMs:r})}catch(e){if(Date.now()>=t)throw e;await Le(n);continue}if(a.contentSeen||Date.now()>=t)break;await Le(n)}}finally{i.stop()}if(!a)throw Error(`onboarding status check returned no result`);xs(a,e.agent),a.contentSeen||(process.exitCode=1)}function xs(e,t){if(e.contentSeen){B(`Content flowing — Tangle Intelligence can analyze this feed.`),U({"Last seen":e.lastSeenAt??`just now`,Window:`${e.windowDays}d`});return}if(e.tracesSeen){En(`Metadata-only — traces are arriving but carry no content. You missed a content gate.`);let n=t?[t]:Object.keys(e.byAgent).filter(Jo),r=n.length>0?n:Ko;for(let n of r){let r=e.byAgent[n];(t||!r||r.tracesSeen&&!r.contentSeen)&&V(ys(n))}return}En(`No traces yet for your tenant. Run your agent once on a real task, then re-run --verify.`),t&&V(ys(t))}function Ss(e){let t=e??process.env.TANGLE_INTELLIGENCE_API_KEY??Gr(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 Cs(){return new S(`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`,Ga).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=so(t.endpoint);if(t.run){if((e?Ts(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 ks({endpoint:n,apiKey:Ss(t.apiKey),opencodeUrl:t.opencodeUrl});return}if(t.verify){await bs({endpoint:n,apiKey:Ss(t.apiKey),agent:e?Ts(e):void 0,timeoutSeconds:Go(t.timeout,`--timeout`)});return}let r=e?Ts(e):await Es(),i=t.inlineKey?Ss(t.apiKey):void 0;r===`claude-code`?await ls({endpoint:n,apiKey:i,projectKey:t.project,rcPath:t.rc,write:t.write!==!1,content:cs(t.content),format:ss(t.format)}):r===`codex`?vs({endpoint:n,apiKey:i,projectKey:t.project,write:t.write!==!1}):r===`opencode`?Ds({endpoint:n}):Os(r,{endpoint:n}),console.log(),V(`Run your agent on a real task, then verify content is flowing: tangle connect ${r} --verify`)})}function ws(){return new S(`opencode-exporter`).description(`Export a running OpenCode's content to Tangle Intelligence (standalone shim)`).option(`--endpoint <url>`,`OTLP endpoint base`,Ga).option(`--opencode-url <url>`,`OpenCode server base URL (or set OPENCODE_BASE_URL)`).action(async e=>{await ks({endpoint:so(e.endpoint),apiKey:Ss(e.apiKey),opencodeUrl:e.opencodeUrl})})}function Ts(e){if(Jo(e))return e;throw Error(`Unknown agent '${e}'. Choose one of: ${Ko.join(`, `)}`)}async function Es(){if(!process.stdin.isTTY)throw Error(`Specify an agent: tangle connect <${Ko.join(`|`)}>`);console.log(`Which coding agent are you connecting?`),Ko.forEach((e,t)=>{console.log(` ${t+1}) ${qo[e]} (${e})`)});let e=await Vi(`Enter a number or name`,`1`);return Ko[Number.parseInt(e,10)-1]||Ts(e.trim())}function Ds(e){let t=so(e.endpoint);En(`OpenCode has no native OTel exporter, so a standalone install emits nothing without a shim.`),console.log(),U({"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(),V(`Start OpenCode in server mode ('opencode serve'), then in another terminal run: tangle connect opencode --run`),V(`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`),V(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting the exporter.`)}function Os(e,t){let n=so(t.endpoint),r=qo[e];En(`${r} has no native OTel exporter, so a standalone install emits nothing without instrumentation.`),console.log(),U({"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(),V(`Label this project so Tangle rolls up + automates per-project: export OTEL_RESOURCE_ATTRIBUTES=tangle.subject.key=my-project before starting ${r}.`),V(`Verify content is flowing: tangle connect ${e} --verify`)}async function ks(e){let t=Bo(e.opencodeUrl),n=new AbortController,r=()=>n.abort();process.on(`SIGINT`,r),process.on(`SIGTERM`,r),V(`Subscribing to OpenCode at ${t} — exporting content to Tangle.`),V(`Run OpenCode tasks now. Press Ctrl-C to stop.`),console.log();let i=0,a;try{a=await Wo({endpoint:e.endpoint,apiKey:e.apiKey,opencodeBaseUrl:t,signal:n.signal,onExport:({eventType:e,records:t})=>{i+=t,V(`exported ${t} record(s) from ${e} (total ${i})`)}})}catch(e){if(e instanceof Ho){let{recordsExported:t,contentEventsExported:n}=e.partial;console.log(),En(`Exporter failed after exporting ${t} content record(s) from ${n} event(s): ${e.message}`)}throw e}finally{process.off(`SIGINT`,r),process.off(`SIGTERM`,r)}if(console.log(),a.contentEventsExported===0){En(`Saw ${a.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}B(`Exported ${a.recordsExported} content record(s) from ${a.contentEventsExported} event(s).`),V(`Verify it landed: tangle connect opencode --verify`)}function As(){let e=new S(`environments`).alias(`env`).description(`Manage sandbox environments`);return e.command(`list`).alias(`ls`).description(`List available environments`).action(async e=>{let{client:t}=J(e),n=H(`Fetching environments...`);e.json||n.start();let r=await t.environments.list();n.stop(),e.json?z(r):r.length===0?console.log(`No environments found`):jn([`ID`,`Description`,`Version`,`Runtimes`],r.map(e=>[e.id,e.description??``,e.version,e.runtimes.join(`, `)]))}),e.command(`get`).description(`Get environment details`).argument(`<id>`,`Environment ID`).action(async(e,t)=>{let{client:n}=J(t),r=H(`Fetching environment...`);t.json||r.start();let i=await n.environments.get(e);if(r.stop(),!i){console.error(`Environment not found: ${e}`),process.exit(1);return}t.json?z(i):(console.log(`ID: ${i.id}`),console.log(`Description: ${i.description??`-`}`),console.log(`Version: ${i.version}`),console.log(`Runtimes: ${i.runtimes.join(`, `)}`),i.base&&console.log(`Base: ${i.base}`))}),e}const js=P.string().trim().toLowerCase().min(1).max(64).regex(/^[a-z][a-z0-9-]*$/),Ms=P.string().trim().toLowerCase().min(1).max(128).regex(/^[a-z0-9][a-z0-9._-]*$/),Ns=P.object({kind:Ms,count:P.number().int().positive().default(1),vramGb:P.number().positive().optional()}).strict();P.object({command:P.string().min(1).max(8192),timeoutMs:P.number().int().positive().max(2147453647).optional(),env:P.record(P.string(),P.string()).optional(),cwd:P.string().min(1).max(2048).optional()}).strict(),P.object({refresh:P.enum([`true`,`false`]).optional(),acceleratorKind:Ms.optional(),acceleratorCount:P.coerce.number().pipe(Ns.shape.count.unwrap()).optional(),acceleratorVramGb:P.coerce.number().positive().optional()}).strict(),P.object({maxSpendUsd:P.number().positive().max(1e4).optional(),maxLifetimeSeconds:P.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 Ps=P.object({provider:js.optional(),image:P.string().min(1).max(512).optional(),env:P.record(P.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),P.string()).optional(),diskGb:P.number().int().positive().optional(),volumeGb:P.number().int().nonnegative().optional(),volumeMountPath:P.string().startsWith(`/`).max(2048).optional(),region:P.string().min(1).max(128).optional(),manifest:P.record(P.string(),P.unknown()).optional(),command:P.array(P.string().max(8192)).min(1).max(256).optional(),ports:P.array(P.number().int().min(1).max(65535)).max(32).optional(),endpoint:P.object({port:P.number().int().min(1).max(65535),healthPath:P.string().regex(/^\/(?![/\\])/).refine(e=>![`\r`,`
143
+ `,` `].some(t=>e.includes(t))).max(2048).optional()}).strict().optional(),allowSpot:P.boolean().optional(),maxHourlyUsd:P.number().positive().optional(),weights:P.object({manifestSha:P.string().regex(/^[a-f0-9]{64}$/),sizeBytes:P.number().int().positive().safe()}).strict().optional(),arms:P.array(P.unknown()).min(1).max(256).optional(),maxSpendUsd:P.number().positive().max(1e4),maxLifetimeSeconds:P.number().int().positive().max(1440*60),idleTimeoutSeconds:P.number().int().positive().optional()}).strict();Ps.extend({accelerator:Ns});const Fs=Ns,Is=js;P.object({...Ps.omit({env:!0}).shape,id:P.string(),projectRef:P.string(),ownerUserId:P.string(),productId:P.string().optional(),provider:Is,providerLeaseId:P.string().optional(),providerInstanceType:P.string().optional(),endpointUrl:P.string().optional(),status:P.enum([`provisioning`,`ready`,`detaching`,`destroyed`,`failed`]),accelerator:Fs,providerCostPerHourUsd:P.number().optional(),customerPricePerHourUsd:P.number().optional(),estimatedProviderCostUsd:P.number().optional(),estimatedCustomerCostUsd:P.number().optional(),providerSelection:P.object({strategy:P.enum([`explicit`,`cheapest`,`ranked`]),selectedProvider:Is,requestedProvider:Is.optional(),candidates:P.array(P.object({provider:Is,accelerator:Fs,providerInstanceType:P.string().optional(),region:P.string().optional(),pricingSource:P.enum([`live`,`configured`]).optional(),providerCostPerHourUsd:P.number(),customerPricePerHourUsd:P.number(),maxLifetimeSeconds:P.number(),estimatedProviderCostUsd:P.number(),estimatedCustomerCostUsd:P.number()})),rejected:P.array(P.object({provider:Is,error:P.string()}))}).optional(),createdAt:P.string(),updatedAt:P.string(),readyAt:P.string().optional(),startedAt:P.string().optional(),lastUsedAt:P.string().optional(),destroyedAt:P.string().optional(),failure:P.string().optional(),billing:P.object({seconds:P.number(),providerCostUsd:P.number(),customerCostUsd:P.number(),providerCostPerHourUsd:P.number(),customerPricePerHourUsd:P.number(),startedAt:P.string(),stoppedAt:P.string()}).optional()});function Ls(e){return{kind:Gs(e.kind),count:e.count?Ws(e.count,`--accelerator-count`):1,...e.memory?{vramGb:qs(e.memory,`--accelerator-memory`)}:{}}}function Rs(e,t,n){if(!t&&Object.values(e).some(Boolean))throw Error(n);return t?Bs(e,`--gpu-`):void 0}function zs(e){return{...Bs(e,`--`),accelerator:Ls({kind:e.acceleratorKind,count:e.acceleratorCount,memory:e.acceleratorMemory})}}function Bs(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:Ks(n,`${t}provider`)}:{},...r?{image:r}:{},...i?{env:Us(i,`${t}env`,`env`)}:{},maxSpendUsd:qs(a,`${t}max-spend-usd`),maxLifetimeSeconds:Ws(o,`${t}max-lifetime`),...s?{idleTimeoutSeconds:Ws(s,`${t}idle-timeout`)}:{}}}function Vs(e){return e.length===1?e[0]:e.map(qe).join(` `)}function Hs(e){return{timeoutMs:e.timeout?Ws(String(e.timeout),`--timeout`):void 0,env:e.env?Us(e.env,`--env`,`env`):void 0}}function Us(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 Ws(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 Gs(e){let t=Ms.safeParse(e);if(t.success)return t.data;throw Error(`--accelerator-kind must contain only letters, numbers, dots, underscores, or hyphens`)}function Ks(e,t){let n=js.safeParse(e);if(n.success)return n.data;throw Error(`${t} must start with a letter and contain only letters, numbers, or hyphens`)}function qs(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 Js(){return new S(`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(e,t,n)=>{try{let{context:r,client:i}=J(n),a=Vs(t),o=Us(n.env??[],`--env`,`env`),s=H(`Executing: ${a}`);n.json||s.start();let c=await Y(i,r,e);c=await X(c);let l=await c.exec(a,{cwd:n.cwd,env:Object.keys(o).length>0?o:void 0,timeoutMs:Number.parseInt(n.timeout,10)});s.stop(),n.json?z(l):(l.stdout&&process.stdout.write(l.stdout),l.stderr&&process.stderr.write(l.stderr)),l.exitCode!==0&&(process.exitCode=l.exitCode)}catch(e){if(e instanceof i){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 G(Error(t,{cause:e}))}G(e)}})}function Ys(e){e.command(`capabilities`).description(`List fleet drivers and their supported features`).action(async e=>{let{client:t}=J(e),n=H(`Fetching capabilities...`);n.start();let r=await t.fleets.capabilities();n.stop(),e.json?z(r):R(r.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}])}),e.command(`usage <fleet-id>`).description(`Show fleet usage and reliability insights`).action(async(e,t)=>{let{client:n}=J(t),r=H(`Fetching usage...`);r.start();let i=await n.fleets.usage(e);if(r.stop(),t.json)z(i);else if(U({"Fleet ID":i.usage.fleetId,Status:i.usage.status,Machines:i.usage.machineCount,Running:i.usage.runningMachines,Failed:i.usage.failedMachines,"Runtime (ms)":i.usage.meteredUsage?.runtimeMs,"Reliability score":i.insights.reliabilityScore,"Failure rate":i.insights.failureRate}),i.insights.recommendedActions.length>0){console.log(`
144
+ Recommended actions:`);for(let e of i.insights.recommendedActions)console.log(` - ${e}`)}}),e.command(`cost <fleet-id>`).description(`Show the fleet's cost estimate`).action(async(e,t)=>{let{client:n}=J(t),r=H(`Estimating cost...`);r.start();let i=await n.fleets.cost(e);r.stop(),t.json?z(i):U({Plan:i.plan,Currency:i.currency,"Hourly (USD)":i.hourlyUsd,"Max lifetime (s)":i.maxLifetimeSeconds,"Estimated max lifetime (USD)":i.estimatedMaxLifetimeUsd,Machines:i.requestedResources.machines,"Total CPU":i.requestedResources.totalCpu,"Total memory (MB)":i.requestedResources.totalMemoryMb})})}function Xs(e){return[...e.entries()].map(([e,t])=>({machineId:e,sandboxId:t.id,status:t.status}))}function Zs(e){e.command(`list <fleet-id>`).description(`List the machines of one fleet (fleet id is required)`).option(`--status <status>`,`Filter machines by status`).action(async(e,t)=>{let{client:n}=J(t),r=H(`Fetching fleet...`);r.start();let i=await n.fleets.list({fleetId:e,status:t.status});r.stop();let a=Xs(i.machines);t.json?z({fleetId:i.fleetId,machines:a}):R(a,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}])}),e.command(`get <fleet-id>`).description(`Show one fleet's manifest (server record)`).action(async(e,t)=>{let{client:n}=J(t),r=H(`Fetching manifest...`);r.start();let i=await n.fleets.manifest(e);r.stop(),t.json?z(i):(U({"Fleet ID":i.fleetId??i.id,Machines:i.machines.length,"Workspace mode":i.workspace?.mode,"Workspace status":i.workspace?.status,"Max lifetime (s)":i.policy?.maxLifetimeSeconds,"Max spend (USD)":i.policy?.maxSpendUsd,Created:i.createdAt,Updated:i.updatedAt}),R(i.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}]))}),e.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(e,t)=>{let{client:n}=J(t),r=H(`Deleting fleet...`);r.start(),await n.fleets.delete(e,{continueOnError:t.continueOnError}),r.stop(),t.json?z({success:!0,fleetId:e}):B(`Fleet deleted: ${e}`)}),e.command(`reap`).description(`TTL cleanup of all expired fleets (fleet-wide)`).option(`--dry-run`,`Report what would be reaped without deleting`).action(async e=>{let{client:t}=J(e),n=H(`Reaping expired fleets...`);n.start();let r=await t.fleets.reapExpired({dryRun:e.dryRun});n.stop(),e.json?z(r):(U({"Dry run":r.dryRun,Expired:r.expired,Deleted:r.deleted}),R(r.fleets,[{key:`fleetId`,header:`Fleet`,width:24},{key:`expiredAt`,header:`Expired`,width:18},{key:`deleted`,header:`Deleted`,width:10}]))}),e.command(`reconcile`).description(`Drop fleet records whose underlying sandboxes vanished`).option(`--dry-run`,`Report orphans without removing them`).action(async e=>{let{client:t}=J(e),n=H(`Reconciling fleets...`);n.start();let r=await t.fleets.reconcile({dryRun:e.dryRun});n.stop(),e.json?z(r):(U({"Dry run":r.dryRun,Checked:r.checked,Orphaned:r.orphaned,Removed:r.removed}),R(r.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 Qs(e,t){let n=await Ci({apiKey:t.apiKey,baseUrl:t.baseUrl??Qr()}),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 $s(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 Hi();if(t.length===0)throw Error(`${e.flagPrefix}-stdin received empty input on stdin`);return t}}function ec(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 tc(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 nc(e,t){let n={};return e.cpu!==void 0&&(n.cpuCores=Ws(e.cpu,`--cpu`)),e.memory!==void 0&&(n.memoryMB=Ws(e.memory,`--memory`)),e.disk!==void 0&&(n.diskGB=Ws(e.disk,`--disk`)),t&&(n.accelerator=t),Object.keys(n).length>0?n:void 0}function rc(e){let t=e.split(`/`);return t.length>=2?{provider:t[0],model:t.slice(1).join(`/`)}:{model:e}}function ic(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]=ac(r.join(`=`))}return t}function ac(e){try{return JSON.parse(e)}catch{return e}}function oc(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`?Ws(e.gitDepth,`--git-depth`):void 0,sparse:Array.isArray(e.gitSparse)?e.gitSparse:void 0,auth:t?{token:t}:void 0}}}function sc(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:cc(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 cc(e){if(e===`s3`||e===`gcs`||e===`r2`)return e;throw Error(`--storage-type must be one of s3, gcs, or r2`)}function lc(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=fe(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=D.parse(t);return n.length>0?n:void 0}function uc(e){V(` Status: ${e.status}`),V(` Provider: ${e.provider}`),V(` GPU: ${e.accelerator.kind} x ${e.accelerator.count}`),e.customerPricePerHourUsd!==void 0&&V(` Customer price: $${e.customerPricePerHourUsd}/hr`),e.estimatedCustomerCostUsd!==void 0&&V(` Max estimate: $${e.estimatedCustomerCostUsd}`),e.billing&&(V(` Billed seconds: ${e.billing.seconds}`),V(` Customer cost: $${e.billing.customerCostUsd}`))}function dc(e){e.result.stdout&&process.stdout.write(e.result.stdout),e.result.stderr&&process.stderr.write(e.result.stderr),V(`Exit code: ${e.result.exitCode}`)}function fc(e){let t=e.command(`gpu`).description(`Manage on-demand GPU leases for a sandbox`);t.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(e,t)=>{let{context:n,client:r}=J(t),i=H(`Checking GPU providers...`);i.start();let a=await(await Y(r,n,e)).gpu.providers(t.acceleratorKind?{accelerator:Ls({kind:t.acceleratorKind,count:t.acceleratorCount,memory:t.acceleratorMemory})}:{});if(i.stop(),t.json){z(a);return}R(a.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 a.statuses){let t=e.state===`credential-invalid`?e.credential?.detail:e.estimateError;t&&V(`${e.provider}: ${t}`)}a.usable.length===0&&V(`No GPU provider is usable on this deployment: set the variables in Needs for one provider on the server.`)}),t.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(e,t)=>{let{context:n,client:r}=J(t),i=H(`Attaching GPU lease...`);i.start();let a=await(await Y(r,n,e)).gpu.attach(zs(t));i.stop(),t.json?z(a):(B(`GPU lease attached: ${a.id}`),uc(a))}),t.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(e,t,n)=>{let r,i,a,o;try{let{context:a,client:o}=J(n),s=await Y(o,a,e),c=H(`Attaching GPU lease...`);c.start(),r=await s.gpu.attach(zs(n)),c.stop();let l=H(`Running GPU command...`);l.start(),i=await s.gpu.exec(r.id,{command:Vs(t),...Hs(n),cwd:n.cwd}),l.stop(),n.json||dc(i)}catch(e){a=e}finally{if(r)try{let{context:t,client:i}=J(n);r=await(await Y(i,t,e)).gpu.detach(r.id)}catch(e){o=e}}if(a){G(a),o&&G(o);return}if(o){G(o);return}n.json?z({lease:r,result:i}):r&&B(`GPU lease detached: ${r.id}`);let s=i?.result.exitCode;s&&s!==0&&(process.exitCode=s)}),t.command(`list <id-or-name>`).description(`List GPU leases attached to a sandbox`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching GPU leases...`);i.start();let a=await(await Y(r,n,e)).gpu.list();i.stop(),t.json?z(a):a.length===0?V(`No GPU leases attached.`):R(a.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}])}),t.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(e,t,n,r)=>{let{context:i,client:a}=J(r),o=H(`Running GPU command...`);o.start();let s=await(await Y(a,i,e)).gpu.exec(t,{command:Vs(n),...Hs(r),cwd:r.cwd});o.stop(),r.json?z(s):dc(s)}),t.command(`detach <id-or-name> <lease-id>`).description(`Detach and destroy a GPU lease`).action(async(e,t,n)=>{let{context:r,client:i}=J(n),a=H(`Detaching GPU lease...`);a.start();let o=await(await Y(i,r,e)).gpu.detach(t);a.stop(),n.json?z(o):(B(`GPU lease detached: ${o.id}`),uc(o))})}function pc(e,t){if(t){z(e);return}if(!e.id){e.kind===`snapshot`&&e.result?.snapshot?B(`Snapshot created: ${e.result.snapshot.snapshotId}`):B(`Sandbox ${e.sandboxId} stopped.`);return}B(`${e.kind===`snapshot`?`Snapshot`:`Stop`} of sandbox ${e.sandboxId} accepted.`),V(`Operation: ${e.id}`),V(`Status: ${e.statusUrl}`)}function mc(e){return`${e.name} (${e.id})`}async function hc(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 gc(e,t,n){if(t)return hc(e,t);let r=ti(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 _c(e,t){ni({id:e.id,name:e.name},t)}function vc(e){ri(e)}async function yc(e){if(e.explicitTeam&&e.personal)throw Error(`--team and --personal cannot be used together`);if(!e.personal)return e.explicitTeam?(await hc(e.client,e.explicitTeam)).id:e.activeTeamId}async function bc(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 hc(e.client,e.explicitTeam)).id}`;if(e.activeTeamId)return`team:${e.activeTeamId}`}function xc(e){if(!e)return e;let t={...e};for(let e of[`authToken`,`execToken`])t[e]!==void 0&&(t[e]=`[REDACTED]`);return t}function Sc(e){e.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(e,t)=>{let{context:n,client:r}=J(t),i=t.nonce===`auto`?g():t.nonce,a=H(`Fetching TEE attestation...`);a.start();let o=await(await Y(r,n,e)).getTeeAttestation(i?{attestationNonce:i}:void 0);a.stop(),t.json?z(o):(B(`Attestation fetched for ${e}`),console.log(`TEE type: ${o.attestation.tee_type}`),console.log(`Evidence bytes: ${o.attestation.evidence.length}`),console.log(`Measurement bytes: ${o.attestation.measurement.length}`),console.log(`Timestamp: ${o.attestation.timestamp}`),o.attestationNonce&&console.log(`Nonce: ${o.attestationNonce}`))}),e.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 e=>{let{context:t,client:n}=J(e),r=H(`Fetching sandboxes...`);r.start();let i=await bc({client:n,explicitTeam:e.team,personal:e.personal,allScopes:e.allScopes,activeTeamId:t.activeTeamId}),a=await n.list({status:e.status===`all`?void 0:e.status,limit:Number.parseInt(e.limit,10),scope:i});r.stop(),e.json?z(a):R(a.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}])}),e.command(`get <id-or-name>`).description(`Get sandbox details`).option(`--profile`,`Show the active agent profile provenance (name, hash, skills)`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching sandbox...`);i.start();let a=await Y(r,n,e);if(i.stop(),t.profile){let e=a.getProfileProvenance?.();e?(V(`Agent profile provenance:`),V(` Base profile: ${e.base.name??`(inline)`} (${e.base.sha256.slice(0,12)}...)`),V(` Effective: ${e.effective.name??`(inline)`} (${e.effective.sha256.slice(0,12)}...)`),V(` Materialized: ${e.materializedAt}`),e.base.sha256!==e.effective.sha256&&V(` ⚠ Profile changed since creation (base ≠ effective)`)):V(`No profile materialized (bare sandbox). Create with --profile <name> to install one.`);return}t.json?z(a):An({id:a.id,name:a.name,status:a.status,resources:a.resources,createdAt:a.createdAt?.toISOString(),expiresAt:a.expiresAt?.toISOString(),connection:a.connection})}),e.command(`shapes`).description(`List the named sandbox sizes, the default, and this account's ceiling`).action(async e=>{let{client:t}=J(e),n=await t.shapes();if(e.json){z(n);return}let r=e=>e.cpuCores<=n.ceiling.cpuCores&&e.memoryMB<=n.ceiling.memoryMB&&e.diskGB<=n.ceiling.diskGB;R(n.presets.map(e=>({name:e.name===n.default?`${e.name} (default)`:e.name,cpu:e.cpuCores,memory:`${e.memoryMB} MB`,disk:`${e.diskGB} GB`,available:r(e)?`yes`:e.name===n.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}]),V(`Ceiling for this account: ${kn(n.ceiling)}`)}),e.command(`delete <id-or-name>`).description(`Delete a sandbox`).option(`-f, --force`,`Skip confirmation`).option(`--name`,`Treat the reference as a sandbox name`).option(`--retry-cleanup`,`Retry server-side cleanup after the sandbox disappeared from get/list`).action(async(e,t)=>{if(!t.force&&!await Bi(`Delete sandbox ${e}? [y/N] `,`--force`)){V(`Cancelled.`);return}let{context:n,client:r}=J(t),i=H(`Deleting sandbox...`);i.start();let a=await Ni(r,n,e,{retryCleanup:t.retryCleanup,name:t.name});i.stop(),B(a===`already_absent`?`Sandbox ${e} was already gone.`:`Sandbox ${e} deleted.`)}),e.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:r}=J(t),i=H(`Stopping sandbox...`);i.start();let a=await Y(r,n,e,{nameOnly:t.name});if(t.wait===!1){let e=await a.stop({wait:!1});i.stop(),pc(e.info,!!t.json);return}await a.stop(),i.stop(),B(`Sandbox ${e} stopped.`)}),e.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 r=K({apiKey:t.apiKey,baseUrl:t.baseUrl,timeout:n}),i=q(r),a=H(`Resuming sandbox...`);a.start();let o=await Y(i,r,e);await o.resume({timeoutMs:n}),t.wait&&(a.text=`Waiting for sandbox to start...`,await o.waitFor(`running`,{timeoutMs:n})),a.stop(),B(`Sandbox ${o.id} resumed.`)})}function Cc(e){e.command(`create`).description(`Create a new sandbox`).option(`-n, --name <name>`,`Sandbox name`).option(`-e, --environment <environment>`,wc).addOption(Tc()).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 C(`--driver <type>`,`Run on Tangle network operators instead of the platform's hosts (--tee needs it)`).choices([`tangle`])).option(`--backend <type>`,`Backend agent type (${n.join(`, `)})`).option(`--backend-model <model>`,`Model override (format: provider/model)`).addOption(new C(`--reasoning-effort <level>`,`Reasoning effort for the backend's model; overrides the profile's model.reasoningEffort`).choices(O)).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 e=>{let t=await $s({envVarName:e.gitTokenEnv,fromStdin:e.gitTokenStdin,flagPrefix:`--git-token`}),n=await $s({envVarName:e.storageSecretAccessKeyEnv,fromStdin:e.storageSecretAccessKeyStdin,flagPrefix:`--storage-secret-access-key`}),r=await $s({envVarName:e.backendApiKeyEnv,fromStdin:e.backendApiKeyStdin,flagPrefix:`--backend-api-key`}),i=ec({secret:e.cliAuth,backend:e.backend,apiKeyGiven:r!==void 0}),a;if(e.profileStdin){let e=await Hi(`--profile-stdin`,`the AgentProfile JSON`);try{a=JSON.parse(e)}catch{G(Error(`--profile-stdin: the input is not valid JSON`));return}}else if(e.profile){let t=String(e.profile);if(t.startsWith(`.`)||t.startsWith(`/`)||t.endsWith(`.json`))try{a=JSON.parse(fe(t,`utf8`))}catch(e){G(Error(`--profile ${t}: ${e.message}`));return}else try{a=await Qs(t,e)}catch(e){G(Error(`--profile ${t}: ${e.message}`));return}}a=Dc(a,e.reasoningEffort);let o=K({apiKey:e.apiKey,baseUrl:e.baseUrl,timeout:e.timeout?Number.parseInt(e.timeout,10):void 0}),s=q(o),c=H(`Creating sandbox...`);c.start();let l=await yc({client:s,explicitTeam:e.team,personal:e.personal,activeTeamId:o.activeTeamId}),u=Us(e.env??[],`--env`,`env`),d=e.metadata?ic(e.metadata):void 0,f=oc(e,t),p=sc(e,n),m=e.acceleratorKind?Ls({kind:String(e.acceleratorKind),count:String(e.acceleratorCount),memory:typeof e.acceleratorMemory==`string`?e.acceleratorMemory:void 0}):void 0,g=Rs({provider:typeof e.gpuProvider==`string`?e.gpuProvider:void 0,image:typeof e.gpuWorkerImage==`string`?e.gpuWorkerImage:void 0,env:Array.isArray(e.gpuEnv)?e.gpuEnv:void 0,maxSpendUsd:typeof e.gpuMaxSpendUsd==`string`?e.gpuMaxSpendUsd:void 0,maxLifetime:typeof e.gpuMaxLifetime==`string`?e.gpuMaxLifetime:void 0,idleTimeout:typeof e.gpuIdleTimeout==`string`?e.gpuIdleTimeout:void 0},!!m,`Create-time GPU lease flags require --accelerator-kind`),v=e.driver?{type:`tangle`}:void 0,y=e.backend||e.backendModel||a?{...e.backend?{type:_(e.backend)}:{},...a?{profile:a}:{},model:e.backendModel||r||i?{...e.backendModel?rc(e.backendModel):{},apiKey:r,...i?{cliAuth:i}:{}}:void 0}:void 0,b=tc(e.secret),x=i?[...new Set([...b??[],i.secretEnv])]:b,S=lc(e.proxySecret),C=nc(e,m),w=e.sshKeyFile??(e.ssh&&!e.sshKey&&!e.sshKeys?.length?[Ec()]:[]),T=[...e.sshKey?[e.sshKey]:[],...w.map(e=>fe(e,`utf8`).trim())],E={name:e.name,environment:e.environment,runtime:e.runtime,bare:e.bare||void 0,sshEnabled:e.ssh||!!e.sshKey||T.length>0||!!e.sshKeys?.length,sshPublicKeys:T.length>0?T:void 0,sshKeyIds:e.sshKeys,webTerminalEnabled:e.webTerminal,env:Object.keys(u).length>0?u:void 0,git:f,...C?{resources:C}:{},gpuLease:g,maxLifetimeSeconds:Number.parseInt(e.lifetime,10),idleTimeoutSeconds:Number.parseInt(e.idleTimeout,10),storage:p,fromSnapshot:e.fromSnapshot,publicTemplateId:e.publicTemplate,publicTemplateVersionId:e.publicTemplateVersion,teamId:l,...e.billingOwner?{billingOwnerId:e.billingOwner}:{},secrets:x,...S?{proxySecrets:S}:{},metadata:d,driver:v,backend:y},D=e.tee?{tee:e.tee,sealed:e.sealed||void 0,attestationRefresh:e.attestationRefresh||e.attestationNonce===`auto`||void 0}:void 0,O=D?await h(s,{...E,confidential:D,attestationNonce:e.attestationNonce??(e.attestationRefresh?`auto`:void 0),requireAttestation:e.requireAttestation??!0}):void 0,k=O?.sandbox??await s.create(E);e.wait&&(c.text=`Waiting for sandbox to start...`,await k.waitFor(`running`,{timeoutMs:12e4}),await k.refresh()),c.stop(),e.json?z({id:k.id,name:k.name,status:k.status,resources:k.resources,createdAt:k.createdAt,expiresAt:k.expiresAt,connection:xc(k.connection),teamId:l,gpuLease:k.gpuLease,confidential:D,attestation:O?.attestation,attestationNonce:O?.attestationNonce}):(B(`Sandbox created: ${k.id}`),An({id:k.id,name:k.name,status:k.status,resources:k.resources,createdAt:k.createdAt?.toISOString(),expiresAt:k.expiresAt?.toISOString(),connection:k.connection}),l&&console.log(`Team: ${l}`),k.gpuLease&&(console.log(`GPU lease: ${k.gpuLease.id}`),uc(k.gpuLease)),D&&(console.log(`TEE: ${D.tee}`),console.log(`Attestation: ${O?.attestation?`present`:`not returned`}`),O?.attestationNonce&&console.log(`Attestation nonce: ${O.attestationNonce}`)))})}const wc="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 Tc(){return new C(`--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(c)}function Ec(){let e=[`id_ed25519`,`id_ecdsa`,`id_rsa`].map(e=>`${N()}/.ssh/${e}.pub`),t=e.find(e=>ue(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 Dc(e,t){if(!t)return e;let n=e?.model??{};return{...e,model:{...n,reasoningEffort:t}}}function Oc(e){if(e.spec){let t=JSON.parse(fe(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=jc(e),n=Mc(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=Nc(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 kc(e){let{base:t,machines:n}=Oc(e);return{...t,machines:n}}function Ac(e){let{base:t,machines:n}=Oc(e);return{...t,workers:n}}function jc(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=Ls({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 Mc(e,t){return Rs({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 Nc(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 Pc(e){e.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>`,wc).addOption(Tc()).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 e=>{let{client:t}=J(e),n=H(`Creating fleet...`);n.start();let r=e.coordinator?await t.fleets.createWithCoordinator(Ac(e)):await t.fleets.create(kc(e));n.stop();let i=Xs(r.machines);e.json?z({fleetId:r.fleetId,machines:i}):(B(`Fleet created: ${r.fleetId}`),R(i,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`status`,header:`Status`,width:14}]))})}function Fc(e){e.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(e,t,n)=>{let{client:r}=J(n),i=H(`Dispatching command...`);i.start();let a=await(await r.fleets.list({fleetId:e})).dispatchExecDetailed(t,{machines:n.machine,cwd:n.cwd,timeoutMs:n.timeout?Number(n.timeout):void 0,maxConcurrent:n.maxConcurrent?Number(n.maxConcurrent):void 0});if(i.stop(),n.json)z(a);else{R(a.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 a.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}`)}}a.results.some(e=>e.ok===!1)&&(process.exitCode=1)}),e.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(e,t)=>{let n=/^\d+$/.test(t.agents)?Number(t.agents):JSON.parse(fe(t.agents,`utf8`));if(!Array.isArray(n)&&e===void 0)throw Error(`A prompt is required unless --agents names a file whose agents carry tasks`);let{client:r}=J(t);if(!!t.parentFleet!=!!t.parentAgent)throw Error(`--parent-fleet and --parent-agent go together`);let i=t.placement===`auto`||t.placement===`dedicated`?t.placement:{agentsPerSandbox:Number(t.placement)},a=t.maxSpendUsd?Number(t.maxSpendUsd):void 0,o=H(`Creating fleet...`);o.start();let s=Date.now(),c=await r.fleets.create({fleetId:t.fleetId,agents:n,placement:i,defaults:{...t.environment?{environment:t.environment}:{},...t.memory?{resources:{memoryMB:Number(t.memory)}}:{},...t.model?{backend:{type:`opencode`,model:{model:t.model}}}:{}},...a===void 0?{}:{budgetUsd:a},...t.parentFleet?{parent:{fleetId:t.parentFleet,agentId:t.parentAgent}}:{}}),l=Date.now()-s;o.stop(),t.json||B(`Fleet ${c.fleetId}: ${c.agents.length} agents on ${c.machines.size} sandboxes in ${l} ms`);let u=[],d;try{for await(let n of c.run(e,{timeoutMs:t.timeout?Number(t.timeout):void 0})){if(n.type===`agent.finished`&&!t.json){let e=n.result;console.log(`[${e.agentId}] ${e.harness??`default`}/${e.model??`default`} ${e.status} ${e.durationMs}ms ${e.costUsd===void 0?`no cost reported`:`$${e.costUsd.toFixed(5)}`} ${e.result?.response??e.error??``}`)}n.type===`fleet.finished`&&(u=n.results,d=n.spend)}}finally{t.keep||await c.delete({continueOnError:!0})}t.json?z({fleetId:c.fleetId,createMs:l,sandboxes:c.machines.size,results:u,spend:d,deleted:!t.keep}):U({fleetId:c.fleetId,completed:u.filter(e=>e.status===`completed`).length,agents:u.length,spend:JSON.stringify(d),deleted:!t.keep}),u.some(e=>e.status!==`completed`)&&(process.exitCode=1)}),e.command(`cancel <fleet-id>`).description(`Interrupt every agent of a fleet and cancel its child fleets; sandboxes keep running`).action(async(e,t)=>{let{client:n}=J(t),r=await(await n.fleets.list({fleetId:e})).cancel();t.json?z({fleetId:e,...r}):B(`Fleet ${e}: interrupted ${r.interrupted} agents, cancelled ${r.children} child fleets`)})}const Ic=[`list`,`create`,`delete`,`exec`,`prompt`,`read`,`write`];function Lc(e){if(!(!e||e.length===0)){for(let t of e)if(!Ic.includes(t))throw Error(`Invalid token action '${t}'. Allowed: ${Ic.join(`, `)}`);return e}}function Rc(e){return e.length<=12?`****`:`${e.slice(0,6)}...${e.slice(-4)} (masked — use --json for full value)`}function zc(e){e.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(e,t)=>{let{client:n}=J(t),r=H(`Minting fleet token...`);r.start();let i=await n.fleets.createToken(e,{actions:Lc(t.action),ttlMinutes:t.ttlMinutes?Number(t.ttlMinutes):void 0});r.stop(),t.json?z(i):(U({"Fleet ID":i.fleetId,Token:Rc(i.token),"Expires at":new Date(i.expiresAt).toISOString(),Actions:i.actions.join(`, `)}),console.log(`
145
+ Re-run with --json to print the full token value.`))})}function Bc(){let e=new S(`workspace`).description(`Manage a fleet's shared workspace`);return e.command(`snapshot <fleet-id>`).description(`Snapshot the fleet's shared workspace`).action(async(e,t)=>{let{client:n}=J(t),r=H(`Creating workspace snapshot...`);r.start();let i=await n.fleets.createWorkspaceSnapshot(e);r.stop(),t.json?z(i):B(`Workspace snapshot created: ${i.snapshotId??i.id}`)}),e.command(`restore <fleet-id> <snapshot-id>`).description(`Restore the fleet's shared workspace from a snapshot`).action(async(e,t,n)=>{let{client:r}=J(n),i=H(`Restoring workspace...`);i.start();let a=await r.fleets.restoreWorkspaceSnapshot(e,t);i.stop(),n.json?z(a):B(`Workspace restored from ${a.snapshotId??t}`)}),e.command(`reconcile <fleet-id>`).description(`Re-mount the shared workspace on all fleet machines`).action(async(e,t)=>{let{client:n}=J(t),r=H(`Reconciling workspace...`);r.start();let i=await n.fleets.reconcileWorkspace(e);r.stop(),t.json?z(i):(U({"Fleet ID":i.fleetId,Checked:i.checked,"Orphaned mounts":i.orphanedMounts}),R(i.machines,[{key:`machineId`,header:`Machine`,width:20},{key:`sandboxId`,header:`Sandbox`,width:24},{key:`mounted`,header:`Mounted`,width:10}]))}),e}function Vc(){let e=new S(`fleet`).description(`Manage sandbox fleets`);return Pc(e),Zs(e),e.addCommand(Bc()),Fc(e),Ys(e),zc(e),e}function Hc(){let e=new S(`fs`).description(`File system operations on sandboxes`);return e.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(e,t,n,r)=>{let{context:i,client:a}=J(r),o=await Y(a,i,e);if(o=await X(o),!se.existsSync(t))throw Error(`Local file not found: ${t}`);let s=se.statSync(t),c=Date.now();r.json||console.error(`Uploading ${t} to ${n}...`),await o.fs.upload(t,n,{onProgress:e=>{if(r.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesUploaded}/${e.totalBytes} bytes)`)}});let l=Date.now()-c;r.json||console.error(``),r.json?z({success:!0,localPath:t,remotePath:n,size:s.size,durationMs:l}):console.log(`✓ Uploaded ${s.size} bytes in ${l}ms`)}),e.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(e,t,n,r)=>{let{context:i,client:a}=J(r),o=await Y(a,i,e);o=await X(o);let s=Date.now();r.json||console.error(`Downloading ${t} to ${n}...`),await o.fs.download(t,n,{onProgress:e=>{if(r.json)return;let t=e.percentage.toFixed(1);process.stderr.write(`\rProgress: ${t}% (${e.bytesDownloaded}/${e.totalBytes} bytes)`)}});let c=Date.now()-s,l=se.statSync(n);r.json||console.error(``),r.json?z({success:!0,remotePath:t,localPath:n,size:l.size,durationMs:c}):console.log(`✓ Downloaded ${l.size} bytes in ${c}ms`)}),e.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(e,t,n)=>{let{context:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a);let o=await a.fs.list(t,{all:n.all,long:n.long});if(n.json)z(o);else if(n.long)jn([`Mode`,`Owner`,`Group`,`Size`,`Modified`,`Name`],o.map(e=>{let t=e.isDir?`d`:e.isSymlink?`l`:`-`,n=Uc(e.permissions),r=e.isDir?`<DIR>`:Wc(e.size),i=e.modTime.toLocaleDateString();return[t+n,e.owner,e.group,r,i,e.name]}));else{let e=o.map(e=>e.isDir?`${e.name}/`:e.name);console.log(e.join(` `))}}),e.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(e,t,n)=>{let{context:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a);let o=await a.fs.stat(t);n.json?z(o):(console.log(` File: ${o.name}`),console.log(` Path: ${o.path}`),console.log(` Size: ${Wc(o.size)} (${o.size} bytes)`),console.log(` Type: ${o.isDir?`directory`:o.isSymlink?`symlink`:`file`}`),console.log(` Mode: ${Uc(o.permissions)} (${o.permissions.toString(8)})`),console.log(` Owner: ${o.owner}`),console.log(` Group: ${o.group}`),console.log(` Modified: ${o.modTime.toISOString()}`),console.log(` Accessed: ${o.accessTime.toISOString()}`))}),e.command(`cat`).description(`Print file contents`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to file`).action(async(e,t,n)=>{let{context:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a);let o=await a.read(t);n.json?z({path:t,content:o}):console.log(o)}),e.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(e,t,n)=>{let{context:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a),await a.fs.delete(t,{recursive:n.recursive}),n.json?z({success:!0,path:t,deleted:!0}):console.log(`✓ Deleted: ${t}`)}),e.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(e,t,n)=>{let{context:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a),await a.fs.mkdir(t,{recursive:n.parents}),n.json?z({success:!0,path:t,created:!0}):console.log(`✓ Created: ${t}`)}),e.command(`exists`).description(`Check if a path exists`).argument(`<sandbox-id-or-name>`,`Sandbox ID or name`).argument(`<path>`,`Path to check`).action(async(e,t,n)=>{let{context:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a);let o=await a.fs.exists(t);n.json?z({path:t,exists:o}):(console.log(o?`exists`:`not found`),process.exit(+!o))}),e}function Uc(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 Wc(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 Gc(){let e=new S(`git`).description(`Git operations in a sandbox workspace`);return e.command(`status`).description(`Show git repository status`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching status...`);t.json||i.start();let a=await Y(r,n,e);a=await X(a);let o=await a.git.status();if(i.stop(),t.json)z(o);else if(!o.isRepo)console.log(`No git repository in the sandbox workspace.`);else{if(console.log(`Branch: ${o.branch??`unknown`}`),console.log(`HEAD: ${o.head.slice(0,7)||`(no commits)`}`),console.log(`Dirty: ${o.isDirty?`yes`:`no`}`),o.ahead&&console.log(`Ahead: ${o.ahead}`),o.behind&&console.log(`Behind: ${o.behind}`),o.staged.length>0){console.log(`\nStaged (${o.staged.length}):`);for(let e of o.staged)console.log(` + ${e}`)}if(o.modified.length>0){console.log(`\nModified (${o.modified.length}):`);for(let e of o.modified)console.log(` M ${e}`)}if(o.untracked.length>0){console.log(`\nUntracked (${o.untracked.length}):`);for(let e of o.untracked)console.log(` ? ${e}`)}}}),e.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(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching log...`);t.json||i.start();let a=await Y(r,n,e);a=await X(a);let o=await a.git.log(Number.parseInt(t.limit,10));if(i.stop(),t.json)z(o);else if(o.length===0)console.log(`No commits found`);else for(let e of o)console.log(`${e.shortSha} ${e.message.split(`
146
+ `)[0]} (${e.author}, ${e.date.toLocaleDateString()})`)}),e.command(`diff`).description(`Show diff`).argument(`<id-or-name>`,`Sandbox ID or name`).option(`--ref <ref>`,`Ref to diff against`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching diff...`);t.json||i.start();let a=await Y(r,n,e);a=await X(a);let o=await a.git.diff(t.ref);i.stop(),t.json?z(o):o.raw?console.log(o.raw):console.log(`${o.additions} additions, ${o.deletions} deletions across ${o.files.length} files`)}),e.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:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a),await a.git.add(t),B(`Staged: ${t.join(`, `)}`)}),e.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(e,t)=>{let{context:n,client:r}=J(t),i=await Y(r,n,e);i=await X(i);let a=await i.git.commit(t.message,{amend:t.amend});t.json?z(a):B(`Committed: ${a.shortSha} ${a.message}`)}),e.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:r}=J(t),i=H(`Pushing...`);i.start();let a=await Y(r,n,e);a=await X(a),await a.git.push({force:t.force}),i.stop(),B(`Pushed to remote`)}),e.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:r}=J(t),i=H(`Pulling...`);i.start();let a=await Y(r,n,e);a=await X(a),await a.git.pull({rebase:t.rebase}),i.stop(),B(`Pulled from remote`)}),e.command(`branches`).description(`List branches`).argument(`<id-or-name>`,`Sandbox ID or name`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching branches...`);t.json||i.start();let a=await Y(r,n,e);a=await X(a);let o=await a.git.branches();i.stop(),t.json?z(o):o.length===0?console.log(`No branches found`):jn([`Name`,`Current`,`Remote`],o.map(e=>[e.name,e.current?`* `:` `,e.upstream??`-`]))}),e.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:r,client:i}=J(n),a=await Y(i,r,e);a=await X(a),await a.git.checkout(t,{create:n.create}),B(`Checked out: ${t}${n.create?` (new)`:``}`)}),e}function Kc(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 w(`sha256`).update(n).digest(`hex`).slice(0,t)}Object.freeze([`HS256`]),Object.freeze([`RS256`]);async function qc(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 W&&e.code===`RUN_STOPPED`)throw e;let t=new W(`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 Jc(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 W(`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 Yc(e,t){let n=t.signal;return async r=>{let i=Object.hasOwn(e,r.gate)?e[r.gate]:void 0,a=`--param ${qe(`gate.${r.gate}=<choice>`)}`,o=`${r.question} Choose one of: ${r.choices.join(`, `)}`,s=()=>new W(`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 Vi(`${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 Xc=P.strictObject({sourceId:P.string().min(1),generation:P.string().regex(/^kg_[a-f0-9]{64}$/)}),Zc=P.discriminatedUnion(`kind`,[P.strictObject({kind:P.literal(`local`),root:P.string().refine(ve),sourceDigest:P.string().regex(/^sha256:[a-f0-9]{64}$/)}),P.strictObject({kind:P.literal(`hub`),references:P.array(Xc).min(1)})]);async function Qc(e){let t=await I(e);return{kind:`local`,root:t,sourceDigest:`sha256:${await lt(t)}`}}function $c(e){throw Object.assign(Error(e),{code:`KNOWLEDGE_BACKEND_UNSUPPORTED`})}const el=P.strictObject({question:P.string().trim().min(1).max(16e3),limit:P.number().int().min(1).max(20).default(5)}),tl=P.object({results:P.array(P.object({sourceId:P.string().min(1),generation:P.string().regex(/^kg_[a-f0-9]{64}$/),hits:P.array(P.object({id:P.string(),snippet:P.string()}).passthrough()),evidence:P.object({receipt:P.unknown(),visibility:P.unknown(),sources:P.array(P.object({id:P.string(),uri:P.string(),contentHash:P.string()}))})}).passthrough()),failures:P.array(P.unknown()),partial:P.boolean()}).passthrough();let nl;function rl(){return nl??=(async()=>{let e=t(`@tangle-network/agent-knowledge`,import.meta.url);if(!e)throw Error(`Cannot identify the installed Knowledge retriever`);return JSON.parse(await F(e,`utf8`)).version})(),nl}async function il(e){let t=Zc.parse(e.binding),n=Object.freeze({...e.context});if(t.kind===`hub`){let r=e.queryHub;return r||$c(`This backend has no owner-authorized Hub knowledge query binding`),[{name:`knowledge_search`,description:`Search the graph's exact owner-authorized knowledge generations and retain retrieval evidence.`,inputSchema:el,inputSchemaJson:P.toJSONSchema(el),handler:async i=>{let a=el.parse(i),o=await r({query:a.question,limit:a.limit,expectedReferences:t.references,context:n},e.signal),s=tl.parse(o);if(!s.partial&&(s.results.length!==t.references.length||t.references.some(e=>s.results.filter(t=>t.sourceId===e.sourceId&&t.generation===e.generation).length!==1)))throw Error(`Hub knowledge omitted or duplicated a selected source generation`);let c=[],l=[];for(let r of s.results){let i=mt(r.evidence.receipt),o=r.evidence.visibility,s=ct(o);if(i.runId!==n.runId||i.actorId!==n.nodeId||i.profileDigest!==n.profileDigest||i.query!==a.question)throw Error(`Hub knowledge receipt does not match the trusted graph invocation`);if(i.attributes.sourceId!==r.sourceId||i.attributes.generation!==r.generation||!t.references.some(e=>e.sourceId===r.sourceId&&e.generation===r.generation))throw Error(`Hub knowledge receipt does not match an exact selected source generation`);if(r.hits.length!==i.results.length||r.hits.some((e,t)=>e.id!==i.results[t]?.pageId||e.snippet!==i.results[t]?.snippet))throw Error(`Hub knowledge hits do not match their retrieval receipt`);await it(i,()=>s),c.push(await e.record({context:n,binding:t,receipt:i,visibility:o,sources:r.evidence.sources})),l.push({sourceId:r.sourceId,generation:r.generation,hits:r.hits,retrievalReceiptDigest:i.receiptDigest})}return{partial:s.partial,failures:s.failures,results:l,retainedEvidence:c}}},{name:`knowledge_record`,description:`Retain an isolated knowledge proposal; it does not alter published source generations.`,inputSchema:P.strictObject({proposal:P.string().min(1)}),inputSchemaJson:{type:`object`,properties:{proposal:{type:`string`}},required:[`proposal`],additionalProperties:!1},handler:async r=>{let{proposal:i}=P.strictObject({proposal:P.string().min(1)}).parse(r);return dt(i),{isolated:!0,evaluated:!1,artifact:await e.recordProposal({context:n,binding:t,proposal:i,digest:A({context:n,binding:t,proposal:i})}),activation:`unsupported-for-hub-generations`}}}]}let r=async()=>{if(`sha256:${await lt(t.root)}`!==t.sourceDigest)throw Error(`The graph's pinned local knowledge changed`)};if(await r(),!e.storeRoot)throw Error(`Local graph Knowledge needs its private run-store root`);let i=await I(t.root),a=be(e.storeRoot),o=(e,t)=>{let n=ye(e,t);return n===``||!n.startsWith(`..`)&&!ve(n)};if(o(i,a)||o(a,i))throw Error(`Knowledge run stores must be separate from the curated corpus`);let s=ot({root:a,sharedRoot:i});await s.init(n.runId);let c=new Map;return at({stores:s,runId:n.runId,actorId:n.nodeId,retrieverVersion:await rl(),retainHistory:!0,recordRetrieval:async i=>{if(await r(),!i.visibility.artifact)throw Error(`Knowledge did not retain the visibility snapshot`);let a=await F(new URL(i.visibility.artifact.uri));await it(i,()=>a);let o=st(a),s=await ut(t.root),l=new Set(o.entries.flatMap(e=>e.sourceIds)),u=Object.values(s.sources).filter(e=>l.has(e.id)).map(({id:e,uri:t,contentHash:n})=>({id:e,uri:t,contentHash:n}));c.set(i.receiptDigest,await e.record({context:n,binding:t,receipt:i,visibility:o,sources:u}))}}).map(t=>({...t,handler:async(n,i)=>{e.signal?.throwIfAborted(),await r();let a=await t.handler(n,i);return await r(),a&&typeof a==`object`&&`retrievalReceiptDigest`in a?{...a,retainedEvidence:c.get(String(a.retrievalReceiptDigest))}:a}}))}function al(e){return async t=>{if(!Object.entries(t.profile.tools??{}).some(([e,t])=>t===!0&&/_knowledge_(search|read|record|resolve)$/.test(e)))return[];if(!t.identity.profileDigest)throw Error(`Knowledge tools require Runtime's exact profile identity`);return(await il({...e,...e.storeRoot?{storeRoot:M(e.storeRoot,t.nodeId)}:{},context:{runId:t.runId,nodeId:t.nodeId,profileDigest:t.identity.profileDigest}})).map(e=>{if(!e.inputSchemaJson)throw Error(`Knowledge tool lacks its wire input schema`);return{name:e.name,description:e.description,inputSchema:e.inputSchemaJson,handler:t=>e.handler(t,{})}})}}async function ol(e,t,n){let r=Zc.parse(e);r.kind!==`local`&&$c(`Measured file-backed Knowledge candidates cannot activate Hub generations; use the source generation owner's publication path`);let i=rt.parse(t);if(`sha256:${i.baseHash}`!==r.sourceDigest)throw Error(`Knowledge candidate does not match the graph's pinned baseline`);return n===`promote`?ft({root:r.root,candidate:i}):pt({root:r.root,candidate:i})}function sl(e,t,n,r){if(e==null)return;let i=Zc.parse(e);if(i.kind!==`local`)throw Error(`A local graph needs a pinned local Knowledge binding; Hub generations require the hosted workflow owner`);return al({binding:i,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 cl(e){let t=e.command(`knowledge`).description(`Exact measured Knowledge candidate transitions`);t.command(`bind <root>`).description(`Identify exact bytes of an existing local Knowledge store`).action(async e=>z(await Qc(e)));for(let e of[`promote`,`restore`])t.command(`${e} <binding> <candidate>`).description(`${e} the exact measured local Knowledge candidate through its owner`).action(async(t,n)=>{let r=Zc.parse(JSON.parse(await F(t,`utf8`))),i=await ol(r,JSON.parse(await F(n,`utf8`)),e);z({...i,nextBinding:{...r,sourceDigest:`sha256:${i.mutation.afterHash}`}})})}const ll=()=>new C(`--mcp-secret <key=variable>`,`Private local MCP secret reference binding; repeatable, values are never recorded`).argParser((e,t)=>[...t,e]).default([]);function ul(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 W(`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 dl(e){try{return ke.parse(JSON.parse(await F(e,`utf8`)))}catch(e){throw new W(`GRAPH_MCP_POLICY_INVALID`,`The graph MCP policy is invalid`,e instanceof Error?e.message:String(e),`tangle graph run --help`)}}const fl=[`claude-code`,`opencode`,`codex`,`kimi-code`,`prime`],pl=process.env.TANGLE_ROUTER_URL??`https://router.tangle.tools/v1`;function ml(e){let t=ie(e);if(t)return t;throw Error(`--model '${e}' has no provider. Pass a canonical id, for example 'google/${e}'.`)}function hl(e){let t=e.harness??`claude-code`;if(!fl.includes(t))throw Error(`Unknown --harness '${t}'. Supported: ${fl.join(`, `)}.`);let n=gl(e.maxTokens,2e5,`--max-tokens`),r=gl(e.maxIterations,50,`--max-iterations`),i=e.maxWorkers===void 0?void 0:gl(e.maxWorkers,0,`--max-workers`);return{harness:t,...e.model?{model:e.model}:{},maxTokens:n,maxIterations:r,...i===void 0?{}:{maxWorkers:i}}}function gl(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 _l(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 vl(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 yl=null;function bl(){return yl??=import(`@tangle-network/agent-runtime/kernel`).catch(e=>{throw yl=null,e?.code===`ERR_MODULE_NOT_FOUND`?new W(`RUNTIME_UNAVAILABLE`,`Agent Runtime could not be loaded`,e.message,`npm install -g @tangle-network/sandbox-cli@latest`):e}),yl}async function xl(e,t,n){let r=K({apiKey:n.apiKey,baseUrl:n.baseUrl}),i=q(r),{budget:a,perWorker:o}=_l(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||V(`worker ${a.id} spawned`),a}},l=await bl(),u=l.workerFromBackend({backend:`sandbox`,sandboxClient:c,maxIterations:1}),d=(e,n)=>u({...e,harness:t.harness},n),f={name:`supervisor`,harness:`cli-base`,model:{default:t.model??`gemini-3.5-flash-lite`,provider:t.model?ml(t.model):`google`},tools:{agent_runtime_coordination_spawn_worker:!0,agent_runtime_coordination_observe_agent:!0}},p={routerBaseUrl:pl,routerKey:r.apiKey},m=vl(await l.supervise(f,{goal:e},{budget:a,makeWorkerAgent:d,router:p,...o?{perWorker:o}:{},...t.model?{allowedModels:[t.model]}:{},runId:`supervise-${E()}`})),h=m.status===`winner`?`settled`:`failed`;for(let e of s)e.status=h,n.json||V(`worker ${e.id} settled (${e.status})`);return{task:e,result:m.text,workers:s,tokenUsage:m.tokenUsage,costUsd:m.costUsd,status:m.status}}function Sl(){let e=new S(`supervise`);return e.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 (${fl.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(e,t)=>{let n=hl({harness:t.harness,model:t.model,maxTokens:t.maxTokens,maxIterations:t.maxIterations,maxWorkers:t.maxWorkers});t.json||(V(`Supervising: ${e}`),V(`harness=${n.harness} budget=${n.maxTokens}tok/${n.maxIterations}it`),console.log());let r=await xl(e,n,{apiKey:t.apiKey,baseUrl:t.baseUrl,json:t.json});if(t.json){z(r),r.status!==`winner`&&(process.exitCode=1);return}if(console.log(),r.result&&(console.log(r.result),console.log()),U({"Input Tokens":r.tokenUsage.input??`Unavailable`,"Output Tokens":r.tokenUsage.output??`Unavailable`,Cost:r.costUsd===null?`Unavailable`:`$${r.costUsd.toFixed(4)}`}),r.status!==`winner`)throw Error(`Supervisor finished without a winner: ${r.status}`)}),e}const Cl=`graph-task-workspaces`,wl=P.number().int().positive().max(2**53-1),Tl=P.strictObject({maxArchiveBytes:wl.optional(),maxEmbeddedArtifactBytes:wl.optional(),maxFiles:wl.optional(),maxFileBytes:wl.optional(),maxTotalFileBytes:wl.optional(),maxPathBytes:wl.optional(),maxRepositoryBundleBytes:wl.optional()}),El=ee.shape,Dl=P.strictObject({snapshot:P.strictObject({kind:El.kind,digest:El.digest,manifest:k,archive:k}).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:P.strictObject({mode:P.literal(`git-working-tree`),runtimeVersion:P.string().min(1),limits:Tl}),gaps:P.tuple([P.literal(`environment-and-toolchain-not-snapshotted`),P.literal(`git-ignored-files-excluded`)])}),Ol=e=>A(Dl.parse(e));function kl(e){for(let t of[e.snapshot.manifest,e.snapshot.archive])if(t.locator.kind!==`private-cas`||t.locator.namespace!==Cl)throw Error(`Task workspace artifacts require their original local private CAS; cross-backend activation is unsupported`)}async function Al(){let e=M(N(),`.tangle`);return await Ze(e,{recursive:!0,mode:448}),I(e)}const jl=e=>Ct(M(e,`artifacts`),Cl);async function Ml(e){let t=await $e(be(e),le.O_RDONLY|le.O_NOFOLLOW);try{if(!(await t.stat()).isFile())throw Error(`Task workspace reference must be a regular file`);let e=Dl.parse(JSON.parse(await t.readFile(`utf8`)));return kl(e),e}finally{await t.close()}}async function Nl(e,n={}){n.signal?.throwIfAborted();let r=be(e),i=await Xe(r);if(!i.isDirectory()||i.isSymbolicLink())throw Error(`Task workspace must be one real repository root`);let a=await I(r),o=await I(N()),s=await Al();if(a===o||a===ge(a)||Sf(s,a)||Sf(a,s))throw Error(`Task workspace capture cannot include the home, filesystem or private evidence root`);let{release:c}=ht({lockPath:`${a}.graph-workspace.lock`});try{let e=Tl.parse(n.limits??{}),r=await bt(a,{includeRepository:!0,repositoryContents:`working-tree`,limits:e,artifactPersistence:{executionId:E(),outputArtifacts:jl(s),signal:n.signal}}),i=t(`@tangle-network/agent-runtime`,import.meta.url);if(!i)throw Error(`Cannot identify the Runtime workspace archive owner`);let o=JSON.parse(await F(i,`utf8`));return Dl.parse({snapshot:r,capture:{mode:`git-working-tree`,runtimeVersion:o.version,limits:e},gaps:[`environment-and-toolchain-not-snapshotted`,`git-ignored-files-excluded`]})}finally{c()}}async function Pl(e,t){let n=P.uuid().parse(t.runId),r=Dl.parse(e);kl(r);let i=await Al(),a=M(i,`workspaces`);if(await Ze(a,{recursive:!0,mode:448}),await I(a)!==a)throw Error(`Task workspace allocation root redirects elsewhere`);let o=M(a,n),{release:s}=ht({lockPath:`${o}.lock`});try{t.signal?.throwIfAborted();let e=`${o}.task-workspace.json`,a;try{a=JSON.parse(await F(e,`utf8`))}catch(e){if(e.code!==`ENOENT`)throw e}let c=Ol(r);if(a!==void 0){let e=P.strictObject({runId:P.uuid(),identity:P.string()}).parse(a);if(e.runId!==n||e.identity!==c||t.resumeCwd!==void 0&&be(t.resumeCwd)!==o||await I(o)!==o||!(await Xe(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 xt({snapshot:r.snapshot,artifacts:jl(i),destination:o,limits:r.capture.limits,signal:t.signal}),await L(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([Xe(o,{bigint:!0}),Xe(e,{bigint:!0})]);return{cwd:o,release:async()=>{try{for(let[t,r]of[o,e].entries()){let e=await Xe(r,{bigint:!0});if(!(t===0?e.isDirectory():e.isFile())||e.dev!==l[t]?.dev||e.ino!==l[t]?.ino||await I(r)!==r)throw Error(`Validation allocation ${n} changed; retained`)}if(A(JSON.parse(await F(e,`utf8`)))!==A({runId:n,identity:c}))throw Error(`Validation allocation ${n} receipt changed; retained`);try{throw await Xe(M(i,`runs`,n)),Error(`Validation allocation ${n} has run state; retained`)}catch(e){if(e.code!==`ENOENT`)throw e}await nt(o,{recursive:!0}),await nt(e)}finally{s()}}}}catch(e){throw s(),e}}function Fl(e){e.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(e,t)=>{let n=await I(be(e)),r=M(await I(ge(be(t.output))),he(be(t.output)));if(Sf(n,r))throw Error(`The task reference must be written outside the original workspace`);try{throw await Xe(r),Error(`Task workspace reference already exists; choose a new output file`)}catch(e){if(e.code!==`ENOENT`)throw e}let i=await Nl(n,{limits:t.limits?Tl.parse(JSON.parse(await F(t.limits,`utf8`))):void 0});await L(r,JSON.stringify(i),{flag:`wx`,mode:384,flush:!0}),z(i)})}const Il=P.string().regex(/^[a-f0-9]{64}$/),Ll=P.strictObject({version:P.literal(1),runId:P.uuid(),file:P.string().refine(ve),cwd:P.string().refine(ve),sourceDigest:Il,source:P.string().optional(),graphDigest:Il,params:P.record(P.string(),P.unknown()),trigger:P.record(P.string(),P.unknown()).optional(),gateChoices:P.record(P.string(),P.string()).optional(),startedAt:P.iso.datetime(),seat:P.string().optional(),mcpPolicy:Ae.optional(),taskWorkspace:Dl.optional()});async function Rl(e){let t=await bl(),n=t.graphRegistry(M(N(),`.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 A({mcpPolicy:Ae.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 Z(e){throw new W(`GRAPH_RESUME_REFUSED`,`The graph run cannot be resumed`,e,`tangle graph run --help`)}async function zl(e){P.uuid().safeParse(e).success||Z(`Use a recorded graph run ID`);let t;try{let n=M(await I(M(N(),`.tangle`)),`runs`,e);await I(n)!==n&&Z(`The run directory redirects elsewhere`),t=await $e(M(n,`input.json`),le.O_RDONLY|le.O_NOFOLLOW),(await t.stat()).isFile()||Z(`The run input is not a regular file`);let r=Ll.parse(JSON.parse(await t.readFile(`utf8`)));return r.runId!==e&&Z(`The recorded run identity changed`),r.source!==void 0&&Vl(r,r.source),r}catch(e){if(e instanceof W)throw e;return Z(`The private recorded run input is missing or invalid`)}finally{await t?.close()}}async function Bl(e,t){let n=t.source??await F(t.file,`utf8`);Vl(t,n),await L(M(e,`input.json`),JSON.stringify({...t,source:n}),{flag:`wx`,mode:384,flush:!0})}function Vl(e,t){return w(`sha256`).update(t).digest(`hex`)!==e.sourceDigest&&Z(`The retained graph source does not match this run`),t}async function Hl(e){return Vl(e,e.source??await F(e.file,`utf8`))}function Ul(e,t,n,r,i={}){e.sourceDigest!==n&&Z(`The authored graph source changed`),t.cloud&&Z(`A local run cannot move to cloud execution`),Object.entries(r).some(([t,n])=>!Object.hasOwn(e.params,t)||A(n)!==A(e.params[t]))&&Z(`A recorded graph parameter changed`),Object.entries(i).some(([t,n])=>e.gateChoices?.[t]!==n)&&Z(`A recorded gate choice changed`),t.seat!==void 0&&t.seat!==e.seat&&Z(`The recorded graph seat override changed`),t.mcpPolicy!==void 0&&(e.mcpPolicy===void 0||A(t.mcpPolicy)!==A(e.mcpPolicy))&&Z(`The recorded graph MCP policy changed`)}const Wl=e=>Object.entries(e).map(([e,t])=>`${e}=${typeof t==`string`?t:JSON.stringify(t)}`),Gl=`claude,codex,kimi,opencode,gemini,pi`;function Kl(e,t){let n;return async(r,{node:i,lastCandidate:a})=>{t.throwIfAborted();let o;try{o=r===void 0?void 0:ae(r)}catch(e){throw e instanceof Error&&Object.assign(e,{node:i,seat:r,fixCommand:`tangle graph run --help`}),e}n??=Et({cwd:e,signal:t,config:Dt({...process.env,BRIDGE_BACKENDS:Gl,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 W(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??ae(f.id).harness,m=o?.provider??f.provider,h=o?.model??f.id.slice(p.length+1);if(!m||!h)throw new W(`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 ql=Ot(we);function Jl(e,t,n=`tangle graph run --help`){throw new W(`SEAT_NONE_DETECTED`,e,t,n)}function Yl(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 W(`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 Xl(e){return e.some(e=>(e.profile?.seats?.length??0)>0)}function Zl(e){let t=e?.trim();if(t)return/\s/u.test(t)&&Jl(`A seat account, command, or credential must be a single token`,`The seat command is an executable path, not a shell line`),t}function Ql(e){let t=Zl(e.seatAccount),n=Zl(e.seatCommand),r=Zl(e.seatCredential);return r&&!n&&!t&&Jl(`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 $l(e,t,n){if(e.account)return e.account;e.command||Jl(`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 ql(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`;Jl(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))&&Jl(`The seat command did not print an account id`,`The command must print one account id and nothing else`),i}function eu(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 $l(t,a,n);return!o&&!t.account&&r.set(s,c),(!c||/\s/u.test(c)||i.resumeSeatId!==void 0&&i.resumeSeatId!==c)&&Jl(`Node '${i.nodeId}' has no seat account`,`The authored seat, account flag, or seat command did not yield one`),{seat:c,backend:{backend:`provider`,provider:At({baseUrl:e.bridgeUrl,bearerToken:e.bridgeBearer}),defaults:{workspace:{cwd:{base:`host`,path:e.cwd}}},runtime:`cli`,outputFormat:`json`,destroyOnSettle:!0,requireTerminalEvent:!0}}}}function Q(e){return Di({signal:e.signal,...e.apiKey===void 0?{}:{apiKey:e.apiKey},...e.baseUrl===void 0?{}:{baseUrl:e.baseUrl}})}const tu=P.object({version:P.literal(1),type:P.enum([`state`,`ack`,`error`,`event`]),requestId:P.string().optional(),operationId:P.string().optional(),command:P.string().optional(),code:P.string().optional(),message:P.string().optional(),result:P.unknown().optional()}).passthrough(),nu=P.object({state:P.object({runConfiguration:P.unknown()}),view:P.object({capabilities:P.record(P.string(),P.object({available:P.boolean(),reason:P.string().optional()}))})}),ru=P.object({status:P.enum([`completed`,`failed`,`cancelled`]),analysis:P.object({id:P.string().min(1)}).passthrough(),source:P.object({runtimeRun:P.unknown()}).passthrough()}).passthrough(),iu=`TANGLE_GRAPH_ANALYSIS_SOURCE`;async function au(e,t,n){if(!e.startsWith(`wfrun_`)){let t=M(await I(M(N(),`.tangle`)),`runs`,e);if(await I(t)!==t)throw new W(`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:P.object({runId:P.literal(e),runDir:P.literal(t)})}}let r={signal:n,...t.apiKey===void 0?{}:{apiKey:t.apiKey},...t.baseUrl===void 0?{}:{baseUrl:t.baseUrl}},i=await Q(r),a=P.object({id:P.literal(e),workflowId:P.string(),revUsed:P.number().int(),execution:P.object({kind:P.literal(`graph`),sourceSha:P.string(),authoredGraphDigest:P.string(),graphDigest:P.string()}),runtime:P.object({snapshot:P.object({supervisors:P.tuple([P.object({id:P.string()})])})})}).parse(await i.workflows.getRun(e,{signal:n})),o=a.runtime.snapshot.supervisors[0];if(!o)throw new W(`BRAID_RPC_FAILED`,`The cloud run has no retained Runtime root`,`Wait for execution evidence before analysis`,`tangle graph inspect ${e}`);let s=await Ci(r);if(new URL(s.baseUrl.replace(/\/+$/,``)).href!==new URL(i.baseUrl.replace(/\/+$/,``)).href)throw new W(`AUTH_REQUIRED`,`The analysis source origin changed`,`Use the same authenticated platform origin`,`tangle auth status --json`);return{source:`runtime:${e}@${iu}`,env:{[iu]:JSON.stringify({url:`${s.baseUrl.replace(/\/+$/,``)}/v1/workflows/runs/${encodeURIComponent(e)}`,headers:{Authorization:`Bearer ${s.token}`}})},schema:P.object({runId:P.literal(e),remoteEndpointEnv:P.literal(iu),checkpoint:P.object({workflowId:P.literal(a.workflowId),runtimeRunId:P.literal(o.id),revUsed:P.literal(a.revUsed),sourceSha:P.literal(a.execution.sourceSha),authoredGraphDigest:P.literal(a.execution.authoredGraphDigest),graphDigest:P.literal(a.execution.graphDigest)})})}}async function ou(e,t){if(!e.startsWith(`wfrun_`)&&!P.uuid().safeParse(e).success)throw new W(`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 W(`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 W(`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)?be(process.cwd(),n):n;return qc(t.signal,async n=>{let i=await au(e,t,n),a=i.source;return wf({signal:n,errorRunId:e},async n=>{let o=await n.bridge(),s=await Qe(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 L(l,T(32),{mode:384,flag:`wx`}),await L(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-${E()}`,h=`op-${E()}`,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,D,O={transform:e=>{let t=tu.parse(e);return t.type===`error`||t.type===`state`&&t.requestId===g||t.type===`ack`&&[_,v].includes(t.requestId??``)?t:null},onError:e=>{D??=e},onEvent:e=>{e.type===`error`&&(D??=new W(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)}},k=await Ke({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},O,{stdin:[y,...t.dryRun?[]:[b],x].map(e=>JSON.stringify(e)).join(`
150
148
  `)+`
151
- `});if(T)throw T;let O=D.exit;if(!O.success||!x||!C||C.operationId!==h||C.command!==`shutdown`)throw new V(`BRAID_RPC_FAILED`,`Braid graph analysis did not finish`,O.spawnError??O.timeoutDiagnostic??O.stdinError??O.processGroupError??O.captureError??O.terminateError??(D.stderr||`Exit ${O.code}, signal ${O.signal}; complete shutdown acknowledgement: ${!!C}`),`npm install --global @tangle-network/braid`);let ne=Tc.parse(x),re=ne.view.capabilities[`analysis.recipe`];if(t.dryRun)return{source:a,statePath:u,configuration:ne.state.runConfiguration,capability:re};if(!S||S.operationId!==m||S.command!==`analyze`)throw Error(`Braid did not acknowledge this analysis operation`);let ie=Ec.parse(S.result);if(!i.schema.safeParse(ie.source.runtimeRun).success)throw new V(`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{...ie,statePath:u}})},`tangle graph analyze ${e}`)}function Ac(e){e.command(`analyze <run>`).description(`Analyze retained graph evidence through Braid`).addHelpText(`after`,`
149
+ `});if(D)throw D;let ee=k.exit;if(!ee.success||!S||!w||w.operationId!==h||w.command!==`shutdown`)throw new W(`BRAID_RPC_FAILED`,`Braid graph analysis did not finish`,ee.spawnError??ee.timeoutDiagnostic??ee.stdinError??ee.processGroupError??ee.captureError??ee.terminateError??(k.stderr||`Exit ${ee.code}, signal ${ee.signal}; complete shutdown acknowledgement: ${!!w}`),`npm install --global @tangle-network/braid`);let te=nu.parse(S),ne=te.view.capabilities[`analysis.recipe`];if(t.dryRun)return{source:a,statePath:u,configuration:te.state.runConfiguration,capability:ne};if(!C||C.operationId!==m||C.command!==`analyze`)throw Error(`Braid did not acknowledge this analysis operation`);let re=ru.parse(C.result);if(!i.schema.safeParse(re.source.runtimeRun).success)throw new W(`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{...re,statePath:u}})},`tangle graph analyze ${e}`)}function su(e){e.command(`analyze <run>`).description(`Analyze retained graph evidence through Braid`).addHelpText(`after`,`
152
150
  Requires the Braid companion CLI: npm install --global @tangle-network/braid.
153
151
  BRAID_BIN may select its installed executable. Select an existing canonical AgentProfile with --profile. Analysis uses the owned subscription-only Bridge.
154
- `).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(e,t)=>{let n=await kc(e,t);I(n),`status`in n&&n.status!==`completed`&&(process.exitCode=1)})}const jc=1e3;function Mc(e,t){return[...t,e]}function Nc(e,t=`input`,n){if(n===void 0&&!e?.length)return;let r={};if(n!==void 0)try{if(r=JSON.parse(ue(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 V(`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 Pc(e){F(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 Fc(e){if(B({"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){R(`Actions`);let t=e.actionResults.some(e=>e.nodeId!==void 0||e.visit!==void 0);F(e.actionResults.map(e=>({index:e.index,...t?{node:e.nodeId??``,visit:e.visit??``}:{},kind:e.kind,status:e.status,error:e.error??``,cost:e.costUsd??``})),[{key:`index`,header:`#`},...t?[{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&&(R(`Graph`),B({Nodes:e.graph.nodes.length,Edges:e.graph.edges.length,"Max node visits":e.graph.maxNodeVisits}),F(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&&(R(`Edge verdicts`),F(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 Ic(e){if(e.status===`cancelled`){R(`Cancelled run ${e.runId}.`);return}if(e.signalled){R(`Cancelling run ${e.runId} — signalled the worker; it will stop shortly.`);return}R(`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 Lc(e){switch(e.type){case`snapshot`:R(`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 Rc(e){e.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.`,Mc,[]).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(e,t)=>{let n=Nc(t.input,`input`,t.inputFile),r=t.timeout===void 0?void 0:no(t.timeout,`--timeout`),i=t.pollInterval===void 0?void 0:no(t.pollInterval,`--poll-interval`),a=await Z(t),{runId:o}=await a.workflows.run(e,n);if(!t.wait){if(t.json)return I({runId:o});R(`Started run ${o} for workflow ${e}.`),R(`Inspect it with: tangle workflows run-detail ${e} ${o}`);return}let s=t.json?null:z(`Waiting for run ${o} to finish...`).start(),c;try{c=await a.workflows.waitForRun(e,o,{...r===void 0?{}:{timeoutMs:r},...i===void 0?{}:{pollIntervalMs:i}})}finally{s?.stop()}if(c.status===`failed`&&(process.exitCode=1),t.json)return I(c);Fc(c)}),e.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(e,t)=>{let n=await Z(t),r=t.limit===void 0?void 0:no(t.limit,`--limit`);if(t.all){let i=[],a=t.cursor,o=0,s=null;for(;;){let c=await n.workflows.listRuns(e,{...r===void 0?{}:{limit:r},...a===void 0?{}:{cursor:a}});if(i.push(...c.runs),o+=1,!c.nextCursor)break;if(o>=jc){s=c.nextCursor,t.json||R(`Stopped after ${jc} pages (${i.length} runs); more may exist — resume with --cursor ${c.nextCursor}`);break}a=c.nextCursor}if(t.json)return I({runs:i,nextCursor:s});Pc(i);return}let i=await n.workflows.listRuns(e,{...r===void 0?{}:{limit:r},...t.cursor===void 0?{}:{cursor:t.cursor}});if(t.json)return I(i);Pc(i.runs),i.nextCursor&&R(`More runs available — next page: --cursor ${i.nextCursor}`)}),e.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(e,t,n)=>{let r=await(await Z(n)).workflows.getRun(e,t);if(n.json)return I(r);Fc(r)}),e.command(`cancel`).description(`Cancel a queued or in-progress run`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(e,t,n)=>{let r=await(await Z(n)).workflows.cancel(e,t);if(n.json)return I(r);Ic(r)}),e.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(e,t,n)=>{let r=n.timeout===void 0?void 0:no(n.timeout,`--timeout`),i=n.pollInterval===void 0?void 0:no(n.pollInterval,`--poll-interval`),a=await Z(n),o=await a.workflows.retryRun(e,t);if(!n.wait){if(n.json)return I(o);R(`Started run ${o.runId} (retry of ${t}).`),R(`Inspect it with: tangle workflows run-detail ${e} ${o.runId}`);return}let s=n.json?null:z(`Waiting for run ${o.runId} to finish...`).start(),c;try{c=await a.workflows.waitForRun(e,o.runId,{...r===void 0?{}:{timeoutMs:r},...i===void 0?{}:{pollIntervalMs:i}})}finally{s?.stop()}if(c.status===`failed`&&(process.exitCode=1),n.json)return I(c);Fc(c)}),e.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 Z(n);for await(let i of r.workflows.watchRun(e,t))n.json?console.log(JSON.stringify(i)):Lc(i),i.type===`run.done`&&i.status===`failed`&&(process.exitCode=1)})}async function zc(e,t,n,r){let i=await Z({...n,signal:r}),a=Xl(t),o=Nc(n.param,`param`),s={name:pe(e).replace(/(\.graph)?\.(yaml|yml|json)$/i,``),...o?{params:o}:{},...n.seat?{seat:n.seat}:{}},c,l;if(n.resume){let e=await i.workflows.getRun(n.resume,{signal:r});e.id!==n.resume&&X(`The cloud owner returned another run identity`);let t=e.execution;if((t?.kind!==`graph`||t.sourceSha!==a)&&X(`The authored cloud graph source changed`),Object.entries(o??{}).some(([e,n])=>!Object.hasOwn(t.params,e)||re(t.params[e])!==re(n))&&X(`A recorded cloud graph parameter changed`),n.seat!==void 0&&n.seat!==t.deploy.seat&&X(`The recorded cloud seat override changed`),n.dryRun)return{run:e};if((e.status===`cancelled`||e.status===`failed`)&&X(`The cloud run is terminal: ${e.status}`),e.status===`succeeded`)return e.graphResult||X(`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`&&X(`The owner has not confirmed recovery eligibility`),c=e.workflowId,l=e.revUsed??X(`The captured cloud revision is unavailable`)}else{if(n.dryRun)return i.workflows.validate(t,{format:`graph`,deploy:s});let e=await i.workflows.create(t,{format:`graph`,deploy:s});c=e.id,l=e.headRev??X(`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&&X(`The cloud owner recovered another run identity`),{...u,workflowId:c,sourceDigest:a,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(c)}/runs/${encodeURIComponent(u.runId)}`}}const Bc=[`claude-code`,`opencode`,`codex`,`kimi-code`,`prime`],Vc=process.env.TANGLE_ROUTER_URL??`https://router.tangle.tools/v1`;function Hc(e){let t=ie(e);if(t)return t;throw Error(`--model '${e}' has no provider. Pass a canonical id, for example 'google/${e}'.`)}function Uc(e){let t=e.harness??`claude-code`;if(!Bc.includes(t))throw Error(`Unknown --harness '${t}'. Supported: ${Bc.join(`, `)}.`);let n=Wc(e.maxTokens,2e5,`--max-tokens`),r=Wc(e.maxIterations,50,`--max-iterations`),i=e.maxWorkers===void 0?void 0:Wc(e.maxWorkers,0,`--max-workers`);return{harness:t,...e.model?{model:e.model}:{},maxTokens:n,maxIterations:r,...i===void 0?{}:{maxWorkers:i}}}function Wc(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 Gc(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 Kc(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 qc=null;function Jc(){return qc??=import(`@tangle-network/agent-runtime/kernel`).catch(e=>{throw qc=null,e?.code===`ERR_MODULE_NOT_FOUND`?new V(`RUNTIME_UNAVAILABLE`,`Agent Runtime could not be loaded`,e.message,`npm install -g @tangle-network/sandbox-cli@latest`):e}),qc}async function Yc(e,t,n){let r=W({apiKey:n.apiKey,baseUrl:n.baseUrl}),i=G(r),{budget:a,perWorker:o}=Gc(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||R(`worker ${a.id} spawned`),a}},l=await Jc(),u=l.workerFromBackend({backend:`sandbox`,sandboxClient:c,maxIterations:1}),d=(e,n)=>u({...e,harness:t.harness},n),f={name:`supervisor`,harness:`cli-base`,model:{default:t.model??`gemini-3.5-flash-lite`,provider:t.model?Hc(t.model):`google`},tools:{agent_runtime_coordination_spawn_worker:!0,agent_runtime_coordination_observe_agent:!0}},p={routerBaseUrl:Vc,routerKey:r.apiKey},m=Kc(await l.supervise(f,{goal:e},{budget:a,makeWorkerAgent:d,router:p,...o?{perWorker:o}:{},...t.model?{allowedModels:[t.model]}:{},runId:`supervise-${w()}`})),h=m.status===`winner`?`settled`:`failed`;for(let e of s)e.status=h,n.json||R(`worker ${e.id} settled (${e.status})`);return{task:e,result:m.text,workers:s,tokenUsage:m.tokenUsage,costUsd:m.costUsd,status:m.status}}function Xc(){let e=new x(`supervise`);return e.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 (${Bc.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(e,t)=>{let n=Uc({harness:t.harness,model:t.model,maxTokens:t.maxTokens,maxIterations:t.maxIterations,maxWorkers:t.maxWorkers});t.json||(R(`Supervising: ${e}`),R(`harness=${n.harness} budget=${n.maxTokens}tok/${n.maxIterations}it`),console.log());let r=await Yc(e,n,{apiKey:t.apiKey,baseUrl:t.baseUrl,json:t.json});if(t.json){I(r),r.status!==`winner`&&(process.exitCode=1);return}if(console.log(),r.result&&(console.log(r.result),console.log()),B({"Input Tokens":r.tokenUsage.input??`Unavailable`,"Output Tokens":r.tokenUsage.output??`Unavailable`,Cost:r.costUsd===null?`Unavailable`:`$${r.costUsd.toFixed(4)}`}),r.status!==`winner`)throw Error(`Supervisor finished without a winner: ${r.status}`)}),e}const Zc=Xe(Se),Qc=async(e,...t)=>(await Zc(`bash`,[`-ec`,e,`gi`,...t],{maxBuffer:3e8})).stdout,$c=j(M(),`.tangle`,`graph-improve`,`v5`),el=j(M(),`.tangle`,`workspaces`),tl=j(M(),`.tangle`,`runs`),nl=e=>({inputTokens:0,outputTokens:e,usageUnknown:!0}),rl=e=>!!e&&e.owner!==`work`&&e.code!==`budget-exhausted`;async function il(e){let[t,n]=[j(e,`bin`),j(e,`remotes`)];for(let e of[t,n])await Ve(e);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(e,t)=>{let n=await ou(e,t);z(n),`status`in n&&n.status!==`completed`&&(process.exitCode=1)})}async function cu(e,t){let n=[],r=[],i=(e,t)=>{if(!t||typeof t!=`object`)return;let i=P.object({status:P.string(),files:P.array(P.object({path:P.string(),artifact:k})),missing:P.unknown()}).parse(t);r.push({node:e,status:i.status,missing:i.missing}),n.push(...i.files.map(t=>({node:e,...t})))},a;if(e.startsWith(`wfrun_`)){let n=await Q(t),r=await n.workflows.getRun(e);for(let e of r.runtime?.checks??[])i(e.nodeId,e.outputs);a=async({artifact:t})=>{let i=(await n.workflows.listArtifacts(r.workflowId,e)).artifacts.find(e=>e.name===`runtime/${t.sha256}`&&e.byteSize===t.byteLength);if(!i)throw Error(`The workflow owner has no retained bytes for this artifact`);return(await n.workflows.downloadArtifact(r.workflowId,e,i.id)).bytes}}else{if(!P.uuid().safeParse(e).success)throw Error(`Use a recorded graph run ID`);let t=M(await I(M(N(),`.tangle`,`runs`)),e);if(await I(t)!==t)throw Error(`The graph run directory redirects elsewhere`);let{FileSpawnJournal:n,FileResultBlobStore:r,loadSpawnForest:o,createPrivateCasArtifactPort:s}=await import(`@tangle-network/agent-runtime/kernel`),c=new r(M(t,`blobs`)),l=await o(new n(M(t,`spawn-journal.jsonl`)),e);for(let e of l.nodes){if(e.runtime!==`graph-check`||!e.outRef)continue;let t=await c.get(e.outRef);i(e.id,t?.outputs)}let u=s(M(t,`artifacts`),e);a=e=>u.read(e.artifact)}if(!t.artifact)return z({runId:e,capture:r,files:n});if(!t.out)throw new W(`USAGE_INVALID`,`Select an output file`,`Artifact downloads require --out`,`tangle graph inspect ${e} --artifact <node/path> --out <file>`);let o=n.filter(e=>`${e.node}/${e.path}`===t.artifact||e.artifact.sha256===t.artifact);if(o.length!==1)throw Error(`Select one exact node/path from graph inspect --artifacts`);let s=o[0],c=await a(s);if(c.byteLength!==s.artifact.byteLength||`sha256:${$(Buffer.from(c))}`!==s.artifact.sha256)throw Error(`Retained artifact bytes do not match their recorded identity`);let l=be(t.out);await Ze(ge(l),{recursive:!0}),await L(l,c,{mode:384,flag:`wx`});let u={runId:e,node:s.node,path:s.path,artifact:s.artifact,destination:l};t.json?z(u):V(`Saved ${s.path} to ${l}`)}const lu=1e3;function uu(e,t){return[...t,e]}function du(e,t=`input`,n){if(n===void 0&&!e?.length)return;let r={};if(n!==void 0)try{if(r=JSON.parse(fe(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 W(`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 fu(e){R(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 pu(e){if(U({"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){V(`Actions`);let t=e.actionResults.some(e=>e.nodeId!==void 0||e.visit!==void 0);R(e.actionResults.map(e=>({index:e.index,...t?{node:e.nodeId??``,visit:e.visit??``}:{},kind:e.kind,status:e.status,error:e.error??``,cost:e.costUsd??``})),[{key:`index`,header:`#`},...t?[{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&&(V(`Graph`),U({Nodes:e.graph.nodes.length,Edges:e.graph.edges.length,"Max node visits":e.graph.maxNodeVisits}),R(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&&(V(`Edge verdicts`),R(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 mu(e){if(e.status===`cancelled`){V(`Cancelled run ${e.runId}.`);return}if(e.signalled){V(`Cancelling run ${e.runId} — signalled the worker; it will stop shortly.`);return}V(`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 hu(e){switch(e.type){case`snapshot`:V(`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 gu(e){e.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.`,uu,[]).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(e,t)=>{let n=du(t.input,`input`,t.inputFile),r=t.timeout===void 0?void 0:Go(t.timeout,`--timeout`),i=t.pollInterval===void 0?void 0:Go(t.pollInterval,`--poll-interval`),a=await Q(t),{runId:o}=await a.workflows.run(e,n);if(!t.wait){if(t.json)return z({runId:o});V(`Started run ${o} for workflow ${e}.`),V(`Inspect it with: tangle workflows run-detail ${e} ${o}`);return}let s=t.json?null:H(`Waiting for run ${o} to finish...`).start(),c;try{c=await a.workflows.waitForRun(e,o,{...r===void 0?{}:{timeoutMs:r},...i===void 0?{}:{pollIntervalMs:i}})}finally{s?.stop()}if(c.status===`failed`&&(process.exitCode=1),t.json)return z(c);pu(c)}),e.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(e,t)=>{let n=await Q(t),r=t.limit===void 0?void 0:Go(t.limit,`--limit`);if(t.all){let i=[],a=t.cursor,o=0,s=null;for(;;){let c=await n.workflows.listRuns(e,{...r===void 0?{}:{limit:r},...a===void 0?{}:{cursor:a}});if(i.push(...c.runs),o+=1,!c.nextCursor)break;if(o>=lu){s=c.nextCursor,t.json||V(`Stopped after ${lu} pages (${i.length} runs); more may exist — resume with --cursor ${c.nextCursor}`);break}a=c.nextCursor}if(t.json)return z({runs:i,nextCursor:s});fu(i);return}let i=await n.workflows.listRuns(e,{...r===void 0?{}:{limit:r},...t.cursor===void 0?{}:{cursor:t.cursor}});if(t.json)return z(i);fu(i.runs),i.nextCursor&&V(`More runs available — next page: --cursor ${i.nextCursor}`)}),e.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(e,t,n)=>{let r=await(await Q(n)).workflows.getRun(e,t);if(n.json)return z(r);pu(r)}),e.command(`cancel`).description(`Cancel a queued or in-progress run`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(e,t,n)=>{let r=await(await Q(n)).workflows.cancel(e,t);if(n.json)return z(r);mu(r)}),e.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(e,t,n)=>{let r=n.timeout===void 0?void 0:Go(n.timeout,`--timeout`),i=n.pollInterval===void 0?void 0:Go(n.pollInterval,`--poll-interval`),a=await Q(n),o=await a.workflows.retryRun(e,t);if(!n.wait){if(n.json)return z(o);V(`Started run ${o.runId} (retry of ${t}).`),V(`Inspect it with: tangle workflows run-detail ${e} ${o.runId}`);return}let s=n.json?null:H(`Waiting for run ${o.runId} to finish...`).start(),c;try{c=await a.workflows.waitForRun(e,o.runId,{...r===void 0?{}:{timeoutMs:r},...i===void 0?{}:{pollIntervalMs:i}})}finally{s?.stop()}if(c.status===`failed`&&(process.exitCode=1),n.json)return z(c);pu(c)}),e.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 Q(n);for await(let i of r.workflows.watchRun(e,t))n.json?console.log(JSON.stringify(i)):hu(i),i.type===`run.done`&&i.status===`failed`&&(process.exitCode=1)})}async function _u(e,t){let n;try{if(n=t.deploy?jt(await F(t.deploy,`utf8`)):{name:he(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 W(`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=du(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 vu(e){if(e.execution?.kind!==`graph`||!e.headRev)throw new W(`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 yu(e,t){let n=await e.workflows.list({name:t});if(n.length>1)throw new W(`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 bu(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 yu(e,n.name);let o=await e.workflows.validate(t,{format:`graph`,deploy:i});if(!o.valid)throw new W(`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}`}),vu(a);let s=e=>!e.triggers?.some(e=>e.kind===`provider_event`)&&e.enabled===(i.enabled??!0)&&e.execution.sourceSha===$(t)&&o.graphDigest!==void 0&&e.execution.graphDigest===o.graphDigest&&A(e.execution.deploy)===A(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(vu(n),!s(n))throw t;return{action:`unchanged`,workflow:n}}}function xu(e,t){e.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(e,t)=>{let n=await Q(t);vu(await n.workflows.get(e)),z(await n.workflows.rotateHookToken(e))}),e.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(e,n)=>qc(void 0,async r=>{let i=t(e,process.cwd()),a=await F(i,`utf8`),o=await _u(i,n),s=await Q({...n,signal:r}),c=n.dryRun?await s.workflows.validate(a,{format:`graph`,deploy:o}):await bu(s,a,o,n.workflow);`valid`in c&&!c.valid&&(process.exitCode=1),n.json||`valid`in c?z(c):V(`${c.action} · ${c.workflow.id} · revision ${c.workflow.headRev}`)},`tangle graph apply --help`))}async function Su(e,t,n,r){if(n.mcpSecret?.length)throw new W(`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 Q({...n,signal:r}),a=$(t),o=du(n.param,`param`),s=await _u(e,n),c,l;if(n.resume){let e=await i.workflows.getRun(n.resume,{signal:r});e.id!==n.resume&&Z(`The cloud owner returned another run identity`),n.workflow&&e.workflowId!==n.workflow&&Z(`The recorded cloud deployment changed`);let t=e.execution;if((t?.kind!==`graph`||t.sourceSha!==a)&&Z(`The authored cloud graph source changed`),n.deploy&&A(t.deploy)!==A({on:[],...s})&&Z(`The recorded cloud deployment settings changed`),Object.entries(o??{}).some(([e,n])=>!Object.hasOwn(t.params,e)||A(t.params[e])!==A(n))&&Z(`A recorded cloud graph parameter changed`),n.seat!==void 0&&n.seat!==t.deploy.seat&&Z(`The recorded cloud seat override changed`),n.mcpPolicy!==void 0&&A(n.mcpPolicy)!==A(t.deploy.mcpPolicy??{allowLocalMcp:!1,allowedMcpHosts:[]})&&Z(`The recorded cloud MCP policy changed`),n.dryRun)return{run:e};if((e.status===`cancelled`||e.status===`failed`)&&Z(`The cloud run is terminal: ${e.status}`),e.status===`succeeded`)return e.graphResult||Z(`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`&&Z(`The owner has not confirmed recovery eligibility`),c=e.workflowId,l=e.revUsed??Z(`The captured cloud revision is unavailable`)}else{let e=n.workflow?await i.workflows.get(n.workflow):!n.deploy&&!n.dryRun?await yu(i,s.name):void 0;if(e){if((e.execution?.kind!==`graph`||e.execution.sourceSha!==a)&&Z(`The selected deployment does not contain this graph source; use graph apply first`),(n.deploy&&A(e.execution.deploy)!==A({on:[],...s})||Object.entries(o??{}).some(([t,n])=>!Object.hasOwn(e.execution?.kind===`graph`?e.execution.params:{},t)||A(e.execution?.kind===`graph`?e.execution.params[t]:null)!==A(n))||n.seat!==void 0&&n.seat!==e.execution.deploy.seat||n.mcpPolicy!==void 0&&A(n.mcpPolicy)!==A(e.execution.deploy.mcpPolicy??{allowLocalMcp:!1,allowedMcpHosts:[]}))&&Z(`The selected deployment bindings changed; use graph apply first`),n.dryRun)return{workflow:e};c=e.id,l=e.headRev??Z(`The selected deployment has no retained revision`)}else{if(n.dryRun)return i.workflows.validate(t,{format:`graph`,deploy:s});let{workflow:e}=await bu(i,t,s);c=e.id,l=e.headRev??Z(`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&&Z(`The cloud owner recovered another run identity`),{...u,workflowId:c,sourceDigest:a,viewerUrl:`${i.baseUrl}/app/workflows/${encodeURIComponent(c)}/runs/${encodeURIComponent(u.runId)}`}}const Cu=P.strictObject({runId:P.uuid(),identity:P.string(),request:P.string()});function wu(e,t){e.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(ll()).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(e,n)=>{let r={...n,mcpPolicy:n.mcpPolicy===void 0?void 0:await dl(n.mcpPolicy)},i=e=>{throw new W(`GRAPH_DELIVERY_REFUSED`,`Local graph delivery was not admitted`,e,`tangle graph dispatch --help`)};r.delivery.trim()||i(`A stable nonempty delivery id is required`);let a;try{a=P.record(P.string(),P.unknown()).parse(JSON.parse(await F(r.event,`utf8`)))}catch{return i(`The event file must contain a JSON object`)}let o=await I(t(e,process.cwd())),s=await I(process.cwd()),c=await F(o,`utf8`),l=A({file:o,cwd:s,delivery:r.delivery}),u=A({source:$(c),trigger:a,mcpPolicy:Ae.parse(r.mcpPolicy??{}),params:du(r.param,`param`)??{},...r.seat===void 0?{}:{seat:r.seat}}),d=M(N(),`.tangle`,`deliveries`,$(l));await Ze(d,{recursive:!0,mode:448}),await I(d)!==d&&i(`The delivery store redirects elsewhere`);let f=M(d,`delivery.json`),p;try{let e=await $e(f,le.O_WRONLY|le.O_CREAT|le.O_EXCL|le.O_NOFOLLOW,384);try{p={runId:E(),identity:l,request:u},await e.writeFile(JSON.stringify(p)),await e.sync()}finally{await e.close()}}catch(e){if(e.code!==`EEXIST`)throw e;let t=await $e(f,le.O_RDONLY|le.O_NOFOLLOW);try{p=Cu.parse(JSON.parse(await t.readFile(`utf8`)))}catch{return i(`The durable delivery record is incomplete; inspect it before retrying`)}finally{await t.close()}}(p.identity!==l||p.request!==u)&&i(`This delivery id already belongs to different graph bytes, event data or parameters`);let m;try{m=ht({lockPath:`${f}.lock`}).release}catch(e){return i(`Delivery ${r.delivery} cannot acquire its owner lock; inspect run ${p.runId}: ${e instanceof Error?e.message:`lock unavailable`}`)}try{let e=M(N(),`.tangle`,`runs`,p.runId,`input.json`),t=!1;try{await F(e),t=!0}catch(e){if(e.code!==`ENOENT`)throw e}let n=await Ef(o,{...r,...t?{resume:p.runId}:{}},{cwd:s,source:c,trigger:a,runId:p.runId});r.json?z({delivery:r.delivery,...n}):V(`Delivery ${r.delivery} · run ${p.runId}`)}finally{await m()}})}const Tu=e=>`${e}.tmp-${T(6).toString(`hex`)}`,Eu=new Map;function Du(e){let t=be(e),n=Eu.get(t)??{};if(Eu.set(t,n),n.queued)return n.queued;let r=(n.running??Promise.resolve()).catch(()=>void 0).then(async()=>{n.running=r,n.queued=void 0;try{let e=await Ye.open(t,`r`);await e.sync().finally(()=>e.close())}finally{n.queued||Eu.delete(t)}});return n.queued=r,r}async function Ou(e,t,{mode:n=384,owner:r,directory:i}={}){if(i&&!/^(?!\.\.?$)[^/]+$/.test(e))throw Error(`Not an entry name in the open directory: ${e}`);let a=i?`/proc/self/fd/${i.fd}/${e}`:e,o=Tu(a);try{let e=await Ye.open(o,`wx`,n);try{r&&await e.chown(r.uid,r.gid),await e.chmod(n),await e.writeFile(t,`utf-8`),await e.sync()}finally{await e.close()}await Ye.rename(o,a)}catch(e){throw await Ye.rm(o,{force:!0}).catch(()=>void 0),e}await(i?i.sync():Du(ge(a)))}const ku=P.number().int().positive(),Au=async e=>JSON.parse(await F(e,`utf8`)),ju=(e,t)=>Ou(e,JSON.stringify(t));function Mu(e,t){let n=e.readout(),r=n.tokensKnown?n.deadlineMs>0&&Date.now()>=n.deadlineMs?`Campaign deadline exhausted`:t.maxTokens!==void 0&&n.tokensCapped&&t.maxTokens>n.tokensLeft?`Campaign token ceiling cannot fund the next graph`:t.maxIterations!==void 0&&n.iterationsCapped&&t.maxIterations>n.iterationsLeft?`Campaign iteration ceiling cannot fund the next graph`:void 0:`Campaign token accounting is incomplete`;if(r)throw Object.assign(new Nt(r),{code:`GRAPH_CAMPAIGN_BUDGET_EXHAUSTED`})}const Nu=P.strictObject({runId:P.uuid(),budget:P.object({maxTokens:ku,maxIterations:ku,deadlineMs:ku}).passthrough(),sourceDigest:P.string(),graphDigest:P.string()});async function Pu(e,t,n,r){let i=M(e,`budget.json`),a;try{a=await Au(i)}catch(e){if(e.code!==`ENOENT`)throw e;a={identity:n,startedAt:Date.now()}}if(a.identity!==n)throw Error(`Campaign configuration changed; use a new campaign directory`);let o=a.readout;if(o?.reservedTokens)throw Error(`Campaign backing has unresolved historical reservations`);let s=async e=>{let t=await zt(M(N(),`.tangle`,`runs`,e.runId));if(!t)return;let n=await zl(e.runId);if(t.tree.root!==e.runId||e.sourceDigest!==void 0&&n.sourceDigest!==e.sourceDigest||e.graphDigest!==void 0&&n.graphDigest!==e.graphDigest)throw Error(`Campaign settlement does not match its exact admitted graph`);return{settled:t,digest:A({runId:e.runId,sourceDigest:n.sourceDigest,graphDigest:n.graphDigest,spend:t.spentTotal})}},c=St(t,a.startedAt),l=P.record(P.uuid(),P.string()).parse(a.settlements??{});for(let[e,t]of Object.entries(l)){let n=await s({runId:e});if(!n||n.digest!==t)throw Error(`Historical campaign settlement is missing or changed; accounting cannot resume`);c.observe(n.settled.spentTotal,{alreadySpent:!0}),r?.(e,n.settled.spentTotal)}if(o&&A(o)!==A(JSON.parse(JSON.stringify(c.readout()))))throw Error(`Historical campaign backing cannot be reconstructed from its retained settlements`);let u=a.pending===void 0?void 0:Nu.parse(a.pending),d=o??c.readout(),f,p=()=>ju(i,{identity:n,startedAt:a.startedAt,readout:u?d:c.readout(),settlements:l,...u?{pending:u}:{}}),m=(e,t=!1)=>{t||Mu(c,e.budget),d=c.readout();let n=c.reserve(e.budget,{assignment:e.runId,stage:`executing`});if(!n.ok)throw new Nt(`Campaign cannot reserve the next graph's complete ceiling`);f=n.ticket,u=e},h=async()=>{if(!u||!f)return;let e=await s(u);if(!e)return;let t=f,n;try{c.reconcile(t,e.settled.spentTotal)}catch(e){if(c.openReservations().some(({ticketId:e})=>e===t.id))throw await p(),e;n=e}let i=u.runId;if(l[i]=e.digest,u=void 0,f=void 0,await p(),r?.(i,e.settled.spentTotal),n)throw n};if(u){let e=u;u=void 0,m(e,!0),await h()}return await p(),{pool:c,checkpoint:async e=>{if(e){if(l[e.runId]){let t=await s(e);if(!t||t.digest!==l[e.runId])throw Error(`An accounted campaign settlement changed`);r?.(e.runId,t.settled.spentTotal);return}if(u&&A(u)!==A(e))throw new Nt(`Campaign must reconcile its exact pending run ${u.runId} before admitting another graph`);u||m(e)}else{if(await h(),u)throw new Nt(`Campaign run ${u.runId} has no retained settlement; its reservation remains pending`);c.assertNoOpenTickets()}await p()},startedAt:a.startedAt,pendingAttempt:()=>u&&structuredClone(u)}}const Fu=P.strictObject({id:P.string(),kind:P.literal(`retained-graph`),domain:P.string().min(1),unit:P.string().min(1),split:P.enum([`train`,`dev`,`test`]),run:P.string().min(1),origin:P.string(),sourceDigest:P.string().nullable(),graphDigest:P.string().nullable(),params:P.record(P.string(),P.unknown()),trigger:P.record(P.string(),P.unknown()).nullable().optional(),mcpPolicy:Ae.optional(),taskWorkspace:Dl.optional(),outcome:P.string(),gaps:P.array(P.string()),evidence:P.string(),quality:P.null()}),Iu=async e=>JSON.parse(await F(e,`utf8`)),Lu=e=>e.code===`ENOENT`;function Ru(e,{name:t,provenance:n}){let r={train:0,dev:0,test:0,holdout:0};for(let t of e)r[t.split]++;return{name:t,provenance:n,contentHash:A(e.map(e=>({id:e.id,split:e.split,payload:e})).sort((e,t)=>e.id<t.id?-1:+(e.id>t.id))).slice(7),scenarioCount:e.length,splitCounts:r}}async function zu(e,t){let n=A(t),r=M(e,`objects`,`${n.slice(7)}.json`);await Ze(M(e,`objects`),{recursive:!0,mode:448});let i=JSON.stringify(t);try{await L(r,i,{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e;if(A(await Iu(r))!==n)throw Error(`Dataset evidence object changed`)}return n}async function Bu(e,t){if(!/^sha256:[a-f0-9]{64}$/.test(t))throw Error(`Invalid dataset object digest`);let n=await Iu(M(e,`objects`,`${t.slice(7)}.json`));if(A(n)!==t)throw Error(`Dataset evidence object changed`);return n}async function Vu(e,t){if(e.startsWith(`wfrun_`)){let n=await Q(t),[r,i]=await Promise.all([n.workflows.getRun(e,{signal:t.signal}),n.workflows.getRunInput(e,{signal:t.signal})]),a=i.completeness===`complete`&&i.id===r.id&&i.workflowId===r.workflowId&&i.revUsed===r.revUsed&&A({definitionSnapshot:i.definitionSnapshot,execution:i.execution,triggerContext:i.triggerContext,revUsed:i.revUsed})===i.inputDigest?i:void 0,o=a?.execution,s=a?.triggerContext;return{origin:new URL(n.baseUrl).origin,sourceDigest:i.sourceSha,graphDigest:i.graphDigest,params:o?.params??{},...a?{trigger:s}:{},mcpPolicy:o?.deploy?.mcpPolicy,outcome:r.status,source:a?.definitionSnapshot??null,gaps:[`task-workspace-not-snapshotted`,`environment-and-toolchain-not-snapshotted`,...a?[]:[`retained-input-unavailable`,...i.gaps],...o?[]:[`graph-execution-missing`],...a?.definitionSnapshot?[]:[`source-snapshot-missing`],...r.runtime?[]:[`runtime-evidence-missing`],...r.runtime?.trace?.gaps.map(e=>e.reason)??[],...r.runtime?.blobs.filter(e=>!e.found).map(e=>`blob-missing:${e.ref}`)??[]],record:{run:r.id,workflowId:r.workflowId,revUsed:r.revUsed,execution:o??null,trigger:a?.triggerContext??null,retainedInput:{completeness:a?`complete`:i.completeness===`complete`?`invalid`:i.completeness,inputDigest:a?.inputDigest??null,gaps:a?[]:[...i.gaps,`retained-input-unavailable`]},...o?.deploy?.mcpPolicy&&{mcpPolicy:o.deploy?.mcpPolicy},status:r.status,error:r.error,graphResult:r.graphResult??null,runtime:r.runtime?{namespace:r.runtime.namespace??null,journal:r.runtime.journal,blobs:r.runtime.blobs,trace:r.runtime.trace??null}:null}}}if(!P.uuid().safeParse(e).success)throw Error(`Use a retained local UUID or cloud wfrun_ ID`);let n=M(N(),`.tangle`,`runs`,e),r=await zl(e),[i,a,o,s]=await Promise.all([Hl(r),zt(n),Vt(n,{capturedAt:r.startedAt,verdict:null}),Bt(n,{totalChars:48e3})]);return{origin:`local`,sourceDigest:r.sourceDigest,graphDigest:r.graphDigest,params:r.params,trigger:r.trigger??null,mcpPolicy:r.mcpPolicy,taskWorkspace:r.taskWorkspace,source:i,outcome:a?.kind??`interrupted`,gaps:[...r.taskWorkspace?.gaps??[`task-workspace-not-snapshotted`,`environment-and-toolchain-not-snapshotted`],...o.gaps.map(e=>e.code),...s.truncated?[`summary-truncated`]:[]],record:{run:e,sourceDigest:r.sourceDigest,graphDigest:r.graphDigest,params:r.params,trigger:r.trigger??null,...r.mcpPolicy&&{mcpPolicy:r.mcpPolicy},...r.taskWorkspace&&{taskWorkspace:r.taskWorkspace},settled:a??null,rollouts:o.lines,summary:s}}}async function Hu(e,t){let n=be(e),r=t??(await Iu(M(n,`latest.json`))).version;if(!/^[a-f0-9]{64}$/.test(r))throw Error(`Invalid graph dataset version`);let i=await Iu(M(n,`versions`,`${r}.json`)),a=P.array(Fu).parse(i.cases),o=Ru(a,i.manifest);if(o.contentHash!==r||A(o)!==A(i.manifest))throw Error(`Graph dataset manifest changed`);for(let e of a)if(a.some(t=>t.domain===e.domain&&t.unit===e.unit&&t.split!==e.split))throw Error(`An independent unit crosses dataset splits`);return{root:n,version:r,manifest:o,cases:a}}async function Uu(e,t,n){let r=n;if(t.some(e=>e.startsWith(`wfrun_`))){let e=await Q(r);r={...r,baseUrl:e.baseUrl}}let i=be(e);await Ze(i,{recursive:!0,mode:448});let{release:a}=ht({lockPath:`${await I(i)}.lock`});try{let e;try{e=await Hu(i)}catch(e){if(!Lu(e))throw e}let n=new Map((e?.cases??[]).map(e=>[e.id,e]));for(let e of t){r.signal?.throwIfAborted();let t;try{t=await Vu(e,r)}catch(n){r.signal?.throwIfAborted(),t={origin:e.startsWith(`wfrun_`)?new URL(r.baseUrl).origin:`local`,sourceDigest:null,graphDigest:null,params:{},source:null,outcome:`unavailable`,gaps:[`retained-attempt-unavailable`],record:{run:e,error:n.name}}}let a=A({origin:t.origin,run:e}),o=n.get(a);if(o&&[`domain`,`unit`,`split`].some(e=>o[e]!==r[e]))throw Error(`A retained attempt cannot change domain, unit or split; fork the dataset`);let s=await zu(i,{...t.record,source:t.source});n.set(a,Fu.parse({id:a,kind:`retained-graph`,domain:r.domain,unit:r.unit,split:r.split,run:e,origin:t.origin,sourceDigest:t.sourceDigest,graphDigest:t.graphDigest,params:t.params,...t.trigger===void 0?{}:{trigger:t.trigger},...t.mcpPolicy===void 0?{}:{mcpPolicy:t.mcpPolicy},...`taskWorkspace`in t&&t.taskWorkspace?{taskWorkspace:t.taskWorkspace}:{},outcome:t.outcome,gaps:t.gaps,evidence:s,quality:null}))}let a=[...n.values()].sort((e,t)=>e.id.localeCompare(t.id));if(a.some(e=>a.some(t=>e.domain===t.domain&&e.unit===t.unit&&e.split!==t.split)))throw Error(`An independent unit crosses dataset splits`);let o=Ru(a,{name:e?.manifest.name??`graph-runs`,provenance:e?.manifest.provenance??{createdAt:new Date().toISOString(),version:`1`}});await Ze(M(i,`versions`),{recursive:!0});let s=M(i,`versions`,`${o.contentHash}.json`);try{await L(s,JSON.stringify({manifest:o,cases:a}),{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e}let c=M(i,`latest-${E()}.json`);return await L(c,JSON.stringify({version:o.contentHash}),{mode:384,flush:!0}),await tt(c,M(i,`latest.json`)),Hu(i)}finally{await a()}}const Wu=P.number().int().positive().max(2**53-1),Gu=P.strictObject({maxEvaluations:Wu,maxConcurrency:Wu.max(1,`Retained graph campaigns admit one pending graph`).default(1)}),Ku=P.discriminatedUnion(`kind`,[P.strictObject({kind:P.literal(`native`)}),P.strictObject({kind:P.literal(`gepa`),recipe:P.discriminatedUnion(`kind`,[P.strictObject({kind:P.literal(`engine`),run:Gu}),P.strictObject({kind:P.literal(`omni`),explore:P.array(Gu).min(1),continueWith:Gu,maxWorkers:Wu.max(1,`Retained graph campaigns admit one pending graph`).default(1)})]),maxModelRequests:Wu,maxRequestBytes:Wu,maxResponseBytes:Wu,maxCandidateChars:Wu,maxEvidenceChars:Wu,resume:P.enum([`never`,`if-compatible`,`required`]).default(`never`),trustLocalState:P.boolean().default(!1)})]);function qu(e,t,n=`prompt`){if(n!==`prompt`)throw Error(`Graph learning currently materializes only the prompt surface`);let r=Ku.parse(e??{kind:`native`});if(r.kind===`native`)return{kind:`native`,identity:A(r)};if(!t)throw Error(`Official GEPA requires caller-owned subscription execution`);if(r.recipe.kind===`omni`&&r.resume!==`never`)throw Error(`Official Omni does not support resumable state; use resume=never`);if(r.resume!==`never`&&!r.trustLocalState)throw Error(`Resumable GEPA requires explicit trust in local pickle state`);Wu.parse(t.maxOutputTokens),P.number().int().positive().max(2147483647).parse(t.timeoutMs);let i=e=>({engine:`gepa`,...e,engineConfig:{engine:{capture_stdio:!1,max_workers:e.maxConcurrency,parallel:e.maxConcurrency>1,raise_on_exception:!0},reflection:{reflection_minibatch_size:1,skip_perfect_score:!1}}}),a=r.recipe.kind===`engine`?{kind:`engine`,run:i(r.recipe.run)}:{kind:`omni`,explore:r.recipe.explore.map(i),continueWith:i(r.recipe.continueWith),maxWorkers:r.recipe.maxWorkers},o=t.subscriptionOnlyModel,s={maxRequests:r.maxModelRequests,maxRequestBytes:r.maxRequestBytes,maxResponseBytes:r.maxResponseBytes,maxOutputTokensPerRequest:t.maxOutputTokens,requestTimeoutMs:t.timeoutMs,pricing:{inputUsdPerMillion:0,outputUsdPerMillion:0}};return{kind:`official`,identity:A({config:r,model:o.model,callRef:o.callRef,budget:s,objective:t.objective}),method:Ft({objective:t.objective,recipe:a,optimizer:{...o,budget:s,servedModelPolicy:`exact`},runner:t.runner,timeoutMs:t.timeoutMs,maxCandidateChars:r.maxCandidateChars,maxEvidenceChars:r.maxEvidenceChars,resume:r.resume,trustResumeState:r.trustLocalState,describeScenario:t.describeScenario,describeArtifact:t.describeArtifact})}}const Ju=`tangle-native-reflection-json-content-v1`,Yu=`You are a native-agent reflection adapter. The task contains the original ordered role/content messages as JSON. Follow those messages as the reflection request. Return exactly one JSON object {"content":string}; content is the complete text response to that request. Do not add usage, model, or other fields.`;function Xu(e){let{profile:t,budget:n}=structuredClone({profile:e.profile,budget:e.budget});for(let e of Object.values(n))Wu.parse(e);let r=t.model?.default;if(!r||!t.harness)throw Error(`Native reflection requires an exact admitted harness and model profile`);let i=`${Ju}:${A({profile:t,budget:n,reflectionInstruction:Yu,binding:`params.reflection:whole-json-value`})}`;return{model:r,call:async({request:a,callId:o,signal:s})=>{let c=P.strictObject({model:P.literal(r),messages:P.array(P.strictObject({role:P.enum([`system`,`user`,`assistant`]),content:P.union([P.string(),P.array(P.strictObject({type:P.literal(`text`),text:P.string()}))])})).min(1),maxTokens:P.literal(n.maxTokens).optional(),timeoutMs:Wu.max(n.deadlineMs).optional()}).parse(a),l=JSON.stringify({graph:Ju,workspace:`fresh`,params:{reflection:{type:`object`,default:{protocol:Ju,messages:c.messages}}},nodes:[{id:`proposal`,profile:{...t,connections:void 0,mcp:void 0,hooks:void 0,resources:void 0,subagents:void 0,tools:{websearch:!1,webfetch:!1},prompt:{systemPrompt:Yu}}}],entry:[{node:`proposal`,task:"${params.reflection}"}],edges:[],budget:{...n,...c.timeoutMs&&{deadlineMs:c.timeoutMs}},check:{node:`proposal`,pointer:`/content`,exists:!0}}),u=await e.run(l,o,s),d=u.settlement,f=d.spentTotal,p=u.sourceDigest===w(`sha256`).update(l).digest(`hex`)&&d.tree.root===u.runId,m=f.tokensKnown!==!1&&f.tokens.tokensKnown!==!1,h={model:r,inputTokens:f.tokens.input,outputTokens:f.tokens.output,usageUnknown:!p||!m,...!p||f.usdKnown===!1?{costUnknown:!0}:{actualCostUsd:f.usd}},g={kind:Ju,callRef:i,callId:o,runId:u.runId,sourceDigest:u.sourceDigest,graphDigest:u.graphDigest,providerModel:d.providerModel??null};if(!p)return{succeeded:!1,error:`Reflection source or settlement run identity mismatched`,receipt:h,execution:g};if(d.kind!==`winner`||d.providerModel?.status!==`known`||d.providerModel.models.length!==1||d.providerModel.models[0]!==r)return{succeeded:!1,error:`Reflection failed or served model identity is unavailable/mismatched`,receipt:h,execution:g};let _=d.out?.proposal,v=_&&typeof _==`object`&&`json`in _?_.json:_,y=P.strictObject({content:P.string()}).safeParse(v);return y.success?{succeeded:!0,receipt:h,execution:g,response:{content:y.data.content,model:r,servedModel:d.providerModel.models[0],usage:{promptTokens:f.tokens.input,completionTokens:f.tokens.output,totalTokens:f.tokens.input+f.tokens.output,captured:m},costUsd:f.usdKnown===!1?null:f.usd,durationMs:u.durationMs,raw:{runId:u.runId,sourceDigest:u.sourceDigest}}}:{succeeded:!1,error:`Reflection omitted its exact content envelope`,receipt:h,execution:g}},callRef:i}}const Zu=P.number().int().positive(),Qu=P.strictObject({quality:P.number().min(0).max(1),notes:P.string()}),$u=P.strictObject({version:P.literal(1),optimizer:Ku.default({kind:`native`}),domain:P.string().min(1),node:P.string().min(1),objective:P.string().min(1),evaluator:P.strictObject({command:P.string().min(1).refine(ve,`Use an absolute evaluator executable path`),args:P.array(P.string()),files:P.array(P.string().min(1)).min(1),timeoutMs:Zu}),calibration:P.array(P.strictObject({request:P.unknown(),quality:P.union([P.literal(0),P.literal(1)])})).min(2),budget:P.strictObject({maxTokens:Zu,maxIterations:Zu,deadlineMs:Zu,maxExpansions:Zu,proposalTokens:Zu,proposalIterations:Zu,proposalDeadlineMs:Zu}),minimumEffect:P.number().positive().max(1),reps:Zu,operatingConstraints:P.strictObject({maxMeanTokens:Zu,maxMeanDurationMs:Zu,requireKnownOperatingCost:P.boolean().default(!1)})});async function ed(e,t,n,r,i){await i?.();let a=await Ke({command:e.evaluator.command,args:e.evaluator.args,cwd:t,timeoutMs:e.evaluator.timeoutMs,signal:r,ownProcessGroup:!0},void 0,{stdin:`${JSON.stringify(n)}\n`,maxOutputBytes:1024*1024});if(await i?.(),!a.exit.success)throw new Nt(`Independent evaluator failed (exit ${a.exit.code??`unknown`})`);return Qu.parse(JSON.parse(a.stdout??``))}async function td(e,t){let n=await I(e),r=$u.parse(await Au(n)),i=async()=>A({suite:await Au(n),files:await Promise.all([r.evaluator.command,...r.evaluator.files].map(async t=>{let n=await I(be(ge(e),t));return{path:n,digest:$(await F(n))}}))}),a=await i(),o=async()=>{if(await i()!==a)throw Error(`Independent evaluator dependencies changed during use`)};if(!r.calibration.some(e=>e.quality===0)||!r.calibration.some(e=>e.quality===1))throw Error(`Evaluator calibration needs both accepted and rejected examples`);let s=[];for(let e of r.calibration){let i=await ed(r,ge(n),e.request,t,o);if(i.quality!==e.quality)throw Error(`Independent evaluator failed its accepted/rejected calibration; no inference started`);s.push(i)}return{suite:r,cwd:ge(n),identity:a,calibration:s,assertUnchanged:o}}const nd=P.strictObject({evidence:P.string(),sourceDigest:P.string(),scenario:P.string(),unit:P.string(),split:P.enum([`train`,`dev`,`test`]),quality:P.number().min(0).max(1),tokens:P.number().nonnegative().nullable(),durationMs:P.number().nonnegative(),latencyKnown:P.boolean().default(!1),operatingCostUsd:P.null()});async function rd(e,t,n,r,i,a){let o=await F(new URL(a.ledger.uri),`utf8`);if(`sha256:${$(o)}`!==a.ledger.sha256||Buffer.byteLength(o)!==a.ledger.byteLength)throw Error(`Closed search ledger bytes changed`);vt(o,a.runId,a.ledger.uri);let s=new Map;for(let[t,n]of o.trim().split(`
154
+ `).entries()){let{event:r}=_t(n,a.runId,{path:a.ledger.uri,line:t+1});if(r.kind===`cell-settled`)try{let t=await Au(M(e,`attempts`,`${$(r.runId)}.json`));s.set(t.runId,r.wallMs===null||r.queueMs===null?null:r.wallMs+r.queueMs)}catch(e){if(e.code!==`ENOENT`)throw e}}let c=M(e,`judgments`),l=await et(c).catch(e=>{if(e.code!==`ENOENT`)throw e;return[]}),u=await Promise.all(l.filter(e=>e.endsWith(`.json`)).map(async e=>({...nd.parse(await Au(M(c,e))),durationMs:s.get(e.slice(0,-5))??null}))),d=e=>e.reduce((e,t)=>e+t,0)/e.length,f=[...new Set(u.map(e=>e.sourceDigest))].sort().map(e=>{let r=u.filter(t=>t.sourceDigest===e&&t.split===`test`),i=r.length===t.length*n.reps&&t.every(e=>r.filter(t=>t.scenario===e.id).length===n.reps),a=[...new Set(t.map(e=>e.unit))],o=e=>d(a.map(t=>d(r.filter(e=>e.unit===t).map(e))));return{sourceDigest:e,complete:i,observations:r.length,independentUnits:a.length,quality:i?o(e=>e.quality):null,meanTokens:i&&r.every(e=>e.tokens!==null)?o(e=>e.tokens):null,meanDurationMs:i&&r.every(e=>e.durationMs!==null&&e.latencyKnown)?o(e=>e.durationMs):null,operatingCostUsd:null}}),p=Ht(f,[{name:`independent quality`,direction:`maximize`,value:e=>e.quality??NaN},{name:`reported input plus output tokens`,direction:`minimize`,value:e=>e.meanTokens??NaN},{name:`end-to-end graph milliseconds`,direction:`minimize`,value:e=>e.meanDurationMs??NaN}]),m=f.find(e=>e.sourceDigest===r),h=f.find(e=>e.sourceDigest===i),g=[...!h?.complete||h.meanTokens===null||h.meanDurationMs===null?[`baseline operational evidence is incomplete`]:[],...m?.complete?[]:[`candidate final-test cohort is incomplete`],...m?.meanTokens==null?[`candidate token usage is unknown`]:m.meanTokens>n.operatingConstraints.maxMeanTokens?[`candidate exceeds mean token ceiling`]:[],...m?.meanDurationMs==null?[`candidate latency is unknown`]:m.meanDurationMs>n.operatingConstraints.maxMeanDurationMs?[`candidate exceeds mean latency ceiling`]:[],...p.frontier.some(e=>e.sourceDigest===r)?[]:[`candidate is absent from the matched quality/token/latency frontier`],...n.operatingConstraints.requireKnownOperatingCost?[`operating dollar cost is unknown`]:[]];return{admissible:g.length===0,reasons:g,constraints:n.operatingConstraints,reports:f,frontier:p.frontier.map(e=>e.sourceDigest),dollarFrontierEstablished:!1}}async function id(e,t){let n=be(e),{release:r}=ht({lockPath:`${await I(n)}.lock`}),i,a;try{let{record:e}=await Au(M(n,`result.json`)),r=await Bu(n,e);if(r.decision!==`promote`)throw Error(`The independent comparison held this candidate`);let o=await I(t);if(o!==r.sourcePath)throw Error(`Activation target differs from the measured source path`);i=ht({lockPath:`${o}.lock`}).release;let s=await F(r.candidate,`utf8`);if($(s)!==r.candidateDigest)throw Error(`Measured candidate bytes changed`);let c=$(await F(o));if(c!==r.baselineDigest&&c!==r.candidateDigest)throw Error(`Activation baseline changed; evaluate the new baseline`);let l=async()=>{if($(await F(o))!==c)throw Error(`Activation target changed while evidence was checked; the edit was preserved`)},{identity:u,assertUnchanged:d}=await td(r.suite);if(await l(),u!==r.evaluatorIdentity)throw Error(`Independent evaluator changed since measurement`);if(!r.operational.admissible)throw Error(`Measured operational constraints held this candidate`);let f=P.array(P.strictObject({runId:P.uuid(),scenario:P.string(),graphDigest:P.string()})).min(1).parse(r.executionIdentities),p=await Hu(r.dataset.root,r.dataset.version),m=new Set;for(let e of f){let t=p.cases.find(t=>t.id===e.scenario);if(!t||t.trigger===void 0)throw Error(`Measured execution inputs are unavailable`);let n=await zl(e.runId);if(n.sourceDigest!==r.candidateDigest||n.graphDigest!==e.graphDigest||A(Ae.parse(n.mcpPolicy??{}))!==A(Ae.parse(r.mcpPolicy??{})))throw Error(`Measured execution configuration changed`);m.add(await Rl(n));let i=await Ef(o,{param:Wl(t.params),dryRun:!0,mcpPolicy:Ae.parse(r.mcpPolicy??{})},{source:s,...t.trigger&&{trigger:t.trigger}});if(!(`graph`in i)||i.graph.digest!==e.graphDigest)throw Error(`Ordinary execution differs from the measured configuration; express its seat through the maintained graph contract and reevaluate under the intended host policy`)}await d(),await l();let h=await Au(M(n,`activation.json`)).catch(e=>{if(e.code!==`ENOENT`)throw e}),g={record:e,baselineDigest:r.baselineDigest,candidateDigest:r.candidateDigest,executionConfigurations:[...m].sort(),target:o,activatedAt:h?.record===e&&c===r.candidateDigest?h.activatedAt:new Date().toISOString()};return await ju(M(n,`activation.pending.json`),g),c!==r.candidateDigest&&(a=M(ge(o),`.${E()}.graph.yaml`),await L(a,s,{mode:384,flush:!0}),await l(),await tt(a,o),a=void 0,await Du(ge(o))),await ju(M(n,`activation.json`),g),g}finally{a&&await nt(a,{force:!0}),await i?.(),await r()}}async function ad(e,t,n){let r=be(e),{release:i}=ht({lockPath:`${await I(r)}.lock`});try{let e=await Au(M(r,`activation.json`)),i=await Bu(r,e.record),a=await zl(t);if($(await Hl(a))!==i.candidateDigest)throw Error(`Observation did not execute the activated candidate`);if(!P.array(P.string().regex(/^sha256:[a-f0-9]{64}$/)).min(1).parse(e.executionConfigurations).includes(await Rl(a)))throw Error(`Observation execution configuration differs from the activated measurement`);if(!n.trim())throw Error(`Observation needs an independent task unit`);if(Date.parse(a.startedAt)<=Date.parse(P.iso.datetime().parse(e.activatedAt)))throw Error(`Observation must have started after this candidate was activated`);let o=await Hu(i.dataset.root,i.dataset.version),s=A({params:a.params,trigger:a.trigger??null,taskWorkspace:a.taskWorkspace?Ol(a.taskWorkspace):null});if((await Promise.all((await et(M(r,`attempts`))).filter(e=>e.endsWith(`.json`)).map(e=>Au(M(r,`attempts`,e))))).some(e=>e.runId===t)||o.cases.some(e=>e.run===t||e.unit===n||A({params:e.params,trigger:e.trigger??null,taskWorkspace:e.taskWorkspace?Ol(e.taskWorkspace):null})===s))throw Error(`A learning execution or task is not a subsequent independent production observation`);let c=M(r,`observations`);await Ze(c,{recursive:!0,mode:448});for(let i of(await et(c)).filter(e=>e.endsWith(`.json`))){let a=await Au(M(c,i)),o=await Bu(r,a.record);if(o.runId===t){if(o.unit!==n||o.taskDigest!==s||o.activation.record!==e.record)throw Error(`The retained observation identity changed`);return{record:a.record,runId:t,verdict:o.verdict}}if(o.unit===n||o.taskDigest===s)throw Error(`An independent observation unit or task cannot be counted twice`)}let{suite:l,cwd:u,identity:d,assertUnchanged:f}=await td(i.suite);if(d!==i.evaluatorIdentity)throw Error(`Observation evaluator changed`);let p=await zt(M(N(),`.tangle`,`runs`,t));if(!p)throw Error(`Observation has not settled`);if(p.tree.root!==t)throw Error(`Observation settlement names another native run`);let m={...vl(p),runId:t,sourceDigest:a.sourceDigest,graphDigest:a.graphDigest},h=await ed(l,u,{scenario:{params:a.params,trigger:a.trigger??null,unit:n,taskDigest:s},artifact:m},void 0,f),g=await zu(r,{activation:e,runId:t,unit:n,taskDigest:s,activatedAt:e.activatedAt,artifact:m,verdict:h});return await ju(M(r,`observations`,`${t}.json`),{record:g}),{record:g,runId:t,verdict:h}}finally{i()}}async function od(e,t,n,r,i,a={}){let o=i===void 0?Ar().seat??null:null,s=be(r);await Ze(s,{recursive:!0,mode:448});let{release:c}=ht({lockPath:`${await I(s)}.lock`});try{let r=await pd(e,t,n,s,i,o,a),{suite:c,dataset:l,profile:u,sourceForProfile:d,assertUnchanged:f,baselineDigest:p,optimizedCoordinate:m,evaluatorIdentity:h,calibration:g,hostBindings:_}=r,v=Xu({profile:u,budget:{maxTokens:c.budget.proposalTokens,maxIterations:c.budget.proposalIterations,deadlineMs:c.budget.proposalDeadlineMs},run:async(e,t,n)=>{let r=await C(e,t,{},n),i=await zt(M(N(),`.tangle`,`runs`,r.runId));if(!i)throw Error(`Reflection has no retained settlement`);return{...r,settlement:i}}}),y=await sd(r,v);try{let e=await Au(M(s,`result.json`)),t=await Bu(s,e.record);if(t.identity!==y)throw Error(`Completed campaign configuration changed; use a new directory`);if($(await F(t.candidate))!==t.candidateDigest)throw Error(`Measured candidate bytes changed`);return{...t,record:e.record}}catch(e){if(e.code!==`ENOENT`)throw e}let b=await cd(r,y),x=new Map;for(let e of l.cases)x.set(e.id,await Bu(l.root,e.evidence));let S=E(),C=ld(r,b,S),w=ud(r,x,S),T=await fd(r,v,y,{...b,run:C,judge:w});if(!T.searchHistory?.complete)throw await T.dispose(),new Nt(`Optimizer did not retain complete verified search history`);let D=d(T.candidate.profile),O=$(D);await f();let k=await rd(s,l.cases.filter(e=>e.split===`test`),c,O,p,T.searchHistory),ee=M(s,`${O}.graph.yaml`);await L(ee,D,{mode:384,flush:!0});let te=await Promise.all((await et(M(s,`judgments`)).catch(e=>{if(e.code!==`ENOENT`)throw e;return[]})).filter(e=>e.endsWith(`.json`)).map(async e=>{let t=nd.parse(await Au(M(s,`judgments`,e)));if(t.sourceDigest!==O)return null;let n=await Bu(s,t.evidence);if(n.artifact.sourceDigest!==O||typeof n.artifact.graphDigest!=`string`)throw Error(`Candidate judgment has no exact measured execution identity`);return{runId:n.artifact.runId,scenario:t.scenario,graphDigest:n.artifact.graphDigest}})),{dispose:ne,...re}=T,A={version:1,identity:y,optimizedCoordinate:m,baselineDigest:p,candidateDigest:O,candidate:ee,sourcePath:await I(e),dataset:{root:l.root,version:l.version},workspaceGaps:[...new Set(l.cases.flatMap(e=>e.taskWorkspace?.gaps??[`task-workspace-not-snapshotted`,`environment-and-toolchain-not-snapshotted`]))],suite:await I(n),evaluatorIdentity:h,calibration:g,executionIdentities:te.filter(e=>e!==null),mcpPolicy:_.mcpPolicy,decision:T.decision===`ship`&&k.admissible?`promote`:`hold`,operational:k,measurement:re,operatingCost:{known:!1,reason:`subscription and environment allocation are not metered as incremental provider charges`},campaignBudget:{limits:c.budget,readout:b.pool.readout()}};await f();let ie=await zu(s,A);return await ju(M(s,`result.json`),{record:ie}),await T.dispose(),{...A,record:ie}}finally{await c()}}async function sd(e,n){let{seat:r,defaultSeat:i,optimizedCoordinate:a,suite:o,baselineDigest:s,dataset:c,evaluatorIdentity:l,hostBindings:u,loaded:d}=e,f=t(import.meta.url);if(!f)throw Error(`Cannot identify the CLI dependency manifest`);return A({consumer:`graph-learning-v1`,optimizedCoordinate:a,optimizer:Ku.parse(o.optimizer),reflection:n.callRef,consumerBytes:$(await F(new URL(import.meta.url))),consumerManifest:$(await F(f)),environment:{node:process.version,platform:process.platform,architecture:process.arch,packages:await Promise.all([`@tangle-network/agent-runtime`,`@tangle-network/agent-eval`,`cli-bridge`].map(async e=>{let n=t(e,import.meta.url);if(!n)throw Error(`Cannot identify ${e} for reproducible learning`);return{name:e,version:(await Au(n)).version,entryDigest:$(await F(new URL(import.meta.resolve(e))))}}))},baselineDigest:s,dataset:c.version,evaluatorIdentity:l,seat:r??null,defaultSeat:i,mcpPolicy:u.mcpPolicy,graph:d.graph,budget:o.budget,reps:o.reps})}async function cd(e,t){let{root:n,suite:r,defaultSeat:i,bindings:a}=e,o=new AbortController,{pool:s,checkpoint:c,startedAt:l,pendingAttempt:u}=await Pu(n,r.budget,t,(e,t)=>{if(t.usd-(t.usdEstimated??0)>0){let t=new Nt(`Native subscription run ${e} reported positive provider billing; no further campaign work is admitted`);throw o.abort(t),t}}),d=AbortSignal.any([AbortSignal.timeout(Math.max(1,l+r.budget.deadlineMs-Date.now())),o.signal]);d.throwIfAborted();let f=u();if(f){let e=await zl(f.runId);if(e.sourceDigest!==f.sourceDigest||e.graphDigest!==f.graphDigest)throw Error(`Pending native input changed its admitted execution identity`);try{await Ef(e.file,{param:[],resume:e.runId,json:!0,mcpPolicy:e.mcpPolicy,mcpSecret:a.mcpSecret},{defaultSeat:i,cwd:e.cwd,source:await Hl(e),runId:e.runId,graphDigest:e.graphDigest,signal:d,...e.trigger&&{trigger:e.trigger}})}catch(e){if(e.code!==`GRAPH_RUN_FAILED`)throw e}finally{await c()}}return{pool:s,checkpoint:c,startedAt:l,signal:d}}function ld(e,t,n){let{root:r,hostBindings:i,seat:a,defaultSeat:o}=e,{signal:s,checkpoint:c}=t;return async(e,t,l,u,d=null,f)=>{await Ze(M(r,`attempts`),{recursive:!0,mode:448});let p=M(r,`attempts`,`${$(t)}.json`),m=!1;try{await L(p,JSON.stringify({runId:E(),startedAt:Date.now()}),{flag:`wx`,mode:384,flush:!0}),m=!0}catch(e){if(e.code!==`EEXIST`)throw e}let{runId:h,startedAt:g}=P.strictObject({runId:P.uuid(),startedAt:P.number().int().nonnegative()}).parse(await Au(p)),_=M(r,`executions`,h);await Ze(_,{recursive:!0,mode:448});let v=M(_,`graph.yaml`);try{await L(v,e,{flag:`wx`,mode:384,flush:!0})}catch(t){if(t.code!==`EEXIST`)throw t;if($(await F(v))!==$(e))throw Error(`Attempt source identity changed`)}let y;try{await F(M(N(),`.tangle`,`runs`,h,`input.json`)),y=await zl(h)}catch(e){if(e.code!==`ENOENT`)throw e}if(y&&$(await Hl(y))!==$(e))throw Error(`Attempt snapshot changed`);if(y&&(f?Ol(f):null)!==(y.taskWorkspace?Ol(y.taskWorkspace):null))throw Error(`Attempt task workspace identity changed`);let b=f?await Pl(f,{runId:h,resumeCwd:y?.cwd,signal:AbortSignal.any([s,u])}):void 0;try{let t=await Ef(v,{...i,param:Wl(l),dryRun:!0,...y&&{resume:h},...a&&{seat:a}},{defaultSeat:o,cwd:b?.cwd??_,signal:s,...d&&{trigger:d},...f&&{taskWorkspace:f}});if(!(`graph`in t))throw Error(`Attempt did not load locally`);if(!t.graph.budget?.maxTokens||!t.graph.budget.maxIterations||!t.graph.budget.deadlineMs)throw Error(`Every materialized case needs finite token, iteration and deadline budgets`);await c({runId:h,budget:t.graph.budget,sourceDigest:$(e),graphDigest:t.graph.digest});let r;try{await Ef(v,{...i,param:Wl(l),json:!0,...a&&{seat:a},...y&&{resume:h}},{defaultSeat:o,runId:h,cwd:b?.cwd??_,...f&&{taskWorkspace:f},graphDigest:t.graph.digest,signal:AbortSignal.any([s,u]),...d&&{trigger:d}})}catch(e){r=e}finally{await c()}let p=await zt(M(N(),`.tangle`,`runs`,h));if(!p)throw new Nt(`Native graph attempt has no retained settlement`,{cause:r});return{...vl(p),runId:h,sourceDigest:$(e),graphDigest:t.graph.digest,durationMs:Math.max(Date.now()-g,p.spentTotal.ms),latencyKnown:m,invocation:n,taskWorkspaceDigest:f?Ol(f):null}}finally{b?.release()}}}function ud(e,t,n){let{root:r,suite:i,evaluatorCwd:a,evaluatorIdentity:o,assertUnchanged:s}=e;return{name:`independent-domain-evaluator`,judgeVersion:o,dimensions:[{key:`quality`,description:i.objective}],score:async({artifact:e,scenario:c,signal:l})=>{let u=await ed(i,a,{scenario:c,evidence:t.get(c.id),artifact:e},l,s),d=await zu(r,{evaluatorIdentity:o,scenario:c.id,artifact:e,verdict:u});return await Ze(M(r,`judgments`),{recursive:!0,mode:448}),await ju(M(r,`judgments`,`${e.runId}.json`),{evidence:d,sourceDigest:e.sourceDigest,scenario:c.id,unit:c.unit,split:c.split,quality:u.quality,tokens:e.tokenUsage.input===null||e.tokenUsage.output===null?null:e.tokenUsage.input+e.tokenUsage.output,durationMs:e.durationMs,latencyKnown:e.latencyKnown&&e.invocation===n,operatingCostUsd:null}),{dimensions:{quality:u.quality},composite:u.quality,notes:u.notes}}}}function dd(e,t){let{root:n,profile:r,suite:i,dataset:a}=e;return It({model:r.model?.default??`subscription-native`,pricing:{inputUsdPerMillion:0,outputUsdPerMillion:0},maxOutputTokens:i.budget.proposalTokens,frame:`Improve only the ${i.node} node's inline prompt. Domain: ${i.domain}. Objective: ${i.objective}. Preserve independent checks.`,evidence:async({trainCells:e})=>Promise.all(e.map(async e=>{let t=await Au(M(n,`attempts`,`${$(`${e.cellId}:${e.attempt}`)}.json`)),r=await Bt(M(N(),`.tangle`,`runs`,t.runId),{totalChars:48e3});return JSON.stringify({cell:e,tasks:a.cases.filter(t=>t.split===`train`&&t.unit===e.unitId).map(e=>({id:e.id,params:e.params,trigger:e.trigger,taskWorkspace:e.taskWorkspace?Ol(e.taskWorkspace):null})),records:r})})),chat:async({messages:e,callId:n,signal:r})=>{let a=await t.call({callId:n,signal:r,request:{model:t.model,messages:e,maxTokens:i.budget.proposalTokens}});if(!a.succeeded)throw Error(a.error);return{content:a.response.content,usage:a.response.usage.captured===!1?null:{inputTokens:a.response.usage.promptTokens,outputTokens:a.response.usage.completionTokens}}}})}async function fd(e,t,n,r){let{root:i,suite:a,dataset:o,profile:s,profileComponents:c,sourceForProfile:l}=e,{signal:u,startedAt:d,run:f,judge:p}=r,m=dd(e,t),h=qu(a.optimizer,{subscriptionOnlyModel:t,runner:{},maxOutputTokens:a.budget.proposalTokens,timeoutMs:a.budget.proposalDeadlineMs,objective:a.objective,describeScenario:e=>({id:e.id,params:e.params,trigger:e.trigger}),describeArtifact:e=>({text:e.text,status:e.status})}),g={surface:`agent-profile`,profileComponents:c,executionRef:n,trainScenarios:o.cases.filter(e=>e.split===`train`),selectionScenarios:o.cases.filter(e=>e.split===`dev`),testScenarios:o.cases.filter(e=>e.split===`test`),judges:[p],costCeiling:0,runDir:M(i,`search`),signal:u,agent:async(e,t,n)=>{let r=l(e),i=await n.cost.runPaidCall({actor:`native-graph`,model:s.model?.default??`subscription-native`,maximumCharge:{externallyEnforcedMaximumUsd:0},signal:n.signal,execute:()=>f(r,`search`in n?n.search.runId:`${n.cellId}:${n.runAttemptId}`,t.params,n.signal,t.trigger??null,t.taskWorkspace),receipt:e=>({model:s.model?.default??`subscription-native`,...e.costUsd===null?{costUnknown:!0}:{actualCostUsd:e.costUsd},inputTokens:e.tokenUsage.input??0,outputTokens:e.tokenUsage.output??0,usageUnknown:e.tokenUsage.input===null||e.tokenUsage.output===null})});if(!i.succeeded)throw i.error;return i.value}};return h.kind===`official`?await Pt(s,{...g,method:h.method,minimumLift:a.minimumEffect,reps:a.reps,maxConcurrency:1,optimizationRunOptions:{reps:a.reps,maxConcurrency:1}}):await Pt(s,{...g,method:Lt({proposer:m,maxExpansions:a.budget.maxExpansions,policy:gt(),allocation:yt({reps:a.reps}),lanes:[Rt({seats:1,cellUsd:0})],deadline:new Date(d+a.budget.deadlineMs).toISOString(),maxAttempts:1}),claim:{use:`comparison`,population:{id:a.domain,description:a.objective},samplingFrame:`retained graph dataset ${o.version}`,independentUnit:`unit`,generalization:`new-units`,minimumEffect:a.minimumEffect},executionRunId:e=>e.runId})}async function pd(e,t,n,r,i,a,o){let{suite:s,cwd:c,identity:l,calibration:u,assertUnchanged:d}=await td(n),f=await F(e,`utf8`),p=wt(f)[s.node];if(typeof p!=`string`)throw Error(`The selected node needs an unshared inline prompt`);let m=await Hu(t);if(m.cases.some(e=>e.domain!==s.domain))throw Error(`Dataset contains a different domain`);if(m.cases.some(e=>e.outcome===`unavailable`||!e.sourceDigest))throw Error(`Dataset retains unavailable attempts; reconcile them before freezing a learning cohort`);for(let e of[`train`,`dev`,`test`])if(!m.cases.some(t=>t.split===e))throw Error(`Dataset needs an independent ${e} partition`);if(m.cases.some(e=>e.trigger===void 0))throw Error(`Dataset lacks retained trigger context; reingest legacy runs before replay`);let h=[...new Set(m.cases.map(e=>JSON.stringify(Ae.parse(e.mcpPolicy??{}))))];if(!o.mcpPolicy&&h.length!==1)throw Error(`Retained MCP host policies differ; select an explicit --mcp-policy`);let g={...o,mcpPolicy:o.mcpPolicy??Ae.parse(JSON.parse(h[0]??`{}`))},_=m.cases.find(e=>e.split===`train`);if(!_)throw Error(`Dataset needs a train case`);let v=M(r,`baseline.graph.yaml`),y=$(f);try{await L(v,f,{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e;if($(await F(v))!==y)throw Error(`Frozen baseline changed`)}let b;if(_.taskWorkspace){let e=M(r,`task-workspace-admission.json`);try{await L(e,JSON.stringify({runId:E()}),{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e}let t=P.strictObject({runId:P.uuid()}).parse(await Au(e));b=await Pl(_.taskWorkspace,{...t,validationOnly:!0})}let x;try{x=await Ef(v,{...g,param:Wl(_.params),dryRun:!0,...i&&{seat:i}},{defaultSeat:a,..._.trigger&&{trigger:_.trigger},...b&&{cwd:b.cwd,taskWorkspace:_.taskWorkspace}})}finally{await b?.release()}if(!(`graph`in x))throw Error(`Baseline did not load locally`);if(!x.graph.budget?.maxTokens||!x.graph.budget.maxIterations||!x.graph.budget.deadlineMs)throw Error(`Graph needs finite token, iteration and deadline budgets for bounded improvement`);let S=x.graph.nodes.find(e=>e.id===s.node)?.profile;if(!S)throw Error(`Selected node was not materialized`);let C=typeof S.prompt?.systemPrompt==`string`?`systemPrompt`:`appendSystemPrompt`;if(typeof S.prompt?.[C]!=`string`)throw Error(`The selected source coordinate was not materialized`);let w=`prompt.${C}`,T={...S,prompt:{...S.prompt,[C]:p}},D=e=>{let t=e.prompt?.[C];if(typeof t!=`string`)throw Error(`Candidate lost its selected prompt coordinate`);return t},O={read:e=>({[w]:D(e)}),apply(e,t){if(Object.keys(t).length!==1||Object.keys(t)[0]!==w||typeof t[w]!=`string`)throw Error(`Candidate changed the selected prompt coordinate`);return{...e,prompt:{...e.prompt,[C]:t[w]}}}},k=e=>{let t=D(e);return t===p?f:Tt(f,{[s.node]:t})},ee={node:s.node,profileField:w,binding:`authored-source-compiled-per-case`};return{root:r,seat:i,defaultSeat:a,bindings:o,suite:s,evaluatorCwd:c,evaluatorIdentity:l,calibration:u,assertUnchanged:d,baselineDigest:y,dataset:m,hostBindings:g,loaded:x,profile:T,profileComponents:O,sourceForProfile:k,optimizedCoordinate:ee}}async function md(e,t,n,r){let i={mcpPolicy:n.mcpPolicy?await dl(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 F(M(t,`cases.jsonl.gz`)),l=Ut(c).toString().trim().split(`
155
+ `).map(e=>JSON.parse(e)),u=new Map(l.map(e=>[e.id,e])),d=e=>u.get(e.split(`:`).pop()??e),f=e=>`graph-improve-js::${d(e).upstream}`,p=e=>r.deterministicSplit(f(e),`agent-eval-v1`,[.32,.38]),m=(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}`],h=m(l[0],`none`),g=[];for(let e of a){let t=await F(e,`utf8`),n=await Ef(e,{...i,param:h,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`);g.push({file:e,source:t,sourceDigest:$(t),digest:n.graph.digest,cap:a,iterations:o,deadline:s})}return{bindings:i,files:a,sealed:s,manifest:c,cases:u,at:d,split:p,params:m,arms:g}}const hd=Ot(we),gd=async(e,...t)=>(await hd(`bash`,[`-ec`,e,`gi`,...t],{maxBuffer:3e8})).stdout,_d=M(N(),`.tangle`,`graph-improve`,`v5`),vd=M(N(),`.tangle`,`runs`),yd=e=>({inputTokens:0,outputTokens:e,usageUnknown:!0}),bd=e=>!!e&&e.owner!==`work`&&e.code!==`budget-exhausted`;async function xd(e){let[t,n]=[M(e,`bin`),M(e,`remotes`)];for(let e of[t,n])await Ze(e,{recursive:!0});let r=`#!/bin/sh
155
156
  [ "$1 $2" = "issue view" ] || { echo "gh: offline replay; only 'gh issue view <n>' answers" >&2; exit 1; }
156
157
  shift 2; n=; repo=; prev=
157
158
  for a; do
@@ -160,22 +161,19 @@ for a; do
160
161
  prev=$a
161
162
  done
162
163
  exec cat "${e}/remotes/$repo.git/tangle-issue-$n.json"
163
- `;for(let t of[`gh`,`gh-drew`])await qe(j(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 qe(j(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:j(t,`gitconfig`),BRIDGE_JAIL_RW_PATHS:n})}async function al(e,t,n){let{decidePairedPromotion:r,runCampaign:i,wilson:a}=await import(`@tangle-network/agent-eval`),o=await import(`@tangle-network/agent-eval/benchmarks`),{durableRunToolSpans:s,readSettleRecord:c}=await import(`@tangle-network/agent-runtime/durable`),l=[e,...n.arm],u=n.split===`test`;if(u?l.length!==2||!n.unseal:n.split!==`train`)throw Error(`--split is train, or test with one --arm and --unseal`);let d=u?`holdout`:`search`,f=await We(j(t,`cases.jsonl.gz`)),p=$e(f).toString().trim().split(`
164
- `).map(e=>JSON.parse(e)),m=new Map(p.map(e=>[e.id,e])),h=e=>m.get(e.split(`:`).pop()??e),g=e=>`graph-improve-js::${h(e).upstream}`,_=e=>o.deterministicSplit(g(e),`agent-eval-v1`,[.32,.38]),v=(e,t)=>[`issue=https://github.com/${e.upstream}/issues/${e.issue}`,...[`deliver=branch`,`base=main`,`test=${e.test}`],`verify_image=${t}`,`agent_tools={"websearch":false,"webfetch":false}`],y=v(p[0],`none`),b=[];for(let e of l){let t=await tu(e,{param:y,dryRun:!0});if(!(`graph`in t))throw Error(`${e} did not load locally`);let n=t.graph.nodes.filter(({check:e,profile:{tools:t}})=>!e&&(t?.websearch!==!1||t?.webfetch!==!1));if(n.length)throw Error(`${n.map(e=>e.id)} can use web tools; refusing`);let r=t.graph.budget?.maxTokens;if(!r)throw Error(`${e} sets no budget.maxTokens to book at`);b.push({file:e,digest:t.graph.digest,cap:r})}let ee=await He(j(xe(),`tangle-graph-improve-`));await il(ee);let x=n.dockerHost;x&&(process.env.DOCKER_HOST=`ssh://${x}`);let S=o.createHarborBenchmarkAdapter({id:`graph-improve-js`,datasetDir:t,assignSplit:_,tasks:[...m.keys()].filter(e=>_(e)===d).sort(),source:{name:`js-issues`,revision:Xl(f).slice(0,12)},grade:o.gradeHarborPatch({jobsDir:j($c,`jobs`)})}),C=new AbortController,te=async(e,t,{seat:n,signal:r})=>{let i=await o.prepareCaseEnvironment(t,{host:x,signal:r}),a=j($c,`remotes`,`${t.id}.git`);await Qc(`[ -d "$2/refs" ] && exit; g=$(mktemp -d); trap 'rm -rf "$g"' EXIT
164
+ `;for(let t of[`gh`,`gh-drew`])await L(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 L(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 Sd(e,t,n){let{CostLedger:r,decidePairedPromotion:i,runCampaign:a,wilson:o}=await import(`@tangle-network/agent-eval`),s=await import(`@tangle-network/agent-eval/benchmarks`),{durableRunToolSpans:c,readSettleRecord:l}=await import(`@tangle-network/agent-runtime/durable`),u=await md(e,t,n,s),{bindings:d,files:f,sealed:p,manifest:m,cases:h,at:g,split:_,arms:v}=u,y={},b,x=n.dockerHost;x&&(process.env.DOCKER_HOST=`ssh://${x}`);let S=s.createHarborBenchmarkAdapter({id:`graph-improve-js`,datasetDir:t,assignSplit:_,tasks:[...h.keys()].filter(e=>_(e)===p).sort(),source:{name:`js-issues`,revision:$(m).slice(0,12)},grade:s.gradeHarborPatch({jobsDir:M(_d,`jobs`)})}),C=new AbortController,w=await s.benchmarkScenarios(S,[p]),T=new Set(w.slice(0,n.probe).map(e=>e.id)),E=n.reps??1;if(!Number.isSafeInteger(E)||E<1||n.probe!==void 0&&(!Number.isSafeInteger(n.probe)||n.probe<1))throw Error(`--reps and --probe must be positive integers`);let D={maxTokens:n.maxTokens??v.reduce((e,t)=>e+t.cap,0)*w.length*E,maxIterations:n.maxIterations??v.reduce((e,t)=>e+t.iterations,0)*w.length*E,deadlineMs:n.deadlineMs??v.reduce((e,t)=>e+t.deadline,0)*w.length*E},O=$(JSON.stringify({dataset:$(m),sealed:p,arms:v.map(e=>({graph:e.digest,source:e.sourceDigest})),mcpPolicy:d.mcpPolicy??null,seats:n.seat,reps:E})),k=be(n.campaign??M(_d,`campaigns`,O));await Ze(k,{recursive:!0,mode:448}),b=M(k,`environment`);let{release:ee}=ht({lockPath:`${await I(k)}.lock`});try{await xd(b);for(let[e,t]of v.entries()){t.evidence=await zu(k,{kind:`graph-arm-source`,source:t.source,sourceDigest:t.sourceDigest});let n=M(k,`arm-${e}.json`),r=JSON.stringify({evidence:t.evidence});try{await L(n,r,{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e;if(await F(n,`utf8`)!==r)throw Error(`Benchmark arm source changed; use a new campaign`)}}let e=await Pu(k,D,$(JSON.stringify({identity:O,ceilings:D}))),{pool:t}=e,d=Dd({prepared:u,bench:s,conserved:e,campaign:k,live:b,host:x,stop:C,state:y,durableRunToolSpans:c,readSettleRecord:l}),m=AbortSignal.any([C.signal,AbortSignal.timeout(Math.max(1,e.startedAt+D.deadlineMs-Date.now()))]),h=new r({costCeilingUsd:0}),_=[...Array(E).keys()],ee=[...T].flatMap(e=>_.flatMap(t=>v.map((n,r)=>`${r}|${e}:${t}`))),te=new Map,ne=new Map(ee.map(e=>[e,new Promise(t=>te.set(e,t))])),re=new Map([...T].map(e=>[e,E*v.length]));m.addEventListener(`abort`,()=>{y.incomplete??=`Campaign deadline or cancellation interrupted matched comparison`;for(let e of te.values())e()},{once:!0});let A=v.map(async(t,r)=>{let i=`${t.digest}:${n.seat.join(`,`)}`,o=M(k,`arms`,`${r}`);if(p===`holdout`){await Ze(o,{recursive:!0});let e={at:new Date,reason:n.unseal,arms:f};await L(M(o,`holdout-access.jsonl`),`${JSON.stringify(e)}\n`,{flag:`a`})}return a({scenarios:w,reps:E,runDir:o,resumable:!0,dispatchRef:i,costLedger:h,costCeiling:0,cellFilter:e=>T.has(e.scenario.id),judges:[s.benchmarkJudge(S)],maxConcurrency:3,signal:m,dispatchTimeoutMs:Math.max(1,e.startedAt+D.deadlineMs-Date.now()),onCellSettled:async(e,{id:t,item:n})=>{e.cached&&te.get(`${r}|${e.cellId}`)?.(),re.set(t,(re.get(t)??1)-1),re.get(t)||await s.releaseCaseEnvironment(n,{host:x})},dispatch:async(e,i)=>{let a=ee.indexOf(`${r}|${i.cellId}`),o=n.seat[Math.floor(a/v.length)%n.seat.length],s=o??`graph-default`;try{await Promise.all(ee.slice(0,a).map(e=>ne.get(e)));let n=await i.cost.runPaidCall({actor:t.file,model:s,signal:i.signal,maximumCharge:{externallyEnforcedMaximumUsd:0},execute:n=>d(t,e.item,{seat:o,signal:n,attempt:i.cellId}),receipt:({tokens:e})=>({model:s,...e,actualCostUsd:0}),receiptFromError:()=>({model:s,...yd(t.cap),actualCostUsd:0})});if(!n.succeeded)throw n.error;return n.value}finally{te.get(`${r}|${i.cellId}`)?.()}}})}),ie=await Promise.allSettled(A.map(e=>e.catch(e=>{throw C.abort(e),e})));if(C.signal.aborted)throw C.signal.reason;let{reports:ae,paired:oe}=Od({campaigns:ie.map(e=>{if(e.status===`rejected`)throw e.reason;return e.value}),files:f,probe:T,reps:E,repList:_,at:g,state:y,wilson:o,decidePairedPromotion:i}),se={split:n.split,arms:ae,paired:oe,incomplete:y.incomplete??(ae.some(e=>!e.usageComplete||e.unmeasured.length)?`Campaign evidence is incomplete`:null),campaign:k,campaignBudget:{limits:D,readout:t.readout()},operatingCost:{known:!1,reason:`subscription and environment allocation are not incrementally metered`}};await L(M(k,`result.json`),JSON.stringify(se),{mode:384,flush:!0}),z(se)}finally{await ee()}}async function Cd(e,t,n){try{let{trigger:r,...i}=n,a=await Ef(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 wd=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(vd,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 Td(e,t){let n=await zl(e),r={...t,seat:t.seat??n.seat,mcpPolicy:t.mcpPolicy??n.mcpPolicy,trigger:n.trigger},i=await Hl(n),a=M(_d,`repairs`,e);await Ze(a,{recursive:!0});let o=M(a,`original.graph.yaml`);await L(o,i);let{runEvidence:s}=await import(`@tangle-network/agent-runtime/durable`),c=await s(M(vd,e),{settledChars:4e3,totalChars:48e3}),l=[`from`,`branch`,`failure`,`approved_head`],u=Object.entries(n.params).filter(([e])=>!l.includes(e)).map(([e,t])=>`${e}=${typeof t==`string`?t:JSON.stringify(t)}`),d=JSON.stringify({records:c,graph:i}),f=await Cd(o,[...u,`from=diagnose`,`failure=${d}`],r),p=await wd(f,`diagnose`),m={run:e,diagnoseRun:f,verdict:p};if(p.owner!==`graph`||!p.patch)return z(m);let h=M(a,`graph.yaml`);await L(h,i),await L(M(a,`patch.diff`),p.patch),await gd(`patch -s -p1 -d "$1" -i "$1/patch.diff"`,a);let g=async e=>{let t=await Ef(e,{...r,param:u,dryRun:!0},{...n.trigger&&{trigger:n.trigger}});if(!(`graph`in t))throw Error(`${e} did not load locally`);let{nodes:i,deliverable:a,edges:o}=t.graph,s=e=>o.filter(t=>[`from`in t&&t.from,t.to].flat().includes(e)),c=i.filter(e=>e.check).map(e=>[e.id,e.check,s(e.id)]);return JSON.stringify([a,c])};if(await g(o)!==await g(h))return z({...m,refused:`patch touches a check; not resumed`});let[_,v,y]=await Promise.all([wd(e,`verify`,!1),wd(e,`plan`,!1),wd(e,`intake`)]),{from:b=`intake`,failure:x,approved_head:S}=p.resume??{},C=(...e)=>e.find(e=>typeof e==`string`&&e.trim().length>0),w=C(y.branch,n.params.branch),T=C(_.test,v.test,n.params.test,y.test),E=C(_.setup,n.params.setup,v.setup,y.setup);if(b!==`intake`&&(!w||!T))throw Error(`Repair from=${b} requires a retained branch and resolved test command`);let D=[`from=${b}`];b!==`intake`&&D.push(`branch=${w}`),b!==`intake`&&D.push(`test=${T}`),E&&`setup`in n.params&&D.push(`setup=${E}`),x&&D.push(`failure=${x}`),S&&D.push(`approved_head=${S}`);let O=await Cd(h,[...u,...D],r),k={parentRunId:e,sourceDigest:n.sourceDigest,candidateDigest:$(await F(h)),diagnoseRun:f,resumed:O};await L(M(a,`parent.json`),JSON.stringify(k)),z({...m,patched:h,resumed:O,lineage:k})}function Ed(e){cl(e),e.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(e,t,n)=>{if(t.length&&(!n.domain||!n.unit||![`train`,`dev`,`test`].includes(n.split)))throw Error(`Ingestion requires --domain, --unit and --split train|dev|test`);z(t.length?await Uu(e,t,n):await Hu(e))}),e.command(`activate <campaign> <graph>`).description(`Activate the exact promoted graph under a target lock and fresh evidence checks`).action(async(e,t)=>z(await id(e,t))),e.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(e,t,n)=>z(await ad(e,t,n.unit))),e.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(ll()).action(async(e,t)=>Td(e,{...t,mcpPolicy:t.mcpPolicy?await dl(t.mcpPolicy):void 0}));let t=(e,t)=>[...t,e];e.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`,t,[]).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`,t,[]).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(ll()).action(async(e,t,n)=>{if(!n.suite)return Sd(e,t??M(_d,`js-issues`),n);if(!t||!n.campaign)throw Error(`Learning requires a retained dataset and --campaign directory`);if(n.arm.length||n.seat.length>1)throw Error(`Learning generates its candidate; use one matched --seat`);z(await od(e,t,n.suite,n.campaign,n.seat[0],{mcpPolicy:n.mcpPolicy?await dl(n.mcpPolicy):void 0,mcpSecret:n.mcpSecret}))})}function Dd(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})=>{if(o.incomplete)throw new Nt(o.incomplete);if(!t.evidence)throw Error(`Benchmark arm has no retained source`);let h=await Bu(r,t.evidence);if($(h.source)!==t.sourceDigest)throw Error(`Frozen benchmark arm changed`);let g=M(r,`attempts`,`${$(`${t.digest}:${f??`default`}:${m}`)}.json`);await Ze(M(r,`attempts`),{recursive:!0,mode:448});try{await L(g,JSON.stringify({runId:E()}),{flag:`wx`,mode:384,flush:!0})}catch(e){if(e.code!==`EEXIST`)throw e}let _=P.strictObject({runId:P.uuid()}).parse(JSON.parse(await F(g,`utf8`))),v;try{v=await zl(_.runId)}catch(e){try{throw await F(M(vd,_.runId,`input.json`)),e}catch(e){if(e.code!==`ENOENT`)throw e}}let y=await e.bench.prepareCaseEnvironment(n,{host:a,signal:p}),b=M(_d,`remotes`,`${n.id}.git`);await gd(`[ -d "$2/refs" ] && exit; g=$(mktemp -d); trap 'rm -rf "$g"' EXIT
165
165
  docker run --rm --network none "$1" tar -C /app/.git -c . | tar -x -C "$g"
166
166
  c=$(git -c user.name=graph-improve -c user.email=gi@local --git-dir "$g" commit-tree 'HEAD^{tree}' -m Base)
167
167
  git init -q --bare -b main "$2.partial" && git --git-dir "$g" push -q "$2.partial" "$c:refs/heads/main"
168
- mv "$2.partial" "$2"`,i,a);let l=h(t.id),u=j(ee,`remotes`,`${l.upstream}.git`),{issueTitle:d,issueBodyClean:f}=l,p=`https://github.com/${l.upstream}/issues/${l.issue}`,m=JSON.stringify({title:d,body:f,url:p,state:`OPEN`}),[g,_]=[];try{await Qc(`rm -rf "$2" && git clone -q --bare "$1" "$2" && printf %s "$4" > "$2/tangle-issue-$3.json"`,a,u,`${l.issue}`,m);try{let t={param:v(l,i),json:!0,...n&&{seat:n}},a=await tu(e.file,t,{signal:r});g=`runId`in a?a.runId:void 0;let o=JSON.parse(`text`in a?a.text:`{}`);_=Object.values(o).find(e=>e?.json?.branch)?.json?.branch}catch(e){let n=e;if(n.code!==`GRAPH_RUN_FAILED`)throw e;if(e.runtimeFailures?.some(({failure:e})=>rl(e)))throw new et(t.id,{cause:e});g=n.runId}let o=j(M(),`.tangle`,`runs`,`${g}`),d=(await s(o)).map(e=>e.toolName).find(e=>/web.?(search|fetch)/i.test(e));d&&C.abort(Error(`${g} called ${d}: not offline`)),C.signal.throwIfAborted();let f=_?await Qc(`b=$(git --git-dir "$1" rev-parse main); git --git-dir "$2" diff --binary "$b" "$3"`,a,u,_):``,p=await c(o),h=p&&Kc(p).tokenUsage;return{patch:f,tokens:h?.input!=null&&h.output!=null?{inputTokens:h.input??0,outputTokens:h.output??0}:nl(e.cap),...g&&{runId:g}}}finally{let e=g&&(await uc(g)).cwd;await Ke(u,{recursive:!0,force:!0}),e?.startsWith(`${el}/`)&&await Ke(e,{recursive:!0})}},w=await o.benchmarkScenarios(S,[d]),T=new Set(w.slice(0,n.probe).map(e=>e.id)),E=n.reps??1,D=[...Array(E).keys()],O=[...T].flatMap(e=>D.flatMap(t=>b.map((n,r)=>`${r}|${e}:${t}`))),ne=new Map,re=new Map(O.map(e=>[e,new Promise(t=>ne.set(e,t))])),ie=new Map([...T].map(e=>[e,E*b.length])),ae=b.map(async(e,r)=>{let a=`${e.digest}:${n.seat.join(`,`)}`,s=j($c,`base`,Xl(`${t}:${d}:${a}`));if(d===`holdout`){await Ve(s,{recursive:!0});let e={at:new Date,reason:n.unseal,arms:l};await qe(j(s,`holdout-access.jsonl`),`${JSON.stringify(e)}\n`,{flag:`a`})}return i({scenarios:w,reps:E,runDir:s,resumable:!0,dispatchRef:a,cellFilter:e=>T.has(e.scenario.id),judges:[o.benchmarkJudge(S)],maxConcurrency:3,signal:C.signal,dispatchTimeoutMs:4*36e5,onCellSettled:async(e,{id:t,item:n})=>{e.cached&&ne.get(`${r}|${e.cellId}`)?.(),ie.set(t,(ie.get(t)??1)-1),ie.get(t)||await o.releaseCaseEnvironment(n,{host:x})},dispatch:async(t,i)=>{let a=O.indexOf(`${r}|${i.cellId}`),o=n.seat[a%n.seat.length],s=o??`graph-default`;try{await Promise.all(O.slice(0,a).map(e=>re.get(e)));let n=await i.cost.runPaidCall({actor:e.file,model:s,signal:i.signal,maximumCharge:{model:s,inputTokens:0,outputTokens:e.cap},execute:n=>te(e,t.item,{seat:o,signal:n}),receipt:({tokens:e})=>({model:s,...e}),receiptFromError:()=>({model:s,...nl(e.cap)})});if(!n.succeeded)throw n.error;return n.value}finally{ne.get(`${r}|${i.cellId}`)?.()}}})}),k=await Promise.all(ae);if(C.signal.aborted)throw C.signal.reason;let oe=e=>e.reduce((e,t)=>e+t,0)/e.length,se=k.map((e,t)=>{let n=e.cells.filter(e=>!e.error),r=e=>Object.values(e.judgeScores)[0]?.composite??0,i=n.filter(e=>e.rep===0),o=i.filter(e=>r(e)>=1).length,s=e.cells.filter(e=>e.error),{inputTokens:c,outputTokens:u,usageComplete:d}=e.aggregates.cost;return{graph:l[t],resolved:o,n:i.length,runDir:e.runDir,wilson95:a(o,i.length),unmeasured:s.map(e=>`${e.cellId}: ${e.error}`),tokens:c+u,usageComplete:d,rewards:Object.fromEntries(n.map(e=>[e.cellId,r(e)]))}}),ce=({rewards:e},t)=>D.flatMap(n=>e[`${t}:${n}`]??[]),[le,...ue]=se,de=ue.map((e,t)=>{let n=[...T].filter(t=>ce(le,t).length&&ce(e,t).length),i=[...new Set(n.map(e=>h(e).upstream))],a=i.map(e=>n.filter(t=>h(t).upstream===e)),o=e=>a.map(t=>oe(t.map(t=>oe(ce(e,t))))),[s,c]=[o(le),o(e)],u=r(s,c,{continuous:!0}),{n:d,minimumPairs:f,low:p,threshold:m}=u,g=u.promote?void 0:!u.sufficient&&`insufficient pairs: n ${d} < minimumPairs ${f}`||p<=m&&`interval low ${p} ≤ threshold ${m}`||u.exactTestVetoes&&`McNemar exact test vetoes`||`indeterminate interval`;return{arm:l[t+1],cases:n.length,repos:i.length,rates:[oe(s),oe(c)],delta:u.delta,method:u.method,interval95:[u.low,u.high],sufficient:u.sufficient,decision:u.promote?`promote`:`hold`,why:g}});I({split:n.split,arms:se,paired:de})}async function ol(e,t,n){try{let r=await tu(e,{param:t,json:!0,...n});return`runId`in r?r.runId:void 0}catch(e){if(e.code!==`GRAPH_RUN_FAILED`)throw e;return e.runId}}const sl=async(e,t)=>JSON.parse(await Qc(`cat "$(ls -t "$1"/*/"$2".json | head -1)"`,j(tl,`${e}`,`graph-evidence`),t));async function cl(e,t){let n=await uc(e),r=await We(n.file,`utf8`),i=await Qc(`cd "$1"; jq -c '{kind,reason,nodes:[.tree.nodes[]|select(.status!="done")|{label,status,failure}]}' result.json
169
- jq -c 'select(.valid==false)|{node:.nodeName,exit:.exitCode,tail:.output[-3000:]}' command-checks.jsonl 2>/dev/null || :
170
- for f in $(ls -tr graph-evidence/*/*.json 2>/dev/null); do printf '%s ' "$(basename "$f")"; tail -c 2000 "$f"; echo; done | tail -c 24000`,j(tl,e)),a=[`from`,`branch`,`failure`,`approved_head`],o=Object.entries(n.params).filter(([e])=>!a.includes(e)).map(([e,t])=>`${e}=${typeof t==`string`?t:JSON.stringify(t)}`),s=JSON.stringify({records:i,graph:r}),c=[...o,`from=diagnose`,`failure=${s}`],l=await ol(n.file,c,t),u=await sl(l,`diagnose`),d={run:e,diagnoseRun:l,verdict:u};if(u.owner!==`graph`||!u.patch)return I(d);let f=j($c,`repairs`,e);await Ve(f,{recursive:!0});let p=j(f,`graph.yaml`);await qe(p,r),await qe(j(f,`patch.diff`),u.patch),await Qc(`patch -s -p1 -d "$1" -i "$1/patch.diff"`,f);let m=async e=>{let t=await tu(e,{param:o,dryRun:!0});if(!(`graph`in t))throw Error(`${e} did not load locally`);let{nodes:n,deliverable:r,edges:i}=t.graph,a=e=>i.filter(t=>[`from`in t&&t.from,t.to].flat().includes(e)),s=n.filter(e=>e.check).map(e=>[e.id,e.check,a(e.id)]);return JSON.stringify([r,s])};if(await m(n.file)!==await m(p))return I({...d,refused:`patch touches a check; not resumed`});let{branch:h,test:g}=(await sl(e,`intake`)).json??{},{from:_=`intake`,failure:v,approved_head:y}=u.resume??{},b=[`from=${_}`];_!==`intake`&&b.push(`branch=${h}`),`test`in n.params||b.push(`test=${g}`),v&&b.push(`failure=${v}`),y&&b.push(`approved_head=${y}`);let ee=await ol(p,[...o,...b],t);I({...d,patched:p,resumed:ee})}function ll(e){e.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`).action(cl);let t=(e,t)=>[...t,e];e.command(`improve <graph> [dataset]`).description(`Measure graph arms on js-issues by offline replay`).option(`--arm <graph>`,`Another arm, interleaved; repeatable`,t,[]).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`,t,[]).option(`--docker-host <ssh>`,`Build, verify and grade on this ssh host`).action((e,t,n)=>al(e,t??j($c,`js-issues`),n))}const ul=1e5;function Q(e){throw new V(`GRAPH_INVALID`,`Graph creation failed`,e,`tangle graph new --help`)}function dl(e){return typeof e==`string`&&/^[a-z0-9][a-z0-9-]{0,62}$/i.test(e)}const fl={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 pl=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||Q(`No graph file was saved`);let t=await Ue(e.file,se.O_RDONLY|se.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)&&Q(`The owned graph file was replaced`),Xl(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||Q(`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&&Q(`The graph is accepted; submit its recorded successful run`),this.enqueue(()=>this.write(e,t)).catch(e=>(this.lastFailure=e,{ok:!1,diagnostic:$t(e)}))}async write(e,t){t.throwIfAborted(),this.lastFailure=void 0;let n=e;(!n||!dl(n.name)||typeof n.source!=`string`||typeof n.run!=`boolean`||Object.keys(n).some(e=>![`name`,`source`,`run`].includes(e)))&&Q(`Expected only name, source and boolean run`),this.options.name!==void 0&&n.name!==this.options.name&&Q(`The graph name must match --name`),this.owned&&(this.owned.result=void 0);let r=j(this.directory,`${n.name}.yaml`);if(this.owned&&this.owned.file!==r&&Q(`This invocation owns one named graph file`),!this.owned)try{this.owned={file:r,handle:await Ue(r,se.O_RDWR|se.O_CREAT|se.O_EXCL|se.O_NOFOLLOW,384),digest:Xl(``)}}catch(e){throw e.code===`EEXIST`&&Q(`Graph already exists: ${r}; choose another --name`),e}let i=this.owned;await this.digest()!==i.digest&&Q(`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=Xl(a);let o={...this.options,param:[]},s={cwd:this.cwd,signal:t,source:n.source},c=await tu(r,{...o,dryRun:!0},{...s,connectNeeds:!0});`graph`in c||Q(`No canonical graph was returned`),c.graph.deliverable.checkRef===`command`&&Q(`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)*ul;if(d?.maxTokens!==void 0&&d.maxTokens<p&&Q(`budget.maxTokens ${d.maxTokens} is below ${p}: ${f} agent spawns plus one reservation at ${ul} tokens per native turn`),await this.digest()!==i.digest&&Q(`Graph changed during validation`),!n.run)return{file:r,graphDigest:c.graph.digest,validated:!0};let m=await tu(r,o,{...s,graphDigest:c.graph.digest});return(!(`status`in m)||m.status!==`winner`||m.graphDigest!==c.graph.digest||await this.digest()!==i.digest)&&Q(`The graph must succeed with unchanged YAML`),i.result=m,this.receipt()}async close(){await this.pending,await this.owned?.handle.close()}};async function ml(e,t,n){let{runId:r,runDir:i,cwd:a,bridge:o,signal:s}=e,c=await o(),l=j(await Ge(j(M(),`.tangle`)),`graphs`);(Zl(a,l)||Zl(l,a))&&Q(`The graph store must be outside the agent workspace; choose another working directory`);try{await Ve(l,{mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}await Ge(l)!==l&&Q(`The graph store redirects outside its canonical location`);let u=n.seat??Vn().seat,d=await mc(a,s)(u,{node:`graph-designer`,cwd:a,signal:s,lastCandidate:!0});d||Q(`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=ne(m),g=new pl(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:fl,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)&&Q(`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 V(`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 hl(e){e.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(e,t)=>{process.env.BRIDGE_JAIL_RW_PATHS?.trim()&&Q(`Remove BRIDGE_JAIL_RW_PATHS before graph new; extra native write roots cannot contain its host store`),t.name!==void 0&&!dl(t.name)&&Q(`Use letters, numbers and hyphens in --name`);let n=await $l({},n=>ml(n,e,t));t.json?I(n):R(`Created ${n.file} · run ${n.result.runId}`)})}const gl=e=>e===void 0?[]:(Array.isArray(e)?e:[e]).map(String),_l=(e=``)=>{let t=e.replace(/\s+/g,` `).trim(),n=t.match(/^.+?[.!?](?=\s|$)/)?.[0]??t;return n.length>90?`${n.slice(0,89)}…`:n},vl=e=>e&&(e.all??[e]).map(e=>{let t=`equals`in e?`= ${JSON.stringify(e.equals)}`:`in`in e?`∈ ${JSON.stringify(e.in)}`:e.exists===!1?`absent`:`exists`;return`${e.node??``}${e.pointer||`/`} ${t}`}).join(` and `);function yl(e,t){try{let n=rt(t,{uniqueKeys:!0,strict:!0}),r=[...n.errors,...n.warnings][0];if(r)throw r;let i=he(e)===`.json`?JSON.parse(t):n.toJS();if(Array.isArray(i?.nodes)&&Array.isArray(i.edges))return i;throw Error(`A graph needs nodes and edges lists`)}catch(t){throw new V(`GRAPH_INVALID`,`Graph file ${e} cannot be read`,t.message,`tangle graph show --help`)}}function bl(e,t){let n=yl(e,t),r=e=>{let t=String(e).match(/^\$\{params\.([\w-]+)\}$/)?.[1];return t?`${n.params?.[t]?.default??`?`} (params.${t})`:e},i=n.nodes.map(e=>{if(e.check){let t=String(e.check.command??``),n=t.match(RegExp(`#\\s*${e.id}:\\s*(.+)`))?.[1],r=t.split(`
171
- `).find(e=>e.trim()&&!/^\s*#/.test(e)),i=_l(n??`$ ${r}`);return{id:e.id,kind:`check`,detail:i,body:t.trim()}}let t=[e.profile?.harness,e.profile?.model?.default],n=gl(e.seat).join(` › `)||t.filter(Boolean).join(` · `),r=e.profile?.prompt?.systemPrompt?.trim(),i=_l(r),a=[n||`default seat`,i].filter(Boolean).join(`
172
- `);return{id:e.id,kind:`agent`,detail:a,body:r}});for(let e of n.gates??[]){let t=gl(e.choices).join(` | `);i.push({id:e.id,kind:`gate`,detail:`${t}\n${e.question}`})}let a=gl(n.entry?.map(e=>e.node??e)),o=[];if(a.length){i.unshift({id:`start`,kind:`start`,detail:``});let e=a.length>1?`fork`:``;o.push({from:[`start`],to:a,label:e,loop:!1})}for(let e of n.edges){let t=e.to?.finish===void 0?`stop`:`finish`,a=e.to?.[t]===void 0?void 0:`${t}:${e.to[t]}`,s=a===void 0?gl(e.to??e.join):[a];a&&!i.some(e=>e.id===a)&&i.push({id:a,kind:t,detail:``});let c=gl(e.kind===`analyzes`?e.over:e.from),l=n.edges.some(t=>!e.when&&t.when&&gl(t.from).join()===c.join()),u=e.maxTraversals!==void 0,d=[vl(e.when)??(l?`otherwise`:e.kind?.replace(`routes`,``)),c.length>1&&`join`,s.length>1&&`fork`,u&&`↺ loop ≤${r(e.maxTraversals)}`];o.push({from:c,to:s,label:d.filter(Boolean).join(` · `),loop:u})}let s=n.check??{},c=[[`params`,Object.entries(n.params??{}).map(([e,t])=>`${e}${`default`in t?`=${JSON.stringify(t.default)}`:` (required)`}`).join(`, `)],[`workspace`,n.workspace],[`done when`,s.command?.command??s.command??vl(s.all||s.pointer?s:void 0)],[``,s.describe]];return{name:n.graph??e.replace(/^.*\/|(\.graph)?\.(ya?ml|json)$/g,``),describe:n.describe?.trim(),facts:c.filter(e=>e[1]),nodes:i,edges:o}}const xl={start:[`▶`,b.green],agent:[`●`,b.cyan.bold],check:[`▣`,b.yellow.bold],gate:[`◇`,b.magenta.bold],finish:[`✓`,b.green.bold],stop:[`■`,b.red.bold]};function Sl(e){let t=t=>e.nodes.find(e=>e.id===t)?.kind??`agent`,n=e=>{let[n,r]=xl[t(e)];return r(`${n} ${e.replace(/^(finish|stop):/,``)}`)},r=Math.max(...e.nodes.map(e=>e.id.length))+4,i=[`${b.bold(`◆ ${e.name}`)}`,...e.describe?[` ${e.describe}`]:[],``];for(let[t,n]of e.facts)i.push(` ${b.dim(t.padEnd(10))} ${n}`);i.push(``,b.bold(`NODES`));for(let t of e.nodes.filter(e=>[`agent`,`check`,`gate`].includes(e.kind))){let[e,...a]=t.detail.split(`
173
- `);i.push(` ${n(t.id)}${` `.repeat(Math.max(1,r-t.id.length))}${e}`);for(let e of a)i.push(`${` `.repeat(r+4)}${b.dim(e)}`)}i.push(``,b.bold(`FLOW`));for(let t of e.edges){let e=` ${t.from.map(n).join(b.dim(` + `))} ${b.dim(`─▶`)} ${t.to.map(n).join(b.dim(` ∥ `))}`,r=t.loop?b.magenta(t.label):b.blue(t.label);i.push(...t.label.length+Ze(e).length>100?[e,` ${r}`]:[`${e} ${r}`])}return i.join(`
174
- `)}async function Cl(e,t){let n=j(t,`dist`,`graph-show`),[r,i]=await Promise.all([`viewer.iife.js`,`styles.css`].map(e=>We(j(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>
168
+ mv "$2.partial" "$2"`,y,b);let x=c(n.id),S=M(i,`remotes`,`${x.upstream}.git`),{issueTitle:C,issueBodyClean:w}=x,T=`https://github.com/${x.upstream}/issues/${x.issue}`,D=JSON.stringify({title:C,body:w,url:T,state:`OPEN`}),O=_.runId,k;{v||await gd(`rm -rf "$2" && git clone -q --bare "$1" "$2" && printf %s "$4" > "$2/tangle-issue-$3.json"`,b,S,`${x.issue}`,D);try{let e=l(x,y),n={...s,param:e,json:!0,...f&&{seat:f},...v&&{resume:_.runId}},r=await Ef(t.file,{...n,dryRun:!0},{signal:p,source:h.source,...v&&{cwd:v.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:_.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 Ef(t.file,n,{signal:p,source:h.source,runId:_.runId,graphDigest:r.graph.digest,...v&&{cwd:v.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}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 Nt(o.incomplete,{cause:e});if(e.runtimeFailures?.some(({failure:e})=>bd(e)))throw new Nt(n.id,{cause:e})}let r=M(N(),`.tangle`,`runs`,`${O}`),i=(await e.durableRunToolSpans(r)).map(e=>e.toolName).find(e=>/web.?(search|fetch)/i.test(e));i&&e.stop.abort(Error(`${O} called ${i}: not offline`)),e.stop.signal.throwIfAborted();let a=k?await gd(`b=$(git --git-dir "$1" rev-parse main); git --git-dir "$2" diff --binary "$b" "$3"`,b,S,k):``,c=await e.readSettleRecord(r),m=c&&vl(c).tokenUsage,g=u.readout();if(!g.tokensKnown||g.tokensLeft<0||g.iterationsLeft<0||g.deadlineMs>0&&Date.now()>=g.deadlineMs)throw o.incomplete=`Shared campaign budget exhausted or its accounting is incomplete`,new Nt(o.incomplete);return{patch:a,tokens:m?.input!=null&&m.output!=null?{inputTokens:m.input??0,outputTokens:m.output??0}:yd(t.cap),...O&&{runId:O}}}}}function Od(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 kd=1e5;function Ad(e){throw new W(`GRAPH_INVALID`,`Graph creation failed`,e,`tangle graph new --help`)}function jd(e){return typeof e==`string`&&/^[a-z0-9][a-z0-9-]{0,62}$/i.test(e)}const Md={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 Nd=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||Ad(`No graph file was saved`);let t=await $e(e.file,le.O_RDONLY|le.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)&&Ad(`The owned graph file was replaced`),$(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||Ad(`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&&Ad(`The graph is accepted; submit its recorded successful run`),this.enqueue(()=>this.write(e,t)).catch(e=>(this.lastFailure=e,{ok:!1,diagnostic:Un(e)}))}async write(e,t){t.throwIfAborted(),this.lastFailure=void 0;let n=e;(!n||!jd(n.name)||typeof n.source!=`string`||typeof n.run!=`boolean`||Object.keys(n).some(e=>![`name`,`source`,`run`].includes(e)))&&Ad(`Expected only name, source and boolean run`),this.options.name!==void 0&&n.name!==this.options.name&&Ad(`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&&Ad(`This invocation owns one named graph file`),!this.owned)try{this.owned={file:r,handle:await $e(r,le.O_RDWR|le.O_CREAT|le.O_EXCL|le.O_NOFOLLOW,384),digest:$(``)}}catch(e){throw e.code===`EEXIST`&&Ad(`Graph already exists: ${r}; choose another --name`),e}let i=this.owned;await this.digest()!==i.digest&&Ad(`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=$(a);let o={...this.options,param:[]},s={cwd:this.cwd,signal:t,source:n.source},c=await Ef(r,{...o,dryRun:!0},{...s,connectNeeds:!0});`graph`in c||Ad(`No canonical graph was returned`),c.graph.deliverable.checkRef===`command`&&Ad(`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)*kd;if(d?.maxTokens!==void 0&&d.maxTokens<p&&Ad(`budget.maxTokens ${d.maxTokens} is below ${p}: ${f} agent spawns plus one reservation at ${kd} tokens per native turn`),await this.digest()!==i.digest&&Ad(`Graph changed during validation`),!n.run)return{file:r,graphDigest:c.graph.digest,validated:!0};let m=await Ef(r,o,{...s,graphDigest:c.graph.digest});return(!(`status`in m)||m.status!==`winner`||m.graphDigest!==c.graph.digest||await this.digest()!==i.digest)&&Ad(`The graph must succeed with unchanged YAML`),i.result=m,this.receipt()}async close(){await this.pending,await this.owned?.handle.close()}};async function Pd(e,t,n){let{runId:r,runDir:i,cwd:a,bridge:o,signal:s}=e,c=await o(),l=M(await I(M(N(),`.tangle`)),`graphs`);(Sf(a,l)||Sf(l,a))&&Ad(`The graph store must be outside the agent workspace; choose another working directory`);try{await Ze(l,{mode:448})}catch(e){if(e.code!==`EEXIST`)throw e}await I(l)!==l&&Ad(`The graph store redirects outside its canonical location`);let u=n.seat??Ar().seat,d=await Kl(a,s)(u,{node:`graph-designer`,cwd:a,signal:s,lastCandidate:!0});d||Ad(`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=re(m),g=new Nd(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:Md,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)&&Ad(`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 W(`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 Fd(e){e.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(e,t)=>{process.env.BRIDGE_JAIL_RW_PATHS?.trim()&&Ad(`Remove BRIDGE_JAIL_RW_PATHS before graph new; extra native write roots cannot contain its host store`),t.name!==void 0&&!jd(t.name)&&Ad(`Use letters, numbers and hyphens in --name`);let n=await wf({},n=>Pd(n,e,t));t.json?z(n):V(`Created ${n.file} · run ${n.result.runId}`)})}const Id=e=>e===void 0?[]:(Array.isArray(e)?e:[e]).map(String),Ld=(e=``)=>{let t=e.replace(/\s+/g,` `).trim(),n=t.match(/^.+?[.!?](?=\s|$)/)?.[0]??t;return n.length>90?`${n.slice(0,89)}…`:n},Rd=e=>e&&(e.all??[e]).map(e=>{let t=`equals`in e?`= ${JSON.stringify(e.equals)}`:`in`in e?`∈ ${JSON.stringify(e.in)}`:e.exists===!1?`absent`:`exists`;return`${e.node??``}${e.pointer||`/`} ${t}`}).join(` and `);function zd(e,t){try{let n=Mt(t,{uniqueKeys:!0,strict:!0}),r=[...n.errors,...n.warnings][0];if(r)throw r;let i=_e(e)===`.json`?JSON.parse(t):n.toJS();if(Array.isArray(i?.nodes)&&Array.isArray(i.edges))return i;throw Error(`A graph needs nodes and edges lists`)}catch(t){throw new W(`GRAPH_INVALID`,`Graph file ${e} cannot be read`,t.message,`tangle graph show --help`)}}function Bd(e,t){let n=zd(e,t),r=e=>{let t=String(e).match(/^\$\{params\.([\w-]+)\}$/)?.[1];return t?`${n.params?.[t]?.default??`?`} (params.${t})`:e},i=n.nodes.map(e=>{if(e.check){let t=String(e.check.command??``),n=t.match(RegExp(`#\\s*${e.id}:\\s*(.+)`))?.[1],r=t.split(`
169
+ `).find(e=>e.trim()&&!/^\s*#/.test(e)),i=Ld(n??`$ ${r}`);return{id:e.id,kind:`check`,detail:i,body:t.trim()}}let t=[e.profile?.harness,e.profile?.model?.default],n=Id(e.seat).join(` › `)||t.filter(Boolean).join(` · `),r=e.profile?.prompt?.systemPrompt?.trim(),i=Ld(r),a=[n||`default seat`,i].filter(Boolean).join(`
170
+ `);return{id:e.id,kind:`agent`,detail:a,body:r}});for(let e of n.gates??[]){let t=Id(e.choices).join(` | `);i.push({id:e.id,kind:`gate`,detail:`${t}\n${e.question}`})}let a=Id(n.entry?.map(e=>e.node??e)),o=[];if(a.length){i.unshift({id:`start`,kind:`start`,detail:``});let e=a.length>1?`fork`:``;o.push({from:[`start`],to:a,label:e,loop:!1})}for(let e of n.edges){let t=e.to?.finish===void 0?`stop`:`finish`,a=e.to?.[t]===void 0?void 0:`${t}:${e.to[t]}`,s=a===void 0?Id(e.to??e.join):[a];a&&!i.some(e=>e.id===a)&&i.push({id:a,kind:t,detail:``});let c=Id(e.kind===`analyzes`?e.over:e.from),l=n.edges.some(t=>!e.when&&t.when&&Id(t.from).join()===c.join()),u=e.maxTraversals!==void 0,d=[Rd(e.when)??(l?`otherwise`:e.kind?.replace(`routes`,``)),c.length>1&&`join`,s.length>1&&`fork`,u&&`↺ loop ≤${r(e.maxTraversals)}`];o.push({from:c,to:s,label:d.filter(Boolean).join(` · `),loop:u})}let s=n.check??{},c=[[`params`,Object.entries(n.params??{}).map(([e,t])=>`${e}${`default`in t?`=${JSON.stringify(t.default)}`:` (required)`}`).join(`, `)],[`workspace`,n.workspace],[`done when`,s.command?.command??s.command??Rd(s.all||s.pointer?s:void 0)],[``,s.describe]];return{name:n.graph??e.replace(/^.*\/|(\.graph)?\.(ya?ml|json)$/g,``),describe:n.describe?.trim(),facts:c.filter(e=>e[1]),nodes:i,edges:o}}const Vd={start:[`▶`,b.green],agent:[`●`,b.cyan.bold],check:[`▣`,b.yellow.bold],gate:[`◇`,b.magenta.bold],finish:[`✓`,b.green.bold],stop:[`■`,b.red.bold]};function Hd(e){let t=t=>e.nodes.find(e=>e.id===t)?.kind??`agent`,n=e=>{let[n,r]=Vd[t(e)];return r(`${n} ${e.replace(/^(finish|stop):/,``)}`)},r=Math.max(...e.nodes.map(e=>e.id.length))+4,i=[`${b.bold(`◆ ${e.name}`)}`,...e.describe?[` ${e.describe}`]:[],``];for(let[t,n]of e.facts)i.push(` ${b.dim(t.padEnd(10))} ${n}`);i.push(``,b.bold(`NODES`));for(let t of e.nodes.filter(e=>[`agent`,`check`,`gate`].includes(e.kind))){let[e,...a]=t.detail.split(`
171
+ `);i.push(` ${n(t.id)}${` `.repeat(Math.max(1,r-t.id.length))}${e}`);for(let e of a)i.push(`${` `.repeat(r+4)}${b.dim(e)}`)}i.push(``,b.bold(`FLOW`));for(let t of e.edges){let e=` ${t.from.map(n).join(b.dim(` + `))} ${b.dim(`─▶`)} ${t.to.map(n).join(b.dim(` ∥ `))}`,r=t.loop?b.magenta(t.label):b.blue(t.label);i.push(...t.label.length+kt(e).length>100?[e,` ${r}`]:[`${e} ${r}`])}return i.join(`
172
+ `)}async function Ud(e,t){let n=M(t,`dist`,`graph-show`),[r,i]=await Promise.all([`viewer.iife.js`,`styles.css`].map(e=>F(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>
175
173
  <meta name="description" content="${(e.describe??o).replace(/[&<>"]/g,``)}">
176
174
  <style>${i}html,body,#root{margin:0;height:100%;font-family:ui-sans-serif,system-ui,sans-serif}</style></head>
177
175
  <body><div id="root"></div><script id="graph" type="application/json">${JSON.stringify(e).replace(/</g,`\\u003c`)}<\/script>
178
- <script>${a(r)}<\/script></body></html>`,c=j(await He(j(xe(),`tangle-graph-`)),`${o}.html`);return await qe(c,s,{mode:384}),c}function wl(e,t,n){e.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(e,r)=>{let i=await Ge(t(e,process.cwd())),a=bl(i,await We(i,`utf8`));if(r.json)return I(a);if(!r.open)return console.log(Sl(a));let o=await Cl(a,n);R(await wi(nt(o).href)?`Opened ${o}`:`Open ${o}`)})}async function Tl(e){if(!nr(e.apiKey)){if(e.json||e.dryRun||!process.stdin.isTTY)return;await Ni({baseUrl:e.sandboxBaseUrl,signal:e.signal})}return q(e)}async function El(e,t,n){let r=Wl(t.parameter),i=n??await Tl(t);if(!i)throw new V(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured`,`tangle auth login`);let a=await i.connections.start(e,{cli:!0,connectionParameters:r});return t.json?(I(Kl(a)),a):(Gl(a,t.browser===!1?!1:await wi(a.redirectUrl),t.wait),a)}async function Dl(e,t,n){let r=async()=>{n.signal?.throwIfAborted();let{connections:r}=await e.connections.list(),i=r.filter(e=>e.status===`active`&&e.providerId.toLowerCase()===t.trim().toLowerCase());return i.length?Sr(i,t):void 0},i=await r();if(i||n.json||n.dryRun||!process.stdin.isTTY)return i;let a=await El(t,{...n,wait:!0},e);for(;!i&&Date.now()<Date.parse(a.expiresAt);)await Ae(1e3,void 0,{signal:n.signal}),i=await r();return i}function Ol(){let e=new x(`hub`).description(`Discover and run Tangle Hub tools`);e.command(`connect`).description(`Connect a provider account`).argument(`provider`,`Provider to connect`).option(`--no-browser`,`Print the authorization URL instead of opening it`).option(`--parameter <key=value>`,`Provider-specific OAuth value. Repeatable.`,(e,t)=>[...t,e],[]).action(async(e,t)=>{await El(e,t)});let t=new x(`connections`).description(`List Hub provider connections`).action(async e=>{let t=await(await q(e)).connections.list();if(e.json){I(t);return}Ul(t.connections)});t.command(`revoke <connection-id>`).description(`Revoke a Hub provider connection`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=await q(t),r=await xr(n,e);if(!t.force&&!await Qr(`Revoke Hub connection ${r}? `,`--force`)){R(`Revoke cancelled.`);return}let i=await n.connections.revoke(r);if(t.json){I(i);return}R(`Revoked Hub connection ${i.connection.id}.`)}),e.addCommand(t);let n=new x(`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 e=>{if(!e.connection)throw Error(`--connection is required.`);let t=await q(e),n=await xr(t,e.connection),r=await t.permissions.list(n);if(e.json){I(r);return}Rl(r.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 e=>{if(!e.connection)throw Error(`--connection is required.`);if(!e.action)throw Error(`--action is required.`);let t=zl(e.decision),n=await q(e),r=await xr(n,e.connection),i=await n.permissions.set({connectionId:r,actionPath:e.action,decision:t});if(e.json){I(i);return}Rl([i.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 e=>{if(!e.connection)throw Error(`--connection is required.`);let t=await q(e),n=await xr(t,e.connection),r=await t.permissions.revertWrites(n);if(e.json){I(r);return}R(`Reverted ${r.reverted} write permission${r.reverted===1?``:`s`} for connection ${r.connectionId}.`)}),e.addCommand(n),e.addCommand(Al());let r=new x(`tools`).description(`Discover Hub tools`);return r.command(`sources`).description(`List Hub tool sources`).action(async e=>{let t=await(await q(e)).tools.sources();if(e.json){I(t);return}Bl(t.sources)}),r.command(`describe`).description(`Describe a Hub tool`).argument(`path`,`Executor tool path`).action(async(e,t)=>{let n=await(await q(t)).tools.describe(e);if(t.json){I(n);return}Vl(n.tool)}),r.command(`search`).description(`Search Hub tools`).argument(`<query...>`,`Search query`).option(`--provider <provider>`,`Filter by provider/source ID`).action(async(e,t)=>{let n=await(await q(t)).tools.search(e.join(` `),{provider:t.provider});if(t.json){I(n);return}Ll(n.tools)}),e.addCommand(r),e.addCommand(kl(`call`)),e.addCommand(kl(`exec`)),e.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(Ml(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 q(t);Pl(t.decline?await n.approvals.deny(e):await n.approvals.approve(e),t.json===!0)}),e.command(`status`).description(`Show Hub auth and connection status`).action(async e=>{let t=await(await q(e)).status();if(e.json){I(t);return}ql(t)}),e}function kl(e){return new x(e).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(e,t)=>{let{args:n,approve:r}=jl(e,t),{path:i,input:a}=Il(n),o=await q(t),s=t.connection?await xr(o,t.connection):void 0;I((await o.tools.invoke(i,a,{connectionId:s,approve:r})).result)})}function Al(){let e=new x(`approvals`).description(`List and resolve Hub execution approvals`);e.command(`list`).description(`List pending Hub execution approvals`).action(async e=>{let t=await(await q(e)).approvals.list();if(e.json){I(t);return}Nl(t.approvals)});for(let t of[`approve`,`deny`])e.command(t).description(`${t===`approve`?`Approve`:`Deny`} a pending Hub execution approval`).argument(`approval-id`,`Hub approval ID`).action(async(e,n)=>{Ml(e),Pl(await(await q(n)).approvals[t](e),n.json===!0)});return e}function jl(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 Ml(e){if(!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`Hub approval ID must contain only letters, numbers, underscores, and dashes.`)}function Nl(e){F(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 Pl(e,t){if(t){I(Fl(e));return}R(`Hub approval ${e.approval.id} ${e.approval.status}.`),e.capabilityToken&&R("Capability token minted. Re-run the original command with `--approve` to execute automatically.")}function Fl(e){return{approval:e.approval,...e.capabilityToken?{capabilityToken:{tokenId:e.capabilityToken.tokenId,expiresAt:e.capabilityToken.expiresAt}}:{}}}function Il(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 Ll(e){F(e.map(e=>({...e,provider:e.providerId??e.requiredConnectionProviderId,connection:Hl(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 Rl(e){F(e,[{key:`connectionId`,header:`Connection`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`decision`,header:`Decision`},{key:`updatedAt`,header:`Updated`}])}function zl(e){if(e===`allow`||e===`ask`||e===`deny`)return e;throw Error(`--decision must be one of: allow, ask, deny.`)}function Bl(e){F(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 Vl(e){B({Path:e.path,Provider:e.providerId??e.requiredConnectionProviderId,Title:e.title,Description:e.description,Connection:Hl(e),Policy:e.policyState}),e.inputSchema!==void 0&&(R(`Input schema`),console.log(JSON.stringify(e.inputSchema,null,2))),e.outputSchema!==void 0&&(R(`Output schema`),console.log(JSON.stringify(e.outputSchema,null,2)))}function Hl(e){if(e.connectionRequired===!1)return`not required`;if(e.connectionStatus)return e.connectionStatus}function Ul(e){F(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 Wl(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 Gl(e,t,n=!1){t?R(`Opened browser to connect ${e.provider}.`):(R(`Open this URL to connect ${e.provider}:`),console.log(e.redirectUrl)),R(n?`Finish authorization in the browser; this run resumes when connected.`:"Finish authorization in the browser, then rerun `tangle hub status`.")}function Kl(e){return{provider:e.provider,redirectUrl:e.redirectUrl,expiresAt:e.expiresAt,scopes:e.scopes,cli:e.cli}}function ql(e){let{principal:t,connections:n}=e;R(`Hub status`),B({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&&R(`Some providers require reconnect.`)}const Jl=t(import.meta.url);if(!Jl)throw Error(`Tangle CLI package metadata was not found`);const Yl=me(Jl),Xl=e=>C(`sha256`).update(e).digest(`hex`);function Zl(e,t){let n=_e(e,t);return n!==`..`&&!n.startsWith(`..${ye}`)&&!ge(n)}function Ql(e,t){if(/[\\/]/.test(e)||/\.(yaml|yml|json)$/.test(e))return ve(t,e);let n=t;for(;!ce(j(n,`.git`))&&me(n)!==n;)n=me(n);ce(j(n,`.git`))||(n=t);let r=[`yaml`,`yml`,`json`].flatMap(e=>[`graph.${e}`,e]),i=[n,M()].flatMap(t=>r.map(n=>j(t,`.tangle/graphs/${e}.${n}`))),a=i.find(ce);if(a)return a;throw new V(`GRAPH_NOT_FOUND`,`Graph '${e}' was not found`,`Looked in ${i.join(`, `)}`,`tangle graph --help`)}async function $l(e,t){return ac(e.signal,async n=>{let r=e.runId??w(),i;try{let a=j(M(),`.tangle`,`runs`,r);await Ve(a,{recursive:!0,mode:448});let o=await Ge(j(M(),`.tangle`)),s=await Ge(e.cwd??process.cwd()),c=[`runs`,`graph-registry`,`graphs`].some(e=>Zl(s,j(o,e))||Zl(j(o,e),s))?j(M(),`.tangle`,`workspaces`,r):s;await Ve(c,{recursive:!0,mode:448});let l;return await t({runId:r,runDir:a,cwd:c,bridge:t=>l??=(async()=>{n.throwIfAborted();let r=te(32).toString(`hex`),{loadConfig:o,startServer:s}=await import(`cli-bridge`),l=j(Yl,`dist`,`stdio.mjs`),u={...process.env,BRIDGE_HOST:`127.0.0.1`,BRIDGE_BEARER:r,BRIDGE_DATA_DIR:j(a,`bridge`),BRIDGE_BACKENDS:pc,BRIDGE_JAIL_MODE:`fs-jail`,BRIDGE_JAIL_FALLBACK:`deny`,BRIDGE_JAIL_NETWORK:`relay`,BRIDGE_SUBSCRIPTIONS_ONLY:`1`};e.relayAllow?u.BRIDGE_JAIL_RELAY_ALLOW=e.relayAllow:delete u.BRIDGE_JAIL_RELAY_ALLOW;let d=o(u);t&&d.jailReadablePaths.push(l),i=await s({cwd:c,config:{...d,port:0},handleSignals:!1,quiet:!0,hub:t?{client:t,hash:ic,serverForGrant:e=>{if(!i)throw Error(`Hub host is not ready`);return{transport:`stdio`,command:process.execPath,args:[{kind:`public`,value:l}],env:{TANGLE_HUB_MCP_ENDPOINT:{kind:`public`,value:`${i.url}/hub/mcp/grants/${e}`}}}}}:void 0});let{graphNativeCapture:f}=await import(`./graph-native-af-gs1TS.mjs`);return{harnessTranscript:f({bridgeUrl:i.url,bridgeBearer:r,cwd:c}),backend:`bridge`,bridgeUrl:i.url,bridgeBearer:r,cwd:c}})(),signal:n})}catch(t){throw t instanceof Error&&Object.assign(t,{runId:e.errorRunId??r}),t}finally{await i?.close()}},e.fix??`tangle graph --help`)}function eu(e,t){return[`tangle graph run`,Be(e),...t.dryRun?[`--dry-run`]:[],...t.cloud?[`--cloud`]:[],...t.resume?[`--resume`,Be(t.resume)]:[],...t.seat?[`--seat`,Be(t.seat)]:[],...t.seatAccount?[`--seat-account`,Be(t.seatAccount)]:[],...t.seatCommand?[`--seat-command`,Be(t.seatCommand)]:[],...t.param.flatMap(e=>[`--param`,Be(e)])].join(` `)}async function tu(e,t,n={}){let r=eu(e,t);return await ac(n.signal,async i=>{i.throwIfAborted();let a=await Ge(Ql(e,n.cwd??process.cwd())),o=n.source??await We(a,`utf8`);if(!t.resume&&t.cloud||t.resume?.startsWith(`wfrun_`))return zc(a,o,t,i);let s=await Jc(),c=Xl(o),l=Object.entries(Nc(t.param,`param`)??{}),u=Object.fromEntries(l.filter(([e])=>!e.startsWith(`gate.`))),d=Object.fromEntries(l.filter(([e])=>e.startsWith(`gate.`)).map(([e,t])=>[e.slice(5),t])),f=t.resume?await uc(t.resume):void 0,p=s.graphRegistry(j(M(),`.tangle`,`graph-registry`)),m;if(f){f.file!==a&&X(`The recorded graph source path changed`);let e=await s.loadGraph(p,f.graphDigest);e||X(`The recorded executable graph is unavailable`),m=s.validateStoredGraph(e),fc(f,t,c,u,d)}let h={apiKey:t.apiKey,sandboxBaseUrl:t.baseUrl,signal:i,json:t.json,dryRun:t.dryRun&&!n.connectNeeds},g,_=()=>g??=Tl(h),v=new Map,y=e=>{let t=e.trim().toLowerCase(),n=v.get(t)??(async()=>{let e=await _(),n=e&&await Dl(e,t,h);return n?{connectionId:n,capabilities:[`*`]}:void 0})();return v.set(t,n),n},b=async e=>{if(i.throwIfAborted(),f&&m)return oc(m,f.gateChoices??{}),{graph:m,params:f.params};let r=await s.loadGraphFile(a,{source:o,seat:t.seat??Vn().seat,resolveSeat:mc(e,i),resolveNeed:y,params:u,cwd:e,signal:i});if(i.throwIfAborted(),oc(r.graph,d),n.graphDigest&&r.graph.digest!==n.graphDigest)throw new V(`GRAPH_CHANGED`,`The validated graph changed before execution`,`Its compiled graph digest no longer matches validation`,`tangle graph run --help`);return r},ee=n.cwd??process.cwd(),x=await b(f?.cwd??ee),S=_c(x.graph);if(t.dryRun)return x;let C=vc(x.graph.nodes)?bc(t):void 0,te=f?.runId??n.runId??w(),T=f?.cwd??await s.graphWorkspace(x.graph,{cwd:ee,runId:te});return $l({...n,runId:te,cwd:T,signal:i,fix:r,relayAllow:S},async({runId:e,runDir:n,cwd:r,bridge:o})=>{let{superviseGraphPursuit:l,readSettleRecord:u}=await import(`@tangle-network/agent-runtime/durable`),m=await s.recordStoredGraphRun(p,x.graph),h=f??{version:1,runId:e,cwd:r,file:a,graphDigest:m.digest,sourceDigest:c,params:x.params,...Object.keys(d).length?{gateChoices:d}:{},startedAt:new Date().toISOString(),...t.seat===void 0?{}:{seat:t.seat}};f||await dc(n,h);let g=f?await u(n):void 0;if(g&&g.tree.root!==e&&X(`The settlement names another run`),g?.kind===`no-winner`&&X(`The local run is terminal: ${g.reason}`),g)return{runId:e,graphDigest:m.digest,sourceDigest:c,...Kc(g),replayed:!0};let v=s.graphFromStored(m),y=m.nodes.some(e=>e.profile.connections?.length),b=y?await _():void 0;if(y&&!b)throw new V(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured for this local graph`,`tangle auth login`);let ee=await o(b),S=C?Cc(ee,C,i):void 0,te=h.startedAt;R(`Run ${e} · ${pe(a)} · ${r}`);let w=await nu(n);R(`Viewer ${w.url}`);let T=new AbortController,E=await l(v,{pursuitId:m.digest,runDir:n,runId:e,backend:ee,...v.entry===void 0?{driverBackend:ee}:{},...m.gates?.length?{decideGate:sc(h.gateChoices??{},{json:t.json,signal:AbortSignal.any([i,T.signal])})}:{},resume:!!f,signal:i,...S?{selectSeat:S,coordination:{authentication:!0}}:{},profileSecurity:{allowConnections:y,allowLocalMcp:!1,allowHooks:!1,allowedMcpHosts:[]}}).finally(async()=>{T.abort(),await w.close()}),D={runId:e,graphDigest:m.digest,sourceDigest:c,...Kc(E.result.result)},O=E.result.result,{tokens:ne,tokensKnown:re,iterations:ie,ms:ae}=O.spentTotal;if(await s.recordStoredGraphRun(p,m,{graphDigest:m.digest,evidence:[{kind:`authored-graph`,url:`urn:sha256:${m.digest}`},{kind:`authored-yaml`,url:`urn:sha256:${c}`}],taskDigest:s.taskShapeDigest({graph:pe(a),params:x.params}),startedAt:te,finishedAt:new Date().toISOString(),outcome:O.kind===`no-winner`?{kind:`no-winner`,reason:O.reason}:{kind:`delivered`,summary:D.text},cost:{iterations:ie,ms:ae,...re===!1?{}:{tokens:ne.input+ne.output},...D.costUsd===null?{}:{usd:D.costUsd}},traversals:E.result.ledger.length,exhaustedEdges:E.result.exhaustedEdges,source:{kind:`tangle-cli-graph`,id:e}}),O.kind===`no-winner`)throw Object.assign(new V(`GRAPH_RUN_FAILED`,`Graph '${pe(a)}' finished without a result`,E.result.stopped?.reason||E.result.ledger.filter(e=>e.outcome===`unpropagated`&&e.reason).pop()?.reason||O.reason,`tangle graph inspect ${e}`),{runId:e,runtimeFailures:[...O.tree.nodes.filter(e=>e.failure).map(e=>({node:e.label,failure:e.failure})),...O.reason===`driver-failed`&&O.error.failure?[{node:`root`,failure:O.error.failure}]:[]]});return D})},r)}async function nu(e){let{serveTopWeb:t}=await import(`@tangle-network/agent-runtime/tui`),{readGraphSessions:n}=await import(`./graph-native-af-gs1TS.mjs`);return t({roots:[e],assets:j(Yl,`dist`,`graph-viewer`),readSessions:n})}async function ru(e,t){if(e.startsWith(`wfrun_`)){let n=await Z(t),r=await n.workflows.getRun(e);if(t.json)return I(r);for(let e of r.runtime?.checks??[])R(`${e.node} ${e.status} · exit ${e.exitCode??`none`} · pass ${e.pass??`none`}\n${e.reason??e.tail}`);return R(`Run ${e} · ${n.baseUrl}/app/workflows/${encodeURIComponent(r.workflowId)}/runs/${encodeURIComponent(e)}`)}let n=j(M(),`.tangle`,`runs`,e);if(!/^[a-f0-9-]{36}$/i.test(e)||!ce(n))throw new V(`RUN_NOT_FOUND`,`Run '${e}' was not found`,`Use a run ID printed by tangle graph run`,`tangle graph inspect --help`);let{loadTopSnapshot:r}=await import(`@tangle-network/agent-runtime/tui`);if(t.json)return I(await r(process.cwd(),{runDir:n}));R(`Run ${e} · ${(await nu(n)).url}`)}function iu(){let e=new x(`graph`).description(`Build and run portable agent graphs`);return hl(e),Ac(e),ll(e),wl(e,Ql,Yl),e.command(`inspect <run>`).description(`Inspect a live or retained graph run`).action(ru),e.command(`run <name-or-file>`).description(`Run a saved graph over native subscriptions`).option(`--cloud`,`Run through Tangle's durable cloud workflow owner`).option(`--resume <run>`,`Resume this run's saved graph and durable execution`).option(`--seat <seat>`,`Use harness/model@effort for every node`).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(`--dry-run`,`Validate and print the graph without starting agents`).action(async(e,t)=>{let n=await tu(e,t);t.json||t.dryRun?I(n):`status`in n?(R(`${n.status} · ${n.runId}`),n.text&&console.log(n.text)):`viewerUrl`in n&&R(`Run ${n.runId} · ${n.viewerUrl}`)}),e}function au(){let e=new x(`intelligence`).description(`Create and inspect trace intelligence reports`);return e.command(`connect [agent]`).alias(`connect-agent`).description(`Connect local agent CLIs to Tangle Intelligence`).option(`--endpoint <url>`,`OTLP endpoint base`,ra).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(e,t)=>{let n=e??`local`;ca(n);let r=su(t.apiKey),i=await pa({selection:n,workspace:t.workspace,apiKey:r,endpoint:t.endpoint,serviceName:t.serviceName??ua(t.workspace),environment:t.environment,smoke:t.smoke,dryRun:!!t.dryRun,hookCommand:t.hookCommand}),a={configPath:i.configPath,agents:i.agents,nativeAgents:i.nativeAgents,manual:i.manual,written:i.written,smokeTraceId:i.smokeTraceId};if(t.json){I(a);return}B({Config:i.configPath,Agents:i.agents.join(`, `),"Native Hooks":i.nativeAgents.join(`, `)||void 0,"Manual Setup":i.manual.length?i.manual.map(e=>`${e.label}: ${e.reason}`).join(` `):void 0,Files:i.written.join(`, `),"Smoke Trace":i.smokeTraceId})}),e.command(`doctor`).description(`Check whether your agent traces carry CONTENT or are metadata-only`).option(`--endpoint <url>`,`OTLP endpoint base`,ra).action(async e=>{let t=fa(),n=await va({endpoint:e.endpoint===`https://intelligence.tangle.tools/v1/otlp`?t?.endpoint??`https://intelligence.tangle.tools/v1/otlp`:e.endpoint,apiKey:su(e.apiKey??t?.apiKey)});e.json?I(n):ou(n),n.contentSeen||(process.exitCode=1)}),e.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 e=>{try{let t=cu(e.agent),n=fa(),r={agent:t,event:e.event,endpoint:e.endpoint??n?.endpoint??`https://intelligence.tangle.tools/v1/otlp`,apiKey:su(e.apiKey??n?.apiKey),serviceName:e.serviceName??n?.serviceName??ua(process.cwd()),environment:e.environment??n?.environment??`local`,sessionId:e.sessionId,payload:e.payload===void 0?await uu():lu(e.payload)};if(e.dryRun){let n=ha(r);if(e.json){I(n);return}B({Trace:n.traceId,Agent:t,Event:e.event});return}let i=await ga(r);if(e.json){I({traceId:i});return}B({Trace:i,Agent:t,Event:e.event})}catch(t){if(e.nonBlocking){let n=t instanceof Error?t.message:String(t);e.json?I({ok:!1,error:n}):console.error(`Tangle Intelligence hook skipped: ${n}`);return}U(t)}}),e.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 du({type:`sandbox`,id:e},t)}),e.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 du({type:`fleet`,id:e},t)}),e.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 du({type:pu(e.subjectType),id:e.subjectId},e)}),e.command(`get <job-id>`).description(`Get an intelligence report`).action(async(e,t)=>{let{client:n}=K(t),r=t.json?null:z(`Fetching intelligence report...`);r?.start();let i=await n.intelligence.getReport(e);if(r?.stop(),t.json){I(i);return}fu(i)}),e.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 e=>{let{client:t}=K(e),n=e.json?null:z(`Fetching intelligence reports...`);n?.start();let r=await t.intelligence.listReports({subjectType:e.subjectType===void 0?void 0:pu(e.subjectType),subjectId:e.subjectId,limit:e.limit===void 0?void 0:gu(e.limit)});if(n?.stop(),e.json){I(r);return}F(r.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}])}),e}function ou(e){B({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 t=Object.entries(e.byAgent);t.length>0&&(console.log(),F(t.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 su(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 cu(e){if(la(e))return e;throw Error(`agent must be a known Tangle Intelligence agent surface`)}function lu(e){try{return JSON.parse(e)}catch(e){throw Error(`--payload must be JSON: ${e instanceof Error?e.message:String(e)}`)}}async function uu(){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 du(e,t){let n=mu(t.mode),r=_u(t.metadata),i=t.maxUsd===void 0?void 0:hu(t.maxUsd);if(n===`agentic`&&i===void 0)throw Error(`Agentic intelligence reports require --max-usd`);let{client:a}=K(t),o=t.json?null:z(`Creating intelligence report...`);o?.start();let s=await a.intelligence.createReport({subject:e,mode:n,...i===void 0?{}:{budget:{billTo:`customer`,maxUsd:i}},...r===void 0?{}:{metadata:r}});if(o?.stop(),t.json){I(s);return}fu(s)}function fu(e){B({Job:e.jobId,Subject:`${e.subject.type}:${e.subject.id}`,Mode:e.mode,Status:e.status,"Billed To":e.billing.billedTo,Cost:`$${e.billing.costUsd.toFixed(2)}`,Budget:e.billing.budgetMaxUsd===void 0?void 0:`$${e.billing.budgetMaxUsd.toFixed(2)}`,Updated:e.updatedAt}),e.result!==null&&(console.log(),I(e.result))}function pu(e){if(e===`sandbox`||e===`fleet`)return e;throw Error(`subject type must be sandbox or fleet`)}function mu(e){if(e===`deterministic`||e===`agentic`)return e;throw Error(`mode must be deterministic or agentic`)}function hu(e){let t=Number(e);if(!Number.isFinite(t)||t<0)throw Error(`--max-usd must be a non-negative number`);return t}function gu(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}function _u(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 vu=[`router`,`sandbox`,`blueprint-agent`,`evals`,`agent-builder`];async function yu(e,t){let n=await Ir({...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 bu(e,t,n={}){let r=new Headers(n.headers);n.body&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`);let i=await Lr(e,t,{...n,headers:r});if(n.expected!==void 0&&i.status!==n.expected)throw Error(await xu(i,t));return i}async function xu(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 Su=[`ID`,`Prefix`,`Name`,`Product`,`Created`,`Last used`,`Expires`];function Cu(e){return[e.id,e.keyPrefix??``,e.name,e.product??`all`,e.createdAt,e.lastUsedAt??`—`,e.expiresAt??`—`]}function wu(){let e=new x(`keys`).description(`Manage sk-tan-* API keys on id.tangle.tools`);return e.command(`list`).description(`List your active API keys`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async e=>{let t=await yu(e,!1),n=t.baseUrl,r=await(await bu(t,`${n}/v1/keys`,{expected:200})).json();if(e.json){I(r);return}Ht(Su,r.data.map(Cu))}),e.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 (${vu.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(e,t)=>{if(t.product!==void 0&&!vu.includes(t.product))throw Error(`Invalid --product. Expected one of ${vu.join(`, `)}`);let n=await yu(t,!0),r=n.baseUrl,i=t.expiresInDays===void 0?void 0:new Date(Date.now()+Number.parseInt(t.expiresInDays,10)*24*60*60*1e3).toISOString(),a=z(`Creating API key...`);a.start();let o=await bu(n,`${r}/v1/keys`,{method:`POST`,expected:201,body:JSON.stringify({name:e,product:t.product,budgetUsd:t.budgetUsd?Number.parseFloat(t.budgetUsd):void 0,rpmLimit:t.rpmLimit?Number.parseInt(t.rpmLimit,10):void 0,expiresAt:i})});a.stop();let s=await o.json();if(t.json){I(s);return}L(`API key created: ${s.data.prefix}…`),R(`Copy this key now — it will never be shown again:\n${s.data.key}`)}),e.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(e,t)=>{let n=await yu(t,!0),r=n.baseUrl;if(!t.yes&&!await Qr(`Revoke key ${e}? Any service still using it will start to fail.`,`--yes`)){R(`Aborted.`);return}let i=await(await bu(n,`${r}/v1/keys/${encodeURIComponent(e)}`,{method:`DELETE`,expected:200})).json();if(t.json){I(i);return}L(`Revoked ${e}`)}),e}function Tu(e){if(Gn().token)throw Error(`A line relay cannot manage numbers or attachments. Use your owner CLI outside the agent box.`);return G(W(e))}function Eu(e){if(!e.yes)throw Error(`Review the selected line and use --yes to authorize this change. Attaching enables metered agent work.`)}function Du(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 Ou(e){return e().catch(U)}async function ku(e){let t=await Ue(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 Au(e){e.command(`providers`).description(`List provider transports supported by this Hub deployment`).action(e=>Ou(async()=>{I(await Tu(e).lines.providers())})),e.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(e=>Ou(async()=>{I(await Tu(e).lines.list({profileId:e.profileId,sandboxId:e.sandbox}))})),e.command(`get`).argument(`<line-id>`).description(`Inspect a line and its current attachment`).action((e,t)=>Ou(async()=>{I(await Tu(t).lines.get(e))})),e.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((e,t)=>Ou(async()=>{let n=Du(t.transport);if(n===`email`)throw Error(`Email uses an owned mailbox, not phone inventory`);if(n===`voice`)throw Error(`Voice numbers are listed by ph0ny; provide the owned number ID to lines connect`);if(n===`telegram`)throw Error(`Telegram uses an owned bot, not phone inventory`);I(await Tu(t).lines.numbers(e,n))})),e.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((e,t)=>Ou(async()=>{Eu(t);let n=Du(t.transport);if(n!==`email`&&t.address)throw Error(`--address is email-only`);if((n===`email`||n===`telegram`)&&t.numberId)throw Error(`${n} does not take --number-id`);let r={connectionId:e,label:t.label,clientReference:t.reference},i;if(n===`email`)i={...r,transport:n,address:t.address};else if(n===`telegram`)i={...r,transport:n};else if(n===`imessage`)i={...r,transport:n,phoneNumberId:t.numberId};else{if(!t.numberId)throw Error(`${n} requires --number-id`);i={...r,transport:n,phoneNumberId:t.numberId}}I(await Tu(t).lines.fromConnection(i))})),e.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((e,t)=>Ou(async()=>{Eu(t);let n=Tu(t),r;if(t.file){if(t.profileId||t.member||t.sandbox||t.instancePrefix||t.tools||t.turnsPerDay)throw Error(`Choose --file or quick-setup flags, not both`);r=await ku(t.file)}else{if(!t.profileId||!t.member)throw Error(`Provide --profile-id and --member, or --file`);if(t.sandbox&&t.instancePrefix)throw Error(`Choose --sandbox or --instance-prefix`);let e=t.tools??`chat`,n=Number(t.turnsPerDay??`30`);if(e!==`chat`&&e!==`act`)throw Error(`--tools must be chat or act`);if(!Number.isSafeInteger(n)||n<1||n>1e4)throw Error(`--turns-per-day must be 1–10000`);if(e===`act`&&t.sandbox)throw Error(`Acting tools require an isolated on-demand instance; omit --sandbox`);r={mode:`personal`,members:[{address:t.member,role:`owner`}],unknownSenders:`reject`,roles:{owner:{context:`own`,tools:e}},respond:{kind:`agent`,profileId:t.profileId,...e===`act`?{rolePolicy:{version:1,roles:{owner:{kind:`general`}},members:{}}}:{}},limits:{turnsPerMemberPerDay:n},...t.sandbox?{sandboxId:t.sandbox}:{instance:{keyPrefix:t.instancePrefix??`profile:${t.profileId}:`,create:{ownerContext:`isolated`,...e===`act`?{egressPolicy:{mode:`strict`,allowDomains:[new URL(lr()).hostname],includeImplicitDomains:!1}}:{}}}}}}if(typeof r.sandboxId==`string`==(r.instance!==void 0))throw Error(`Attachment requires exactly one of sandboxId and instance`);let{sandboxId:i,instance:a,...o}=r,s;if(i){let t=await n.get(i);if(!t)throw Error(`Sandbox not found`);s=await t.lines.attach({...o,number:e})}else{if(!a)throw Error(`Attachment requires an instance`);s=await n.lines.attach({...o,number:e,instance:a})}I(s)}));for(let t of[`detach`,`release`])e.command(t).argument(`<line-id>`).description(t===`detach`?`Stop dispatch; preserve history and provider rental`:`Retire a detached Hub line; does not cancel provider rental`).option(`--yes`,`Authorize this change`).action((e,n)=>Ou(async()=>{Eu(n),I({[t]:await Tu(n).lines[t](e)})}));e.command(`threads`).argument(`<line-id>`).description(`List this line's separate participant threads`).action((e,t)=>Ou(async()=>{I(await Tu(t).lines.threads(e).list())})),e.command(`messages`).argument(`<line-id>`).argument(`<thread-id>`).description(`Read one authorized participant thread`).action((e,t,n)=>Ou(async()=>{I(await Tu(n).lines.threads(e).messages(t))}))}async function ju(e){let{token:t,baseUrl:n}=Gn();if(t===void 0)return q(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 Ee({baseUrl:n,authHeaders:()=>({Authorization:`Bearer ${t}`})})}async function Mu(e,t){if(t)return t;if(!Gn().token)throw Error(`Provide --line <line-id>`);return(await e.lines.context()).line.id}function Nu(e){return e().catch(U)}function Pu(){return new x(`context`).description(`Show live line identity, members, consent, reminders and quotas`).action(e=>Nu(async()=>{I(await(await ju(e)).lines.context())}))}function Fu(){let e=new x(`lines`).description(`Connect, manage, message and schedule on a Hub line`);return e.command(`members`).description(`List names, roles and consent on this line`).option(`--line <line-id>`,`Line ID; inferred in a line box`).action(e=>Nu(async()=>{let t=await ju(e);I(await t.lines.members.list(await Mu(t,e.line)))})),e.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((e,t,n)=>Nu(async()=>{let r=await ju(n),i=await Mu(r,n.line);if(!Gn().token){if(n.onBehalfOf)throw Error(`--on-behalf-of is only available inside a line box`);if(!n.idempotencyKey)throw Error(`Owner sends require --idempotency-key so a retry keeps the same message`);if(!(await r.lines.members.list(i)).some(t=>t.id===e))throw Error(`Owner sends require an exact member ID from tangle lines members`);I(await r.lines.send(i,{memberId:e,text:t,idempotencyKey:n.idempotencyKey,...n.notBefore?{notBefore:n.notBefore}:{}}));return}I(await r.lines.send(i,{toMember:e,text:t,...n.onBehalfOf?{onBehalfOf:n.onBehalfOf}:{},...n.notBefore?{notBefore:n.notBefore}:{},...n.idempotencyKey?{idempotencyKey:n.idempotencyKey}:{}}))})),e.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((e,t)=>Nu(async()=>{if(!t.at)throw Error(`--at is required`);let n=await ju(t),r=t.idempotencyKey??C(`sha256`).update(JSON.stringify([e,t.at])).digest(`hex`).slice(0,32);I(await n.lines.remind(await Mu(n,t.line),{text:e,notBefore:t.at,idempotencyKey:r}))})),Au(e),e}function Iu(){let e=new x(`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=W({apiKey:t.apiKey,baseUrl:t.baseUrl}),r=await J(G(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 it(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 Lu(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=In(),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??tr():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=W({apiKey:a,baseUrl:r}),s=G(o);return t.self?st(s):J(s,o,e)}async function Ru(e,t,n){let r=z(e);t||r.start();try{return await n()}finally{r.stop()}}function zu(e){return e}function Bu(){let e=new x(`preview`).description(`Manage sandbox preview links`);return zu(e.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(e,t)=>{let n=await Lu(e,t),r=await Ru(`Starting managed preview...`,t.json,()=>at(n,{cwd:t.cwd,sessionId:t.session,name:t.name}));t.json?I(r):(L(`Preview ready: ${r.url}`),console.log(`Preview ID: ${r.previewId}`))}),zu(e.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(e,t)=>{let n=await Lu(e,t),r=await Ru(`Fetching preview links...`,t.json,()=>n.previewLinks.list());t.json?I(r):r.length===0?console.log(`No preview links found`):Ht([`App`,`Preview ID`,`Port`,`URL`,`Status`],r.map(e=>[Vu(e.metadata),e.previewId.slice(0,12),String(e.port),e.url,e.status]))}),zu(e.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(e,t)=>{if(!t.port||!/^\d+$/.test(t.port))throw Error(`An integer service port is required`);let n=await Lu(e,t),r=await Ru(`Publishing service...`,t.json,()=>ot(n,{port:Number(t.port),name:t.name}));t.json?I(r):L(`Preview ready: ${r.url}`)}),zu(e.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(e,t,n)=>{if(!/^\d+$/.test(t)||Number(t)<1||Number(t)>65535)throw Error(`Port must be an integer between 1 and 65535`);let r=await Lu(e,n),i=await Ru(`Creating preview for port ${t}...`,n.json,()=>r.previewLinks.create(Number(t)));n.json?I(i):(L(`Preview created: ${i.url}`),console.log(`Preview ID: ${i.previewId}`))}),zu(e.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(e,t,n)=>{let r=await Lu(e,n);await Ru(`Removing preview...`,n.json,()=>r.previewLinks.remove(t)),n.json?I({success:!0,previewId:t}):L(`Preview removed: ${t}`)}),e}function Vu(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 Hu(){let e=new x(`process`).description(`Manage processes in a sandbox`);return e.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(e,t,n)=>{let{context:r,client:i}=K(n),a=ts(n.env??[],`--env`,`env`),o=z(`Spawning: ${t}`);n.json||o.start();let s=await J(i,r,e);if(s=await Y(s),n.blocking){let e=await s.exec(t,{cwd:n.cwd,env:Object.keys(a).length>0?a:void 0,timeoutMs:n.timeout?Number.parseInt(n.timeout,10):void 0});o.stop(),n.json?I(e):(e.stdout&&globalThis.process.stdout.write(e.stdout),e.stderr&&globalThis.process.stderr.write(e.stderr),e.exitCode!==0&&globalThis.process.exit(e.exitCode))}else{let r=await s.process.spawn(t,{cwd:n.cwd,env:Object.keys(a).length>0?a:void 0,timeoutMs:n.timeout?Number.parseInt(n.timeout,10):void 0});o.stop(),n.json?I({pid:r.pid,command:r.command}):(console.log(`Process started with PID: ${r.pid}`),console.log(`Use 'tangle process logs ${e} ${r.pid}' to view output`))}}),e.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(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching processes...`);t.json||i.start();let a=await J(r,n,e);a=await Y(a);let o=await a.process.list();t.running&&(o=o.filter(e=>e.running)),i.stop(),t.json?I(o):o.length===0?console.log(`No processes found`):Ht([`PID`,`Command`,`Status`,`Exit Code`,`Started`],o.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()]))}),e.command(`get`).description(`Get detailed info about a process`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).action(async(e,t,n)=>{let{context:r,client:i}=K(n),a=z(`Fetching process info...`);n.json||a.start();let o=await J(i,r,e);o=await Y(o);let s=await o.process.get(Number.parseInt(t,10));if(a.stop(),!s){console.error(`Process ${t} not found`),globalThis.process.exit(1);return}let c=await s.status();n.json?I(c):(console.log(`PID: ${c.pid}`),console.log(`Command: ${c.command}`),console.log(`CWD: ${c.cwd||`(default)`}`),console.log(`Status: ${c.running?`running`:`exited`}`),console.log(`Exit Code: ${c.exitCode}`),c.exitSignal&&console.log(`Signal: ${c.exitSignal}`),console.log(`Started: ${c.startedAt.toLocaleString()}`),c.exitedAt&&console.log(`Exited: ${c.exitedAt.toLocaleString()}`))}),e.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(e,t,n)=>{let{context:r,client:i}=K(n),a=z(`Sending ${n.signal} to PID ${t}...`);n.json||a.start();let o=await J(i,r,e);o=await Y(o);let s=await o.process.get(Number.parseInt(t,10));if(!s){a.stop(),console.error(`Process ${t} not found`),globalThis.process.exit(1);return}n.tree?await s.kill(n.signal,{tree:!0}):await s.kill(n.signal),a.stop(),n.json?I({pid:Number.parseInt(t,10),signal:n.signal,...n.tree===!0?{tree:!0}:{},killed:!0}):console.log(n.tree?`Sent ${n.signal} to process tree ${t}`:`Sent ${n.signal} to process ${t}`)}),e.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}=K(n),a=await J(i,r,e);a=await Y(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))}),e}const Uu=[`python`,`node`,`typescript`,`bash`];function Wu(e){switch(he(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 Gu(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 We(ve(e),`utf8`)}async function Ku(e,t,n=Gu){let r=t?Uu.find(e=>e===t)??(()=>{throw Error(`unknown --lang ${t}: must be one of ${Uu.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=Wu(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 qu(e){return j(xe(),`tangle-run-images`,e)}function Ju(){return new x(`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: ${Uu.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(e,t,n)=>{let{language:r,source:i}=await Ku(t,n.lang),{context:a,client:o}=K(n),s=await J(o,a,e);s=await Y(s);let c=z(`Running ${r} (${i.length}b)…`);n.json||c.start();let l=await s.runCode(r,i,{sessionId:n.session,timeoutMs:Number.parseInt(n.timeout,10)});if(c.stop(),n.json){I(l),l.exitCode!==0&&process.exit(l.exitCode);return}l.stdout&&process.stdout.write(l.stdout),l.stderr&&process.stderr.write(l.stderr);let u=0;for(let t of l.results)if(t.type===`image`)if(n.saveImages!==!1){let r=typeof n.saveImages==`string`?n.saveImages:qu(e);le(r,{recursive:!0});let i=`${r}/${Date.now()}-${u}.${t.format}`;fe(i,Buffer.from(t.data,`base64`)),process.stderr.write(b.green(`✓ image → ${i}\n`)),u++}else process.stderr.write(b.gray(`[image: ${t.format}, ${t.data.length}b base64]\n`));else if(t.type===`dataframe`){let e=t.columns.map(e=>`${e.name}:${e.dtype}`).join(` | `);process.stderr.write(b.gray(`[dataframe ${t.rows.length}×${t.columns.length}${t.truncated?` (truncated)`:``}]\n`)),process.stderr.write(`${e}\n`);for(let e of t.rows.slice(0,20))process.stderr.write(`${e.map(e=>String(e)).join(` | `)}\n`);t.rows.length>20&&process.stderr.write(b.gray(`… ${t.rows.length-20} more rows\n`))}else t.type===`json`?(process.stderr.write(b.gray(`[json] `)),process.stderr.write(`${JSON.stringify(t.value,null,2)}\n`)):t.type===`html`?process.stderr.write(b.gray(`[html ${t.value.length}b]\n`)):t.type===`error`?(process.stderr.write(b.red(`✗ ${t.name}: ${t.message}\n`)),t.traceback&&process.stderr.write(`${t.traceback}\n`)):t.type===`text`&&process.stderr.write(`${t.value}\n`);l.error&&(process.stderr.write(b.red(`\n✗ ${l.error.name}: ${l.error.message}\n`)),l.error.traceback&&process.stderr.write(`${l.error.traceback}\n`)),l.exitCode!==0&&process.exit(l.exitCode)})}function Yu(e){e.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(e,t)=>{let{context:n,client:r}=K(t),i=z(`Updating network configuration...`);i.start();let a=await J(r,n,e);i.stop();let o=await a.network.getConfig();t.json?I(o):(R(`Network Configuration:`),o.ports&&o.ports.length>0?R(` Exposed Ports: ${o.ports.join(`, `)}`):R(` No exposed ports`))}),e.command(`expose <id-or-name>`).description(`Expose a port and get a public URL`).option(`-p, --port <port>`,`Port to expose`,`8000`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=Number.parseInt(t.port,10);if(Number.isNaN(i)||i<1||i>65535)throw Error(`Port must be a number between 1 and 65535`);let a=z(`Exposing port ${i}...`);a.start();let o=await(await J(r,n,e)).network.exposePort(i);a.stop(),t.json?I({port:i,url:o}):(L(`Port ${i} exposed.`),R(` URL: ${o}`))}),e.command(`urls <id-or-name>`).description(`List exposed port URLs for a sandbox`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching exposed URLs...`);i.start();let a=await(await J(r,n,e)).network.listUrls();if(i.stop(),t.json)I(a);else{let e=Object.entries(a);if(e.length===0)R(`No ports exposed.`);else{R(`Exposed Ports:`);for(let[t,n]of e)R(` ${t}: ${n}`)}}})}function Xu(){let e=new x(`sandbox`).description(`Manage sandboxes`);return Fs(e),Ps(e),ws(e),Yu(e),e}function Zu(){return new x(`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}=K(n),a=z(`Searching...`);n.json||a.start();let o=await J(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 Qu(){let e=new x(`secret`).description(`Manage secrets`);return e.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(e,t,n)=>{let r=await K(n).client.secrets.create(e,await $u({value:t,valueStdin:n.valueStdin,prompt:`Enter value for secret '${e}': `}));n.json?I(r):(L(`Secret created: ${r.name}`),R(`Use --secret ${r.name} when creating a sandbox to select it for delivery.`))}),e.command(`list`).description(`List all secrets`).action(async e=>{let t=await K(e).client.secrets.list();e.json?I(t):t.length===0?(R(`No secrets found.`),R(`Use 'tangle secret create <name> [value]' to create one.`)):Ht([`Name`,`Created At`,`Updated At`],t.map(e=>[e.name,e.createdAt.toLocaleString(),e.updatedAt.toLocaleString()]))}),e.command(`delete`).description(`Delete a secret`).argument(`<name>`,`Secret name`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=K(t).client;if(!t.force&&!await Qr(`Are you sure you want to delete secret '${e}'? This cannot be undone. (y/N) `,`--force`)){R(`Cancelled.`);return}await n.secrets.delete(e),t.json?I({success:!0,deleted:e}):L(`Secret deleted: ${e}`)}),e}async function $u(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 ei():await Zr(e.prompt));if(!t.length)throw Error(e.valueStdin?`Secret value from stdin cannot be empty`:`Secret value cannot be empty`);return t}function ed(){let e=new x(`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=A.dirname(tt(import.meta.url)),t=A.resolve(e,`..`,`SKILL.md`);console.log(t)}),e}function td(){let e=new x(`snapshot`).description(`Manage snapshots`);return e.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(e,t)=>{let{context:n,client:r}=K(t),i=z(`Creating snapshot...`);i.start();let a=await J(r,n,e);if(t.wait===!1){let e=await a.snapshot({tags:t.tags,wait:!1});i.stop(),Ts(e.info,!!t.json);return}let o=await a.snapshot({tags:t.tags});i.stop(),t.json?I(o):(L(`Snapshot created: ${o.snapshotId}`),console.log(`Size: ${nd(o.sizeBytes??0)}`))}),e.command(`list <sandbox-id-or-name>`).description(`List snapshots for a sandbox`).action(async(e,t)=>{let{context:n,client:r}=K(t),i=z(`Fetching snapshots...`);i.start();let a=await(await J(r,n,e)).listSnapshots();i.stop(),t.json?I(a):F(a.map(e=>({...e,size:nd(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}])}),e.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(e,t,n)=>{let{client:r}=K(n),i=z(`Restoring from snapshot...`);i.start();let a=await r.create({fromSnapshot:t,fromSandboxId:e,...n.billingOwner?{billingOwnerId:n.billingOwner}:{}});await a.waitFor(`running`,{timeoutMs:12e4}),i.stop(),n.json?I({sandboxId:a.id,restoredFrom:t,status:a.status}):(L(`New sandbox created: ${a.id}`),console.log(`Source snapshot: ${t}`))}),e.command(`revert <sandbox-id-or-name> <snapshot-id>`).description(`Revert an existing sandbox to a snapshot`).action(async(e,t,n)=>{let{context:r,client:i}=K(n),a=z(`Reverting sandbox to snapshot...`);a.start();let o=await J(i,r,e),s=await o.revertToSnapshot(t);await o.refresh(),a.stop(),n.json?I({sandboxId:o.id,snapshotId:s.snapshotId,status:o.status}):(L(`Sandbox reverted: ${o.id}`),console.log(`Source snapshot: ${s.snapshotId}`))}),e.command(`delete <sandbox-id-or-name> <snapshot-id>`).description(`Delete a sandbox snapshot`).action(async(e,t,n)=>{let{context:r,client:i}=K(n),a=z(`Deleting snapshot...`);a.start();let o=await(await J(i,r,e)).deleteSnapshot(t);a.stop(),n.json?I({success:!0,sandboxId:e,snapshotId:t,outcome:o.outcome}):o.outcome===`already_absent`?L(`Snapshot already gone: ${t}`):L(`Snapshot deleted: ${t}`)}),e}function nd(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 rd=`solve:device:secp256k1`,id=/^0x[0-9a-f]{64}$/i;function ad(e){return e&&id.test(e)?e:void 0}function od(){let e=mn(rd),t=ad(e.value);if(!(!t||e.source===`none`))return{account:lt(t),source:e.source}}function sd(){let e=od();if(e)return e;let t=ct(),n=hn(rd,t);return{account:lt(t),source:n}}function cd(e){let t=ad(mn(rd).value);if(!t||lt(t).address!==e.account.address)throw Error(`The local Solve device key changed; it was not retired`);let n=`${rd}:retired:${e.account.address.toLowerCase()}`;if(hn(n,t),mn(n).value!==t)throw Error(`The revoked device key could not be retired safely`);return _n(rd),n}function ld(e){let t=e.create?sd():od();if(!t)throw Error("No Solve device signer found. Run `tangle solve account --create`");e.json?I({address:t.account.address,source:t.source}):B({Address:t.account.address,Source:t.source})}const ud=/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i;function dd(e){return[...e].some(e=>{let t=e.charCodeAt(0);return t<32||t===127})}function fd(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function pd(e,t,n=2048){if(typeof e!=`string`||!e.trim()||e.length>n)throw Error(`${t} is missing or invalid`);if(dd(e))throw Error(`${t} contains control characters`);return e.trim()}function md(e,t){let n=pd(e,t,64).toLowerCase();if(!ud.test(n))throw Error(`${t} must be a 40 or 64 character Git revision`);return n}function hd(e,t,n=!1){let r=typeof e==`number`&&Number.isSafeInteger(e)?String(e):pd(e,t,80);if(!/^\d+$/.test(r)||!n&&r===`0`)throw Error(`${t} must be an unsigned integer`);return BigInt(r).toString()}function gd(e,t){let n=pd(e,t,2048),r=new URL(n);if(r.protocol!==`https:`&&!(r.protocol===`http:`&&(r.hostname===`localhost`||r.hostname===`127.0.0.1`)))throw Error(`${t} must use HTTPS outside local development`);return n.replace(/\/$/,``)}function _d(e,t){let n=gd(e,t).replace(/\.git$/,``),r=new URL(n),i=r.pathname.split(`/`).filter(Boolean);if(r.hostname!==`github.com`||r.username||r.password||r.search||r.hash||i.length!==2)throw Error(`${t} must be an HTTPS GitHub repository URL`);return`https://github.com/${i.join(`/`)}`}function vd(e,t){let n=pd(e,t,42);if(!_t(n,{strict:!1}))throw Error(`${t} must be an EVM address`);return ht(n)}function yd(e,t){let n=hd(e,t),r=Number(n);if(!Number.isSafeInteger(r)||r<=0)throw Error(`${t} is out of range`);return r}function bd(...e){for(let t of e)if(typeof t==`string`&&t.trim())return t.trim()}function xd(e){let t=e.trim().replace(/\.git$/,``);return t.startsWith(`git@github.com:`)?`https://github.com/${t.slice(15)}`:t.startsWith(`ssh://git@github.com/`)?`https://github.com/${t.slice(21)}`:t}function Sd(e){if(e===void 0)return;let t=pd(e,`pull request URL`,2048);if(!/^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+(?:\/[^\s]*)?$/i.test(t))throw Error(`pull request URL must point to a GitHub pull request`);return t}function Cd(e,t){if(!/^https:\/\/[^\s]+$/i.test(e)&&!/^\/(?!\/).*$/.test(e)&&!/^[a-z][a-z0-9+.-]*:[^\s]+$/i.test(e))throw Error(`${t} must be an HTTPS URL or an absolute repository path`);if(e.split(/[?#]/,1)[0].split(`/`).includes(`..`))throw Error(`${t} cannot contain parent-directory segments`);return e}function wd(e){return Ln(`solve`,e.profile)}function Td(e){let t=wd(e),n=rr(void 0,t);if(!n)throw Error(`No Solve credential found for profile '${t}'. Run: tangle auth login --provider github --app solve`);return n}async function Ed(e){let t=ur(e.apiUrl),n=await fetch(`${t}${e.path}`,{method:e.method??`GET`,headers:{Accept:`application/json`,...e.body===void 0?{}:{"Content-Type":`application/json`},Authorization:`Bearer ${Td(e)}`},...e.body===void 0?{}:{body:JSON.stringify(e.body)},signal:AbortSignal.timeout(3e4)}),r=await n.json().catch(()=>null);if(!n.ok||!r?.success||r.data===void 0){let e=r?.error?.message??`Solve API request failed with HTTP ${n.status}`;throw Error(r?.error?.code?`${r.error.code}: ${e}`:e)}return r.data}function Dd(e){return Ed({path:`/v1/wallet/challenges`,method:`POST`,apiUrl:e.apiUrl,profile:e.profile,body:{deviceAddress:e.deviceAddress,...e.purpose?{purpose:e.purpose}:{}}})}function Od(e){return Ed({path:`/v1/devices`,apiUrl:e.apiUrl,profile:e.profile})}function kd(e){return Ed({path:`/v1/devices/revoke`,method:`POST`,apiUrl:e.apiUrl,profile:e.profile,body:{deviceAddress:e.deviceAddress,...e.reason?{reason:e.reason}:{},...e.challengeId&&e.signature?{challengeId:e.challengeId,signature:e.signature}:{}}})}const Ad={chainId:42431,rpcUrl:`https://rpc.moderato.tempo.xyz`,sponsorUrl:`https://drew-gtr-pro.taild10bfc.ts.net/solve-sponsor`,tangleAddress:`0xff137B9C879c47C28ce389e84501925438AB4cdA`,managerAddress:`0x5271732F893B622ac6793d6DBA5B2626CCa4EA14`,paymentAsset:`0x20C0000000000000000000000000000000000000`,blueprintId:15n,serviceId:9n,competitionId:1n,minStakeWei:0n};function jd(e,t){return e.toLowerCase()===t.toLowerCase()}function Md(e){if(e.chainId!==Ad.chainId)throw Error(`Solve submissions require Tempo Moderato (chain ${Ad.chainId}); received ${e.chainId}`);if(e.rpcUrl!==Ad.rpcUrl)throw Error(`Solve metadata RPC does not match the trusted deployment`);if(e.sponsorUrl!==Ad.sponsorUrl)throw Error(`Solve metadata sponsor does not match the trusted deployment`);if(!jd(e.tangleAddress,Ad.tangleAddress))throw Error(`Solve metadata Tangle contract does not match the trusted deployment`);if(!jd(e.managerAddress,Ad.managerAddress))throw Error(`Solve metadata competition manager does not match the trusted deployment`);if(!jd(e.paymentAsset,Ad.paymentAsset))throw Error(`Solve metadata payment asset does not match the trusted deployment`);if(e.blueprintId!==Ad.blueprintId)throw Error(`Solve submissions require blueprint ${Ad.blueprintId}; received ${e.blueprintId}`);if(e.serviceId!==Ad.serviceId)throw Error(`Solve submissions require service ${Ad.serviceId}; received ${e.serviceId}`);if(e.competitionId!==Ad.competitionId)throw Error(`Solve submissions require competition ${Ad.competitionId}; received ${e.competitionId}`);if(e.minStakeWei!==Ad.minStakeWei)throw Error(`Solve submissions require zero stake for the trusted deployment`)}function Nd(e,t){let n=fd(t.check??e.check,`competition.participation.check`),r=pd(n.command,`competition.participation.check.command`,512);if(!Array.isArray(n.args)||n.args.some(e=>typeof e!=`string`))throw Error(`competition.participation.check.args must be an array of strings`);let i=n.args.map(e=>pd(e,`competition checker argument`,2048)),a=bd(n.result_file,n.resultFile),o=n.timeout_ms??n.timeoutMs,s=o===void 0?void 0:yd(o,`competition checker timeout`);return{command:r,args:i,...a?{result_file:a}:{},...s?{timeout_ms:s}:{}}}function Pd(e){if(e.provenance===void 0)return;let t=fd(e.provenance,`competition.participation.provenance`);if(t.mode!==`github_pull_request`)throw Error(`competition.participation.provenance.mode is unsupported`);if(t.required!==void 0&&typeof t.required!=`boolean`)throw Error(`competition.participation.provenance.required must be a boolean`);return{mode:`github_pull_request`,required:t.required===!0}}function Fd(e){let t=fd(e.chain??e.network??{},`competition.chain`),n=e.rewards&&typeof e.rewards==`object`&&!Array.isArray(e.rewards)?fd(e.rewards,`competition.rewards`):{},r=n.minStake&&typeof n.minStake==`object`&&!Array.isArray(n.minStake)?fd(n.minStake,`competition.rewards.minStake`).raw:void 0,i=bd(t.minStakeWei,t.min_stake_wei,e.minStakeWei,e.min_stake_wei,r),a=t.chainId??t.chain_id??e.chainId??e.chain_id,o=bd(t.chainName,t.chain_name,e.chainName,e.chain_name)??`Tempo`,s=bd(t.nativeSymbol,t.native_symbol,e.nativeSymbol,e.native_symbol)??`TNT`,c=bd(t.rpcUrl,t.rpc_url,e.rpcUrl,e.rpc_url,process.env.TANGLE_SOLVE_RPC_URL),l=bd(t.sponsorUrl,t.sponsor_url,e.sponsorUrl,e.sponsor_url,process.env.TANGLE_SOLVE_SPONSOR_URL),u=bd(t.tangleAddress,t.tangle_address,t.coreAddress,t.core_address,e.tangleAddress,e.tangle_address,e.coreAddress,e.core_address),d=bd(t.managerAddress,t.manager_address,e.managerAddress,e.manager_address),f=bd(t.paymentAsset,t.payment_asset,t.servicePaymentAsset,t.service_payment_asset,e.paymentAsset,e.payment_asset,e.servicePaymentAsset,e.service_payment_asset),p=bd(t.blueprintId,t.blueprint_id,e.blueprintId,e.blueprint_id),m=bd(t.serviceId,t.service_id,e.serviceId,e.service_id),h=bd(t.competitionId,t.competition_id,e.competitionId,e.competition_id,e.id);if(!c||!l||!u||!d||!p||!m||!h||!i||a===void 0)throw Error(`Solve competition metadata must include complete Tempo chain configuration`);return{chainId:yd(a,`chain.chainId`),chainName:o,nativeSymbol:s,rpcUrl:gd(c,`chain.rpcUrl`),sponsorUrl:gd(l,`chain.sponsorUrl`),tangleAddress:vd(u,`chain.tangleAddress`),managerAddress:vd(d,`chain.managerAddress`),paymentAsset:vd(f??Ad.paymentAsset,`chain.paymentAsset`),blueprintId:hd(p,`chain.blueprintId`),serviceId:hd(m,`chain.serviceId`),competitionId:hd(h,`chain.competitionId`,!0),minStakeWei:hd(i,`chain.minStakeWei`,!0)}}function Id(e){let t=fd(e,`competition`),n=fd(t.participation??t.task,`competition.task`),r={...t,participation:{...n,...n.repositoryRevision===void 0&&n.revision!==void 0?{repositoryRevision:n.revision}:{}}},i=r.participation,a=_d(bd(r.repository,r.repo_url,i.repository)??``,`competition.repository`),o=md(bd(r.repositoryRevision,r.repository_revision,i.revision,i.repositoryRevision,i.repository_revision),`competition.repositoryRevision`),s=pd(r.slug??r.id,`competition.slug`,128),c=pd(r.name??r.title??s,`competition.name`,256),l=Nd(r,i),u=Pd(i);return{version:1,slug:s,title:c,repository:a,taskRevision:o,checker:l,chain:Fd(r),...u?{provenance:u}:{}}}function Ld(e){return{chainId:e.chain.chainId,chainName:e.chain.chainName,nativeSymbol:e.chain.nativeSymbol,rpcUrl:e.chain.rpcUrl,sponsorUrl:e.chain.sponsorUrl,tangleAddress:e.chain.tangleAddress,managerAddress:e.chain.managerAddress,paymentAsset:e.chain.paymentAsset,blueprintId:BigInt(e.chain.blueprintId),serviceId:BigInt(e.chain.serviceId),competitionId:BigInt(e.chain.competitionId),minStakeWei:BigInt(e.chain.minStakeWei)}}async function Rd(e){let t=fd(JSON.parse(await P.readFile(A.join(e,`.tangle-solve.json`),`utf8`)),`.tangle-solve.json`);if(t.version!==1)throw Error(`.tangle-solve.json has an unsupported version`);let n=fd(t.checker,`.tangle-solve.json.checker`),r=fd(t.chain,`.tangle-solve.json.chain`);return Id({slug:t.slug,name:t.title,repository:t.repository,repositoryRevision:t.taskRevision,participation:{check:n,provenance:t.provenance},chain:r,competitionId:r.competitionId})}const zd=Xe(Se),Bd=`.tangle-solve-run.json`,Vd=`.tangle-solve.json`,Hd=`tangle.solve.manifestSha256`,Ud=new Set([Vd,Bd]),Wd=`upstream`;async function Gd(e,t){let n=await zd(`git`,[`-C`,e,...t],{encoding:`utf8`,maxBuffer:1e6});return String(n.stdout).trim()}async function Kd(e,t){let n=A.resolve(t??process.cwd()),r=await Rd(n);if(e&&e!==r.slug&&e!==r.chain.competitionId)throw Error(`This directory contains '${r.slug}', not '${e}'`);return{root:n,manifest:r}}async function qd(e){let t=A.join(e,Vd),n;try{n=await P.lstat(t)}catch{throw Error(`${Vd} is missing`)}if(n.isSymbolicLink()||!n.isFile())throw Error(`${Vd} must be a regular file`);return C(`sha256`).update(await P.readFile(t)).digest(`hex`)}async function Jd(e){let t=await qd(e);return await Gd(e,[`config`,`--local`,`--replace-all`,Hd,t]),t}async function Yd(e){let t;try{t=await Gd(e,[`config`,`--local`,`--get`,Hd])}catch{throw Error(`The local Git metadata has no ${Hd} pin; run tangle solve clone again`)}if(!/^[0-9a-f]{64}$/i.test(t))throw Error(`The local ${Hd} pin is invalid`);if(await qd(e)!==t.toLowerCase())throw Error(`${Vd} changed after clone; run tangle solve clone again`)}async function Xd(e,t){try{return await Gd(e,[`ls-files`,`--error-unmatch`,`--`,t]),!0}catch{return!1}}async function Zd(e){await Yd(e);for(let t of Ud)if(await Xd(e,t))throw Error(`${t} must remain untracked and local to this Solve workspace`);let t=await zd(`git`,[`-C`,e,`status`,`--porcelain=v1`,`--untracked-files=all`,`--ignored=matching`],{encoding:`utf8`,maxBuffer:1e6});if(String(t.stdout).split(/\r?\n/).filter(Boolean).filter(e=>{let t=e.slice(0,2),n=e.slice(3);return!((t===`??`||t===`!!`)&&Ud.has(n))}).length>0)throw Error(`Commit the candidate before running Solve. Only the local manifest and run record may remain uncommitted.`);return md(await Gd(e,[`rev-parse`,`HEAD`]),`submission revision`)}async function Qd(e,t,n,r={}){let i=await $d(e,t,r);if(i)return{taskRepository:t.repository,taskRevision:t.taskRevision,submissionRepository:i,submissionRevision:n}}async function $d(e,t,n={}){let r;try{r=xd(await Gd(e,[`config`,`--get`,`remote.origin.pushurl`]))}catch{try{r=xd(await Gd(e,[`config`,`--get`,`remote.origin.url`]))}catch{if(n.allowMissing)return;throw Error(`Add your GitHub fork as the 'origin' remote before submitting. The task repository is available as '${Wd}'.`)}}let i=_d(r,`git remote.origin.url`);if(i.toLowerCase()===t.repository.toLowerCase()){if(n.allowMissing)return;throw Error(`The 'origin' remote is the task repository. Add your GitHub fork as 'origin'; keep the task repository as '${Wd}' before submitting.`)}return i}function ef(e,t){return!e||!t?!1:e.taskRepository.toLowerCase()===t.taskRepository.toLowerCase()&&e.taskRevision.toLowerCase()===t.taskRevision.toLowerCase()&&e.submissionRepository.toLowerCase()===t.submissionRepository.toLowerCase()&&e.submissionRevision.toLowerCase()===t.submissionRevision.toLowerCase()}function tf(e,t){return`${e}/commit/${t}`}function nf(e,t,n,r,i={}){let a=e.evidenceRefs.map(e=>Cd(e.trim(),`checker evidence reference`));if(n){if(!t){if(i.allowMissingSource)return{evidence:e.evidence,evidenceRefs:a};throw Error(`Provenance policy requires a submission source`)}let o=Sd(r);if(n.required&&(i.requirePullRequest??!0)&&!o)throw Error(`This competition requires a GitHub pull request`);a.push(tf(t.taskRepository,t.taskRevision),tf(t.submissionRepository,t.submissionRevision),...o?[o]:[])}return{evidence:e.evidence,evidenceRefs:[...new Set(a)]}}async function rf(e,t){let n=`${e}.${process.pid}.tmp`;await P.writeFile(n,`${JSON.stringify(t,null,2)}\n`,{mode:384}),await P.rename(n,e)}async function af(e){let t=JSON.parse(await P.readFile(A.join(e,Bd),`utf8`));if(t.version!==1||typeof t.competition!=`string`)throw Error(`${Bd} has an unsupported format`);return t}async function of(e){let t=Sd(e.pullRequest);if(!t)throw Error(`A pull request URL is required`);let n=new URL(t).pathname.split(`/`).filter(Boolean),r=await fetch(`https://api.github.com/repos/${n[0]}/${n[1]}/pulls/${n[3]}`,{headers:{Accept:`application/vnd.github+json`,"User-Agent":`tangle-solve-cli`},signal:AbortSignal.timeout(15e3)}),i=await r.json().catch(()=>null),a=e=>e.replace(/\/$/,``).toLowerCase();if(!r.ok||a(i?.base?.repo?.html_url??``)!==a(e.taskRepository)||i?.head?.sha?.toLowerCase()!==e.submissionRevision.toLowerCase()||a(i?.head?.repo?.html_url??``)!==a(e.submissionRepository))throw Error(`GitHub pull request must target the pinned task repository and contain the current committed submission`)}function sf(e){return{...e.authorization?{authorization:e.authorization}:{},...e.stake?{stake:e.stake}:{},join:e.join,commit:e.commit,reveal:e.reveal,report:e.report,evaluation:e.evaluation}}const cf=Xe(Se);function lf(){return`Task source is '${Wd}'. Add your fork as 'origin', commit your candidate, push it, and open a pull request before submitting.`}async function uf(e,t,n){try{let r=fd(await Ed({path:`/v1/competitions/${encodeURIComponent(e)}`,apiUrl:n.apiUrl,profile:n.profile}),`competition response`),i=Id(r.competition??r),a=A.resolve(t??i.slug),o=z(`Cloning ${i.slug}…`);n.json||o.start();try{await cf(`git`,[`clone`,`--no-tags`,`--origin`,Wd,i.repository,a],{encoding:`utf8`,maxBuffer:1e6}),await Gd(a,[`checkout`,`--detach`,i.taskRevision]);let e=await Gd(a,[`rev-parse`,`HEAD`]);if(e.toLowerCase()!==i.taskRevision.toLowerCase())throw Error(`Pinned checkout resolved to ${e}, expected ${i.taskRevision}`);await rf(A.join(a,`.tangle-solve.json`),i),await Jd(a)}finally{o.stop()}n.json?I({competition:i,directory:a}):(L(`Cloned ${i.slug} at ${i.taskRevision.slice(0,12)}`),i.provenance&&R(lf()),R(`Run the pinned checker with: cd ${a} && tangle solve run`))}catch(e){U(e)}}const df=12e4,ff=bt(`event JobSubmitted(uint64 indexed serviceId, uint64 indexed callId, uint8 jobIndex, address caller, bytes inputs)`),pf=bt(`event JobCompleted(uint64 indexed serviceId, uint64 indexed callId)`),mf=bt(`event JobResultSubmitted(uint64 indexed serviceId, uint64 indexed callId, address indexed operator, bytes result)`),hf=bt(`event AggregatedResultSubmitted(uint64 indexed serviceId, uint64 indexed callId, uint256 signerBitmap, bytes output)`),gf=bt(`event EvaluationAccepted(uint64 indexed serviceId, uint64 indexed competitionId, address indexed researcher, bytes32 candidateId, bytes32 submissionRefHash, bytes32 evaluationDigest, bytes32 metricsHash, bytes32 evidenceRefsHash)`),_f=[...yt([`function submitJob(uint64 serviceId, uint8 jobIndex, bytes inputs) payable returns (uint64 callId)`,`function getJobEventRate(uint64 blueprintId, uint8 jobIndex) view returns (uint256 rate)`,`function getServicePaymentAsset(uint64 serviceId) view returns (address)`,`function isPermittedCaller(uint64 serviceId, address caller) view returns (bool)`]),ff,pf,mf,hf],vf=yt([`function authorizeSelf(uint64 serviceId)`,`function revokeSelf(uint64 serviceId)`,`function isDeviceRevoked(address device) view returns (bool)`,`function postStake(uint64 serviceId, uint64 competitionId) payable`,`function stakes(uint64 serviceId, uint64 competitionId, address researcher) view returns (uint256)`,`function pendingResults(uint64 serviceId, uint64 jobCallId) view returns (uint8 job, bytes32 outputHash, uint256 signerBitmap, bool exists, bool executed)`,`function executePendingResult(uint64 serviceId, uint64 jobCallId, bytes output)`,`function acceptedCandidates(uint64 serviceId, uint64 competitionId, address researcher, bytes32 candidateId) view returns (bool)`]),yf=yt([`function allowance(address owner, address spender) view returns (uint256)`,`function approve(address spender, uint256 amount) returns (bool)`]),bf=xt(`uint64 competitionId, uint256 stakeWei`),xf=xt(`uint64 competitionId, bytes32 commitment`),Sf=xt(`uint64 competitionId, bytes32 commitment, string artifactRef, bytes32 salt`),Cf=xt(`string artifactRef, bytes32 salt`),wf=xt(`uint64 competitionId, bytes32 candidateId, string submissionRef, string evidenceJson, string evidenceRefsJson`),Tf=xt(`string status, string detail`),Ef=/^0x[0-9a-f]{64}$/i;function Df(e,t){if(e!==t)throw Error(`Tempo RPC returned chain ${e}; expected ${t}`)}function Of(e,t,n){return{...e,feePayer:!0,nonceKey:t,nonce:n}}function kf(e,t){if(e!==`success`)throw Error(`${t} transaction reverted`)}function Af(e,t,n,r){if(!Ef.test(t))throw Error(`${n} transaction hash is invalid`);if(typeof e.transactionHash!=`string`||e.transactionHash.toLowerCase()!==t.toLowerCase())throw Error(`${n} receipt hash does not match the saved transaction`);if(kf(e.status??``,n),typeof e.from!=`string`||e.from.toLowerCase()!==r.from.toLowerCase())throw Error(`${n} receipt sender does not match the Solve device`);if(typeof e.to!=`string`||e.to.toLowerCase()!==r.to.toLowerCase())throw Error(`${n} receipt destination does not match the expected contract`)}function jf(e,t){return e>=t?[]:e>0n?[0n,t]:[t]}function Mf(e,t,n=Date.now()){return n>=e+t}function Nf(e,t){return e.filter(e=>e.args?.candidateId?.toLowerCase()===t.toLowerCase()).at(-1)?.transactionHash}function Pf(e,t,n,r,i){for(let a of e.logs)if(a.address.toLowerCase()===t.tangleAddress.toLowerCase())try{let e=pt({abi:[ff],eventName:`JobSubmitted`,data:a.data,topics:a.topics});if(e.args.serviceId===t.serviceId&&e.args.jobIndex===n&&e.args.caller.toLowerCase()===r.toLowerCase()&&(!i||e.args.inputs.toLowerCase()===i.toLowerCase()))return e.args.callId}catch{}throw Error(`Tangle did not emit job ${n} for ${r}`)}function Ff(e,t,n,r){for(let i of e.logs)if(i.address.toLowerCase()===t.managerAddress.toLowerCase())try{let e=pt({abi:[gf],eventName:`EvaluationAccepted`,data:i.data,topics:i.topics}).args;if(e.serviceId===t.serviceId&&e.competitionId===t.competitionId&&e.researcher.toLowerCase()===n.address.toLowerCase()&&e.candidateId.toLowerCase()===r.toLowerCase())return!0}catch{}return!1}function If(e){if(e.chainId!==wt.id)throw Error(`Solve submissions require Tempo Moderato (chain ${wt.id}); received ${e.chainId}`);if(!e.sponsorUrl)throw Error(`Solve submissions require a Tempo sponsor relay URL; unsponsored writes are disabled`);return{...wt,name:e.chainName,nativeCurrency:{name:e.nativeSymbol,symbol:e.nativeSymbol,decimals:18},rpcUrls:{default:{http:[e.rpcUrl]}}}}async function Lf(e,t){Md(e);let n=If(e),r=ut({chain:n,transport:gt(e.rpcUrl)});return Df(await r.getChainId(),e.chainId),await Rf({publicClient:r},e),{publicClient:r,walletClient:dt({account:t,chain:n,transport:Et(gt(e.rpcUrl),gt(e.sponsorUrl))}),account:t}}async function Rf(e,t){let n=await e.publicClient.readContract({address:t.tangleAddress,abi:_f,functionName:`getServicePaymentAsset`,args:[t.serviceId]});if(n.toLowerCase()!==t.paymentAsset.toLowerCase())throw Error(`Tempo service payment asset ${n} does not match the trusted Solve asset ${t.paymentAsset}`)}async function zf(e,t,n){let[r,i]=await Promise.all([e.publicClient.readContract({address:t.tangleAddress,abi:_f,functionName:`getJobEventRate`,args:[t.blueprintId,n]}),e.publicClient.readContract({address:t.tangleAddress,abi:_f,functionName:`getServicePaymentAsset`,args:[t.serviceId]})]);if(i.toLowerCase()!==t.paymentAsset.toLowerCase())throw Error(`Tempo job payment asset ${i} does not match the trusted Solve asset ${t.paymentAsset}`);return{asset:i,amount:r,value:i===`0x0000000000000000000000000000000000000000`?r:0n}}async function Bf(e,t,n){return await e.publicClient.readContract({address:t,abi:yf,functionName:`allowance`,args:[e.account.address,n.tangleAddress]})}async function Vf(e,t,n,r,i,a){let o=Date.now();for(;!Mf(o,a);){if((await e.publicClient.getLogs({address:t.tangleAddress,event:pf,args:{serviceId:t.serviceId,callId:n},fromBlock:r,toBlock:`latest`})).length>0){let a=(await e.publicClient.getLogs({address:t.tangleAddress,event:mf,args:{serviceId:t.serviceId,callId:n},fromBlock:r,toBlock:`latest`}))[0]?.args.result;if(!a)throw Error(`Tangle job ${n} completed without a result`);let[o,s]=ft(Tf,a);if(o!==i)throw Error(`Tangle job ${n} ${o}: ${s}`);return{status:o,detail:s}}await new Promise(e=>setTimeout(e,1e3))}throw Error(`Tangle job ${n} did not complete within 120 seconds`)}async function Hf(e,t,n,r,i){let a=Date.now();for(;!Mf(a,i);){let i=(await e.publicClient.getLogs({address:t.tangleAddress,event:hf,args:{serviceId:t.serviceId,callId:n},fromBlock:r,toBlock:`latest`}))[0]?.args.output;if(i)return i;await new Promise(e=>setTimeout(e,1e3))}throw Error(`Tangle job ${n} did not produce an aggregate within 120 seconds`)}async function Uf(e,t,n){return!!await e.publicClient.readContract({address:t.managerAddress,abi:vf,functionName:`acceptedCandidates`,args:[t.serviceId,t.competitionId,e.account.address,n]})}const Wf=BigInt(vt(St(`tangle.solve.v1`)));async function Gf(e,t){let n=await Tt.nonce.getNonce(e.publicClient,{account:e.account.address,nonceKey:Wf});if(n>BigInt(2**53-1))throw Error(`The Solve transaction nonce exceeds the safe range`);return e.walletClient.writeContract(Of(t,Wf,Number(n)))}async function Kf(e,t,n,r){if(!await e.publicClient.readContract({address:t.tangleAddress,abi:_f,functionName:`isPermittedCaller`,args:[t.serviceId,e.account.address]}))try{let i=r??await Gf(e,{address:t.managerAddress,abi:vf,functionName:`authorizeSelf`,args:[t.serviceId]});if(r||await n?.(`authorization`,i),Af(await e.publicClient.waitForTransactionReceipt({hash:i}),i,`Authorization`,{from:e.account.address,to:t.managerAddress}),!await e.publicClient.readContract({address:t.tangleAddress,abi:_f,functionName:`isPermittedCaller`,args:[t.serviceId,e.account.address]}))throw Error(`authorization transaction did not add the device`);return i}catch(e){let t=e instanceof Error?e.message:`unknown chain error`;throw Error(`The competition manager did not authorize this device. The deployed manager must expose authorizeSelf(uint64): ${t}`)}}async function qf(e,t){let n=await Gf(e,{address:t.managerAddress,abi:vf,functionName:`revokeSelf`,args:[t.serviceId]});return Af(await e.publicClient.waitForTransactionReceipt({hash:n}),n,`Revocation`,{from:e.account.address,to:t.managerAddress}),n}async function Jf(e,t,n,r,i=`allowance`,a={}){if(t.amount===0n||t.asset===`0x0000000000000000000000000000000000000000`)return;let o=await Bf(e,t.asset,n);for(let s of jf(o,t.amount)){let o=s===0n?`${i}:reset`:`${i}:approval`,c=a[o];if(c){if(Af(await e.publicClient.waitForTransactionReceipt({hash:c}),c,s===0n?`ERC-20 allowance reset`:`ERC-20 allowance approval`,{from:e.account.address,to:t.asset}),await Bf(e,t.asset,n)!==s)throw Error(`${s===0n?`ERC-20 allowance reset`:`ERC-20 allowance approval`} did not set the expected allowance`);continue}let l=await Gf(e,{address:t.asset,abi:yf,functionName:`approve`,args:[n.tangleAddress,s]});await r?.(o,l),Af(await e.publicClient.waitForTransactionReceipt({hash:l}),l,s===0n?`ERC-20 allowance reset`:`ERC-20 allowance approval`,{from:e.account.address,to:t.asset})}}async function Yf(e,t,n,r,i,a=`job:${n}`,o={}){let s=await zf(e,t,n);await Jf(e,s,t,i,`allowance:${a}`,o);let c=o[a],l=c??await Gf(e,{address:t.tangleAddress,abi:_f,functionName:`submitJob`,args:[t.serviceId,n,r],value:s.value});c||await i?.(a,l);let u=await e.publicClient.waitForTransactionReceipt({hash:l});return Af(u,l,`Job ${n}`,{from:e.account.address,to:t.tangleAddress}),{hash:l,callId:Pf(u,t,n,e.account.address,r),blockNumber:u.blockNumber}}async function Xf(e,t,n,r,i,a,o=`job:${n}`,s={}){let c=await Yf(e,t,n,r,a,o,s),l=await Vf(e,t,c.callId,c.blockNumber,i,df);return{...c,acknowledgement:l}}const Zf={...Ad,chainName:`Tempo Moderato`,nativeSymbol:`TNT`},Qf={async read(e){let t=ut({chain:wt,transport:gt(Zf.rpcUrl,{timeout:15e3})}),n=e=>e.catch(()=>null),r=await Promise.all(e.map(async e=>{let[r,i]=await Promise.all([n(t.readContract({address:Zf.tangleAddress,abi:_f,functionName:`isPermittedCaller`,args:[Zf.serviceId,e]})),n(t.readContract({address:Zf.managerAddress,abi:vf,functionName:`isDeviceRevoked`,args:[e]}))]);return[e.toLowerCase(),{permitted:r,revoked:i}]}));return new Map(r)},async revokeSelf(e){return qf(await Lf(Zf,e),Zf)}},$f={permitted:null,revoked:null};function ep(e){return e.revoked?`revoked`:e.permitted===null?`unknown`:e.permitted?`permitted`:`not permitted`}async function tp(e,t=Qf){try{let{devices:n}=await Od({apiUrl:e.apiUrl,profile:e.profile}),r=od()?.account.address.toLowerCase(),i=n.map(e=>({...e,local:e.address===r,status:e.revokedAt?`revoked`:`active`}));r&&!i.some(e=>e.local)&&i.push({address:r,local:!0,status:`unbound`,boundAt:null,lastUsedAt:null,revokedAt:null,revocationMethod:null,revocationReason:null});let a=await t.read(i.map(e=>ht(e.address))),o=i.map(e=>({...e,onChain:a.get(e.address)??$f}));if(e.json){I({serviceId:Zf.serviceId.toString(),devices:o});return}Ht([`Address`,`Status`,`Local`,`Service ${Zf.serviceId}`,`Last used`,`Revoked`],o.map(e=>[e.address,e.status,e.local?`yes`:``,ep(e.onChain),e.lastUsedAt??``,e.revokedAt?`${e.revokedAt} (${e.revocationMethod})`:``]))}catch(t){U(t,e.json)}}async function np(e,t,n=Qf){try{if(!_t(e))throw Error(`${e} is not an EVM address`);let r=ht(e),i=od(),a=i?.account.address===r;if(!t.yes){if(!process.stdin.isTTY)throw Error(`Revoking a device is permanent. Re-run with --yes to confirm`);if(!await Qr(`Permanently revoke Solve device ${r}${a?` (this machine's device)`:``}? [y/N] `,`--yes`)){R(`Revocation cancelled`);return}}let o;if(i&&a){let e=await Dd({deviceAddress:r,purpose:`revoke`,apiUrl:t.apiUrl,profile:t.profile});o={challengeId:e.challengeId,signature:await i.account.signMessage({message:e.message})}}let s=await kd({deviceAddress:r,reason:t.reason,...o,apiUrl:t.apiUrl,profile:t.profile}),c=r.toLowerCase(),l=(await n.read([r])).get(c)??$f,u;if(i&&a&&!l.revoked){try{u=await n.revokeSelf(i.account)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`The Solve API revoked ${r}, but the on-chain revocation failed and the local key was kept: ${t}. Run the command again to retry`)}l=(await n.read([r])).get(c)??$f}let d=i&&a&&l.revoked?cd(i):void 0;if(t.json){I({...s,serviceId:Zf.serviceId.toString(),onChain:l,...u?{revocationTransaction:u}:{},localKeyRetired:!!d});return}L(s.alreadyRevoked?`${r} was already revoked in the Solve API`:`Revoked ${r}; the Solve API refuses its signatures`),u&&L(`Revoked on Tempo in ${u}; service ${Zf.serviceId} refuses its jobs`),d&&R("The local device key was moved aside because its address may still hold stake or rewards. Run `tangle solve account --create` for a new device"),!a&&l.permitted&&Lt(`The device can still submit jobs to service ${Zf.serviceId}. Only its key, or the Solve blueprint owner, can revoke it on chain`)}catch(e){U(e,t.json)}}function rp(e,t){return vt(mt(Cf,[e.trim(),t]))}function ip(e){let t=/^submission=(\S+)/.exec(e);if(!t?.[1])throw Error(`COMMIT_CANDIDATE did not return a submission reference`);return t[1]}async function ap(e,t,n,r,i){let a=i.resumeTransactions?.evaluation;if(a){let n=await e.publicClient.waitForTransactionReceipt({hash:a});if(Af(n,a,`Evaluation`,{from:e.account.address,to:t.managerAddress}),!Ff(n,t,e.account,r))throw Error(`Saved evaluation transaction did not emit EvaluationAccepted for this candidate`);return a}let o=Date.now();for(;!Mf(o,df);){if(await Uf(e,t,r)){let i=Nf(await e.publicClient.getLogs({address:t.managerAddress,event:gf,args:{serviceId:t.serviceId,competitionId:t.competitionId,researcher:e.account.address},fromBlock:n.blockNumber,toBlock:`latest`}),r);if(i)return i;throw Error(`Candidate is already accepted, but its EvaluationAccepted transaction is unavailable`)}let[a,o,,s,c]=await e.publicClient.readContract({address:t.managerAddress,abi:vf,functionName:`pendingResults`,args:[t.serviceId,n.callId]});if(s&&a!==4)throw Error(`Manager pending result ${n.callId} has unexpected job ${a}`);if(s&&c)throw Error(`Manager executed the report without EvaluationAccepted`);if(s&&!c){if(o.toLowerCase()!==vt(n.output).toLowerCase())throw Error(`Manager pending report output does not match the aggregate`);let a=await Gf(e,{address:t.managerAddress,abi:vf,functionName:`executePendingResult`,args:[t.serviceId,n.callId,n.output]});await i.onTransaction?.(`evaluation`,a);let s=await e.publicClient.waitForTransactionReceipt({hash:a});if(Af(s,a,`Evaluation`,{from:e.account.address,to:t.managerAddress}),!Ff(s,t,e.account,r))throw Error(`Evaluation transaction did not emit EvaluationAccepted for this candidate`);return a}await new Promise(e=>setTimeout(e,1e3))}throw Error(`Manager did not emit EvaluationAccepted within 120 seconds`)}async function op(e,t,n,r={}){if(Md(e),!/^0x[0-9a-f]{64}$/i.test(n.salt))throw Error(`Reveal salt must be bytes32`);if(!n.artifactRef.trim())throw Error(`Candidate reference is required`);if(!n.evidenceJson.trim()||n.evidenceRefs.length===0)throw Error(`Checker evidence is required`);let i=await Lf(e,t),a=await Kf(i,e,r.onTransaction,r.resumeTransactions?.authorization),o,s=await i.publicClient.readContract({address:e.managerAddress,abi:vf,functionName:`stakes`,args:[e.serviceId,e.competitionId,i.account.address]});s<e.minStakeWei&&(o=await Gf(i,{address:e.managerAddress,abi:vf,functionName:`postStake`,args:[e.serviceId,e.competitionId],value:e.minStakeWei-s}),await r.onTransaction?.(`stake`,o),Af(await i.publicClient.waitForTransactionReceipt({hash:o}),o,`Stake`,{from:i.account.address,to:e.managerAddress}));let c=rp(n.artifactRef,n.salt),l=mt(bf,[e.competitionId,e.minStakeWei]),u=mt(xf,[e.competitionId,c]),d=mt(Sf,[e.competitionId,c,n.artifactRef.trim(),n.salt]),f=await Xf(i,e,1,l,`joined`,r.onTransaction,`join`,r.resumeTransactions),p=await Xf(i,e,2,u,`committed`,r.onTransaction,`commit`,r.resumeTransactions),m=ip(p.acknowledgement.detail),h=await Xf(i,e,3,d,`revealed`,r.onTransaction,`reveal`,r.resumeTransactions),g=await Yf(i,e,4,mt(wf,[e.competitionId,c,m,n.evidenceJson,JSON.stringify(n.evidenceRefs)]),r.onTransaction,`report`,r.resumeTransactions),_=await Hf(i,e,g.callId,g.blockNumber,df),v=await ap(i,e,{callId:g.callId,output:_,blockNumber:g.blockNumber},c,r);return{address:i.account.address,...a?{authorization:a}:{},...o?{stake:o}:{},join:f.hash,commit:p.hash,reveal:h.hash,report:g.hash,evaluation:v,candidateId:c,submissionRef:m}}const sp=Xe(Se),cp=`/usr/bin/bwrap`,lp=[`/usr`,`/bin`,`/sbin`,`/lib`,`/lib64`];function up(e){return[...e].some(e=>{let t=e.charCodeAt(0);return t<32||t===127})}function dp(e,t){if(!e||e.length>2048||up(e))throw Error(`${t} contains invalid control characters or is too long`)}function fp(e,t){let n=t;for(;n<e.length&&/\s/.test(e[n]??``);)n+=1;return n}function pp(e,t){if(e[t]!==`"`)throw Error(`Checker output must be valid JSON`);let n=t+1;for(;n<e.length;){let t=e[n];if(t===`\\`){n+=2;continue}if(t===`"`)return n+1;if((t?.charCodeAt(0)??0)<32)throw Error(`Checker output must be valid JSON`);n+=1}throw Error(`Checker output must be valid JSON`)}function mp(e,t,n){let r=new Set,i=fp(e,t+1);if(e[i]===`}`)return i+1;for(;i<e.length;){let t=pp(e,i),a=JSON.parse(e.slice(i,t));if(r.has(a))throw Error(`Checker output must not contain duplicate object keys`);if(r.add(a),i=fp(e,t),e[i]!==`:`)throw Error(`Checker output must be valid JSON`);let o=fp(e,i+1),s=gp(e,o);if(n?.(a,o,s),i=fp(e,s),e[i]===`}`)return i+1;if(e[i]!==`,`)throw Error(`Checker output must be valid JSON`);i=fp(e,i+1)}throw Error(`Checker output must be valid JSON`)}function hp(e,t){let n=fp(e,t+1);if(e[n]===`]`)return n+1;for(;n<e.length;){if(n=fp(e,gp(e,n)),e[n]===`]`)return n+1;if(e[n]!==`,`)throw Error(`Checker output must be valid JSON`);n=fp(e,n+1)}throw Error(`Checker output must be valid JSON`)}function gp(e,t){if(e[t]===`"`)return pp(e,t);if(e[t]===`{`)return mp(e,t);if(e[t]===`[`)return hp(e,t);let n=t;for(;n<e.length&&!/[\s,\]}]/.test(e[n]??``);)n+=1;return n}function _p(e){let t=e.trim();if(fp(t,gp(t,0))!==t.length)throw Error(`Checker output must be valid JSON`)}function vp(e,t){let n=e.trim();if(n[0]!==`{`)return;let r;return mp(n,0,(e,i,a)=>{e===t&&(r=n.slice(i,a).trim())}),r}function yp(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Checker output must be one JSON object`)}if(_p(e),!t||typeof t!=`object`||Array.isArray(t))throw Error(`Checker output must be a JSON object`);let n=t,r=n.candidate_ref;if(typeof r!=`string`||!r.trim())throw Error(`Checker output must include candidate_ref`);let i=r.trim(),a=n.evidence_refs;if(!Array.isArray(a)||a.length===0||a.some(e=>typeof e!=`string`||!e.trim()))throw Error(`Checker output must include a non-empty evidence_refs array`);dp(i,`candidate_ref`);for(let e of a)dp(e.trim(),`evidence_refs`);if(!n.evidence_json||typeof n.evidence_json!=`object`||Array.isArray(n.evidence_json))throw Error(`Checker output must include an evidence_json object`);let o={...n.evidence_json},s=vp(e,`evidence_json`);if(!s)throw Error(`Checker evidence_json source text is missing`);if(o.candidate_ref!==i)throw Error(`Checker evidence_json candidate_ref must match candidate_ref`);return{candidateRef:i,evidenceRefs:a.map(e=>e.trim()),evidence:o,evidenceJson:s}}async function bp(e,t,n){let r=n.trim();if(r.startsWith(`{`)&&r.endsWith(`}`)||!t.result_file)return r;let i=await Ep(e),a=A.resolve(i,t.result_file),o=A.relative(i,a);if(o.startsWith(`..`)||A.isAbsolute(o))throw Error(`Checker result_file must stay inside the competition repository`);let s;try{s=await P.lstat(a)}catch{throw Error(`Checker result_file must be an existing regular file inside the competition repository`)}if(s.isSymbolicLink())throw Error(`Checker result_file must not be a symbolic link`);if(!s.isFile())throw Error(`Checker result_file must be an existing regular file inside the competition repository`);let c;try{c=await P.realpath(a)}catch{throw Error(`Checker result_file must resolve to a regular file inside the competition repository`)}let l=A.relative(i,c);if(l.startsWith(`..`)||A.isAbsolute(l))throw Error(`Checker result_file must stay inside the competition repository`);return(await P.readFile(c,`utf8`)).trim()}function xp(e,t){let n=A.relative(e,t);return n===``||!n.startsWith(`..`)&&!A.isAbsolute(n)}function Sp(e){return lp.some(t=>xp(t,e))}async function Cp(e,t,n){let r=e.includes(`/`)?[A.resolve(t,e)]:(process.env.PATH??``).split(A.delimiter).filter(Boolean).map(t=>A.join(t,e));for(let i of r){let r;try{r=await P.realpath(i),await P.access(r,P.constants.X_OK)}catch{continue}if(!xp(t,r)&&!Sp(r)&&r!==n)throw Error(`Checker executable '${e}' must resolve inside the competition repository or a trusted runtime directory`);return r}throw Error(`Checker executable '${e}' was not found`)}async function wp(e){let t=[];for(let n of e)try{(await P.stat(n)).isDirectory()&&t.push(n)}catch{}return t}async function Tp(e){let t=await P.realpath(be.homedir());if(e===A.parse(e).root||e===t)throw Error(`Solve checker repository must be a dedicated directory, not the filesystem or home root`)}async function Ep(e){let t=await P.realpath(e);return await Tp(t),t}async function Dp(e){let t=A.join(e,`.git`),n;try{n=await P.lstat(t)}catch{return}if(n.isSymbolicLink())throw Error(`Solve checker repository .git must not be a symbolic link`);if(!n.isDirectory()&&!n.isFile())return;let r;try{let t={...process.env};for(let e of[`GIT_DIR`,`GIT_WORK_TREE`,`GIT_INDEX_FILE`,`GIT_OBJECT_DIRECTORY`,`GIT_ALTERNATE_OBJECT_DIRECTORIES`,`GIT_COMMON_DIR`,`GIT_CONFIG_COUNT`,`GIT_CONFIG_PARAMETERS`])delete t[e];let n=await sp(`/usr/bin/git`,[`-C`,e,`rev-parse`,`--verify`,`HEAD^{commit}`],{encoding:`utf8`,maxBuffer:1e5,env:{...t,GIT_CONFIG_GLOBAL:`/dev/null`,GIT_CONFIG_SYSTEM:`/dev/null`,GIT_CONFIG_NOSYSTEM:`1`,GIT_TERMINAL_PROMPT:`0`}}),i=String(n.stdout).trim();/^[0-9a-f]{40}$/i.test(i)&&(r=i.toLowerCase())}catch{}return{kind:n.isDirectory()?`directory`:`file`,...r?{commit:r}:{}}}async function Op(e,t,n){let r=await Ep(e);if(process.platform!==`linux`)throw Error(`Solve checkers require the Linux sandbox runtime (bubblewrap) with network isolation`);try{await P.access(cp,P.constants.X_OK)}catch{throw Error(`Solve checkers require /usr/bin/bwrap; install bubblewrap or run the checker in a Tangle sandbox`)}let i=await Cp(t,r,await P.realpath(process.execPath)),a=await Dp(r),o=(await wp(lp)).flatMap(e=>[`--ro-bind`,e,e]),s=xp(r,i)?`/work/${A.relative(r,i)}`:Sp(i)?i:`/checker/node`;!xp(r,i)&&!Sp(i)&&o.push(`--ro-bind`,i,`/checker/node`);let c=a?.kind===`directory`?[`--tmpfs`,`/work/.git`]:a?.kind===`file`?[`--ro-bind`,`/dev/null`,`/work/.git`]:[];return{executable:cp,args:[`--die-with-parent`,`--new-session`,`--unshare-all`,`--clearenv`,...o,`--proc`,`/proc`,`--dev`,`/dev`,`--tmpfs`,`/tmp`,`--dir`,`/tmp/home`,`--bind`,r,`/work`,...c,`--chdir`,`/work`,`--setenv`,`HOME`,`/tmp/home`,...a?.commit?[`--setenv`,`TANGLE_SOLVE_COMMIT`,a.commit]:[],`--setenv`,`TMPDIR`,`/tmp`,`--setenv`,`PATH`,`/checker:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,`--setenv`,`LANG`,`C.UTF-8`,`--setenv`,`PYTHONDONTWRITEBYTECODE`,`1`,`--setenv`,`XDG_CONFIG_HOME`,`/tmp/home/.config`,`--setenv`,`XDG_CACHE_HOME`,`/tmp/home/.cache`,`--setenv`,`XDG_DATA_HOME`,`/tmp/home/.local/share`,`--setenv`,`GIT_CONFIG_GLOBAL`,`/dev/null`,`--setenv`,`GIT_CONFIG_SYSTEM`,`/dev/null`,`--setenv`,`NPM_CONFIG_USERCONFIG`,`/dev/null`,s,...n]}}async function kp(e,t){if(!t.command||t.command.includes(`/../`)||up(t.command))throw Error(`The competition checker command is invalid`);if(!Array.isArray(t.args))throw Error(`The competition checker arguments must be an array`);for(let e of t.args)dp(e,`Checker argument`);let n=t.timeout_ms??15*6e4;if(!Number.isSafeInteger(n)||n<1e3||n>60*6e4)throw Error(`Checker timeout must be between one second and one hour`);let r=await Ep(e),i;try{let e=await Op(r,t.command,t.args);i=await sp(e.executable,e.args,{cwd:r,timeout:n,maxBuffer:4194304,encoding:`utf8`})}catch(e){let t=e,n=t.stderr?.trim()||t.stdout?.trim()||t.message||`checker failed`;throw Error(`Pinned checker failed: ${n}`)}let a=String(i.stdout),o=String(i.stderr);return{...yp(await bp(r,t,a)),stdout:a,stderr:o}}async function Ap(e,t){try{let{root:n,manifest:r}=await Kd(e,t.directory),i=await Zd(n),a=r.provenance?await Qd(n,r,i,{allowMissing:!0}):void 0,o=sd(),s=z(`Running ${r.title} checker…`);t.json||s.start();let c;try{c=await kp(n,r.checker)}finally{s.stop()}let l=nf(c,a,r.provenance,void 0,{allowMissingSource:!0,requirePullRequest:!1}),u=Ct(te(32)),d=rp(c.candidateRef,u),f={version:1,competition:r.slug,candidateRef:c.candidateRef,evidence:l.evidence,evidenceJson:c.evidenceJson,evidenceRefs:l.evidenceRefs,salt:u,candidateId:d,...a?{source:a}:{},deviceAddress:o.account.address,clientSubmissionId:w(),createdAt:new Date().toISOString()};await rf(A.join(n,`.tangle-solve-run.json`),f),t.json?I({localRun:f}):(L(`Checker output recorded locally for operator evaluation`),B({Competition:r.slug,Candidate:c.candidateRef,"Device address":o.account.address,"Evidence refs":l.evidenceRefs.length}),R("Commit any changes, then run `tangle solve submit` from this directory."),r.provenance&&!a&&R(`Add your GitHub fork as 'origin' before submitting. The task repository is available as '${Wd}'.`))}catch(e){U(e)}}const jp=/^0x[0-9a-f]{64}$/i;async function Mp(e){let t=await Dd({deviceAddress:e.deviceAddress,apiUrl:e.apiUrl,profile:e.profile}),n=await e.signer.signMessage({message:t.message});return{walletChallengeId:t.challengeId,walletSignature:n}}async function Np(e,t){try{let{root:n,manifest:r}=await Kd(e,t.directory);wd({profile:t.profile});let i=await Zd(n),a=await af(n);if(a.competition!==r.slug)throw Error(`.tangle-solve-run.json does not match this competition`);if(!jp.test(a.salt)||!jp.test(a.candidateId))throw Error("This run predates durable candidate identity. Run `tangle solve run` again");let o=r.provenance?await Qd(n,r,i):void 0;if(r.provenance&&a.source&&!ef(a.source,o))throw Error("The saved run points to a different repository or revision. Keep your fork as 'origin' and run `tangle solve run` again before submitting");let s=od();if(!s)throw Error("No Solve device signer found. Run `tangle solve run` first");if(s.account.address.toLowerCase()!==a.deviceAddress.toLowerCase())throw Error("The local Solve device account changed after `tangle solve run`; run the checker again");let c=z(`Checking the committed candidate…`);t.json||c.start();let l;try{l=await kp(n,r.checker)}finally{c.stop()}if(l.candidateRef!==a.candidateRef||l.evidenceJson!==a.evidenceJson)throw Error("The committed checker output changed after `tangle solve run`; run the checker again");if(rp(l.candidateRef,a.salt).toLowerCase()!==a.candidateId.toLowerCase())throw Error(`The saved candidate identity does not match the checker output; run the checker again`);let u=Sd(t.prUrl);if(!r.provenance&&u)throw Error(`This competition does not accept GitHub pull request provenance`);if(u){if(!o)throw Error(`A provenance policy is required for a pull request`);await of({pullRequest:u,taskRepository:o.taskRepository,submissionRepository:o.submissionRepository,submissionRevision:i})}let d=nf(l,o,r.provenance,u,{requirePullRequest:!0}),f={...a,...o?{source:o}:{},chainState:{status:`submitting`,transactions:{...a.chainState?.transactions??{}}}},p=A.join(n,`.tangle-solve-run.json`);await rf(p,f);let m=z(`Submitting candidate to Tempo…`);t.json||m.start();let h;try{h=await op(Ld(r),s.account,{artifactRef:l.candidateRef,salt:a.salt,evidenceJson:l.evidenceJson,evidenceRefs:d.evidenceRefs},{resumeTransactions:f.chainState?.transactions,onTransaction:async(e,t)=>{f={...f,chainState:{status:`submitting`,transactions:{...f.chainState?.transactions??{},[e]:t}}},await rf(p,f)}})}finally{m.stop()}f={...f,chainReceipt:h,chainState:{status:`accepted`,transactions:{...f.chainState?.transactions??{},...sf(h)}}},await rf(p,f);let g=await Mp({deviceAddress:h.address,signer:s.account,apiUrl:t.apiUrl,profile:t.profile}),_=await Ed({path:`/v1/submissions`,method:`POST`,apiUrl:t.apiUrl,profile:t.profile,body:{competition:r.slug,candidateRef:l.candidateRef,candidateId:h.candidateId,evidenceJson:l.evidenceJson,evidenceRefs:d.evidenceRefs,deviceAddress:h.address,reportTxHash:h.report,evaluationTxHash:h.evaluation,transactions:sf(h),...r.provenance&&o?{source:{...o,...u?{pullRequest:u}:{}}}:{},clientSubmissionId:a.clientSubmissionId,...g,...t.model?{model:t.model}:{},...t.note?{note:t.note}:{}}});t.json?I({..._,transactions:sf(h),candidateId:h.candidateId}):(L(`Submission accepted on Tempo`),B({Competition:r.slug,Candidate:h.candidateId,"Device address":h.address,"Report transaction":h.report,"Evaluation transaction":h.evaluation,"Submission ID":typeof _.id==`string`?_.id:_.submission?.id}))}catch(e){U(e)}}function Pp(){let e=new x(`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(uf),e.command(`run [competition]`).description(`Run the competition checker and record its evidence`).option(`--directory <path>`,`Competition directory (defaults to the current directory)`).action(Ap),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(Np),e.command(`account`).description(`Show the local Solve signing account`).option(`--create`,`Create the account if it does not exist`).action(ld);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(e=>tp(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((e,t)=>np(e,t)),e}function Fp(e,t){return`tangle ssh-proxy ${e.replace(/\/+$/,``)}/v1/sandboxes/${t}/runtime/ssh`}function Ip(e){return/^[A-Za-z0-9_/:=@%+.,-]+$/.test(e)?e:`'${e.replace(/'/g,`'"'"'`)}'`}function Lp(e){return`'${e.replace(/'/g,`''`)}'`}function Rp(e){return e===`win32`?`NUL`:`/dev/null`}function zp(e,t){return t===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN=${Lp(`<token>`)}; ssh ${e.map(Lp).join(` `)}`:`TANGLE_SSH_PROXY_AUTH_TOKEN=${Ip(`<token>`)} ssh ${e.map(Ip).join(` `)}`}function Bp(e){return e.connection!==void 0&&!e.connection.ssh}function Vp(){It(`SSH is not enabled for this sandbox.`),R(`Create a sandbox with --ssh to enable SSH access.`),process.exit(1)}function Hp(e,t=[],n=process.platform){let r=Rp(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 Up(){return new x(`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}=K(n),a=z(`Getting SSH credentials...`);a.start();let o=await J(i,r,e);if(Bp(o)){a.stop(),Vp();return}o=await Y(o);let s=await o.ssh();if(a.stop(),!s){Vp();return}let c={...s,proxyCommand:Fp(r.baseUrl,o.id)};if(!r.apiKey)throw Error(`SSH proxy requires API key auth. Set TANGLE_API_KEY or pass --api-key.`);let l=Hp(c,[...n.identityFile?[`-i`,n.identityFile,`-o`,`IdentitiesOnly=yes`]:[],...t]);if(n.print){console.log(zp(l,process.platform));return}R(`Connecting via tunnel...`);let u=we(`ssh`,l,{stdio:`inherit`,env:{...process.env,TANGLE_SSH_PROXY_AUTH_TOKEN:r.apiKey}});u.on(`error`,e=>{e.code===`ENOENT`&&(It(`SSH client not found. Please install OpenSSH.`),process.exit(1)),U(e)}),u.on(`exit`,e=>{process.exit(e??0)})})}function Wp(){let e=new x(`ssh-keys`).description(`Manage SSH keys`);return e.command(`list`).description(`List SSH keys`).action(async e=>{let t=z(`Fetching SSH keys...`);try{t.start();let n=await G(W(e)).sshKeys.list();t.stop(),e.json?I({sshKeys:n}):n.length===0?R(`No SSH keys found.`):Ht([`Name`,`Type`,`Fingerprint`,`Created`],n.map(e=>[e.name,e.keyType,e.fingerprint,e.createdAt.toLocaleString()]))}catch(e){t.stop(),U(e)}}),e.command(`add`).description(`Add SSH key`).argument(`<name>`,`SSH key name`).requiredOption(`--key-file <path>`,`Public key file path`).action(async(e,t)=>{let n=z(`Adding SSH key...`);try{let r=ue(t.keyFile,`utf8`).trim();n.start();let i=await G(W(t)).sshKeys.create(e,r);n.stop(),t.json?I({sshKey:i}):L(`Added SSH key ${i.name} (${i.fingerprint})`)}catch(e){n.stop(),U(e)}}),e.command(`delete`).description(`Delete SSH key`).argument(`<name>`,`SSH key name or ID`).action(async(e,t)=>{let n=z(`Deleting SSH key...`);try{n.start(),await G(W(t)).sshKeys.delete(e),n.stop(),L(`Deleted SSH key ${e}`)}catch(e){n.stop(),U(e)}}),e}function Gp(e,t=1){process.stderr.write(`${e}\n`),process.exit(t)}function Kp(){return new x(`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||Gp(`TANGLE_SSH_PROXY_AUTH_TOKEN not set`);let n=new Dt(new URL(e.replace(/^http/,`ws`)),{headers:{Authorization:`Bearer ${t}`},perMessageDeflate:!1}),r;function i(){r&&=(clearInterval(r),void 0)}n.on(`open`,()=>{r=setInterval(()=>{n.readyState===Dt.OPEN&&n.ping()},15e3),r.unref?.(),process.stdin.on(`data`,e=>{n.readyState===Dt.OPEN&&n.send(e,{binary:!0,compress:!1})}),process.stdin.on(`end`,()=>n.close(1e3))}),n.on(`message`,e=>{let t=Buffer.isBuffer(e)?e:Array.isArray(e)?Buffer.concat(e):Buffer.from(e);process.stdout.write(t)}),n.on(`error`,e=>{i(),Gp(`WebSocket error: ${e.message}`)}),n.on(`close`,e=>{i(),process.exit(e===1e3?0:1)}),process.stdin.on(`error`,()=>n.close())})}function qp(){let e=new x(`team`).description(`Manage teams`);return $(e,`list`).description(`List teams for the current account`).action(async e=>{let t=W(e),n=G(t),r=e.json?null:z(`Fetching teams...`);r?.start();let i=await n.teams.list();if(r?.stop(),e.json){I({teams:i,activeTeamId:t.activeTeamId??null});return}F(i.map(e=>({active:e.id===t.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}])}),$(e,`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(e,t)=>{let n=W(t),r=G(n),i=t.json?null:z(`Creating team...`);i?.start();let a=await r.teams.create({name:e,orgId:t.orgId});if(t.switch&&ks(a,n.profile),i?.stop(),t.json){I({team:a,active:!!t.switch});return}L(`Team created: ${Es(a)}`),t.switch&&L(`Active team set to ${a.name}`)}),$(e,`switch <team>`).description(`Set the active team for the current profile`).action(async(e,t)=>{let n=W(t),r=await Ds(G(n),e);if(ks(r,n.profile),t.json){I({team:r,activeTeamId:r.id});return}L(`Active team set to ${Es(r)}`)}),e.command(`current`).description(`Show the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(e=>{let t=fr(e.profile);if(e.json){I(t.activeTeamId?t:{activeTeamId:null});return}if(!t.activeTeamId){console.log(`No active team.`);return}B({ID:t.activeTeamId,Name:t.activeTeamName})}),e.command(`clear`).description(`Clear the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(e=>{if(As(e.profile),e.json){I({activeTeamId:null});return}L(`Active team cleared.`)}),$(e,`members [team]`).description(`List team members`).action(async(e,t)=>{let n=W(t),r=G(n),i=await Os(r,e,n.profile),a=await r.teams.listMembers(i.id);if(t.json){I({team:i,members:a});return}F(a,[{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}])}),$(e,`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(e,t)=>{let n=W(t),r=G(n),i=await Os(r,t.team,n.profile),a=Jp(t.role),o=await r.teams.updateMember(i.id,e,{role:a});if(t.json){I({team:i,member:o});return}L(`Member updated: ${o.customerEmail}`),B({Team:i.name,Role:o.role,Status:o.status})}),$(e,`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(e,t)=>{let n=W(t),r=G(n),i=await Os(r,t.team,n.profile),a=Jp(t.role),o=await r.teams.invite(i.id,{email:e,role:a,ttlHours:t.ttlHours?Number.parseInt(t.ttlHours,10):void 0});if(t.json){I({team:i,invitation:o});return}L(`Invitation created for ${o.email}`),B({Team:i.name,Role:o.role,Expires:o.expiresAt,"Invitation ID":o.id}),L(`Re-run with --json to retrieve the invitation token for sharing.`)}),$(e,`leave [team]`).description(`Leave a team as the current user`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=W(t),r=G(n),i=await Os(r,e,n.profile);if(!(!t.force&&!t.json&&!await Qr(`Leave team '${i.name}'? (y/N) `,`--force`))){if(await r.teams.leave(i.id),n.activeTeamId===i.id&&As(n.profile),t.json){I({success:!0,teamId:i.id});return}L(`Left team: ${i.name}`)}}),$(e,`transfer <new-owner-customer-id> [team]`).description(`Transfer team ownership to another active member`).option(`--force`,`Skip confirmation prompt`).action(async(e,t,n)=>{let r=W(n),i=G(r),a=await Os(i,t,r.profile);if(!(!n.force&&!n.json&&!await Qr(`Transfer ownership of '${a.name}' to ${e}? This cannot be undone without the new owner's cooperation. (y/N) `,`--force`))){if(await i.teams.transferOwnership(a.id,e),n.json){I({success:!0,teamId:a.id,newOwnerCustomerId:e});return}L(`Ownership transferred for ${a.name}`)}}),e.addCommand(Yp()),e.addCommand(Xp()),$(e,`invitations [team]`).description(`List pending and historical team invitations`).action(async(e,t)=>{let n=W(t),r=G(n),i=await Os(r,e,n.profile),a=await r.teams.listInvitations(i.id);if(t.json){I({team:i,invitations:a});return}F(a,[{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}])}),$(e,`accept <token>`).description(`Accept a team invitation`).option(`--no-switch`,`Do not set the accepted team as active`).action(async(e,t)=>{let n=W(t),r=G(n),i=await r.teams.acceptInvitation(e),a=t.switch===!1?null:await r.teams.get(i.teamId);if(a&&ks(a,n.profile),t.json){I({member:i,activeTeamId:a?.id??null});return}L(`Invitation accepted for team ${i.teamId}`),a&&L(`Active team set to ${a.name}`)}),$(e,`revoke-invitation <invitation-id>`).description(`Revoke a pending team invitation`).action(async(e,t)=>{if(await G(W(t)).teams.revokeInvitation(e),t.json){I({success:!0,invitationId:e});return}L(`Invitation revoked: ${e}`)}),$(e,`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(e,t)=>{let n=W(t),r=G(n),i=await Os(r,t.team,n.profile);if(await r.teams.removeMember(i.id,e),t.json){I({success:!0,teamId:i.id,memberId:e});return}L(`Member removed: ${e}`)}),e}function Jp(e){if(e===`admin`||e===`member`||e===`viewer`)return e;throw Error(`Role must be one of: admin, member, viewer`)}function Yp(){let e=new x(`secret`).description(`Manage team secrets`);return $(e,`list [team]`).description(`List team secret names`).action(async(e,t)=>{let n=W(t),r=G(n),i=await Os(r,e,n.profile),a=await r.teams.listSecrets(i.id);if(t.json){I({team:i,secrets:a});return}F(a,[{key:`name`,header:`Name`,width:28},{key:`updatedAt`,header:`Updated`,width:24},{key:`updatedBy`,header:`Updated By`,width:28}])}),$(e,`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(e,t,n)=>{let r=W(n),i=G(r),a=await Os(i,n.team,r.profile),o=await $u({value:t,valueStdin:n.valueStdin,prompt:`Enter value for team secret '${e}': `}),s=await i.teams.upsertSecret(a.id,e,o);if(n.json){I({team:a,secret:s});return}L(`Team secret saved: ${s.name}`)}),$(e,`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(e,t)=>{let n=W(t),r=G(n),i=await Os(r,t.team,n.profile);if(!(!t.force&&!t.json&&!await Qr(`Delete team secret '${e}' from '${i.name}'? (y/N) `,`--force`))){if(await r.teams.deleteSecret(i.id,e),t.json){I({success:!0,teamId:i.id,name:e});return}L(`Team secret deleted: ${e}`)}}),$(e,`reveal <name>`).description(`Reveal a team secret value`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).action(async(e,t)=>{let n=W(t),r=G(n),i=await Os(r,t.team,n.profile),a=await r.teams.revealSecret(i.id,e);if(t.json){I({teamId:i.id,...a});return}console.log(a.value)}),e}function Xp(){let e=new x(`templates`).description(`Manage team golden-path templates`);return $(e,`list [team]`).description(`List a team's golden-path templates`).action(async(e,t)=>{let n=W(t),r=G(n),i=await Os(r,e,n.profile),a=await r.teams.listTemplates(i.id);if(t.json){I({team:i,templates:a});return}if(a.length===0){console.log(`No templates yet for ${i.name}.`);return}F(a.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}])}),$(e,`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(e,t,n)=>{let r=W(n),i=G(r),a=await Os(i,n.team,r.profile),o;if(n.config)try{let e=JSON.parse(n.config);if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`--config must be a JSON object`);o=e}catch(e){throw Error(`--config is not valid JSON: ${e instanceof Error?e.message:String(e)}`)}let s=await i.teams.createTemplate(a.id,{name:e,snapshotId:t,description:n.description,environment:n.environment,config:o});if(n.json){I({team:a,template:s});return}L(`Team template created: ${s.name} (${s.id})`)}),$(e,`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(e,t)=>{let n=W(t),r=G(n),i=await Os(r,t.team,n.profile);if(!(!t.force&&!t.json&&!await Qr(`Delete template '${e}' from '${i.name}'? (y/N) `,`--force`))){if(await r.teams.deleteTemplate(i.id,e),t.json){I({success:!0,teamId:i.id,templateId:e});return}L(`Team template deleted: ${e}`)}}),e}function $(e,t){return e.command(t).option(`--profile <profile>`,`Credential profile`)}async function Zp(e,t,n){let r=new AbortController,i=()=>r.abort();try{let n=G(W({...e,timeout:void 0}));process.once(`SIGINT`,i),process.once(`SIGTERM`,i);let a=await t(n,{...e.timeout===void 0?{}:{timeoutMs:Number(e.timeout)*1e3},resumeJobId:e.resumeJob,signal:r.signal,onProgress:e=>{process.stderr.write(`Publication ${e.id}: ${e.status}\n`)}}).finally(()=>{process.off(`SIGINT`,i),process.off(`SIGTERM`,i)});e.json?I(a):L(`template`in a?`Published template: ${a.template.slug}`:`Published template version: ${a.version.id}`)}catch(t){if(t instanceof o&&t.status!==401&&t.job&&[`pending`,`scanning`,`ready`].includes(t.job.status)){let e=[`tangle`,`template`,...n,`--resume-job`,t.job.id].map(Be).join(` `);Object.assign(t,{fix:{command:e}})}U(t,e.json)}}function Qp(){let e=new x(`template`).description(`Manage published public templates`);return e.command(`list`).option(`-q, --query <query>`,`Search query`).option(`--tag <tag>`,`Filter by tag`).option(`--featured`,`Show featured templates only`).action(async e=>{let t=G(W(e)),n=e.featured?await t.publicTemplates.featured():await t.publicTemplates.list({query:e.query,tag:e.tag});if(e.json){I({templates:n});return}F(n,[{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}])}),e.command(`get <id-or-slug>`).action(async(e,t)=>{let n=await G(W(t)).publicTemplates.get(e);if(t.json){I({template:n});return}I(n)}),e.command(`versions <id-or-slug>`).action(async(e,t)=>{let n=await G(W(t)).publicTemplates.versions(e);if(t.json){I({versions:n});return}F(n.map(e=>({...e})),[{key:`id`,header:`Version ID`,width:38},{key:`versionNumber`,header:`Version`,width:8},{key:`createdAt`,header:`Created`,width:24}])}),e.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)=>Zp(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])),e.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)=>Zp(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])),e}function $p(){let e=new x(`traces`).description(`Read hosted agent traces, spans, and eval-runs from Tangle Intelligence`);return e.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 e=>{try{let t={from:e.from,to:e.to,model:e.model,runId:e.run,status:e.status===void 0?void 0:um(e.status),q:e.query,cursor:e.cursor,limit:e.limit===void 0?void 0:hm(e.limit)},n=tm(e),r=e.json?null:z(`Fetching traces...`);r?.start();let i=await n.listTraces(t);if(r?.stop(),e.json)return I(i);im(i.items),cm(i.nextCursor)}catch(t){rm(t,e)}}),e.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(e,t)=>{try{let n=tm(t);if(t.ndjson){await nm(n,e);return}let r=t.json?null:z(`Fetching trace spans...`);r?.start();let i=await n.getTraceSpans(e,{cursor:t.cursor,limit:t.limit===void 0?void 0:hm(t.limit)});if(r?.stop(),t.json)return I(i);am(i.items),i.truncated&&B({Spans:`${i.items.length} of ${i.total} (truncated)`}),cm(i.nextCursor)}catch(e){rm(e,t)}}),e.addCommand(em()),e}function em(){let e=new x(`runs`).description(`Read eval-runs pivoted off the trace surface`);return e.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 e=>{try{let t={status:e.status===void 0?void 0:fm(e.status),gate:e.gate===void 0?void 0:mm(e.gate),label:e.label,from:e.from,to:e.to,q:e.query,cursor:e.cursor,limit:e.limit===void 0?void 0:hm(e.limit)},n=tm(e),r=e.json?null:z(`Fetching runs...`);r?.start();let i=await n.listRuns(t);if(r?.stop(),e.json)return I(i);om(i.items),cm(i.nextCursor)}catch(t){rm(t,e)}}),e.command(`get <runId>`).description(`Show a single eval-run`).action(async(e,t)=>{try{let n=tm(t),r=t.json?null:z(`Fetching run...`);r?.start();let i=await n.getRun(e);if(r?.stop(),t.json)return I(i);sm(i)}catch(e){rm(e,t)}}),e}function tm(e){let t=nr(e.apiKey);if(!t)throw Error(`No API key found. Set TANGLE_API_KEY or run: tangle auth login`);return Ot({apiKey:t,baseUrl:e.baseUrl??process.env.TANGLE_INTELLIGENCE_BASE_URL})}async function nm(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 rm(e,t){return U(e,t.json===!0)}function im(e){F(e.map(e=>({traceId:e.traceId,root:e.rootName??`-`,model:e.model??`-`,spans:e.spanCount,errors:e.errorCount,durationMs:e.durationMs,cost:lm(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 am(e){F(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 om(e){F(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 sm(e){B({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 cm(e){e&&B({"Next page":`--cursor ${e}`})}function lm(e){return e===null?`-`:`$${e.toFixed(4)}`}function um(e){if(e===`ERROR`||e===`OK`)return e;throw Error(`--status must be ERROR or OK`)}const dm=[`started`,`baseline-complete`,`generation-complete`,`gate-decided`,`finished`,`errored`];function fm(e){let t=dm.find(t=>t===e);if(t)return t;throw Error(`--status must be one of ${dm.join(`, `)}`)}const pm=[`ship`,`hold`,`need_more_work`,`model_ceiling`,`arch_ceiling`];function mm(e){let t=pm.find(t=>t===e);if(t)return t;throw Error(`--gate must be one of ${pm.join(`, `)}`)}function hm(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}function gm(){return new x(`usage`).description(`Show account usage and billing information`).action(async e=>{let{client:t}=K(e),n=e.json?null:z(`Fetching usage...`);n?.start();let[r,i]=await Promise.all([t.usage(),t.subscription().catch(()=>null)]);n?.stop(),e.json?I({...r,subscription:i}):(console.log(),console.log(`Account Usage`),console.log(`─`.repeat(40)),B({"Active Sandboxes":r.activeSandboxes,"Total Sandboxes":r.totalSandboxes,"Compute Minutes":_m(r.computeMinutes),"GPU Seconds":r.gpuSeconds,"GPU Spend":vm(r.gpuCostUsd)}),i&&(console.log(),console.log(`Subscription`),console.log(`─`.repeat(40)),B({Plan:i.plan,Status:i.status,"Credits Available":vm(i.creditsAvailableUsd),"Credits Used":vm(i.creditsUsedUsd),"Monthly Balance":vm(i.monthlyBalanceUsd)})),console.log(),console.log(`Billing Period`),console.log(`─`.repeat(40)),B({Start:r.periodStart.toLocaleDateString(),End:r.periodEnd.toLocaleDateString()}),console.log())})}function _m(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 vm(e){return e<0?`-$${(-e).toFixed(2)}`:`$${e.toFixed(2)}`}function ym(){return new x(`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){Jn(),R(`Cleared the active sandbox.`);return}if(e){qn(e),R(`Active sandbox set to ${e}. Commands now default to it; override with --box or TANGLE_SANDBOX.`);return}let n=Kn();R(n?`Active sandbox: ${n}`:"No active sandbox. Set one with `tangle use <id>`.")})}function bm(e){F(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 xm(e){e.command(`artifacts`).description(`List a run's artifact metadata (never the bytes)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(e,t,n)=>{let r=await(await Z(n)).workflows.listArtifacts(e,t);if(n.json)return I(r);bm(r.artifacts)}),e.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(e,t,n,r)=>{let i=await(await Z(r)).workflows.downloadArtifact(e,t,n),a=r.out??n;try{fe(a,i.bytes)}catch(e){throw Error(`Could not write artifact to "${a}": ${e instanceof Error?e.message:String(e)}`)}if(r.json)return I({file:a,contentType:i.contentType,bytes:i.bytes.length});R(`Wrote ${a} (${i.bytes.length} bytes, ${i.contentType}).`)})}function Sm(e){F(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 Cm(e){e.command(`decisions`).description(`List a workflow's pending human decisions`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{let n=(await(await Z(t)).workflows.listPendingDecisions()).decisions.filter(t=>t.workflowId===e);if(t.json)return I({decisions:n});Sm(n)}),e.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(e,t,n)=>{let r=await Z(n),i=await r.workflows.getRunDecision(e,t),a=await r.workflows.resolveRunDecision(e,t,{decisionId:i.id,choice:n.choice});if(n.json)return I(a);if(a.resumed){R(`Resolved decision ${a.decisionId} with "${a.choice}" — run ${a.runId} resumed.`);return}R(`Resolved decision ${a.decisionId} with "${a.choice}", but run ${a.runId} had already finished — nothing to resume.`)})}function wm(e){try{return ue(e,`utf8`)}catch(t){throw Error(`Could not read workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function Tm(e){F(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 Em(e){let t=e.workflows.filter(e=>e.failed>0).length,n=e.workflows.filter(e=>e.failed===0&&e.waiting>0).length,r=e.workflows.filter(e=>e.failed===0&&e.waiting===0&&e.runsInWindow>0).length;R(`${t} failing · ${n} waiting · ${r} healthy · ${e.workflows.length} total over ${e.window}`),F(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 Dm(e){if(B({ID:e.id,Name:e.name,Description:e.description??``,Enabled:e.enabled?`yes`:`no`,Actions:e.actions.length}),e.triggers&&e.triggers.length>0&&(R(`Triggers`),Om(e.triggers)),e.validationErrors.length>0){R(`Validation issues`);for(let t of e.validationErrors)console.log(` ${t.path}: ${t.message}`)}}function Om(e){F(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 km(e){e.command(`list`).description(`List your workflows`).action(async e=>{let t=await(await Z(e)).workflows.list();if(e.json)return I(t);Tm(t)}),e.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 e=>{let t=await(await Z(e)).workflows.fleetInsights({window:e.window});if(e.json)return I(t);Em(t)}),e.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(e,t)=>{let n=await(await Z(t)).workflows.get(e);if(t.yaml){if(n.definitionYaml===null)throw Error(`Workflow ${n.id} has no stored definition YAML to export`);process.stdout.write(n.definitionYaml.endsWith(`
179
- `)?n.definitionYaml:`${n.definitionYaml}\n`);return}if(t.json)return I(n);Dm(n)}),e.command(`create`).description(`Create a workflow from a YAML file`).argument(`<file>`,`Path to the workflow YAML`).action(async(e,t)=>{let n=wm(e),r=await(await Z(t)).workflows.create(n);if(t.json)return I(r);R(`Created workflow ${r.id} (${r.name}).`),Dm(r)}),e.command(`apply`).description(`Create or update a workflow idempotently, matched by the definition's name`).argument(`<file>`,`Path to the workflow YAML`).action(async(e,t)=>{let n=wm(e),r=await Z(t),i=await r.workflows.validate(n,{structural:!0});if(!i.valid){if(process.exitCode=1,t.json)return I(i);R(`Invalid workflow:`);for(let e of i.errors)console.log(` ${e.path}: ${e.message}`);return}let a=(await r.workflows.list()).find(e=>e.name===i.name);if(a){let e=await r.workflows.update(a.id,n);if(t.json)return I({action:`updated`,workflow:e});R(`Updated workflow ${e.id} (${e.name}) — matched by name.`),Dm(e);return}let o=await r.workflows.create(n);if(t.json)return I({action:`created`,workflow:o});R(`Created workflow ${o.id} (${o.name}).`),Dm(o)}),e.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(e,t,n)=>{let r=wm(t),i=await(await Z(n)).workflows.update(e,r,{...n.note===void 0?{}:{note:n.note}});if(n.json)return I(i);R(`Updated workflow ${i.id} (${i.name}).`),Dm(i)}),e.command(`delete`).description(`Delete a workflow and its triggers`).argument(`<id>`,`Workflow ID`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{if(!t.force&&!await Qr(`Delete workflow ${e}? `,`--force`)){R(`Delete cancelled.`);return}if(await(await Z(t)).workflows.delete(e),t.json)return I({deleted:!0,id:e});R(`Deleted workflow ${e}.`)}),e.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(e,t)=>{let n=wm(e),r=await(await Z(t)).workflows.validate(n,{...t.structural?{structural:!0}:{}});if(t.json)return I(r);if(r.valid)R(`Valid: ${r.name} (${r.actionCount} action(s), ${r.triggerCount} trigger(s)).`);else{R(`Invalid workflow:`);for(let e of r.errors)console.log(` ${e.path}: ${e.message}`);process.exitCode=1}}),e.command(`schema`).description(`Print the JSON Schema for the workflow YAML`).action(async e=>{I(await(await Z(e)).workflows.schema())})}async function Am(e,t,n){let r=await(await Z(n)).workflows.setEnabled(e,t);if(n.json)return I(r);R(`${t?`Enabled`:`Disabled`} workflow ${r.id}.`),Dm(r)}function jm(e,t){try{return JSON.parse(e)}catch{throw Error(`Invalid ${t}: not valid JSON`)}}function Mm(e,t){try{fe(e,t,`utf8`)}catch(t){throw Error(`Could not write workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function Nm(e){F(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 Pm(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 Fm(e){e.command(`enable`).description(`Enable a workflow so its triggers and manual runs fire`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await Am(e,!0,t)}),e.command(`disable`).description(`Disable a workflow (pause its triggers and manual runs)`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await Am(e,!1,t)}),e.command(`templates`).description(`List the curated starter workflow templates`).action(async e=>{let t=await(await Z(e)).workflows.listTemplates();if(e.json)return I(t);Nm(t)}),e.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.`,Mc,[]).option(`--file <out>`,`Write the instantiated workflow YAML to this file instead of stdout`).action(async(e,t)=>{let n=Nc(t.param,`param`)??{},r=await(await Z(t)).workflows.instantiateTemplate(e,n);if(t.json)return I(r);if(!r.created){R(`Template ${e} needs provider connections before it can run:`);for(let e of r.connectionRequirements)console.log(` ${e.connected?`✓`:`✗`} ${Pm(e,r.connectionRequirements)}`);process.exitCode=1;return}let{workflow:i}=r;if(i.definitionYaml===null)throw Error(`Workflow ${i.id} was created but the server returned no definition YAML`);if(R(`Created workflow ${i.id} (${i.name}).`),t.file){Mm(t.file,i.definitionYaml),R(`Wrote ${t.file}.`);return}process.stdout.write(i.definitionYaml.endsWith(`
180
- `)?i.definitionYaml:`${i.definitionYaml}\n`)})}function Im(e){F(e,[{key:`key`,header:`Key`},{key:`version`,header:`Version`},{key:`updatedAt`,header:`Updated`}])}function Lm(e){B({Key:e.key,Version:e.version,Updated:e.updatedAt}),R(`Value`),I(e.value)}function Rm(e){let t=e.command(`kv`).description(`Read and write a workflow's cross-run KV state`);t.command(`list`).description(`List every KV entry of a workflow`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{let n=await(await Z(t)).workflows.listKv(e);if(t.json)return I(n);Im(n.entries)}),t.command(`get`).description(`Show one KV entry (value and version)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(e,t,n)=>{let r=await(await Z(n)).workflows.getKv(e,t);if(n.json)return I(r);Lm(r)}),t.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(e,t,n,r)=>{let i=jm(n,`<json>`),a=r.cas===void 0?void 0:no(r.cas,`--cas`),o=await Z(r),s=a===void 0?await o.workflows.putKv(e,t,i):await o.workflows.casKv(e,t,a,i);if(r.json)return I(s);Lm(s)}),t.command(`delete`).description(`Delete a KV entry (idempotent)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(e,t,n)=>{let r=await(await Z(n)).workflows.deleteKv(e,t);if(n.json)return I(r);R(r.deleted?`Deleted KV entry "${t}" of workflow ${e}.`:`No KV entry "${t}" on workflow ${e}.`)})}function zm(e){F(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 Bm(e){e.command(`revisions`).description(`List a workflow's definition revision history (newest first)`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{let n=await(await Z(t)).workflows.listRevisions(e);if(t.json)return I(n);zm(n)}),e.command(`revision`).description(`Show one revision's metadata and definition YAML`).argument(`<id>`,`Workflow ID`).argument(`<rev>`,`Revision number`).action(async(e,t,n)=>{let r=no(t,`<rev>`),i=await(await Z(n)).workflows.getRevision(e,r);if(n.json)return I(i);B({Revision:i.rev,Created:i.createdAt,"Created by":i.createdBy,Source:i.source,Note:i.note??``}),process.stdout.write(i.yaml.endsWith(`
181
- `)?i.yaml:`${i.yaml}\n`)}),e.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(e,t,n)=>{let r=no(t,`<rev>`),i=await(await Z(n)).workflows.rollback(e,r);if(n.json)return I(i);R(`Rolled back workflow ${i.id} to rev ${r}.`),Dm(i)})}function Vm(){let e=new x(`workflows`).description(`Create and manage Tangle workflows`);return km(e),Rc(e),Fm(e),Bm(e),Rm(e),xm(e),Cm(e),e}function Hm(e){for(let[t,n]of Object.entries(e.optsWithGlobals()))e.getOptionValue(t)===void 0&&n!==void 0&&e.setOptionValue(t,n)}const Um=e(import.meta.url)(`../package.json`);function Wm(){let e=new x;e.name(`tangle`).description(`CLI for Tangle Sandbox operations`).version(Um.version??`0.0.0`).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,t)=>{Hm(t);let n=t.opts();At(n.json===!0||n.ndjson===!0)}),e.addCommand(Pi()),e.addCommand(Xu()),e.addCommand(ym()),e.addCommand(Qu()),e.addCommand(wu()),e.addCommand(Pu()),e.addCommand(Fu()),e.addCommand(os()),e.addCommand(Up()),e.addCommand(Wp()),e.addCommand(Kp()),e.addCommand(mi()),e.addCommand(td()),e.addCommand($s()),e.addCommand(gm()),e.addCommand(qp()),e.addCommand(Qp()),e.addCommand(Ui()),e.addCommand(ea()),e.addCommand(Hu()),e.addCommand(ec()),e.addCommand(rc()),e.addCommand(iu()),e.addCommand(Ol()),e.addCommand(Vm()),e.addCommand(Ho()),e.addCommand(Zu()),e.addCommand(Pp()),e.addCommand(ed()),e.addCommand(ta()),e.addCommand(Bu()),e.addCommand(au()),e.addCommand(Fo()),e.addCommand(Io()),e.addCommand(Ju()),e.addCommand(Iu()),e.addCommand($p()),e.addCommand(Xc());function t(e){e.configureHelp({showGlobalOptions:!0}),e.configureOutput({writeErr:()=>{}}),e.exitOverride(t=>{t.exitCode===0&&process.exit(0),U(t,e.optsWithGlobals().json===!0)});for(let n of e.commands)t(n)}return t(e),e}const Gm=Wm();Gm.parseAsync(process.argv).catch(e=>{U(e,Gm.opts().json===!0)});export{};
176
+ <script>${a(r)}<\/script></body></html>`,c=M(await Qe(M(Ce(),`tangle-graph-`)),`${o}.html`);return await L(c,s,{mode:384}),c}function Wd(e,t,n){e.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(e,r)=>{let i=await I(t(e,process.cwd())),a=Bd(i,await F(i,`utf8`));if(r.json)return z(a);if(!r.open)return console.log(Hd(a));let o=await Ud(a,n);V(await fa(Gt(o).href)?`Opened ${o}`:`Open ${o}`)})}async function Gd(e){if(!Gr(e.apiKey)){if(e.json||e.dryRun||!process.stdin.isTTY)return;await xa({baseUrl:e.sandboxBaseUrl,signal:e.signal})}return Oi(e)}async function Kd(e,t,n){let r=gf(t.parameter),i=n??await Gd(t);if(!i)throw new W(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured`,`tangle auth login`);let a=await i.connections.start(e,{cli:!0,connectionParameters:r,...t.scope?.length?{requestedScopes:t.scope}:{}});return t.json?(z(vf(a)),a):(_f(a,t.browser===!1?!1:await fa(a.redirectUrl),t.wait),a)}async function qd(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?Ne(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 Kd(t,{...n,wait:!0},e);for(;!a&&Date.now()<Date.parse(o.expiresAt);)await Le(1e3,void 0,{signal:n.signal}),a=await i();return a}function Jd(){let e=new S(`hub`).description(`Discover and run Tangle Hub tools`);return Yd(e),Xd(e),Zd(e),Qd(e),$d(e),e}function Yd(e){e.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(e,t)=>{if(t.keyEnv){if(t.scope?.length)throw Error(`--scope applies to OAuth connections, not --key-env.`);let n=process.env[t.keyEnv];if(!n?.trim())throw Error(`Environment variable '${t.keyEnv}' is empty or unavailable.`);let r=await Gd(t);if(!r)throw new W(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured`,`tangle auth login`);let i;if(t.metadata!==void 0)try{i=JSON.parse(t.metadata)}catch{throw Error(`--metadata must be valid JSON.`)}let a=await r.connections.connectApiKey(e,n,i);t.json?z(a):V(`Connected ${a.connection.providerId} as ${a.connection.id}.`);return}if(t.metadata!==void 0)throw Error(`--metadata requires --key-env.`);await Kd(e,t)});let t=new S(`connections`).description(`List Hub provider connections`).action(async e=>{let t=await(await Oi(e)).connections.list();e.json?z(t):hf(t.connections)});t.command(`revoke <connection-id>`).description(`Revoke a Hub provider connection`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=await Oi(t),r=await ui(n,e);if(!t.force&&!await Bi(`Revoke Hub connection ${r}? `,`--force`)){V(`Revoke cancelled.`);return}let i=await n.connections.revoke(r);if(t.json){z(i);return}V(`Revoked Hub connection ${i.connection.id}.`)}),e.addCommand(t)}function Xd(e){e.command(`providers [provider]`).description(`Show provider setup and action catalog; use hub events for trigger readiness`).action(async(e,t)=>{let n=await(await Oi(t)).connections.providers(),r=n.providers.filter(t=>!e||t.providerId===e.toLowerCase());if(e&&!r.length)throw Error(`Provider '${e}' is absent from this deployment's catalog.`);if(t.json)return z({...n,providers:r});R(r,[{key:`providerId`,header:`Provider`},{key:`authKind`,header:`Auth`},{key:`configured`,header:`Connect configured`},{key:`actionCount`,header:`Catalog actions`}])}),e.command(`events [provider]`).description(`Discover deployed trigger events and ingress readiness separately from callable tools`).action(async(e,t)=>{let n=await Oi(t),[r,i]=await Promise.all([n.connections.providers(),n.workflows.catalogs()]),a=[...new Set([...r.providers.map(e=>e.providerId),...i.providerEventProviders])];if(e&&!a.includes(e.toLowerCase()))throw Error(`Provider '${e}' is absent from this deployment's catalog.`);let o=a.filter(t=>!e||t===e.toLowerCase()).map(e=>({provider:e,supported:i.providerEventProviders.includes(e),ingressConfigured:r.providers.find(t=>t.providerId===e)?.eventIngressConfigured??null,catalog:i.triggerEvents[e]??null}));if(t.json)return z({providers:o});R(o.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 Zd(e){let t=new S(`permissions`).description(`Manage Hub action permissions`);t.command(`list`).description(`List Hub permissions for a connection`).requiredOption(`--connection <ref>`,`Hub connection id, or provider[:account]`).action(async e=>{if(!e.connection)throw Error(`--connection is required.`);let t=await Oi(e),n=await ui(t,e.connection),r=await t.permissions.list(n);e.json?z(r):uf(r.policies)}),t.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 e=>{if(!e.connection)throw Error(`--connection is required.`);if(!e.action)throw Error(`--action is required.`);let t=df(e.decision),n=await Oi(e),r=await ui(n,e.connection),i=await n.permissions.set({connectionId:r,actionPath:e.action,decision:t});e.json?z(i):uf([i.policy])}),t.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 e=>{if(!e.connection)throw Error(`--connection is required.`);let t=await Oi(e),n=await ui(t,e.connection),r=await t.permissions.revertWrites(n);if(e.json){z(r);return}V(`Reverted ${r.reverted} write permission${r.reverted===1?``:`s`} for connection ${r.connectionId}.`)}),e.addCommand(t),e.addCommand(tf())}function Qd(e){let t=new S(`tools`).description(`Discover Hub tools`);t.command(`sources`).description(`List Hub tool sources`).action(async e=>{let t=await(await Oi(e)).tools.sources();e.json?z(t):ff(t.sources)}),t.command(`describe`).description(`Describe a Hub tool`).argument(`path`,`Executor tool path`).action(async(e,t)=>{let n=await(await Oi(t)).tools.describe(e);t.json?z(n):pf(n.tool)}),t.command(`search`).description(`Search Hub tools`).argument(`<query...>`,`Search query`).option(`--provider <provider>`,`Filter by provider/source ID`).action(async(e,t)=>{let n=await(await Oi(t)).tools.search(e.join(` `),{provider:t.provider});t.json?z(n):lf(n.tools)}),e.addCommand(t),e.addCommand(ef(`call`)),e.addCommand(ef(`exec`))}function $d(e){e.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(rf(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 Oi(t);of(t.decline?await n.approvals.deny(e):await n.approvals.approve(e),t.json===!0)}),e.command(`status`).description(`Show Hub auth and connection status`).action(async e=>{let t=await(await Oi(e)).status();e.json?z(t):yf(t)})}function ef(e){return new S(e).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(e,t)=>{let{args:n,approve:r}=nf(e,t),{path:i,input:a}=cf(n),o=await Oi(t),s=t.connection?await ui(o,t.connection):void 0;z((await o.tools.invoke(i,a,{connectionId:s,approve:r})).result)})}function tf(){let e=new S(`approvals`).description(`List and resolve Hub execution approvals`);e.command(`list`).description(`List pending Hub execution approvals`).action(async e=>{let t=await(await Oi(e)).approvals.list();e.json?z(t):af(t.approvals)});for(let t of[`approve`,`deny`])e.command(t).description(`${t===`approve`?`Approve`:`Deny`} a pending Hub execution approval`).argument(`approval-id`,`Hub approval ID`).action(async(e,n)=>{rf(e),of(await(await Oi(n)).approvals[t](e),n.json===!0)});return e}function nf(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 rf(e){if(!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`Hub approval ID must contain only letters, numbers, underscores, and dashes.`)}function af(e){R(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 of(e,t){if(t){z(sf(e));return}V(`Hub approval ${e.approval.id} ${e.approval.status}.`),e.capabilityToken&&V("Capability token minted. Re-run the original command with `--approve` to execute automatically.")}function sf(e){return{approval:e.approval,...e.capabilityToken?{capabilityToken:{tokenId:e.capabilityToken.tokenId,expiresAt:e.capabilityToken.expiresAt}}:{}}}function cf(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 lf(e){R(e.map(e=>({...e,provider:e.providerId??e.requiredConnectionProviderId,connection:mf(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 uf(e){R(e,[{key:`connectionId`,header:`Connection`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`decision`,header:`Decision`},{key:`updatedAt`,header:`Updated`}])}function df(e){if(e===`allow`||e===`ask`||e===`deny`)return e;throw Error(`--decision must be one of: allow, ask, deny.`)}function ff(e){R(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 pf(e){U({Path:e.path,Provider:e.providerId??e.requiredConnectionProviderId,Title:e.title,Description:e.description,Connection:mf(e),Policy:e.policyState}),e.inputSchema!==void 0&&(V(`Input schema`),console.log(JSON.stringify(e.inputSchema,null,2))),e.outputSchema!==void 0&&(V(`Output schema`),console.log(JSON.stringify(e.outputSchema,null,2)))}function mf(e){if(e.connectionRequired===!1)return`not required`;if(e.connectionStatus)return e.connectionStatus}function hf(e){R(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 gf(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 _f(e,t,n=!1){t?V(`Opened browser to connect ${e.provider}.`):(V(`Open this URL to connect ${e.provider}:`),console.log(e.redirectUrl)),V(n?`Finish authorization in the browser; this run resumes when connected.`:"Finish authorization in the browser, then rerun `tangle hub status`.")}function vf(e){return{provider:e.provider,redirectUrl:e.redirectUrl,expiresAt:e.expiresAt,scopes:e.scopes,cli:e.cli}}function yf(e){let{principal:t,connections:n}=e;V(`Hub status`),U({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&&V(`Some providers require reconnect.`)}const bf=t(import.meta.url);if(!bf)throw Error(`Tangle CLI package metadata was not found`);const xf=ge(bf),$=e=>w(`sha256`).update(e).digest(`hex`);function Sf(e,t){let n=ye(e,t);return n!==`..`&&!n.startsWith(`..${xe}`)&&!ve(n)}function Cf(e,t){if(/[\\/]/.test(e)||/\.(yaml|yml|json)$/.test(e))return be(t,e);let n=t;for(;!ue(M(n,`.git`))&&ge(n)!==n;)n=ge(n);ue(M(n,`.git`))||(n=t);let r=[`yaml`,`yml`,`json`].flatMap(e=>[`graph.${e}`,e]),i=[n,N()].flatMap(t=>r.map(n=>M(t,`.tangle/graphs/${e}.${n}`))),a=i.find(ue);if(a)return a;throw new W(`GRAPH_NOT_FOUND`,`Graph '${e}' was not found`,`Looked in ${i.join(`, `)}`,`tangle graph --help`)}async function wf(e,t){return qc(e.signal,async n=>{let r=e.runId??E(),i,a=new Set,{graphNativeRedaction:o}=await import(`./graph-native-Cl6SphYB.mjs`),s=o();try{let o=M(N(),`.tangle`,`runs`,r);await Ze(o,{recursive:!0,mode:448});let c=await I(M(N(),`.tangle`)),l=await I(e.cwd??process.cwd()),u=[`runs`,`graph-registry`,`graphs`].some(e=>Sf(l,M(c,e))||Sf(M(c,e),l))?M(N(),`.tangle`,`workspaces`,r):l;await Ze(u,{recursive:!0,mode:448});let d;return await t({runId:r,runDir:o,cwd:u,bridge:t=>d??=(async()=>{n.throwIfAborted();let r=T(32).toString(`hex`),{loadConfig:c,startServer:l}=await import(`cli-bridge`),d=M(xf,`dist`,`stdio.mjs`),f={...process.env,BRIDGE_HOST:`127.0.0.1`,BRIDGE_BEARER:r,BRIDGE_DATA_DIR:M(o,`bridge`),BRIDGE_BACKENDS:Gl,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:Kc,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-Cl6SphYB.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 Tf(e,t){return[`tangle graph run`,qe(e),...t.dryRun?[`--dry-run`]:[],...t.cloud?[`--cloud`]:[],...t.deploy?[`--deploy`,qe(t.deploy)]:[],...t.workflow?[`--workflow`,qe(t.workflow)]:[],...t.resume?[`--resume`,qe(t.resume)]:[],...t.seat?[`--seat`,qe(t.seat)]:[],...t.seatAccount?[`--seat-account`,qe(t.seatAccount)]:[],...t.seatCommand?[`--seat-command`,qe(t.seatCommand)]:[],...t.param.flatMap(e=>[`--param`,qe(e)])].join(` `)}async function Ef(e,t,n={}){let r=n,i=Tf(e,t);return await qc(r.signal,async n=>{n.throwIfAborted();let a=ul(t.mcpSecret);if(t.resume&&!t.resume.startsWith(`wfrun_`)&&(t.workflow||t.deploy)&&Z(`A local run cannot move to a cloud deployment`),t.deploy&&!t.cloud&&!t.workflow&&!t.resume?.startsWith(`wfrun_`))throw new W(`GRAPH_DEPLOY_INVALID`,`Deployment settings require cloud placement`,`Use --cloud to bind cloud triggers and settings`,`tangle graph run --help`);let o=await I(Cf(e,r.cwd??process.cwd())),s=r.source??await F(o,`utf8`),c=t.resume&&!t.resume.startsWith(`wfrun_`)?await zl(t.resume):void 0,l=r.taskWorkspace??(t.taskWorkspace?await Ml(t.taskWorkspace):void 0)??c?.taskWorkspace;if(c&&(l?Ol(l):null)!==(c.taskWorkspace?Ol(c.taskWorkspace):null)&&Z(`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??E(),d=l&&!r.taskWorkspace?await Pl(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 Su(o,s,t,n);let e=await bl(),l=$(s),u=Object.entries(du(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=Ae.parse(t.mcpPolicy??c?.mcpPolicy??{}),m=e.graphRegistry(M(N(),`.tangle`,`graph-registry`)),h;if(c){await I(c.cwd)!==c.cwd&&Z(`The recorded workspace identity changed`),c.file!==o&&Z(`The recorded graph source path changed`);let n=await e.loadGraph(m,c.graphDigest);n||Z(`The recorded executable graph is unavailable`),h=e.validateStoredGraph(n),Ul(c,t,l,d,f)}let g={apiKey:t.apiKey,sandboxBaseUrl:t.baseUrl,signal:n,json:t.json,dryRun:t.dryRun&&!r.connectNeeds},_,v=()=>_??=Gd(g),y=new Map,b=(e,{account:t})=>{let n=JSON.stringify([e.trim().toLowerCase(),t?.toLowerCase()]),r=y.get(n)??(async()=>{let n=await v(),r=n&&await qd(n,e,g,t);return r?{connectionId:r,capabilities:[`*`]}:void 0})();return y.set(n,r),r},x=async i=>{if(n.throwIfAborted(),c&&h)return Jc(h,c.gateChoices??{}),{graph:h,params:c.params};let a=await e.loadGraphFile(o,{source:s,seat:t.seat??(r.defaultSeat===void 0?Ar().seat:r.defaultSeat??void 0),resolveSeat:Kl(i,n),resolveNeed:b,params:d,...r.trigger?{trigger:r.trigger}:{},cwd:i,signal:n});if(n.throwIfAborted(),Jc(a.graph,f),r.graphDigest&&a.graph.digest!==r.graphDigest)throw new W(`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=oe(e.profile,w);if(!t.ok)throw new W(`GRAPH_MCP_POLICY_REQUIRED`,`A graph profile exceeds its host policy`,`${e.id}: ${t.issues.filter(e=>e.level===`error`).map(e=>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 D=[Yl(C.graph),...T].filter(Boolean).join(`,`)||void 0;if(t.dryRun)return C;let O=Xl(C.graph.nodes)?Ql(t):void 0,k=c?.runId??r.runId??E(),ee=c?.cwd??(r.taskWorkspace?S:await e.graphWorkspace(C.graph,{cwd:S,runId:k}));return await wf({...r,runId:k,cwd:ee,signal:n,fix:i,relayAllow:D,mcpSecretEnv:a},i=>Df(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:O,signal:n}))}finally{await d?.release()}},i)}async function Df({runId:e,runDir:t,cwd:n,bridge:r},{kernel:i,registry:a,loaded:o,gateChoices:s,file:c,source:l,sourceDigest:u,context:d,options:f,prior:p,mcpPolicy:m,getHub:h,seatSource:g,signal:_}){let{superviseGraphPursuit:v,readSettleRecord:y}=await import(`@tangle-network/agent-runtime/durable`),b=await i.recordStoredGraphRun(a,o.graph),x=p??{version:1,runId:e,cwd:n,file:c,graphDigest:b.digest,sourceDigest:u,source:l,params:o.params,...d.trigger?{trigger:d.trigger}:{},...Object.keys(s).length?{gateChoices:s}:{},startedAt:new Date().toISOString(),...f.seat===void 0?{}:{seat:f.seat},mcpPolicy:m,...d.taskWorkspace&&{taskWorkspace:d.taskWorkspace}};p||await Bl(t,x);let S=p?await y(t):void 0;if(S&&S.tree.root!==e&&Z(`The settlement names another run`),S?.kind===`no-winner`&&Z(`The local run is terminal: ${S.reason}`),S)return{runId:e,graphDigest:b.digest,sourceDigest:u,...vl(S),replayed:!0};let C=i.graphFromStored(b,{trigger:x.trigger}),w=b.nodes.some(e=>e.profile.connections?.length),T=w?await h():void 0;if(w&&!T)throw new W(`AUTH_REQUIRED`,`Hub authentication is required`,`No Tangle credential is configured for this local graph`,`tangle auth login`);let E=await r(T),D=i.createPrivateCasArtifactPort(M(t,`artifacts`),e),O=sl(o.params.knowledge,t,D,_),k=g?eu(E,g,_):void 0,ee=x.startedAt;V(`Run ${e} · ${he(c)} · ${n}`);let te=await Of(t);V(`Viewer ${te.url}`);let ne=new AbortController,re=await v(C,{pursuitId:b.digest,runDir:t,runId:e,backend:E,checkArtifacts:D,...O?{resolveSupervisorTools:O}:{},...C.entry===void 0?{driverBackend:E}:{},...b.gates?.length?{decideGate:Yc(x.gateChoices??{},{json:f.json,signal:AbortSignal.any([_,ne.signal])})}:{},resume:!!p,signal:_,...x.trigger?{trigger:x.trigger}:{},...k?{selectSeat:k,coordination:{authentication:!0}}:{},profileSecurity:je(x.mcpPolicy,w)}).finally(async()=>{ne.abort(),await te.close()}),A={runId:e,graphDigest:b.digest,sourceDigest:u,...vl(re.result.result)},ie=re.result.result,{tokens:ae,tokensKnown:oe,iterations:se,ms:ce}=ie.spentTotal;if(await i.recordStoredGraphRun(a,b,{graphDigest:b.digest,evidence:[{kind:`authored-graph`,url:`urn:sha256:${b.digest}`},{kind:`authored-yaml`,url:`urn:sha256:${u}`}],taskDigest:i.taskShapeDigest({graph:he(c),params:o.params,trigger:x.trigger??null,taskWorkspace:x.taskWorkspace?Ol(x.taskWorkspace):null}),startedAt:ee,finishedAt:new Date().toISOString(),outcome:ie.kind===`no-winner`?{kind:`no-winner`,reason:ie.reason}:{kind:`delivered`,summary:A.text},cost:{iterations:se,ms:ce,...oe===!1?{}:{tokens:ae.input+ae.output},...A.costUsd===null?{}:{usd:A.costUsd}},traversals:re.result.ledger.length,exhaustedEdges:re.result.exhaustedEdges,source:{kind:`tangle-cli-graph`,id:e}}),ie.kind===`no-winner`)throw Object.assign(new W(`GRAPH_RUN_FAILED`,`Graph '${he(c)}' finished without a result`,re.result.stopped?.reason||re.result.ledger.filter(e=>e.outcome===`unpropagated`&&e.reason).pop()?.reason||ie.reason,`tangle graph inspect ${e}`),{runId:e,runtimeFailures:[...ie.tree.nodes.filter(e=>e.failure).map(e=>({node:e.label,failure:e.failure})),...ie.reason===`driver-failed`&&ie.error.failure?[{node:`root`,failure:ie.error.failure}]:[]]});return A}async function Of(e){let{serveTopWeb:t}=await import(`@tangle-network/agent-runtime/tui`),{readGraphSessions:n}=await import(`./graph-native-Cl6SphYB.mjs`);return t({roots:[e],assets:M(xf,`dist`,`graph-viewer`),readSessions:n})}async function kf(e,t){if(t.artifacts||t.artifact)return cu(e,t);if(e.startsWith(`wfrun_`)){let n=await Q(t),r=await n.workflows.getRun(e);if(t.json)return z(r);for(let e of r.runtime?.checks??[])V(`${e.node} ${e.status} · exit ${e.exitCode??`none`} · pass ${e.pass??`none`}\n${e.reason??e.tail}`);return V(`Run ${e} · ${n.baseUrl}/app/workflows/${encodeURIComponent(r.workflowId)}/runs/${encodeURIComponent(e)}`)}let n=M(N(),`.tangle`,`runs`,e);if(!/^[a-f0-9-]{36}$/i.test(e)||!ue(n))throw new W(`RUN_NOT_FOUND`,`Run '${e}' was not found`,`Use a run ID printed by tangle graph run`,`tangle graph inspect --help`);let{loadTopSnapshot:r}=await import(`@tangle-network/agent-runtime/tui`);if(t.json)return z(await r(process.cwd(),{runDir:n}));V(`Run ${e} · ${(await Of(n)).url}`)}function Af(){let e=new S(`graph`).description(`Build and run portable agent graphs`);return Fd(e),Fl(e),xu(e,Cf),wu(e,Cf),su(e),Ed(e),Wd(e,Cf,xf),e.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(kf),e.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(ll()).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(e,t)=>{let n={...t,mcpPolicy:t.mcpPolicy===void 0?void 0:await dl(t.mcpPolicy)},r=await Ef(e,n);n.json||n.dryRun?z(r):`status`in r?(V(`${r.status} · ${r.runId}`),r.text&&console.log(r.text)):`viewerUrl`in r&&V(`Run ${r.runId} · ${r.viewerUrl}`)}),e}function jf(){let e=new S(`intelligence`).description(`Create and inspect trace intelligence reports`);return e.command(`connect [agent]`).alias(`connect-agent`).description(`Connect local agent CLIs to Tangle Intelligence`).option(`--endpoint <url>`,`OTLP endpoint base`,Ga).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(e,t)=>{let n=e??`local`;Xa(n);let r=Nf(t.apiKey),i=await to({selection:n,workspace:t.workspace,apiKey:r,endpoint:t.endpoint,serviceName:t.serviceName??Qa(t.workspace),environment:t.environment,smoke:t.smoke,dryRun:!!t.dryRun,hookCommand:t.hookCommand}),a={configPath:i.configPath,agents:i.agents,nativeAgents:i.nativeAgents,manual:i.manual,written:i.written,smokeTraceId:i.smokeTraceId};if(t.json){z(a);return}U({Config:i.configPath,Agents:i.agents.join(`, `),"Native Hooks":i.nativeAgents.join(`, `)||void 0,"Manual Setup":i.manual.length?i.manual.map(e=>`${e.label}: ${e.reason}`).join(` `):void 0,Files:i.written.join(`, `),"Smoke Trace":i.smokeTraceId})}),e.command(`doctor`).description(`Check whether your agent traces carry CONTENT or are metadata-only`).option(`--endpoint <url>`,`OTLP endpoint base`,Ga).action(async e=>{let t=eo(),n=await oo({endpoint:e.endpoint===`https://intelligence.tangle.tools/v1/otlp`?t?.endpoint??`https://intelligence.tangle.tools/v1/otlp`:e.endpoint,apiKey:Nf(e.apiKey??t?.apiKey)});e.json?z(n):Mf(n),n.contentSeen||(process.exitCode=1)}),e.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 e=>{try{let t=Pf(e.agent),n=eo(),r={agent:t,event:e.event,endpoint:e.endpoint??n?.endpoint??`https://intelligence.tangle.tools/v1/otlp`,apiKey:Nf(e.apiKey??n?.apiKey),serviceName:e.serviceName??n?.serviceName??Qa(process.cwd()),environment:e.environment??n?.environment??`local`,sessionId:e.sessionId,payload:e.payload===void 0?await If():Ff(e.payload)};if(e.dryRun){let n=ro(r);if(e.json){z(n);return}U({Trace:n.traceId,Agent:t,Event:e.event});return}let i=await io(r);if(e.json){z({traceId:i});return}U({Trace:i,Agent:t,Event:e.event})}catch(t){if(e.nonBlocking){let n=t instanceof Error?t.message:String(t);e.json?z({ok:!1,error:n}):console.error(`Tangle Intelligence hook skipped: ${n}`);return}G(t)}}),e.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 Lf({type:`sandbox`,id:e},t)}),e.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 Lf({type:`fleet`,id:e},t)}),e.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 Lf({type:zf(e.subjectType),id:e.subjectId},e)}),e.command(`get <job-id>`).description(`Get an intelligence report`).action(async(e,t)=>{let{client:n}=J(t),r=t.json?null:H(`Fetching intelligence report...`);r?.start();let i=await n.intelligence.getReport(e);if(r?.stop(),t.json){z(i);return}Rf(i)}),e.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 e=>{let{client:t}=J(e),n=e.json?null:H(`Fetching intelligence reports...`);n?.start();let r=await t.intelligence.listReports({subjectType:e.subjectType===void 0?void 0:zf(e.subjectType),subjectId:e.subjectId,limit:e.limit===void 0?void 0:Hf(e.limit)});if(n?.stop(),e.json){z(r);return}R(r.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}])}),e}function Mf(e){U({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 t=Object.entries(e.byAgent);t.length>0&&(console.log(),R(t.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 Nf(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 Pf(e){if(Za(e))return e;throw Error(`agent must be a known Tangle Intelligence agent surface`)}function Ff(e){try{return JSON.parse(e)}catch(e){throw Error(`--payload must be JSON: ${e instanceof Error?e.message:String(e)}`)}}async function If(){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 Lf(e,t){let n=Bf(t.mode),r=Uf(t.metadata),i=t.maxUsd===void 0?void 0:Vf(t.maxUsd);if(n===`agentic`&&i===void 0)throw Error(`Agentic intelligence reports require --max-usd`);let{client:a}=J(t),o=t.json?null:H(`Creating intelligence report...`);o?.start();let s=await a.intelligence.createReport({subject:e,mode:n,...i===void 0?{}:{budget:{billTo:`customer`,maxUsd:i}},...r===void 0?{}:{metadata:r}});if(o?.stop(),t.json){z(s);return}Rf(s)}function Rf(e){U({Job:e.jobId,Subject:`${e.subject.type}:${e.subject.id}`,Mode:e.mode,Status:e.status,"Billed To":e.billing.billedTo,Cost:`$${e.billing.costUsd.toFixed(2)}`,Budget:e.billing.budgetMaxUsd===void 0?void 0:`$${e.billing.budgetMaxUsd.toFixed(2)}`,Updated:e.updatedAt}),e.result!==null&&(console.log(),z(e.result))}function zf(e){if(e===`sandbox`||e===`fleet`)return e;throw Error(`subject type must be sandbox or fleet`)}function Bf(e){if(e===`deterministic`||e===`agentic`)return e;throw Error(`mode must be deterministic or agentic`)}function Vf(e){let t=Number(e);if(!Number.isFinite(t)||t<0)throw Error(`--max-usd must be a non-negative number`);return t}function Hf(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}function Uf(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 Wf=[`router`,`sandbox`,`blueprint-agent`,`evals`,`agent-builder`];async function Gf(e,t){let n=await Ci({...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 Kf(e,t,n={}){let r=new Headers(n.headers);n.body&&!r.has(`content-type`)&&r.set(`content-type`,`application/json`);let i=await wi(e,t,{...n,headers:r});if(n.expected!==void 0&&i.status!==n.expected)throw Error(await qf(i,t));return i}async function qf(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 Jf=[`ID`,`Prefix`,`Name`,`Product`,`Created`,`Last used`,`Expires`];function Yf(e){return[e.id,e.keyPrefix??``,e.name,e.product??`all`,e.createdAt,e.lastUsedAt??`—`,e.expiresAt??`—`]}function Xf(){let e=new S(`keys`).description(`Manage sk-tan-* API keys on id.tangle.tools`);return e.command(`list`).description(`List your active API keys`).option(`--platform-url <url>`,`Override the platform URL (id.tangle.tools)`).action(async e=>{let t=await Gf(e,!1),n=t.baseUrl,r=await(await Kf(t,`${n}/v1/keys`,{expected:200})).json();if(e.json){z(r);return}jn(Jf,r.data.map(Yf))}),e.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 (${Wf.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(e,t)=>{if(t.product!==void 0&&!Wf.includes(t.product))throw Error(`Invalid --product. Expected one of ${Wf.join(`, `)}`);let n=await Gf(t,!0),r=n.baseUrl,i=t.expiresInDays===void 0?void 0:new Date(Date.now()+Number.parseInt(t.expiresInDays,10)*24*60*60*1e3).toISOString(),a=H(`Creating API key...`);a.start();let o=await Kf(n,`${r}/v1/keys`,{method:`POST`,expected:201,body:JSON.stringify({name:e,product:t.product,budgetUsd:t.budgetUsd?Number.parseFloat(t.budgetUsd):void 0,rpmLimit:t.rpmLimit?Number.parseInt(t.rpmLimit,10):void 0,expiresAt:i})});a.stop();let s=await o.json();if(t.json){z(s);return}B(`API key created: ${s.data.prefix}…`),V(`Copy this key now — it will never be shown again:\n${s.data.key}`)}),e.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(e,t)=>{let n=await Gf(t,!0),r=n.baseUrl;if(!t.yes&&!await Bi(`Revoke key ${e}? Any service still using it will start to fail.`,`--yes`)){V(`Aborted.`);return}let i=await(await Kf(n,`${r}/v1/keys/${encodeURIComponent(e)}`,{method:`DELETE`,expected:200})).json();if(t.json){z(i);return}B(`Revoked ${e}`)}),e}function Zf(e){if(Pr().token)throw Error(`A line relay cannot manage numbers or attachments. Use your owner CLI outside the agent box.`);return q(K(e))}function Qf(e){if(!e.yes)throw Error(`Review the selected line and use --yes to authorize this change. Attaching enables metered agent work.`)}function $f(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 ep(e){return e().catch(G)}async function tp(e){let t=await $e(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 np(e){e.command(`providers`).description(`List provider transports supported by this Hub deployment`).action(e=>ep(async()=>{z(await Zf(e).lines.providers())})),e.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(e=>ep(async()=>{z(await Zf(e).lines.list({profileId:e.profileId,sandboxId:e.sandbox}))})),e.command(`get`).argument(`<line-id>`).description(`Inspect a line and its current attachment`).action((e,t)=>ep(async()=>{z(await Zf(t).lines.get(e))})),e.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((e,t)=>ep(async()=>{let n=$f(t.transport);if(n===`email`)throw Error(`Email uses an owned mailbox, not phone inventory`);if(n===`voice`)throw Error(`Voice numbers are listed by ph0ny; provide the owned number ID to lines connect`);if(n===`telegram`)throw Error(`Telegram uses an owned bot, not phone inventory`);z(await Zf(t).lines.numbers(e,n))})),e.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((e,t)=>ep(async()=>{Qf(t);let n=$f(t.transport);if(n!==`email`&&t.address)throw Error(`--address is email-only`);if((n===`email`||n===`telegram`)&&t.numberId)throw Error(`${n} does not take --number-id`);let r={connectionId:e,label:t.label,clientReference:t.reference},i;if(n===`email`)i={...r,transport:n,address:t.address};else if(n===`telegram`)i={...r,transport:n};else if(n===`imessage`)i={...r,transport:n,phoneNumberId:t.numberId};else{if(!t.numberId)throw Error(`${n} requires --number-id`);i={...r,transport:n,phoneNumberId:t.numberId}}z(await Zf(t).lines.fromConnection(i))})),e.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((e,t)=>ep(async()=>{Qf(t);let n=Zf(t),r;if(t.file){if(t.profileId||t.member||t.sandbox||t.instancePrefix||t.tools||t.turnsPerDay)throw Error(`Choose --file or quick-setup flags, not both`);r=await tp(t.file)}else{if(!t.profileId||!t.member)throw Error(`Provide --profile-id and --member, or --file`);if(t.sandbox&&t.instancePrefix)throw Error(`Choose --sandbox or --instance-prefix`);let e=t.tools??`chat`,n=Number(t.turnsPerDay??`30`);if(e!==`chat`&&e!==`act`)throw Error(`--tools must be chat or act`);if(!Number.isSafeInteger(n)||n<1||n>1e4)throw Error(`--turns-per-day must be 1–10000`);if(e===`act`&&t.sandbox)throw Error(`Acting tools require an isolated on-demand instance; omit --sandbox`);r={mode:`personal`,members:[{address:t.member,role:`owner`}],unknownSenders:`reject`,roles:{owner:{context:`own`,tools:e}},respond:{kind:`agent`,profileId:t.profileId,...e===`act`?{rolePolicy:{version:1,roles:{owner:{kind:`general`}},members:{}}}:{}},limits:{turnsPerMemberPerDay:n},...t.sandbox?{sandboxId:t.sandbox}:{instance:{keyPrefix:t.instancePrefix??`profile:${t.profileId}:`,create:{ownerContext:`isolated`,...e===`act`?{egressPolicy:{mode:`strict`,allowDomains:[new URL(Qr()).hostname],includeImplicitDomains:!1}}:{}}}}}}if(typeof r.sandboxId==`string`==(r.instance!==void 0))throw Error(`Attachment requires exactly one of sandboxId and instance`);let{sandboxId:i,instance:a,...o}=r,s;if(i){let t=await n.get(i);if(!t)throw Error(`Sandbox not found`);s=await t.lines.attach({...o,number:e})}else{if(!a)throw Error(`Attachment requires an instance`);s=await n.lines.attach({...o,number:e,instance:a})}z(s)}));for(let t of[`detach`,`release`])e.command(t).argument(`<line-id>`).description(t===`detach`?`Stop dispatch; preserve history and provider rental`:`Retire a detached Hub line; does not cancel provider rental`).option(`--yes`,`Authorize this change`).action((e,n)=>ep(async()=>{Qf(n),z({[t]:await Zf(n).lines[t](e)})}));e.command(`threads`).argument(`<line-id>`).description(`List this line's separate participant threads`).action((e,t)=>ep(async()=>{z(await Zf(t).lines.threads(e).list())})),e.command(`messages`).argument(`<line-id>`).argument(`<thread-id>`).description(`Read one authorized participant thread`).action((e,t,n)=>ep(async()=>{z(await Zf(n).lines.threads(e).messages(t))}))}async function rp(e){let{token:t,baseUrl:n}=Pr();if(t===void 0)return Oi(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 Oe({baseUrl:n,authHeaders:()=>({Authorization:`Bearer ${t}`})})}async function ip(e,t){if(t)return t;if(!Pr().token)throw Error(`Provide --line <line-id>`);return(await e.lines.context()).line.id}function ap(e){return e().catch(G)}function op(){return new S(`context`).description(`Show live line identity, members, consent, reminders and quotas`).action(e=>ap(async()=>{z(await(await rp(e)).lines.context())}))}function sp(){let e=new S(`lines`).description(`Connect, manage, message and schedule on a Hub line`);return e.command(`members`).description(`List names, roles and consent on this line`).option(`--line <line-id>`,`Line ID; inferred in a line box`).action(e=>ap(async()=>{let t=await rp(e);z(await t.lines.members.list(await ip(t,e.line)))})),e.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((e,t,n)=>ap(async()=>{let r=await rp(n),i=await ip(r,n.line);if(!Pr().token){if(n.onBehalfOf)throw Error(`--on-behalf-of is only available inside a line box`);if(!n.idempotencyKey)throw Error(`Owner sends require --idempotency-key so a retry keeps the same message`);if(!(await r.lines.members.list(i)).some(t=>t.id===e))throw Error(`Owner sends require an exact member ID from tangle lines members`);z(await r.lines.send(i,{memberId:e,text:t,idempotencyKey:n.idempotencyKey,...n.notBefore?{notBefore:n.notBefore}:{}}));return}z(await r.lines.send(i,{toMember:e,text:t,...n.onBehalfOf?{onBehalfOf:n.onBehalfOf}:{},...n.notBefore?{notBefore:n.notBefore}:{},...n.idempotencyKey?{idempotencyKey:n.idempotencyKey}:{}}))})),e.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((e,t)=>ap(async()=>{if(!t.at)throw Error(`--at is required`);let n=await rp(t),r=t.idempotencyKey??w(`sha256`).update(JSON.stringify([e,t.at])).digest(`hex`).slice(0,32);z(await n.lines.remind(await ip(n,t.line),{text:e,notBefore:t.at,idempotencyKey:r}))})),np(e),e}function cp(){let e=new S(`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=K({apiKey:t.apiKey,baseUrl:t.baseUrl}),r=await Y(q(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 Kt(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 lp(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=Tr(),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??Wr():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=K({apiKey:a,baseUrl:r}),s=q(o);return t.self?Yt(s):Y(s,o,e)}async function up(e,t,n){let r=H(e);t||r.start();try{return await n()}finally{r.stop()}}function dp(e){return e}function fp(){let e=new S(`preview`).description(`Manage sandbox preview links`);return dp(e.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(e,t)=>{let n=await lp(e,t),r=await up(`Starting managed preview...`,t.json,()=>qt(n,{cwd:t.cwd,sessionId:t.session,name:t.name}));t.json?z(r):(B(`Preview ready: ${r.url}`),console.log(`Preview ID: ${r.previewId}`))}),dp(e.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(e,t)=>{let n=await lp(e,t),r=await up(`Fetching preview links...`,t.json,()=>n.previewLinks.list());t.json?z(r):r.length===0?console.log(`No preview links found`):jn([`App`,`Preview ID`,`Port`,`URL`,`Status`],r.map(e=>[pp(e.metadata),e.previewId.slice(0,12),String(e.port),e.url,e.status]))}),dp(e.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(e,t)=>{if(!t.port||!/^\d+$/.test(t.port))throw Error(`An integer service port is required`);let n=await lp(e,t),r=await up(`Publishing service...`,t.json,()=>Jt(n,{port:Number(t.port),name:t.name}));t.json?z(r):B(`Preview ready: ${r.url}`)}),dp(e.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(e,t,n)=>{if(!/^\d+$/.test(t)||Number(t)<1||Number(t)>65535)throw Error(`Port must be an integer between 1 and 65535`);let r=await lp(e,n),i=await up(`Creating preview for port ${t}...`,n.json,()=>r.previewLinks.create(Number(t)));n.json?z(i):(B(`Preview created: ${i.url}`),console.log(`Preview ID: ${i.previewId}`))}),dp(e.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(e,t,n)=>{let r=await lp(e,n);await up(`Removing preview...`,n.json,()=>r.previewLinks.remove(t)),n.json?z({success:!0,previewId:t}):B(`Preview removed: ${t}`)}),e}function pp(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 mp(){let e=new S(`process`).description(`Manage processes in a sandbox`);return e.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(e,t,n)=>{let{context:r,client:i}=J(n),a=Us(n.env??[],`--env`,`env`),o=H(`Spawning: ${t}`);n.json||o.start();let s=await Y(i,r,e);if(s=await X(s),n.blocking){let e=await s.exec(t,{cwd:n.cwd,env:Object.keys(a).length>0?a:void 0,timeoutMs:n.timeout?Number.parseInt(n.timeout,10):void 0});o.stop(),n.json?z(e):(e.stdout&&globalThis.process.stdout.write(e.stdout),e.stderr&&globalThis.process.stderr.write(e.stderr),e.exitCode!==0&&globalThis.process.exit(e.exitCode))}else{let r=await s.process.spawn(t,{cwd:n.cwd,env:Object.keys(a).length>0?a:void 0,timeoutMs:n.timeout?Number.parseInt(n.timeout,10):void 0});o.stop(),n.json?z({pid:r.pid,command:r.command}):(console.log(`Process started with PID: ${r.pid}`),console.log(`Use 'tangle process logs ${e} ${r.pid}' to view output`))}}),e.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(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching processes...`);t.json||i.start();let a=await Y(r,n,e);a=await X(a);let o=await a.process.list();t.running&&(o=o.filter(e=>e.running)),i.stop(),t.json?z(o):o.length===0?console.log(`No processes found`):jn([`PID`,`Command`,`Status`,`Exit Code`,`Started`],o.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()]))}),e.command(`get`).description(`Get detailed info about a process`).argument(`<id-or-name>`,`Sandbox ID or name`).argument(`<pid>`,`Process ID`).action(async(e,t,n)=>{let{context:r,client:i}=J(n),a=H(`Fetching process info...`);n.json||a.start();let o=await Y(i,r,e);o=await X(o);let s=await o.process.get(Number.parseInt(t,10));if(a.stop(),!s){console.error(`Process ${t} not found`),globalThis.process.exit(1);return}let c=await s.status();n.json?z(c):(console.log(`PID: ${c.pid}`),console.log(`Command: ${c.command}`),console.log(`CWD: ${c.cwd||`(default)`}`),console.log(`Status: ${c.running?`running`:`exited`}`),console.log(`Exit Code: ${c.exitCode}`),c.exitSignal&&console.log(`Signal: ${c.exitSignal}`),console.log(`Started: ${c.startedAt.toLocaleString()}`),c.exitedAt&&console.log(`Exited: ${c.exitedAt.toLocaleString()}`))}),e.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(e,t,n)=>{let{context:r,client:i}=J(n),a=H(`Sending ${n.signal} to PID ${t}...`);n.json||a.start();let o=await Y(i,r,e);o=await X(o);let s=await o.process.get(Number.parseInt(t,10));if(!s){a.stop(),console.error(`Process ${t} not found`),globalThis.process.exit(1);return}n.tree?await s.kill(n.signal,{tree:!0}):await s.kill(n.signal),a.stop(),n.json?z({pid:Number.parseInt(t,10),signal:n.signal,...n.tree===!0?{tree:!0}:{},killed:!0}):console.log(n.tree?`Sent ${n.signal} to process tree ${t}`:`Sent ${n.signal} to process ${t}`)}),e.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}=J(n),a=await Y(i,r,e);a=await X(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))}),e}const hp=[`python`,`node`,`typescript`,`bash`];function gp(e){switch(_e(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 _p(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 F(be(e),`utf8`)}async function vp(e,t,n=_p){let r=t?hp.find(e=>e===t)??(()=>{throw Error(`unknown --lang ${t}: must be one of ${hp.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=gp(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 yp(e){return M(Ce(),`tangle-run-images`,e)}function bp(){return new S(`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: ${hp.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(e,t,n)=>{let{language:r,source:i}=await vp(t,n.lang),{context:a,client:o}=J(n),s=await Y(o,a,e);s=await X(s);let c=H(`Running ${r} (${i.length}b)…`);n.json||c.start();let l=await s.runCode(r,i,{sessionId:n.session,timeoutMs:Number.parseInt(n.timeout,10)});if(c.stop(),n.json){z(l),l.exitCode!==0&&process.exit(l.exitCode);return}l.stdout&&process.stdout.write(l.stdout),l.stderr&&process.stderr.write(l.stderr);let u=0;for(let t of l.results)if(t.type===`image`)if(n.saveImages!==!1){let r=typeof n.saveImages==`string`?n.saveImages:yp(e);de(r,{recursive:!0});let i=`${r}/${Date.now()}-${u}.${t.format}`;me(i,Buffer.from(t.data,`base64`)),process.stderr.write(b.green(`✓ image → ${i}\n`)),u++}else process.stderr.write(b.gray(`[image: ${t.format}, ${t.data.length}b base64]\n`));else if(t.type===`dataframe`){let e=t.columns.map(e=>`${e.name}:${e.dtype}`).join(` | `);process.stderr.write(b.gray(`[dataframe ${t.rows.length}×${t.columns.length}${t.truncated?` (truncated)`:``}]\n`)),process.stderr.write(`${e}\n`);for(let e of t.rows.slice(0,20))process.stderr.write(`${e.map(e=>String(e)).join(` | `)}\n`);t.rows.length>20&&process.stderr.write(b.gray(`… ${t.rows.length-20} more rows\n`))}else t.type===`json`?(process.stderr.write(b.gray(`[json] `)),process.stderr.write(`${JSON.stringify(t.value,null,2)}\n`)):t.type===`html`?process.stderr.write(b.gray(`[html ${t.value.length}b]\n`)):t.type===`error`?(process.stderr.write(b.red(`✗ ${t.name}: ${t.message}\n`)),t.traceback&&process.stderr.write(`${t.traceback}\n`)):t.type===`text`&&process.stderr.write(`${t.value}\n`);l.error&&(process.stderr.write(b.red(`\n✗ ${l.error.name}: ${l.error.message}\n`)),l.error.traceback&&process.stderr.write(`${l.error.traceback}\n`)),l.exitCode!==0&&process.exit(l.exitCode)})}function xp(e){e.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(e,t)=>{let{context:n,client:r}=J(t),i=H(`Updating network configuration...`);i.start();let a=await Y(r,n,e);i.stop();let o=await a.network.getConfig();t.json?z(o):(V(`Network Configuration:`),o.ports&&o.ports.length>0?V(` Exposed Ports: ${o.ports.join(`, `)}`):V(` No exposed ports`))}),e.command(`expose <id-or-name>`).description(`Expose a port and get a public URL`).option(`-p, --port <port>`,`Port to expose`,`8000`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=Number.parseInt(t.port,10);if(Number.isNaN(i)||i<1||i>65535)throw Error(`Port must be a number between 1 and 65535`);let a=H(`Exposing port ${i}...`);a.start();let o=await(await Y(r,n,e)).network.exposePort(i);a.stop(),t.json?z({port:i,url:o}):(B(`Port ${i} exposed.`),V(` URL: ${o}`))}),e.command(`urls <id-or-name>`).description(`List exposed port URLs for a sandbox`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching exposed URLs...`);i.start();let a=await(await Y(r,n,e)).network.listUrls();if(i.stop(),t.json)z(a);else{let e=Object.entries(a);if(e.length===0)V(`No ports exposed.`);else{V(`Exposed Ports:`);for(let[t,n]of e)V(` ${t}: ${n}`)}}})}function Sp(){let e=new S(`sandbox`).description(`Manage sandboxes`);return Cc(e),Sc(e),fc(e),xp(e),e}function Cp(){return new S(`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}=J(n),a=H(`Searching...`);n.json||a.start();let o=await Y(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 wp(){let e=new S(`secret`).description(`Manage secrets`);return e.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(e,t,n)=>{let r=await J(n).client.secrets.create(e,await Tp({value:t,valueStdin:n.valueStdin,prompt:`Enter value for secret '${e}': `}));n.json?z(r):(B(`Secret created: ${r.name}`),V(`Use --secret ${r.name} when creating a sandbox to select it for delivery.`))}),e.command(`list`).description(`List all secrets`).action(async e=>{let t=await J(e).client.secrets.list();e.json?z(t):t.length===0?(V(`No secrets found.`),V(`Use 'tangle secret create <name> [value]' to create one.`)):jn([`Name`,`Created At`,`Updated At`],t.map(e=>[e.name,e.createdAt.toLocaleString(),e.updatedAt.toLocaleString()]))}),e.command(`delete`).description(`Delete a secret`).argument(`<name>`,`Secret name`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=J(t).client;if(!t.force&&!await Bi(`Are you sure you want to delete secret '${e}'? This cannot be undone. (y/N) `,`--force`)){V(`Cancelled.`);return}await n.secrets.delete(e),t.json?z({success:!0,deleted:e}):B(`Secret deleted: ${e}`)}),e}async function Tp(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 Hi():await zi(e.prompt));if(!t.length)throw Error(e.valueStdin?`Secret value from stdin cannot be empty`:`Secret value cannot be empty`);return t}function Ep(){let e=new S(`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=j.dirname(Wt(import.meta.url)),t=j.resolve(e,`..`,`SKILL.md`);console.log(t)}),e}function Dp(){let e=new S(`snapshot`).description(`Manage snapshots`);return e.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(e,t)=>{let{context:n,client:r}=J(t),i=H(`Creating snapshot...`);i.start();let a=await Y(r,n,e);if(t.wait===!1){let e=await a.snapshot({tags:t.tags,wait:!1});i.stop(),pc(e.info,!!t.json);return}let o=await a.snapshot({tags:t.tags});i.stop(),t.json?z(o):(B(`Snapshot created: ${o.snapshotId}`),console.log(`Size: ${Op(o.sizeBytes??0)}`))}),e.command(`list <sandbox-id-or-name>`).description(`List snapshots for a sandbox`).action(async(e,t)=>{let{context:n,client:r}=J(t),i=H(`Fetching snapshots...`);i.start();let a=await(await Y(r,n,e)).listSnapshots();i.stop(),t.json?z(a):R(a.map(e=>({...e,size:Op(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}])}),e.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(e,t,n)=>{let{client:r}=J(n),i=H(`Restoring from snapshot...`);i.start();let a=await r.create({fromSnapshot:t,fromSandboxId:e,...n.billingOwner?{billingOwnerId:n.billingOwner}:{}});await a.waitFor(`running`,{timeoutMs:12e4}),i.stop(),n.json?z({sandboxId:a.id,restoredFrom:t,status:a.status}):(B(`New sandbox created: ${a.id}`),console.log(`Source snapshot: ${t}`))}),e.command(`revert <sandbox-id-or-name> <snapshot-id>`).description(`Revert an existing sandbox to a snapshot`).action(async(e,t,n)=>{let{context:r,client:i}=J(n),a=H(`Reverting sandbox to snapshot...`);a.start();let o=await Y(i,r,e),s=await o.revertToSnapshot(t);await o.refresh(),a.stop(),n.json?z({sandboxId:o.id,snapshotId:s.snapshotId,status:o.status}):(B(`Sandbox reverted: ${o.id}`),console.log(`Source snapshot: ${s.snapshotId}`))}),e.command(`delete <sandbox-id-or-name> <snapshot-id>`).description(`Delete a sandbox snapshot`).action(async(e,t,n)=>{let{context:r,client:i}=J(n),a=H(`Deleting snapshot...`);a.start();let o=await(await Y(i,r,e)).deleteSnapshot(t);a.stop(),n.json?z({success:!0,sandboxId:e,snapshotId:t,outcome:o.outcome}):o.outcome===`already_absent`?B(`Snapshot already gone: ${t}`):B(`Snapshot deleted: ${t}`)}),e}function Op(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 kp=`solve:device:secp256k1`,Ap=/^0x[0-9a-f]{64}$/i;function jp(e){return e&&Ap.test(e)?e:void 0}function Mp(){let e=rr(kp),t=jp(e.value);if(!(!t||e.source===`none`))return{account:Zt(t),source:e.source}}function Np(){let e=Mp();if(e)return e;let t=Xt(),n=ir(kp,t);return{account:Zt(t),source:n}}function Pp(e){let t=jp(rr(kp).value);if(!t||Zt(t).address!==e.account.address)throw Error(`The local Solve device key changed; it was not retired`);let n=`${kp}:retired:${e.account.address.toLowerCase()}`;if(ir(n,t),rr(n).value!==t)throw Error(`The revoked device key could not be retired safely`);return or(kp),n}function Fp(e){let t=e.create?Np():Mp();if(!t)throw Error("No Solve device signer found. Run `tangle solve account --create`");e.json?z({address:t.account.address,source:t.source}):U({Address:t.account.address,Source:t.source})}const Ip=/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/i;function Lp(e){return[...e].some(e=>{let t=e.charCodeAt(0);return t<32||t===127})}function Rp(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw Error(`${t} must be an object`);return e}function zp(e,t,n=2048){if(typeof e!=`string`||!e.trim()||e.length>n)throw Error(`${t} is missing or invalid`);if(Lp(e))throw Error(`${t} contains control characters`);return e.trim()}function Bp(e,t){let n=zp(e,t,64).toLowerCase();if(!Ip.test(n))throw Error(`${t} must be a 40 or 64 character Git revision`);return n}function Vp(e,t,n=!1){let r=typeof e==`number`&&Number.isSafeInteger(e)?String(e):zp(e,t,80);if(!/^\d+$/.test(r)||!n&&r===`0`)throw Error(`${t} must be an unsigned integer`);return BigInt(r).toString()}function Hp(e,t){let n=zp(e,t,2048),r=new URL(n);if(r.protocol!==`https:`&&!(r.protocol===`http:`&&(r.hostname===`localhost`||r.hostname===`127.0.0.1`)))throw Error(`${t} must use HTTPS outside local development`);return n.replace(/\/$/,``)}function Up(e,t){let n=Hp(e,t).replace(/\.git$/,``),r=new URL(n),i=r.pathname.split(`/`).filter(Boolean);if(r.hostname!==`github.com`||r.username||r.password||r.search||r.hash||i.length!==2)throw Error(`${t} must be an HTTPS GitHub repository URL`);return`https://github.com/${i.join(`/`)}`}function Wp(e,t){let n=zp(e,t,42);if(!on(n,{strict:!1}))throw Error(`${t} must be an EVM address`);return rn(n)}function Gp(e,t){let n=Vp(e,t),r=Number(n);if(!Number.isSafeInteger(r)||r<=0)throw Error(`${t} is out of range`);return r}function Kp(...e){for(let t of e)if(typeof t==`string`&&t.trim())return t.trim()}function qp(e){let t=e.trim().replace(/\.git$/,``);return t.startsWith(`git@github.com:`)?`https://github.com/${t.slice(15)}`:t.startsWith(`ssh://git@github.com/`)?`https://github.com/${t.slice(21)}`:t}function Jp(e){if(e===void 0)return;let t=zp(e,`pull request URL`,2048);if(!/^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+(?:\/[^\s]*)?$/i.test(t))throw Error(`pull request URL must point to a GitHub pull request`);return t}function Yp(e,t){if(!/^https:\/\/[^\s]+$/i.test(e)&&!/^\/(?!\/).*$/.test(e)&&!/^[a-z][a-z0-9+.-]*:[^\s]+$/i.test(e))throw Error(`${t} must be an HTTPS URL or an absolute repository path`);if(e.split(/[?#]/,1)[0].split(`/`).includes(`..`))throw Error(`${t} cannot contain parent-directory segments`);return e}function Xp(e){return Er(`solve`,e.profile)}function Zp(e){let t=Xp(e),n=Kr(void 0,t);if(!n)throw Error(`No Solve credential found for profile '${t}'. Run: tangle auth login --provider github --app solve`);return n}async function Qp(e){let t=$r(e.apiUrl),n=await fetch(`${t}${e.path}`,{method:e.method??`GET`,headers:{Accept:`application/json`,...e.body===void 0?{}:{"Content-Type":`application/json`},Authorization:`Bearer ${Zp(e)}`},...e.body===void 0?{}:{body:JSON.stringify(e.body)},signal:AbortSignal.timeout(3e4)}),r=await n.json().catch(()=>null);if(!n.ok||!r?.success||r.data===void 0){let e=r?.error?.message??`Solve API request failed with HTTP ${n.status}`;throw Error(r?.error?.code?`${r.error.code}: ${e}`:e)}return r.data}function $p(e){return Qp({path:`/v1/wallet/challenges`,method:`POST`,apiUrl:e.apiUrl,profile:e.profile,body:{deviceAddress:e.deviceAddress,...e.purpose?{purpose:e.purpose}:{}}})}function em(e){return Qp({path:`/v1/devices`,apiUrl:e.apiUrl,profile:e.profile})}function tm(e){return Qp({path:`/v1/devices/revoke`,method:`POST`,apiUrl:e.apiUrl,profile:e.profile,body:{deviceAddress:e.deviceAddress,...e.reason?{reason:e.reason}:{},...e.challengeId&&e.signature?{challengeId:e.challengeId,signature:e.signature}:{}}})}const nm={chainId:42431,rpcUrl:`https://rpc.moderato.tempo.xyz`,sponsorUrl:`https://drew-gtr-pro.taild10bfc.ts.net/solve-sponsor`,tangleAddress:`0xff137B9C879c47C28ce389e84501925438AB4cdA`,managerAddress:`0x5271732F893B622ac6793d6DBA5B2626CCa4EA14`,paymentAsset:`0x20C0000000000000000000000000000000000000`,blueprintId:15n,serviceId:9n,competitionId:1n,minStakeWei:0n};function rm(e,t){return e.toLowerCase()===t.toLowerCase()}function im(e){if(e.chainId!==nm.chainId)throw Error(`Solve submissions require Tempo Moderato (chain ${nm.chainId}); received ${e.chainId}`);if(e.rpcUrl!==nm.rpcUrl)throw Error(`Solve metadata RPC does not match the trusted deployment`);if(e.sponsorUrl!==nm.sponsorUrl)throw Error(`Solve metadata sponsor does not match the trusted deployment`);if(!rm(e.tangleAddress,nm.tangleAddress))throw Error(`Solve metadata Tangle contract does not match the trusted deployment`);if(!rm(e.managerAddress,nm.managerAddress))throw Error(`Solve metadata competition manager does not match the trusted deployment`);if(!rm(e.paymentAsset,nm.paymentAsset))throw Error(`Solve metadata payment asset does not match the trusted deployment`);if(e.blueprintId!==nm.blueprintId)throw Error(`Solve submissions require blueprint ${nm.blueprintId}; received ${e.blueprintId}`);if(e.serviceId!==nm.serviceId)throw Error(`Solve submissions require service ${nm.serviceId}; received ${e.serviceId}`);if(e.competitionId!==nm.competitionId)throw Error(`Solve submissions require competition ${nm.competitionId}; received ${e.competitionId}`);if(e.minStakeWei!==nm.minStakeWei)throw Error(`Solve submissions require zero stake for the trusted deployment`)}function am(e,t){let n=Rp(t.check??e.check,`competition.participation.check`),r=zp(n.command,`competition.participation.check.command`,512);if(!Array.isArray(n.args)||n.args.some(e=>typeof e!=`string`))throw Error(`competition.participation.check.args must be an array of strings`);let i=n.args.map(e=>zp(e,`competition checker argument`,2048)),a=Kp(n.result_file,n.resultFile),o=n.timeout_ms??n.timeoutMs,s=o===void 0?void 0:Gp(o,`competition checker timeout`);return{command:r,args:i,...a?{result_file:a}:{},...s?{timeout_ms:s}:{}}}function om(e){if(e.provenance===void 0)return;let t=Rp(e.provenance,`competition.participation.provenance`);if(t.mode!==`github_pull_request`)throw Error(`competition.participation.provenance.mode is unsupported`);if(t.required!==void 0&&typeof t.required!=`boolean`)throw Error(`competition.participation.provenance.required must be a boolean`);return{mode:`github_pull_request`,required:t.required===!0}}function sm(e){let t=Rp(e.chain??e.network??{},`competition.chain`),n=e.rewards&&typeof e.rewards==`object`&&!Array.isArray(e.rewards)?Rp(e.rewards,`competition.rewards`):{},r=n.minStake&&typeof n.minStake==`object`&&!Array.isArray(n.minStake)?Rp(n.minStake,`competition.rewards.minStake`).raw:void 0,i=Kp(t.minStakeWei,t.min_stake_wei,e.minStakeWei,e.min_stake_wei,r),a=t.chainId??t.chain_id??e.chainId??e.chain_id,o=Kp(t.chainName,t.chain_name,e.chainName,e.chain_name)??`Tempo`,s=Kp(t.nativeSymbol,t.native_symbol,e.nativeSymbol,e.native_symbol)??`TNT`,c=Kp(t.rpcUrl,t.rpc_url,e.rpcUrl,e.rpc_url,process.env.TANGLE_SOLVE_RPC_URL),l=Kp(t.sponsorUrl,t.sponsor_url,e.sponsorUrl,e.sponsor_url,process.env.TANGLE_SOLVE_SPONSOR_URL),u=Kp(t.tangleAddress,t.tangle_address,t.coreAddress,t.core_address,e.tangleAddress,e.tangle_address,e.coreAddress,e.core_address),d=Kp(t.managerAddress,t.manager_address,e.managerAddress,e.manager_address),f=Kp(t.paymentAsset,t.payment_asset,t.servicePaymentAsset,t.service_payment_asset,e.paymentAsset,e.payment_asset,e.servicePaymentAsset,e.service_payment_asset),p=Kp(t.blueprintId,t.blueprint_id,e.blueprintId,e.blueprint_id),m=Kp(t.serviceId,t.service_id,e.serviceId,e.service_id),h=Kp(t.competitionId,t.competition_id,e.competitionId,e.competition_id,e.id);if(!c||!l||!u||!d||!p||!m||!h||!i||a===void 0)throw Error(`Solve competition metadata must include complete Tempo chain configuration`);return{chainId:Gp(a,`chain.chainId`),chainName:o,nativeSymbol:s,rpcUrl:Hp(c,`chain.rpcUrl`),sponsorUrl:Hp(l,`chain.sponsorUrl`),tangleAddress:Wp(u,`chain.tangleAddress`),managerAddress:Wp(d,`chain.managerAddress`),paymentAsset:Wp(f??nm.paymentAsset,`chain.paymentAsset`),blueprintId:Vp(p,`chain.blueprintId`),serviceId:Vp(m,`chain.serviceId`),competitionId:Vp(h,`chain.competitionId`,!0),minStakeWei:Vp(i,`chain.minStakeWei`,!0)}}function cm(e){let t=Rp(e,`competition`),n=Rp(t.participation??t.task,`competition.task`),r={...t,participation:{...n,...n.repositoryRevision===void 0&&n.revision!==void 0?{repositoryRevision:n.revision}:{}}},i=r.participation,a=Up(Kp(r.repository,r.repo_url,i.repository)??``,`competition.repository`),o=Bp(Kp(r.repositoryRevision,r.repository_revision,i.revision,i.repositoryRevision,i.repository_revision),`competition.repositoryRevision`),s=zp(r.slug??r.id,`competition.slug`,128),c=zp(r.name??r.title??s,`competition.name`,256),l=am(r,i),u=om(i);return{version:1,slug:s,title:c,repository:a,taskRevision:o,checker:l,chain:sm(r),...u?{provenance:u}:{}}}function lm(e){return{chainId:e.chain.chainId,chainName:e.chain.chainName,nativeSymbol:e.chain.nativeSymbol,rpcUrl:e.chain.rpcUrl,sponsorUrl:e.chain.sponsorUrl,tangleAddress:e.chain.tangleAddress,managerAddress:e.chain.managerAddress,paymentAsset:e.chain.paymentAsset,blueprintId:BigInt(e.chain.blueprintId),serviceId:BigInt(e.chain.serviceId),competitionId:BigInt(e.chain.competitionId),minStakeWei:BigInt(e.chain.minStakeWei)}}async function um(e){let t=Rp(JSON.parse(await Je.readFile(j.join(e,`.tangle-solve.json`),`utf8`)),`.tangle-solve.json`);if(t.version!==1)throw Error(`.tangle-solve.json has an unsupported version`);let n=Rp(t.checker,`.tangle-solve.json.checker`),r=Rp(t.chain,`.tangle-solve.json.chain`);return cm({slug:t.slug,name:t.title,repository:t.repository,repositoryRevision:t.taskRevision,participation:{check:n,provenance:t.provenance},chain:r,competitionId:r.competitionId})}const dm=Ot(we),fm=`.tangle-solve-run.json`,pm=`.tangle-solve.json`,mm=`tangle.solve.manifestSha256`,hm=new Set([pm,fm]),gm=`upstream`;async function _m(e,t){let n=await dm(`git`,[`-C`,e,...t],{encoding:`utf8`,maxBuffer:1e6});return String(n.stdout).trim()}async function vm(e,t){let n=j.resolve(t??process.cwd()),r=await um(n);if(e&&e!==r.slug&&e!==r.chain.competitionId)throw Error(`This directory contains '${r.slug}', not '${e}'`);return{root:n,manifest:r}}async function ym(e){let t=j.join(e,pm),n;try{n=await Je.lstat(t)}catch{throw Error(`${pm} is missing`)}if(n.isSymbolicLink()||!n.isFile())throw Error(`${pm} must be a regular file`);return w(`sha256`).update(await Je.readFile(t)).digest(`hex`)}async function bm(e){let t=await ym(e);return await _m(e,[`config`,`--local`,`--replace-all`,mm,t]),t}async function xm(e){let t;try{t=await _m(e,[`config`,`--local`,`--get`,mm])}catch{throw Error(`The local Git metadata has no ${mm} pin; run tangle solve clone again`)}if(!/^[0-9a-f]{64}$/i.test(t))throw Error(`The local ${mm} pin is invalid`);if(await ym(e)!==t.toLowerCase())throw Error(`${pm} changed after clone; run tangle solve clone again`)}async function Sm(e,t){try{return await _m(e,[`ls-files`,`--error-unmatch`,`--`,t]),!0}catch{return!1}}async function Cm(e){await xm(e);for(let t of hm)if(await Sm(e,t))throw Error(`${t} must remain untracked and local to this Solve workspace`);let t=await dm(`git`,[`-C`,e,`status`,`--porcelain=v1`,`--untracked-files=all`,`--ignored=matching`],{encoding:`utf8`,maxBuffer:1e6});if(String(t.stdout).split(/\r?\n/).filter(Boolean).filter(e=>{let t=e.slice(0,2),n=e.slice(3);return!((t===`??`||t===`!!`)&&hm.has(n))}).length>0)throw Error(`Commit the candidate before running Solve. Only the local manifest and run record may remain uncommitted.`);return Bp(await _m(e,[`rev-parse`,`HEAD`]),`submission revision`)}async function wm(e,t,n,r={}){let i=await Tm(e,t,r);if(i)return{taskRepository:t.repository,taskRevision:t.taskRevision,submissionRepository:i,submissionRevision:n}}async function Tm(e,t,n={}){let r;try{r=qp(await _m(e,[`config`,`--get`,`remote.origin.pushurl`]))}catch{try{r=qp(await _m(e,[`config`,`--get`,`remote.origin.url`]))}catch{if(n.allowMissing)return;throw Error(`Add your GitHub fork as the 'origin' remote before submitting. The task repository is available as '${gm}'.`)}}let i=Up(r,`git remote.origin.url`);if(i.toLowerCase()===t.repository.toLowerCase()){if(n.allowMissing)return;throw Error(`The 'origin' remote is the task repository. Add your GitHub fork as 'origin'; keep the task repository as '${gm}' before submitting.`)}return i}function Em(e,t){return!e||!t?!1:e.taskRepository.toLowerCase()===t.taskRepository.toLowerCase()&&e.taskRevision.toLowerCase()===t.taskRevision.toLowerCase()&&e.submissionRepository.toLowerCase()===t.submissionRepository.toLowerCase()&&e.submissionRevision.toLowerCase()===t.submissionRevision.toLowerCase()}function Dm(e,t){return`${e}/commit/${t}`}function Om(e,t,n,r,i={}){let a=e.evidenceRefs.map(e=>Yp(e.trim(),`checker evidence reference`));if(n){if(!t){if(i.allowMissingSource)return{evidence:e.evidence,evidenceRefs:a};throw Error(`Provenance policy requires a submission source`)}let o=Jp(r);if(n.required&&(i.requirePullRequest??!0)&&!o)throw Error(`This competition requires a GitHub pull request`);a.push(Dm(t.taskRepository,t.taskRevision),Dm(t.submissionRepository,t.submissionRevision),...o?[o]:[])}return{evidence:e.evidence,evidenceRefs:[...new Set(a)]}}async function km(e,t){let n=`${e}.${process.pid}.tmp`;await Je.writeFile(n,`${JSON.stringify(t,null,2)}\n`,{mode:384}),await Je.rename(n,e)}async function Am(e){let t=JSON.parse(await Je.readFile(j.join(e,fm),`utf8`));if(t.version!==1||typeof t.competition!=`string`)throw Error(`${fm} has an unsupported format`);return t}async function jm(e){let t=Jp(e.pullRequest);if(!t)throw Error(`A pull request URL is required`);let n=new URL(t).pathname.split(`/`).filter(Boolean),r=await fetch(`https://api.github.com/repos/${n[0]}/${n[1]}/pulls/${n[3]}`,{headers:{Accept:`application/vnd.github+json`,"User-Agent":`tangle-solve-cli`},signal:AbortSignal.timeout(15e3)}),i=await r.json().catch(()=>null),a=e=>e.replace(/\/$/,``).toLowerCase();if(!r.ok||a(i?.base?.repo?.html_url??``)!==a(e.taskRepository)||i?.head?.sha?.toLowerCase()!==e.submissionRevision.toLowerCase()||a(i?.head?.repo?.html_url??``)!==a(e.submissionRepository))throw Error(`GitHub pull request must target the pinned task repository and contain the current committed submission`)}function Mm(e){return{...e.authorization?{authorization:e.authorization}:{},...e.stake?{stake:e.stake}:{},join:e.join,commit:e.commit,reveal:e.reveal,report:e.report,evaluation:e.evaluation}}const Nm=Ot(we);function Pm(){return`Task source is '${gm}'. Add your fork as 'origin', commit your candidate, push it, and open a pull request before submitting.`}async function Fm(e,t,n){try{let r=Rp(await Qp({path:`/v1/competitions/${encodeURIComponent(e)}`,apiUrl:n.apiUrl,profile:n.profile}),`competition response`),i=cm(r.competition??r),a=j.resolve(t??i.slug),o=H(`Cloning ${i.slug}…`);n.json||o.start();try{await Nm(`git`,[`clone`,`--no-tags`,`--origin`,gm,i.repository,a],{encoding:`utf8`,maxBuffer:1e6}),await _m(a,[`checkout`,`--detach`,i.taskRevision]);let e=await _m(a,[`rev-parse`,`HEAD`]);if(e.toLowerCase()!==i.taskRevision.toLowerCase())throw Error(`Pinned checkout resolved to ${e}, expected ${i.taskRevision}`);await km(j.join(a,`.tangle-solve.json`),i),await bm(a)}finally{o.stop()}n.json?z({competition:i,directory:a}):(B(`Cloned ${i.slug} at ${i.taskRevision.slice(0,12)}`),i.provenance&&V(Pm()),V(`Run the pinned checker with: cd ${a} && tangle solve run`))}catch(e){G(e)}}const Im=12e4,Lm=ln(`event JobSubmitted(uint64 indexed serviceId, uint64 indexed callId, uint8 jobIndex, address caller, bytes inputs)`),Rm=ln(`event JobCompleted(uint64 indexed serviceId, uint64 indexed callId)`),zm=ln(`event JobResultSubmitted(uint64 indexed serviceId, uint64 indexed callId, address indexed operator, bytes result)`),Bm=ln(`event AggregatedResultSubmitted(uint64 indexed serviceId, uint64 indexed callId, uint256 signerBitmap, bytes output)`),Vm=ln(`event EvaluationAccepted(uint64 indexed serviceId, uint64 indexed competitionId, address indexed researcher, bytes32 candidateId, bytes32 submissionRefHash, bytes32 evaluationDigest, bytes32 metricsHash, bytes32 evidenceRefsHash)`),Hm=[...cn([`function submitJob(uint64 serviceId, uint8 jobIndex, bytes inputs) payable returns (uint64 callId)`,`function getJobEventRate(uint64 blueprintId, uint8 jobIndex) view returns (uint256 rate)`,`function getServicePaymentAsset(uint64 serviceId) view returns (address)`,`function isPermittedCaller(uint64 serviceId, address caller) view returns (bool)`]),Lm,Rm,zm,Bm],Um=cn([`function authorizeSelf(uint64 serviceId)`,`function revokeSelf(uint64 serviceId)`,`function isDeviceRevoked(address device) view returns (bool)`,`function postStake(uint64 serviceId, uint64 competitionId) payable`,`function stakes(uint64 serviceId, uint64 competitionId, address researcher) view returns (uint256)`,`function pendingResults(uint64 serviceId, uint64 jobCallId) view returns (uint8 job, bytes32 outputHash, uint256 signerBitmap, bool exists, bool executed)`,`function executePendingResult(uint64 serviceId, uint64 jobCallId, bytes output)`,`function acceptedCandidates(uint64 serviceId, uint64 competitionId, address researcher, bytes32 candidateId) view returns (bool)`]),Wm=cn([`function allowance(address owner, address spender) view returns (uint256)`,`function approve(address spender, uint256 amount) returns (bool)`]),Gm=un(`uint64 competitionId, uint256 stakeWei`),Km=un(`uint64 competitionId, bytes32 commitment`),qm=un(`uint64 competitionId, bytes32 commitment, string artifactRef, bytes32 salt`),Jm=un(`string artifactRef, bytes32 salt`),Ym=un(`uint64 competitionId, bytes32 candidateId, string submissionRef, string evidenceJson, string evidenceRefsJson`),Xm=un(`string status, string detail`),Zm=/^0x[0-9a-f]{64}$/i;function Qm(e,t){if(e!==t)throw Error(`Tempo RPC returned chain ${e}; expected ${t}`)}function $m(e,t,n){return{...e,feePayer:!0,nonceKey:t,nonce:n}}function eh(e,t){if(e!==`success`)throw Error(`${t} transaction reverted`)}function th(e,t,n,r){if(!Zm.test(t))throw Error(`${n} transaction hash is invalid`);if(typeof e.transactionHash!=`string`||e.transactionHash.toLowerCase()!==t.toLowerCase())throw Error(`${n} receipt hash does not match the saved transaction`);if(eh(e.status??``,n),typeof e.from!=`string`||e.from.toLowerCase()!==r.from.toLowerCase())throw Error(`${n} receipt sender does not match the Solve device`);if(typeof e.to!=`string`||e.to.toLowerCase()!==r.to.toLowerCase())throw Error(`${n} receipt destination does not match the expected contract`)}function nh(e,t){return e>=t?[]:e>0n?[0n,t]:[t]}function rh(e,t,n=Date.now()){return n>=e+t}function ih(e,t){return e.filter(e=>e.args?.candidateId?.toLowerCase()===t.toLowerCase()).at(-1)?.transactionHash}function ah(e,t,n,r,i){for(let a of e.logs)if(a.address.toLowerCase()===t.tangleAddress.toLowerCase())try{let e=tn({abi:[Lm],eventName:`JobSubmitted`,data:a.data,topics:a.topics});if(e.args.serviceId===t.serviceId&&e.args.jobIndex===n&&e.args.caller.toLowerCase()===r.toLowerCase()&&(!i||e.args.inputs.toLowerCase()===i.toLowerCase()))return e.args.callId}catch{}throw Error(`Tangle did not emit job ${n} for ${r}`)}function oh(e,t,n,r){for(let i of e.logs)if(i.address.toLowerCase()===t.managerAddress.toLowerCase())try{let e=tn({abi:[Vm],eventName:`EvaluationAccepted`,data:i.data,topics:i.topics}).args;if(e.serviceId===t.serviceId&&e.competitionId===t.competitionId&&e.researcher.toLowerCase()===n.address.toLowerCase()&&e.candidateId.toLowerCase()===r.toLowerCase())return!0}catch{}return!1}function sh(e){if(e.chainId!==pn.id)throw Error(`Solve submissions require Tempo Moderato (chain ${pn.id}); received ${e.chainId}`);if(!e.sponsorUrl)throw Error(`Solve submissions require a Tempo sponsor relay URL; unsponsored writes are disabled`);return{...pn,name:e.chainName,nativeCurrency:{name:e.nativeSymbol,symbol:e.nativeSymbol,decimals:18},rpcUrls:{default:{http:[e.rpcUrl]}}}}async function ch(e,t){im(e);let n=sh(e),r=Qt({chain:n,transport:an(e.rpcUrl)});return Qm(await r.getChainId(),e.chainId),await lh({publicClient:r},e),{publicClient:r,walletClient:$t({account:t,chain:n,transport:hn(an(e.rpcUrl),an(e.sponsorUrl))}),account:t}}async function lh(e,t){let n=await e.publicClient.readContract({address:t.tangleAddress,abi:Hm,functionName:`getServicePaymentAsset`,args:[t.serviceId]});if(n.toLowerCase()!==t.paymentAsset.toLowerCase())throw Error(`Tempo service payment asset ${n} does not match the trusted Solve asset ${t.paymentAsset}`)}async function uh(e,t,n){let[r,i]=await Promise.all([e.publicClient.readContract({address:t.tangleAddress,abi:Hm,functionName:`getJobEventRate`,args:[t.blueprintId,n]}),e.publicClient.readContract({address:t.tangleAddress,abi:Hm,functionName:`getServicePaymentAsset`,args:[t.serviceId]})]);if(i.toLowerCase()!==t.paymentAsset.toLowerCase())throw Error(`Tempo job payment asset ${i} does not match the trusted Solve asset ${t.paymentAsset}`);return{asset:i,amount:r,value:i===`0x0000000000000000000000000000000000000000`?r:0n}}async function dh(e,t,n){return await e.publicClient.readContract({address:t,abi:Wm,functionName:`allowance`,args:[e.account.address,n.tangleAddress]})}async function fh(e,t,n,r,i,a){let o=Date.now();for(;!rh(o,a);){if((await e.publicClient.getLogs({address:t.tangleAddress,event:Rm,args:{serviceId:t.serviceId,callId:n},fromBlock:r,toBlock:`latest`})).length>0){let a=(await e.publicClient.getLogs({address:t.tangleAddress,event:zm,args:{serviceId:t.serviceId,callId:n},fromBlock:r,toBlock:`latest`}))[0]?.args.result;if(!a)throw Error(`Tangle job ${n} completed without a result`);let[o,s]=en(Xm,a);if(o!==i)throw Error(`Tangle job ${n} ${o}: ${s}`);return{status:o,detail:s}}await new Promise(e=>setTimeout(e,1e3))}throw Error(`Tangle job ${n} did not complete within 120 seconds`)}async function ph(e,t,n,r,i){let a=Date.now();for(;!rh(a,i);){let i=(await e.publicClient.getLogs({address:t.tangleAddress,event:Bm,args:{serviceId:t.serviceId,callId:n},fromBlock:r,toBlock:`latest`}))[0]?.args.output;if(i)return i;await new Promise(e=>setTimeout(e,1e3))}throw Error(`Tangle job ${n} did not produce an aggregate within 120 seconds`)}async function mh(e,t,n){return!!await e.publicClient.readContract({address:t.managerAddress,abi:Um,functionName:`acceptedCandidates`,args:[t.serviceId,t.competitionId,e.account.address,n]})}const hh=BigInt(sn(dn(`tangle.solve.v1`)));async function gh(e,t){let n=await mn.nonce.getNonce(e.publicClient,{account:e.account.address,nonceKey:hh});if(n>BigInt(2**53-1))throw Error(`The Solve transaction nonce exceeds the safe range`);return e.walletClient.writeContract($m(t,hh,Number(n)))}async function _h(e,t,n,r){if(!await e.publicClient.readContract({address:t.tangleAddress,abi:Hm,functionName:`isPermittedCaller`,args:[t.serviceId,e.account.address]}))try{let i=r??await gh(e,{address:t.managerAddress,abi:Um,functionName:`authorizeSelf`,args:[t.serviceId]});if(r||await n?.(`authorization`,i),th(await e.publicClient.waitForTransactionReceipt({hash:i}),i,`Authorization`,{from:e.account.address,to:t.managerAddress}),!await e.publicClient.readContract({address:t.tangleAddress,abi:Hm,functionName:`isPermittedCaller`,args:[t.serviceId,e.account.address]}))throw Error(`authorization transaction did not add the device`);return i}catch(e){let t=e instanceof Error?e.message:`unknown chain error`;throw Error(`The competition manager did not authorize this device. The deployed manager must expose authorizeSelf(uint64): ${t}`)}}async function vh(e,t){let n=await gh(e,{address:t.managerAddress,abi:Um,functionName:`revokeSelf`,args:[t.serviceId]});return th(await e.publicClient.waitForTransactionReceipt({hash:n}),n,`Revocation`,{from:e.account.address,to:t.managerAddress}),n}async function yh(e,t,n,r,i=`allowance`,a={}){if(t.amount===0n||t.asset===`0x0000000000000000000000000000000000000000`)return;let o=await dh(e,t.asset,n);for(let s of nh(o,t.amount)){let o=s===0n?`${i}:reset`:`${i}:approval`,c=a[o];if(c){if(th(await e.publicClient.waitForTransactionReceipt({hash:c}),c,s===0n?`ERC-20 allowance reset`:`ERC-20 allowance approval`,{from:e.account.address,to:t.asset}),await dh(e,t.asset,n)!==s)throw Error(`${s===0n?`ERC-20 allowance reset`:`ERC-20 allowance approval`} did not set the expected allowance`);continue}let l=await gh(e,{address:t.asset,abi:Wm,functionName:`approve`,args:[n.tangleAddress,s]});await r?.(o,l),th(await e.publicClient.waitForTransactionReceipt({hash:l}),l,s===0n?`ERC-20 allowance reset`:`ERC-20 allowance approval`,{from:e.account.address,to:t.asset})}}async function bh(e,t,n,r,i,a=`job:${n}`,o={}){let s=await uh(e,t,n);await yh(e,s,t,i,`allowance:${a}`,o);let c=o[a],l=c??await gh(e,{address:t.tangleAddress,abi:Hm,functionName:`submitJob`,args:[t.serviceId,n,r],value:s.value});c||await i?.(a,l);let u=await e.publicClient.waitForTransactionReceipt({hash:l});return th(u,l,`Job ${n}`,{from:e.account.address,to:t.tangleAddress}),{hash:l,callId:ah(u,t,n,e.account.address,r),blockNumber:u.blockNumber}}async function xh(e,t,n,r,i,a,o=`job:${n}`,s={}){let c=await bh(e,t,n,r,a,o,s),l=await fh(e,t,c.callId,c.blockNumber,i,Im);return{...c,acknowledgement:l}}const Sh={...nm,chainName:`Tempo Moderato`,nativeSymbol:`TNT`},Ch={async read(e){let t=Qt({chain:pn,transport:an(Sh.rpcUrl,{timeout:15e3})}),n=e=>e.catch(()=>null),r=await Promise.all(e.map(async e=>{let[r,i]=await Promise.all([n(t.readContract({address:Sh.tangleAddress,abi:Hm,functionName:`isPermittedCaller`,args:[Sh.serviceId,e]})),n(t.readContract({address:Sh.managerAddress,abi:Um,functionName:`isDeviceRevoked`,args:[e]}))]);return[e.toLowerCase(),{permitted:r,revoked:i}]}));return new Map(r)},async revokeSelf(e){return vh(await ch(Sh,e),Sh)}},wh={permitted:null,revoked:null};function Th(e){return e.revoked?`revoked`:e.permitted===null?`unknown`:e.permitted?`permitted`:`not permitted`}async function Eh(e,t=Ch){try{let{devices:n}=await em({apiUrl:e.apiUrl,profile:e.profile}),r=Mp()?.account.address.toLowerCase(),i=n.map(e=>({...e,local:e.address===r,status:e.revokedAt?`revoked`:`active`}));r&&!i.some(e=>e.local)&&i.push({address:r,local:!0,status:`unbound`,boundAt:null,lastUsedAt:null,revokedAt:null,revocationMethod:null,revocationReason:null});let a=await t.read(i.map(e=>rn(e.address))),o=i.map(e=>({...e,onChain:a.get(e.address)??wh}));if(e.json){z({serviceId:Sh.serviceId.toString(),devices:o});return}jn([`Address`,`Status`,`Local`,`Service ${Sh.serviceId}`,`Last used`,`Revoked`],o.map(e=>[e.address,e.status,e.local?`yes`:``,Th(e.onChain),e.lastUsedAt??``,e.revokedAt?`${e.revokedAt} (${e.revocationMethod})`:``]))}catch(t){G(t,e.json)}}async function Dh(e,t,n=Ch){try{if(!on(e))throw Error(`${e} is not an EVM address`);let r=rn(e),i=Mp(),a=i?.account.address===r;if(!t.yes){if(!process.stdin.isTTY)throw Error(`Revoking a device is permanent. Re-run with --yes to confirm`);if(!await Bi(`Permanently revoke Solve device ${r}${a?` (this machine's device)`:``}? [y/N] `,`--yes`)){V(`Revocation cancelled`);return}}let o;if(i&&a){let e=await $p({deviceAddress:r,purpose:`revoke`,apiUrl:t.apiUrl,profile:t.profile});o={challengeId:e.challengeId,signature:await i.account.signMessage({message:e.message})}}let s=await tm({deviceAddress:r,reason:t.reason,...o,apiUrl:t.apiUrl,profile:t.profile}),c=r.toLowerCase(),l=(await n.read([r])).get(c)??wh,u;if(i&&a&&!l.revoked){try{u=await n.revokeSelf(i.account)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(`The Solve API revoked ${r}, but the on-chain revocation failed and the local key was kept: ${t}. Run the command again to retry`)}l=(await n.read([r])).get(c)??wh}let d=i&&a&&l.revoked?Pp(i):void 0;if(t.json){z({...s,serviceId:Sh.serviceId.toString(),onChain:l,...u?{revocationTransaction:u}:{},localKeyRetired:!!d});return}B(s.alreadyRevoked?`${r} was already revoked in the Solve API`:`Revoked ${r}; the Solve API refuses its signatures`),u&&B(`Revoked on Tempo in ${u}; service ${Sh.serviceId} refuses its jobs`),d&&V("The local device key was moved aside because its address may still hold stake or rewards. Run `tangle solve account --create` for a new device"),!a&&l.permitted&&En(`The device can still submit jobs to service ${Sh.serviceId}. Only its key, or the Solve blueprint owner, can revoke it on chain`)}catch(e){G(e,t.json)}}function Oh(e,t){return sn(nn(Jm,[e.trim(),t]))}function kh(e){let t=/^submission=(\S+)/.exec(e);if(!t?.[1])throw Error(`COMMIT_CANDIDATE did not return a submission reference`);return t[1]}async function Ah(e,t,n,r,i){let a=i.resumeTransactions?.evaluation;if(a){let n=await e.publicClient.waitForTransactionReceipt({hash:a});if(th(n,a,`Evaluation`,{from:e.account.address,to:t.managerAddress}),!oh(n,t,e.account,r))throw Error(`Saved evaluation transaction did not emit EvaluationAccepted for this candidate`);return a}let o=Date.now();for(;!rh(o,Im);){if(await mh(e,t,r)){let i=ih(await e.publicClient.getLogs({address:t.managerAddress,event:Vm,args:{serviceId:t.serviceId,competitionId:t.competitionId,researcher:e.account.address},fromBlock:n.blockNumber,toBlock:`latest`}),r);if(i)return i;throw Error(`Candidate is already accepted, but its EvaluationAccepted transaction is unavailable`)}let[a,o,,s,c]=await e.publicClient.readContract({address:t.managerAddress,abi:Um,functionName:`pendingResults`,args:[t.serviceId,n.callId]});if(s&&a!==4)throw Error(`Manager pending result ${n.callId} has unexpected job ${a}`);if(s&&c)throw Error(`Manager executed the report without EvaluationAccepted`);if(s&&!c){if(o.toLowerCase()!==sn(n.output).toLowerCase())throw Error(`Manager pending report output does not match the aggregate`);let a=await gh(e,{address:t.managerAddress,abi:Um,functionName:`executePendingResult`,args:[t.serviceId,n.callId,n.output]});await i.onTransaction?.(`evaluation`,a);let s=await e.publicClient.waitForTransactionReceipt({hash:a});if(th(s,a,`Evaluation`,{from:e.account.address,to:t.managerAddress}),!oh(s,t,e.account,r))throw Error(`Evaluation transaction did not emit EvaluationAccepted for this candidate`);return a}await new Promise(e=>setTimeout(e,1e3))}throw Error(`Manager did not emit EvaluationAccepted within 120 seconds`)}async function jh(e,t,n,r={}){if(im(e),!/^0x[0-9a-f]{64}$/i.test(n.salt))throw Error(`Reveal salt must be bytes32`);if(!n.artifactRef.trim())throw Error(`Candidate reference is required`);if(!n.evidenceJson.trim()||n.evidenceRefs.length===0)throw Error(`Checker evidence is required`);let i=await ch(e,t),a=await _h(i,e,r.onTransaction,r.resumeTransactions?.authorization),o,s=await i.publicClient.readContract({address:e.managerAddress,abi:Um,functionName:`stakes`,args:[e.serviceId,e.competitionId,i.account.address]});s<e.minStakeWei&&(o=await gh(i,{address:e.managerAddress,abi:Um,functionName:`postStake`,args:[e.serviceId,e.competitionId],value:e.minStakeWei-s}),await r.onTransaction?.(`stake`,o),th(await i.publicClient.waitForTransactionReceipt({hash:o}),o,`Stake`,{from:i.account.address,to:e.managerAddress}));let c=Oh(n.artifactRef,n.salt),l=nn(Gm,[e.competitionId,e.minStakeWei]),u=nn(Km,[e.competitionId,c]),d=nn(qm,[e.competitionId,c,n.artifactRef.trim(),n.salt]),f=await xh(i,e,1,l,`joined`,r.onTransaction,`join`,r.resumeTransactions),p=await xh(i,e,2,u,`committed`,r.onTransaction,`commit`,r.resumeTransactions),m=kh(p.acknowledgement.detail),h=await xh(i,e,3,d,`revealed`,r.onTransaction,`reveal`,r.resumeTransactions),g=await bh(i,e,4,nn(Ym,[e.competitionId,c,m,n.evidenceJson,JSON.stringify(n.evidenceRefs)]),r.onTransaction,`report`,r.resumeTransactions),_=await ph(i,e,g.callId,g.blockNumber,Im),v=await Ah(i,e,{callId:g.callId,output:_,blockNumber:g.blockNumber},c,r);return{address:i.account.address,...a?{authorization:a}:{},...o?{stake:o}:{},join:f.hash,commit:p.hash,reveal:h.hash,report:g.hash,evaluation:v,candidateId:c,submissionRef:m}}const Mh=Ot(we),Nh=`/usr/bin/bwrap`,Ph=[`/usr`,`/bin`,`/sbin`,`/lib`,`/lib64`];function Fh(e){return[...e].some(e=>{let t=e.charCodeAt(0);return t<32||t===127})}function Ih(e,t){if(!e||e.length>2048||Fh(e))throw Error(`${t} contains invalid control characters or is too long`)}function Lh(e,t){let n=t;for(;n<e.length&&/\s/.test(e[n]??``);)n+=1;return n}function Rh(e,t){if(e[t]!==`"`)throw Error(`Checker output must be valid JSON`);let n=t+1;for(;n<e.length;){let t=e[n];if(t===`\\`){n+=2;continue}if(t===`"`)return n+1;if((t?.charCodeAt(0)??0)<32)throw Error(`Checker output must be valid JSON`);n+=1}throw Error(`Checker output must be valid JSON`)}function zh(e,t,n){let r=new Set,i=Lh(e,t+1);if(e[i]===`}`)return i+1;for(;i<e.length;){let t=Rh(e,i),a=JSON.parse(e.slice(i,t));if(r.has(a))throw Error(`Checker output must not contain duplicate object keys`);if(r.add(a),i=Lh(e,t),e[i]!==`:`)throw Error(`Checker output must be valid JSON`);let o=Lh(e,i+1),s=Vh(e,o);if(n?.(a,o,s),i=Lh(e,s),e[i]===`}`)return i+1;if(e[i]!==`,`)throw Error(`Checker output must be valid JSON`);i=Lh(e,i+1)}throw Error(`Checker output must be valid JSON`)}function Bh(e,t){let n=Lh(e,t+1);if(e[n]===`]`)return n+1;for(;n<e.length;){if(n=Lh(e,Vh(e,n)),e[n]===`]`)return n+1;if(e[n]!==`,`)throw Error(`Checker output must be valid JSON`);n=Lh(e,n+1)}throw Error(`Checker output must be valid JSON`)}function Vh(e,t){if(e[t]===`"`)return Rh(e,t);if(e[t]===`{`)return zh(e,t);if(e[t]===`[`)return Bh(e,t);let n=t;for(;n<e.length&&!/[\s,\]}]/.test(e[n]??``);)n+=1;return n}function Hh(e){let t=e.trim();if(Lh(t,Vh(t,0))!==t.length)throw Error(`Checker output must be valid JSON`)}function Uh(e,t){let n=e.trim();if(n[0]!==`{`)return;let r;return zh(n,0,(e,i,a)=>{e===t&&(r=n.slice(i,a).trim())}),r}function Wh(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Checker output must be one JSON object`)}if(Hh(e),!t||typeof t!=`object`||Array.isArray(t))throw Error(`Checker output must be a JSON object`);let n=t,r=n.candidate_ref;if(typeof r!=`string`||!r.trim())throw Error(`Checker output must include candidate_ref`);let i=r.trim(),a=n.evidence_refs;if(!Array.isArray(a)||a.length===0||a.some(e=>typeof e!=`string`||!e.trim()))throw Error(`Checker output must include a non-empty evidence_refs array`);Ih(i,`candidate_ref`);for(let e of a)Ih(e.trim(),`evidence_refs`);if(!n.evidence_json||typeof n.evidence_json!=`object`||Array.isArray(n.evidence_json))throw Error(`Checker output must include an evidence_json object`);let o={...n.evidence_json},s=Uh(e,`evidence_json`);if(!s)throw Error(`Checker evidence_json source text is missing`);if(o.candidate_ref!==i)throw Error(`Checker evidence_json candidate_ref must match candidate_ref`);return{candidateRef:i,evidenceRefs:a.map(e=>e.trim()),evidence:o,evidenceJson:s}}async function Gh(e,t,n){let r=n.trim();if(r.startsWith(`{`)&&r.endsWith(`}`)||!t.result_file)return r;let i=await Zh(e),a=j.resolve(i,t.result_file),o=j.relative(i,a);if(o.startsWith(`..`)||j.isAbsolute(o))throw Error(`Checker result_file must stay inside the competition repository`);let s;try{s=await Je.lstat(a)}catch{throw Error(`Checker result_file must be an existing regular file inside the competition repository`)}if(s.isSymbolicLink())throw Error(`Checker result_file must not be a symbolic link`);if(!s.isFile())throw Error(`Checker result_file must be an existing regular file inside the competition repository`);let c;try{c=await Je.realpath(a)}catch{throw Error(`Checker result_file must resolve to a regular file inside the competition repository`)}let l=j.relative(i,c);if(l.startsWith(`..`)||j.isAbsolute(l))throw Error(`Checker result_file must stay inside the competition repository`);return(await Je.readFile(c,`utf8`)).trim()}function Kh(e,t){let n=j.relative(e,t);return n===``||!n.startsWith(`..`)&&!j.isAbsolute(n)}function qh(e){return Ph.some(t=>Kh(t,e))}async function Jh(e,t,n){let r=e.includes(`/`)?[j.resolve(t,e)]:(process.env.PATH??``).split(j.delimiter).filter(Boolean).map(t=>j.join(t,e));for(let i of r){let r;try{r=await Je.realpath(i),await Je.access(r,Je.constants.X_OK)}catch{continue}if(!Kh(t,r)&&!qh(r)&&r!==n)throw Error(`Checker executable '${e}' must resolve inside the competition repository or a trusted runtime directory`);return r}throw Error(`Checker executable '${e}' was not found`)}async function Yh(e){let t=[];for(let n of e)try{(await Je.stat(n)).isDirectory()&&t.push(n)}catch{}return t}async function Xh(e){let t=await Je.realpath(Se.homedir());if(e===j.parse(e).root||e===t)throw Error(`Solve checker repository must be a dedicated directory, not the filesystem or home root`)}async function Zh(e){let t=await Je.realpath(e);return await Xh(t),t}async function Qh(e){let t=j.join(e,`.git`),n;try{n=await Je.lstat(t)}catch{return}if(n.isSymbolicLink())throw Error(`Solve checker repository .git must not be a symbolic link`);if(!n.isDirectory()&&!n.isFile())return;let r;try{let t={...process.env};for(let e of[`GIT_DIR`,`GIT_WORK_TREE`,`GIT_INDEX_FILE`,`GIT_OBJECT_DIRECTORY`,`GIT_ALTERNATE_OBJECT_DIRECTORIES`,`GIT_COMMON_DIR`,`GIT_CONFIG_COUNT`,`GIT_CONFIG_PARAMETERS`])delete t[e];let n=await Mh(`/usr/bin/git`,[`-C`,e,`rev-parse`,`--verify`,`HEAD^{commit}`],{encoding:`utf8`,maxBuffer:1e5,env:{...t,GIT_CONFIG_GLOBAL:`/dev/null`,GIT_CONFIG_SYSTEM:`/dev/null`,GIT_CONFIG_NOSYSTEM:`1`,GIT_TERMINAL_PROMPT:`0`}}),i=String(n.stdout).trim();/^[0-9a-f]{40}$/i.test(i)&&(r=i.toLowerCase())}catch{}return{kind:n.isDirectory()?`directory`:`file`,...r?{commit:r}:{}}}async function $h(e,t,n){let r=await Zh(e);if(process.platform!==`linux`)throw Error(`Solve checkers require the Linux sandbox runtime (bubblewrap) with network isolation`);try{await Je.access(Nh,Je.constants.X_OK)}catch{throw Error(`Solve checkers require /usr/bin/bwrap; install bubblewrap or run the checker in a Tangle sandbox`)}let i=await Jh(t,r,await Je.realpath(process.execPath)),a=await Qh(r),o=(await Yh(Ph)).flatMap(e=>[`--ro-bind`,e,e]),s=Kh(r,i)?`/work/${j.relative(r,i)}`:qh(i)?i:`/checker/node`;!Kh(r,i)&&!qh(i)&&o.push(`--ro-bind`,i,`/checker/node`);let c=a?.kind===`directory`?[`--tmpfs`,`/work/.git`]:a?.kind===`file`?[`--ro-bind`,`/dev/null`,`/work/.git`]:[];return{executable:Nh,args:[`--die-with-parent`,`--new-session`,`--unshare-all`,`--clearenv`,...o,`--proc`,`/proc`,`--dev`,`/dev`,`--tmpfs`,`/tmp`,`--dir`,`/tmp/home`,`--bind`,r,`/work`,...c,`--chdir`,`/work`,`--setenv`,`HOME`,`/tmp/home`,...a?.commit?[`--setenv`,`TANGLE_SOLVE_COMMIT`,a.commit]:[],`--setenv`,`TMPDIR`,`/tmp`,`--setenv`,`PATH`,`/checker:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`,`--setenv`,`LANG`,`C.UTF-8`,`--setenv`,`PYTHONDONTWRITEBYTECODE`,`1`,`--setenv`,`XDG_CONFIG_HOME`,`/tmp/home/.config`,`--setenv`,`XDG_CACHE_HOME`,`/tmp/home/.cache`,`--setenv`,`XDG_DATA_HOME`,`/tmp/home/.local/share`,`--setenv`,`GIT_CONFIG_GLOBAL`,`/dev/null`,`--setenv`,`GIT_CONFIG_SYSTEM`,`/dev/null`,`--setenv`,`NPM_CONFIG_USERCONFIG`,`/dev/null`,s,...n]}}async function eg(e,t){if(!t.command||t.command.includes(`/../`)||Fh(t.command))throw Error(`The competition checker command is invalid`);if(!Array.isArray(t.args))throw Error(`The competition checker arguments must be an array`);for(let e of t.args)Ih(e,`Checker argument`);let n=t.timeout_ms??15*6e4;if(!Number.isSafeInteger(n)||n<1e3||n>60*6e4)throw Error(`Checker timeout must be between one second and one hour`);let r=await Zh(e),i;try{let e=await $h(r,t.command,t.args);i=await Mh(e.executable,e.args,{cwd:r,timeout:n,maxBuffer:4194304,encoding:`utf8`})}catch(e){let t=e,n=t.stderr?.trim()||t.stdout?.trim()||t.message||`checker failed`;throw Error(`Pinned checker failed: ${n}`)}let a=String(i.stdout),o=String(i.stderr);return{...Wh(await Gh(r,t,a)),stdout:a,stderr:o}}async function tg(e,t){try{let{root:n,manifest:r}=await vm(e,t.directory),i=await Cm(n),a=r.provenance?await wm(n,r,i,{allowMissing:!0}):void 0,o=Np(),s=H(`Running ${r.title} checker…`);t.json||s.start();let c;try{c=await eg(n,r.checker)}finally{s.stop()}let l=Om(c,a,r.provenance,void 0,{allowMissingSource:!0,requirePullRequest:!1}),u=fn(T(32)),d=Oh(c.candidateRef,u),f={version:1,competition:r.slug,candidateRef:c.candidateRef,evidence:l.evidence,evidenceJson:c.evidenceJson,evidenceRefs:l.evidenceRefs,salt:u,candidateId:d,...a?{source:a}:{},deviceAddress:o.account.address,clientSubmissionId:E(),createdAt:new Date().toISOString()};await km(j.join(n,`.tangle-solve-run.json`),f),t.json?z({localRun:f}):(B(`Checker output recorded locally for operator evaluation`),U({Competition:r.slug,Candidate:c.candidateRef,"Device address":o.account.address,"Evidence refs":l.evidenceRefs.length}),V("Commit any changes, then run `tangle solve submit` from this directory."),r.provenance&&!a&&V(`Add your GitHub fork as 'origin' before submitting. The task repository is available as '${gm}'.`))}catch(e){G(e)}}const ng=/^0x[0-9a-f]{64}$/i;async function rg(e){let t=await $p({deviceAddress:e.deviceAddress,apiUrl:e.apiUrl,profile:e.profile}),n=await e.signer.signMessage({message:t.message});return{walletChallengeId:t.challengeId,walletSignature:n}}async function ig(e,t){try{let{root:n,manifest:r}=await vm(e,t.directory);Xp({profile:t.profile});let i=await Cm(n),a=await Am(n);if(a.competition!==r.slug)throw Error(`.tangle-solve-run.json does not match this competition`);if(!ng.test(a.salt)||!ng.test(a.candidateId))throw Error("This run predates durable candidate identity. Run `tangle solve run` again");let o=r.provenance?await wm(n,r,i):void 0;if(r.provenance&&a.source&&!Em(a.source,o))throw Error("The saved run points to a different repository or revision. Keep your fork as 'origin' and run `tangle solve run` again before submitting");let s=Mp();if(!s)throw Error("No Solve device signer found. Run `tangle solve run` first");if(s.account.address.toLowerCase()!==a.deviceAddress.toLowerCase())throw Error("The local Solve device account changed after `tangle solve run`; run the checker again");let c=H(`Checking the committed candidate…`);t.json||c.start();let l;try{l=await eg(n,r.checker)}finally{c.stop()}if(l.candidateRef!==a.candidateRef||l.evidenceJson!==a.evidenceJson)throw Error("The committed checker output changed after `tangle solve run`; run the checker again");if(Oh(l.candidateRef,a.salt).toLowerCase()!==a.candidateId.toLowerCase())throw Error(`The saved candidate identity does not match the checker output; run the checker again`);let u=Jp(t.prUrl);if(!r.provenance&&u)throw Error(`This competition does not accept GitHub pull request provenance`);if(u){if(!o)throw Error(`A provenance policy is required for a pull request`);await jm({pullRequest:u,taskRepository:o.taskRepository,submissionRepository:o.submissionRepository,submissionRevision:i})}let d=Om(l,o,r.provenance,u,{requirePullRequest:!0}),f={...a,...o?{source:o}:{},chainState:{status:`submitting`,transactions:{...a.chainState?.transactions??{}}}},p=j.join(n,`.tangle-solve-run.json`);await km(p,f);let m=H(`Submitting candidate to Tempo…`);t.json||m.start();let h;try{h=await jh(lm(r),s.account,{artifactRef:l.candidateRef,salt:a.salt,evidenceJson:l.evidenceJson,evidenceRefs:d.evidenceRefs},{resumeTransactions:f.chainState?.transactions,onTransaction:async(e,t)=>{f={...f,chainState:{status:`submitting`,transactions:{...f.chainState?.transactions??{},[e]:t}}},await km(p,f)}})}finally{m.stop()}f={...f,chainReceipt:h,chainState:{status:`accepted`,transactions:{...f.chainState?.transactions??{},...Mm(h)}}},await km(p,f);let g=await rg({deviceAddress:h.address,signer:s.account,apiUrl:t.apiUrl,profile:t.profile}),_=await Qp({path:`/v1/submissions`,method:`POST`,apiUrl:t.apiUrl,profile:t.profile,body:{competition:r.slug,candidateRef:l.candidateRef,candidateId:h.candidateId,evidenceJson:l.evidenceJson,evidenceRefs:d.evidenceRefs,deviceAddress:h.address,reportTxHash:h.report,evaluationTxHash:h.evaluation,transactions:Mm(h),...r.provenance&&o?{source:{...o,...u?{pullRequest:u}:{}}}:{},clientSubmissionId:a.clientSubmissionId,...g,...t.model?{model:t.model}:{},...t.note?{note:t.note}:{}}});t.json?z({..._,transactions:Mm(h),candidateId:h.candidateId}):(B(`Submission accepted on Tempo`),U({Competition:r.slug,Candidate:h.candidateId,"Device address":h.address,"Report transaction":h.report,"Evaluation transaction":h.evaluation,"Submission ID":typeof _.id==`string`?_.id:_.submission?.id}))}catch(e){G(e)}}function ag(){let e=new S(`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(Fm),e.command(`run [competition]`).description(`Run the competition checker and record its evidence`).option(`--directory <path>`,`Competition directory (defaults to the current directory)`).action(tg),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(ig),e.command(`account`).description(`Show the local Solve signing account`).option(`--create`,`Create the account if it does not exist`).action(Fp);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(e=>Eh(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((e,t)=>Dh(e,t)),e}function og(e,t){return`tangle ssh-proxy ${e.replace(/\/+$/,``)}/v1/sandboxes/${t}/runtime/ssh`}function sg(e){return/^[A-Za-z0-9_/:=@%+.,-]+$/.test(e)?e:`'${e.replace(/'/g,`'"'"'`)}'`}function cg(e){return`'${e.replace(/'/g,`''`)}'`}function lg(e){return e===`win32`?`NUL`:`/dev/null`}function ug(e,t){return t===`win32`?`$env:TANGLE_SSH_PROXY_AUTH_TOKEN=${cg(`<token>`)}; ssh ${e.map(cg).join(` `)}`:`TANGLE_SSH_PROXY_AUTH_TOKEN=${sg(`<token>`)} ssh ${e.map(sg).join(` `)}`}function dg(e){return e.connection!==void 0&&!e.connection.ssh}function fg(){Tn(`SSH is not enabled for this sandbox.`),V(`Create a sandbox with --ssh to enable SSH access.`),process.exit(1)}function pg(e,t=[],n=process.platform){let r=lg(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 mg(){return new S(`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}=J(n),a=H(`Getting SSH credentials...`);a.start();let o=await Y(i,r,e);if(dg(o)){a.stop(),fg();return}o=await X(o);let s=await o.ssh();if(a.stop(),!s){fg();return}let c={...s,proxyCommand:og(r.baseUrl,o.id)};if(!r.apiKey)throw Error(`SSH proxy requires API key auth. Set TANGLE_API_KEY or pass --api-key.`);let l=pg(c,[...n.identityFile?[`-i`,n.identityFile,`-o`,`IdentitiesOnly=yes`]:[],...t]);if(n.print){console.log(ug(l,process.platform));return}V(`Connecting via tunnel...`);let u=Ee(`ssh`,l,{stdio:`inherit`,env:{...process.env,TANGLE_SSH_PROXY_AUTH_TOKEN:r.apiKey}});u.on(`error`,e=>{e.code===`ENOENT`&&(Tn(`SSH client not found. Please install OpenSSH.`),process.exit(1)),G(e)}),u.on(`exit`,e=>{process.exit(e??0)})})}function hg(){let e=new S(`ssh-keys`).description(`Manage SSH keys`);return e.command(`list`).description(`List SSH keys`).action(async e=>{let t=H(`Fetching SSH keys...`);try{t.start();let n=await q(K(e)).sshKeys.list();t.stop(),e.json?z({sshKeys:n}):n.length===0?V(`No SSH keys found.`):jn([`Name`,`Type`,`Fingerprint`,`Created`],n.map(e=>[e.name,e.keyType,e.fingerprint,e.createdAt.toLocaleString()]))}catch(e){t.stop(),G(e)}}),e.command(`add`).description(`Add SSH key`).argument(`<name>`,`SSH key name`).requiredOption(`--key-file <path>`,`Public key file path`).action(async(e,t)=>{let n=H(`Adding SSH key...`);try{let r=fe(t.keyFile,`utf8`).trim();n.start();let i=await q(K(t)).sshKeys.create(e,r);n.stop(),t.json?z({sshKey:i}):B(`Added SSH key ${i.name} (${i.fingerprint})`)}catch(e){n.stop(),G(e)}}),e.command(`delete`).description(`Delete SSH key`).argument(`<name>`,`SSH key name or ID`).action(async(e,t)=>{let n=H(`Deleting SSH key...`);try{n.start(),await q(K(t)).sshKeys.delete(e),n.stop(),B(`Deleted SSH key ${e}`)}catch(e){n.stop(),G(e)}}),e}function gg(e,t=1){process.stderr.write(`${e}\n`),process.exit(t)}function _g(){return new S(`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||gg(`TANGLE_SSH_PROXY_AUTH_TOKEN not set`);let n=new gn(new URL(e.replace(/^http/,`ws`)),{headers:{Authorization:`Bearer ${t}`},perMessageDeflate:!1}),r;function i(){r&&=(clearInterval(r),void 0)}n.on(`open`,()=>{r=setInterval(()=>{n.readyState===gn.OPEN&&n.ping()},15e3),r.unref?.(),process.stdin.on(`data`,e=>{n.readyState===gn.OPEN&&n.send(e,{binary:!0,compress:!1})}),process.stdin.on(`end`,()=>n.close(1e3))}),n.on(`message`,e=>{let t=Buffer.isBuffer(e)?e:Array.isArray(e)?Buffer.concat(e):Buffer.from(e);process.stdout.write(t)}),n.on(`error`,e=>{i(),gg(`WebSocket error: ${e.message}`)}),n.on(`close`,e=>{i(),process.exit(e===1e3?0:1)}),process.stdin.on(`error`,()=>n.close())})}function vg(){let e=new S(`team`).description(`Manage teams`);return Sg(e,`list`).description(`List teams for the current account`).action(async e=>{let t=K(e),n=q(t),r=e.json?null:H(`Fetching teams...`);r?.start();let i=await n.teams.list();if(r?.stop(),e.json){z({teams:i,activeTeamId:t.activeTeamId??null});return}R(i.map(e=>({active:e.id===t.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}])}),Sg(e,`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(e,t)=>{let n=K(t),r=q(n),i=t.json?null:H(`Creating team...`);i?.start();let a=await r.teams.create({name:e,orgId:t.orgId});if(t.switch&&_c(a,n.profile),i?.stop(),t.json){z({team:a,active:!!t.switch});return}B(`Team created: ${mc(a)}`),t.switch&&B(`Active team set to ${a.name}`)}),Sg(e,`switch <team>`).description(`Set the active team for the current profile`).action(async(e,t)=>{let n=K(t),r=await hc(q(n),e);if(_c(r,n.profile),t.json){z({team:r,activeTeamId:r.id});return}B(`Active team set to ${mc(r)}`)}),e.command(`current`).description(`Show the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(e=>{let t=ti(e.profile);if(e.json){z(t.activeTeamId?t:{activeTeamId:null});return}if(!t.activeTeamId){console.log(`No active team.`);return}U({ID:t.activeTeamId,Name:t.activeTeamName})}),e.command(`clear`).description(`Clear the active team for the current profile`).option(`--profile <profile>`,`Credential profile`).action(e=>{if(vc(e.profile),e.json){z({activeTeamId:null});return}B(`Active team cleared.`)}),Sg(e,`members [team]`).description(`List team members`).action(async(e,t)=>{let n=K(t),r=q(n),i=await gc(r,e,n.profile),a=await r.teams.listMembers(i.id);if(t.json){z({team:i,members:a});return}R(a,[{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}])}),Sg(e,`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(e,t)=>{let n=K(t),r=q(n),i=await gc(r,t.team,n.profile),a=yg(t.role),o=await r.teams.updateMember(i.id,e,{role:a});if(t.json){z({team:i,member:o});return}B(`Member updated: ${o.customerEmail}`),U({Team:i.name,Role:o.role,Status:o.status})}),Sg(e,`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(e,t)=>{let n=K(t),r=q(n),i=await gc(r,t.team,n.profile),a=yg(t.role),o=await r.teams.invite(i.id,{email:e,role:a,ttlHours:t.ttlHours?Number.parseInt(t.ttlHours,10):void 0});if(t.json){z({team:i,invitation:o});return}B(`Invitation created for ${o.email}`),U({Team:i.name,Role:o.role,Expires:o.expiresAt,"Invitation ID":o.id}),B(`Re-run with --json to retrieve the invitation token for sharing.`)}),Sg(e,`leave [team]`).description(`Leave a team as the current user`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{let n=K(t),r=q(n),i=await gc(r,e,n.profile);if(!(!t.force&&!t.json&&!await Bi(`Leave team '${i.name}'? (y/N) `,`--force`))){if(await r.teams.leave(i.id),n.activeTeamId===i.id&&vc(n.profile),t.json){z({success:!0,teamId:i.id});return}B(`Left team: ${i.name}`)}}),Sg(e,`transfer <new-owner-customer-id> [team]`).description(`Transfer team ownership to another active member`).option(`--force`,`Skip confirmation prompt`).action(async(e,t,n)=>{let r=K(n),i=q(r),a=await gc(i,t,r.profile);if(!(!n.force&&!n.json&&!await Bi(`Transfer ownership of '${a.name}' to ${e}? This cannot be undone without the new owner's cooperation. (y/N) `,`--force`))){if(await i.teams.transferOwnership(a.id,e),n.json){z({success:!0,teamId:a.id,newOwnerCustomerId:e});return}B(`Ownership transferred for ${a.name}`)}}),e.addCommand(bg()),e.addCommand(xg()),Sg(e,`invitations [team]`).description(`List pending and historical team invitations`).action(async(e,t)=>{let n=K(t),r=q(n),i=await gc(r,e,n.profile),a=await r.teams.listInvitations(i.id);if(t.json){z({team:i,invitations:a});return}R(a,[{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}])}),Sg(e,`accept <token>`).description(`Accept a team invitation`).option(`--no-switch`,`Do not set the accepted team as active`).action(async(e,t)=>{let n=K(t),r=q(n),i=await r.teams.acceptInvitation(e),a=t.switch===!1?null:await r.teams.get(i.teamId);if(a&&_c(a,n.profile),t.json){z({member:i,activeTeamId:a?.id??null});return}B(`Invitation accepted for team ${i.teamId}`),a&&B(`Active team set to ${a.name}`)}),Sg(e,`revoke-invitation <invitation-id>`).description(`Revoke a pending team invitation`).action(async(e,t)=>{if(await q(K(t)).teams.revokeInvitation(e),t.json){z({success:!0,invitationId:e});return}B(`Invitation revoked: ${e}`)}),Sg(e,`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(e,t)=>{let n=K(t),r=q(n),i=await gc(r,t.team,n.profile);if(await r.teams.removeMember(i.id,e),t.json){z({success:!0,teamId:i.id,memberId:e});return}B(`Member removed: ${e}`)}),e}function yg(e){if(e===`admin`||e===`member`||e===`viewer`)return e;throw Error(`Role must be one of: admin, member, viewer`)}function bg(){let e=new S(`secret`).description(`Manage team secrets`);return Sg(e,`list [team]`).description(`List team secret names`).action(async(e,t)=>{let n=K(t),r=q(n),i=await gc(r,e,n.profile),a=await r.teams.listSecrets(i.id);if(t.json){z({team:i,secrets:a});return}R(a,[{key:`name`,header:`Name`,width:28},{key:`updatedAt`,header:`Updated`,width:24},{key:`updatedBy`,header:`Updated By`,width:28}])}),Sg(e,`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(e,t,n)=>{let r=K(n),i=q(r),a=await gc(i,n.team,r.profile),o=await Tp({value:t,valueStdin:n.valueStdin,prompt:`Enter value for team secret '${e}': `}),s=await i.teams.upsertSecret(a.id,e,o);if(n.json){z({team:a,secret:s});return}B(`Team secret saved: ${s.name}`)}),Sg(e,`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(e,t)=>{let n=K(t),r=q(n),i=await gc(r,t.team,n.profile);if(!(!t.force&&!t.json&&!await Bi(`Delete team secret '${e}' from '${i.name}'? (y/N) `,`--force`))){if(await r.teams.deleteSecret(i.id,e),t.json){z({success:!0,teamId:i.id,name:e});return}B(`Team secret deleted: ${e}`)}}),Sg(e,`reveal <name>`).description(`Reveal a team secret value`).option(`-t, --team <team>`,`Team id or name (defaults to active team)`).action(async(e,t)=>{let n=K(t),r=q(n),i=await gc(r,t.team,n.profile),a=await r.teams.revealSecret(i.id,e);if(t.json){z({teamId:i.id,...a});return}console.log(a.value)}),e}function xg(){let e=new S(`templates`).description(`Manage team golden-path templates`);return Sg(e,`list [team]`).description(`List a team's golden-path templates`).action(async(e,t)=>{let n=K(t),r=q(n),i=await gc(r,e,n.profile),a=await r.teams.listTemplates(i.id);if(t.json){z({team:i,templates:a});return}if(a.length===0){console.log(`No templates yet for ${i.name}.`);return}R(a.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}])}),Sg(e,`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(e,t,n)=>{let r=K(n),i=q(r),a=await gc(i,n.team,r.profile),o;if(n.config)try{let e=JSON.parse(n.config);if(typeof e!=`object`||!e||Array.isArray(e))throw Error(`--config must be a JSON object`);o=e}catch(e){throw Error(`--config is not valid JSON: ${e instanceof Error?e.message:String(e)}`)}let s=await i.teams.createTemplate(a.id,{name:e,snapshotId:t,description:n.description,environment:n.environment,config:o});if(n.json){z({team:a,template:s});return}B(`Team template created: ${s.name} (${s.id})`)}),Sg(e,`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(e,t)=>{let n=K(t),r=q(n),i=await gc(r,t.team,n.profile);if(!(!t.force&&!t.json&&!await Bi(`Delete template '${e}' from '${i.name}'? (y/N) `,`--force`))){if(await r.teams.deleteTemplate(i.id,e),t.json){z({success:!0,teamId:i.id,templateId:e});return}B(`Team template deleted: ${e}`)}}),e}function Sg(e,t){return e.command(t).option(`--profile <profile>`,`Credential profile`)}async function Cg(e,t,n){let r=new AbortController,i=()=>r.abort();try{let n=q(K({...e,timeout:void 0}));process.once(`SIGINT`,i),process.once(`SIGTERM`,i);let a=await t(n,{...e.timeout===void 0?{}:{timeoutMs:Number(e.timeout)*1e3},resumeJobId:e.resumeJob,signal:r.signal,onProgress:e=>{process.stderr.write(`Publication ${e.id}: ${e.status}\n`)}}).finally(()=>{process.off(`SIGINT`,i),process.off(`SIGTERM`,i)});e.json?z(a):B(`template`in a?`Published template: ${a.template.slug}`:`Published template version: ${a.version.id}`)}catch(t){if(t instanceof o&&t.status!==401&&t.job&&[`pending`,`scanning`,`ready`].includes(t.job.status)){let e=[`tangle`,`template`,...n,`--resume-job`,t.job.id].map(qe).join(` `);Object.assign(t,{fix:{command:e}})}G(t,e.json)}}function wg(){let e=new S(`template`).description(`Manage published public templates`);return e.command(`list`).option(`-q, --query <query>`,`Search query`).option(`--tag <tag>`,`Filter by tag`).option(`--featured`,`Show featured templates only`).action(async e=>{let t=q(K(e)),n=e.featured?await t.publicTemplates.featured():await t.publicTemplates.list({query:e.query,tag:e.tag});if(e.json){z({templates:n});return}R(n,[{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}])}),e.command(`get <id-or-slug>`).action(async(e,t)=>{let n=await q(K(t)).publicTemplates.get(e);if(t.json){z({template:n});return}z(n)}),e.command(`versions <id-or-slug>`).action(async(e,t)=>{let n=await q(K(t)).publicTemplates.versions(e);if(t.json){z({versions:n});return}R(n.map(e=>({...e})),[{key:`id`,header:`Version ID`,width:38},{key:`versionNumber`,header:`Version`,width:8},{key:`createdAt`,header:`Created`,width:24}])}),e.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)=>Cg(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])),e.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)=>Cg(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])),e}function Tg(){let e=new S(`traces`).description(`Read hosted agent traces, spans, and eval-runs from Tangle Intelligence`);return e.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 e=>{try{let t={from:e.from,to:e.to,model:e.model,runId:e.run,status:e.status===void 0?void 0:Ig(e.status),q:e.query,cursor:e.cursor,limit:e.limit===void 0?void 0:Vg(e.limit)},n=Dg(e),r=e.json?null:H(`Fetching traces...`);r?.start();let i=await n.listTraces(t);if(r?.stop(),e.json)return z(i);Ag(i.items),Pg(i.nextCursor)}catch(t){kg(t,e)}}),e.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(e,t)=>{try{let n=Dg(t);if(t.ndjson){await Og(n,e);return}let r=t.json?null:H(`Fetching trace spans...`);r?.start();let i=await n.getTraceSpans(e,{cursor:t.cursor,limit:t.limit===void 0?void 0:Vg(t.limit)});if(r?.stop(),t.json)return z(i);jg(i.items),i.truncated&&U({Spans:`${i.items.length} of ${i.total} (truncated)`}),Pg(i.nextCursor)}catch(e){kg(e,t)}}),e.addCommand(Eg()),e}function Eg(){let e=new S(`runs`).description(`Read eval-runs pivoted off the trace surface`);return e.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 e=>{try{let t={status:e.status===void 0?void 0:Rg(e.status),gate:e.gate===void 0?void 0:Bg(e.gate),label:e.label,from:e.from,to:e.to,q:e.query,cursor:e.cursor,limit:e.limit===void 0?void 0:Vg(e.limit)},n=Dg(e),r=e.json?null:H(`Fetching runs...`);r?.start();let i=await n.listRuns(t);if(r?.stop(),e.json)return z(i);Mg(i.items),Pg(i.nextCursor)}catch(t){kg(t,e)}}),e.command(`get <runId>`).description(`Show a single eval-run`).action(async(e,t)=>{try{let n=Dg(t),r=t.json?null:H(`Fetching run...`);r?.start();let i=await n.getRun(e);if(r?.stop(),t.json)return z(i);Ng(i)}catch(e){kg(e,t)}}),e}function Dg(e){let t=Gr(e.apiKey);if(!t)throw Error(`No API key found. Set TANGLE_API_KEY or run: tangle auth login`);return _n({apiKey:t,baseUrl:e.baseUrl??process.env.TANGLE_INTELLIGENCE_BASE_URL})}async function Og(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 kg(e,t){return G(e,t.json===!0)}function Ag(e){R(e.map(e=>({traceId:e.traceId,root:e.rootName??`-`,model:e.model??`-`,spans:e.spanCount,errors:e.errorCount,durationMs:e.durationMs,cost:Fg(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 jg(e){R(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 Mg(e){R(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 Ng(e){U({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 Pg(e){e&&U({"Next page":`--cursor ${e}`})}function Fg(e){return e===null?`-`:`$${e.toFixed(4)}`}function Ig(e){if(e===`ERROR`||e===`OK`)return e;throw Error(`--status must be ERROR or OK`)}const Lg=[`started`,`baseline-complete`,`generation-complete`,`gate-decided`,`finished`,`errored`];function Rg(e){let t=Lg.find(t=>t===e);if(t)return t;throw Error(`--status must be one of ${Lg.join(`, `)}`)}const zg=[`ship`,`hold`,`need_more_work`,`model_ceiling`,`arch_ceiling`];function Bg(e){let t=zg.find(t=>t===e);if(t)return t;throw Error(`--gate must be one of ${zg.join(`, `)}`)}function Vg(e){let t=Number(e);if(!Number.isInteger(t)||t<1)throw Error(`--limit must be a positive integer`);return t}function Hg(){return new S(`usage`).description(`Show account usage and billing information`).action(async e=>{let{client:t}=J(e),n=e.json?null:H(`Fetching usage...`);n?.start();let[r,i]=await Promise.all([t.usage(),t.subscription().catch(()=>null)]);n?.stop(),e.json?z({...r,subscription:i}):(console.log(),console.log(`Account Usage`),console.log(`─`.repeat(40)),U({"Active Sandboxes":r.activeSandboxes,"Total Sandboxes":r.totalSandboxes,"Compute Minutes":Ug(r.computeMinutes),"GPU Seconds":r.gpuSeconds,"GPU Spend":Wg(r.gpuCostUsd)}),i&&(console.log(),console.log(`Subscription`),console.log(`─`.repeat(40)),U({Plan:i.plan,Status:i.status,"Credits Available":Wg(i.creditsAvailableUsd),"Credits Used":Wg(i.creditsUsedUsd),"Monthly Balance":Wg(i.monthlyBalanceUsd)})),console.log(),console.log(`Billing Period`),console.log(`─`.repeat(40)),U({Start:r.periodStart.toLocaleDateString(),End:r.periodEnd.toLocaleDateString()}),console.log())})}function Ug(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 Wg(e){return e<0?`-$${(-e).toFixed(2)}`:`$${e.toFixed(2)}`}function Gg(){return new S(`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){Lr(),V(`Cleared the active sandbox.`);return}if(e){Ir(e),V(`Active sandbox set to ${e}. Commands now default to it; override with --box or TANGLE_SANDBOX.`);return}let n=Fr();V(n?`Active sandbox: ${n}`:"No active sandbox. Set one with `tangle use <id>`.")})}function Kg(e){R(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 qg(e){e.command(`artifacts`).description(`List a run's artifact metadata (never the bytes)`).argument(`<id>`,`Workflow ID`).argument(`<runId>`,`Run ID`).action(async(e,t,n)=>{let r=await(await Q(n)).workflows.listArtifacts(e,t);if(n.json)return z(r);Kg(r.artifacts)}),e.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(e,t,n,r)=>{let i=await(await Q(r)).workflows.downloadArtifact(e,t,n),a=r.out??n;try{me(a,i.bytes)}catch(e){throw Error(`Could not write artifact to "${a}": ${e instanceof Error?e.message:String(e)}`)}if(r.json)return z({file:a,contentType:i.contentType,bytes:i.bytes.length});V(`Wrote ${a} (${i.bytes.length} bytes, ${i.contentType}).`)})}function Jg(e){R(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 Yg(e){e.command(`decisions`).description(`List a workflow's pending human decisions`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{let n=(await(await Q(t)).workflows.listPendingDecisions()).decisions.filter(t=>t.workflowId===e);if(t.json)return z({decisions:n});Jg(n)}),e.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(e,t,n)=>{let r=await Q(n),i=await r.workflows.getRunDecision(e,t),a=await r.workflows.resolveRunDecision(e,t,{decisionId:i.id,choice:n.choice});if(n.json)return z(a);if(a.resumed){V(`Resolved decision ${a.decisionId} with "${a.choice}" — run ${a.runId} resumed.`);return}V(`Resolved decision ${a.decisionId} with "${a.choice}", but run ${a.runId} had already finished — nothing to resume.`)})}function Xg(e){try{return fe(e,`utf8`)}catch(t){throw Error(`Could not read workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function Zg(e){R(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 Qg(e){let t=e.workflows.filter(e=>e.failed>0).length,n=e.workflows.filter(e=>e.failed===0&&e.waiting>0).length,r=e.workflows.filter(e=>e.failed===0&&e.waiting===0&&e.runsInWindow>0).length;V(`${t} failing · ${n} waiting · ${r} healthy · ${e.workflows.length} total over ${e.window}`),R(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 $g(e){if(U({ID:e.id,Name:e.name,Description:e.description??``,Enabled:e.enabled?`yes`:`no`,Actions:e.actions.length}),e.triggers&&e.triggers.length>0&&(V(`Triggers`),e_(e.triggers)),e.validationErrors.length>0){V(`Validation issues`);for(let t of e.validationErrors)console.log(` ${t.path}: ${t.message}`)}}function e_(e){R(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 t_(e){e.command(`list`).description(`List your workflows`).action(async e=>{let t=await(await Q(e)).workflows.list();if(e.json)return z(t);Zg(t)}),e.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 e=>{let t=await(await Q(e)).workflows.fleetInsights({window:e.window});if(e.json)return z(t);Qg(t)}),e.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(e,t)=>{let n=await(await Q(t)).workflows.get(e);if(t.yaml){if(n.definitionYaml===null)throw Error(`Workflow ${n.id} has no stored definition YAML to export`);process.stdout.write(n.definitionYaml.endsWith(`
177
+ `)?n.definitionYaml:`${n.definitionYaml}\n`);return}if(t.json)return z(n);$g(n)}),e.command(`create`).description(`Create a workflow from a YAML file`).argument(`<file>`,`Path to the workflow YAML`).action(async(e,t)=>{let n=Xg(e),r=await(await Q(t)).workflows.create(n);if(t.json)return z(r);V(`Created workflow ${r.id} (${r.name}).`),$g(r)}),e.command(`apply`).description(`Create or update a workflow idempotently, matched by the definition's name`).argument(`<file>`,`Path to the workflow YAML`).action(async(e,t)=>{let n=Xg(e),r=await Q(t),i=await r.workflows.validate(n,{structural:!0});if(!i.valid){if(process.exitCode=1,t.json)return z(i);V(`Invalid workflow:`);for(let e of i.errors)console.log(` ${e.path}: ${e.message}`);return}let a=(await r.workflows.list()).find(e=>e.name===i.name);if(a){let e=await r.workflows.update(a.id,n);if(t.json)return z({action:`updated`,workflow:e});V(`Updated workflow ${e.id} (${e.name}) — matched by name.`),$g(e);return}let o=await r.workflows.create(n);if(t.json)return z({action:`created`,workflow:o});V(`Created workflow ${o.id} (${o.name}).`),$g(o)}),e.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(e,t,n)=>{let r=Xg(t),i=await(await Q(n)).workflows.update(e,r,{...n.note===void 0?{}:{note:n.note}});if(n.json)return z(i);V(`Updated workflow ${i.id} (${i.name}).`),$g(i)}),e.command(`delete`).description(`Delete a workflow and its triggers`).argument(`<id>`,`Workflow ID`).option(`--force`,`Skip confirmation prompt`).action(async(e,t)=>{if(!t.force&&!await Bi(`Delete workflow ${e}? `,`--force`)){V(`Delete cancelled.`);return}if(await(await Q(t)).workflows.delete(e),t.json)return z({deleted:!0,id:e});V(`Deleted workflow ${e}.`)}),e.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(e,t)=>{let n=Xg(e),r=await(await Q(t)).workflows.validate(n,{...t.structural?{structural:!0}:{}});if(t.json)return z(r);if(r.valid)V(`Valid: ${r.name} (${r.actionCount} action(s), ${r.triggerCount} trigger(s)).`);else{V(`Invalid workflow:`);for(let e of r.errors)console.log(` ${e.path}: ${e.message}`);process.exitCode=1}}),e.command(`schema`).description(`Print the JSON Schema for the workflow YAML`).action(async e=>{z(await(await Q(e)).workflows.schema())})}async function n_(e,t,n){let r=await(await Q(n)).workflows.setEnabled(e,t);if(n.json)return z(r);V(`${t?`Enabled`:`Disabled`} workflow ${r.id}.`),$g(r)}function r_(e,t){try{return JSON.parse(e)}catch{throw Error(`Invalid ${t}: not valid JSON`)}}function i_(e,t){try{me(e,t,`utf8`)}catch(t){throw Error(`Could not write workflow file "${e}": ${t instanceof Error?t.message:String(t)}`)}}function a_(e){R(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 o_(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 s_(e){e.command(`enable`).description(`Enable a workflow so its triggers and manual runs fire`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await n_(e,!0,t)}),e.command(`disable`).description(`Disable a workflow (pause its triggers and manual runs)`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{await n_(e,!1,t)}),e.command(`templates`).description(`List the curated starter workflow templates`).action(async e=>{let t=await(await Q(e)).workflows.listTemplates();if(e.json)return z(t);a_(t)}),e.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.`,uu,[]).option(`--file <out>`,`Write the instantiated workflow YAML to this file instead of stdout`).action(async(e,t)=>{let n=du(t.param,`param`)??{},r=await(await Q(t)).workflows.instantiateTemplate(e,n);if(t.json)return z(r);if(!r.created){V(`Template ${e} needs provider connections before it can run:`);for(let e of r.connectionRequirements)console.log(` ${e.connected?`✓`:`✗`} ${o_(e,r.connectionRequirements)}`);process.exitCode=1;return}let{workflow:i}=r;if(i.definitionYaml===null)throw Error(`Workflow ${i.id} was created but the server returned no definition YAML`);if(V(`Created workflow ${i.id} (${i.name}).`),t.file){i_(t.file,i.definitionYaml),V(`Wrote ${t.file}.`);return}process.stdout.write(i.definitionYaml.endsWith(`
178
+ `)?i.definitionYaml:`${i.definitionYaml}\n`)})}function c_(e){R(e,[{key:`key`,header:`Key`},{key:`version`,header:`Version`},{key:`updatedAt`,header:`Updated`}])}function l_(e){U({Key:e.key,Version:e.version,Updated:e.updatedAt}),V(`Value`),z(e.value)}function u_(e){let t=e.command(`kv`).description(`Read and write a workflow's cross-run KV state`);t.command(`list`).description(`List every KV entry of a workflow`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{let n=await(await Q(t)).workflows.listKv(e);if(t.json)return z(n);c_(n.entries)}),t.command(`get`).description(`Show one KV entry (value and version)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(e,t,n)=>{let r=await(await Q(n)).workflows.getKv(e,t);if(n.json)return z(r);l_(r)}),t.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(e,t,n,r)=>{let i=r_(n,`<json>`),a=r.cas===void 0?void 0:Go(r.cas,`--cas`),o=await Q(r),s=a===void 0?await o.workflows.putKv(e,t,i):await o.workflows.casKv(e,t,a,i);if(r.json)return z(s);l_(s)}),t.command(`delete`).description(`Delete a KV entry (idempotent)`).argument(`<id>`,`Workflow ID`).argument(`<key>`,`KV key`).action(async(e,t,n)=>{let r=await(await Q(n)).workflows.deleteKv(e,t);if(n.json)return z(r);V(r.deleted?`Deleted KV entry "${t}" of workflow ${e}.`:`No KV entry "${t}" on workflow ${e}.`)})}function d_(e){R(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 f_(e){e.command(`revisions`).description(`List a workflow's definition revision history (newest first)`).argument(`<id>`,`Workflow ID`).action(async(e,t)=>{let n=await(await Q(t)).workflows.listRevisions(e);if(t.json)return z(n);d_(n)}),e.command(`revision`).description(`Show one revision's metadata and definition YAML`).argument(`<id>`,`Workflow ID`).argument(`<rev>`,`Revision number`).action(async(e,t,n)=>{let r=Go(t,`<rev>`),i=await(await Q(n)).workflows.getRevision(e,r);if(n.json)return z(i);U({Revision:i.rev,Created:i.createdAt,"Created by":i.createdBy,Source:i.source,Note:i.note??``}),process.stdout.write(i.yaml.endsWith(`
179
+ `)?i.yaml:`${i.yaml}\n`)}),e.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(e,t,n)=>{let r=Go(t,`<rev>`),i=await(await Q(n)).workflows.rollback(e,r);if(n.json)return z(i);V(`Rolled back workflow ${i.id} to rev ${r}.`),$g(i)})}function p_(){let e=new S(`workflows`).description(`Create and manage Tangle workflows`);return t_(e),gu(e),s_(e),f_(e),u_(e),qg(e),Yg(e),e}function m_(e){for(let[t,n]of Object.entries(e.optsWithGlobals()))e.getOptionValue(t)===void 0&&n!==void 0&&e.setOptionValue(t,n)}const h_=e(import.meta.url)(`../package.json`);function g_(){let e=new S;e.name(`tangle`).description(`CLI for Tangle Sandbox operations`).version(h_.version??`0.0.0`).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,t)=>{m_(t);let n=t.opts();yn(n.json===!0||n.ndjson===!0)}),e.addCommand(Sa()),e.addCommand(Sp()),e.addCommand(Gg()),e.addCommand(wp()),e.addCommand(Xf()),e.addCommand(op()),e.addCommand(sp()),e.addCommand(Js()),e.addCommand(mg()),e.addCommand(hg()),e.addCommand(_g()),e.addCommand(na()),e.addCommand(Dp()),e.addCommand(Vc()),e.addCommand(Hg()),e.addCommand(vg()),e.addCommand(wg()),e.addCommand(ja()),e.addCommand(Ha()),e.addCommand(mp()),e.addCommand(Hc()),e.addCommand(Gc()),e.addCommand(Af()),e.addCommand(Jd()),e.addCommand(p_()),e.addCommand(As()),e.addCommand(Cp()),e.addCommand(ag()),e.addCommand(Ep()),e.addCommand(Ua()),e.addCommand(fp()),e.addCommand(jf()),e.addCommand(Cs()),e.addCommand(ws()),e.addCommand(bp()),e.addCommand(cp()),e.addCommand(Tg()),e.addCommand(Sl());function t(e){e.configureHelp({showGlobalOptions:!0}),e.configureOutput({writeErr:()=>{}}),e.exitOverride(t=>{t.exitCode===0&&process.exit(0),G(t,e.optsWithGlobals().json===!0)});for(let n of e.commands)t(n)}return t(e),e}const __=g_();__.parseAsync(process.argv).catch(e=>{G(e,__.opts().json===!0)});export{};