@tangle-network/sandbox-cli 0.22.109 → 0.22.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +1 -1
  2. package/package.json +5 -5
package/dist/index.mjs CHANGED
@@ -173,7 +173,7 @@ mv "$2.partial" "$2"`,y,b);let x=c(n.id),S=M(i,`remotes`,`${x.upstream}.git`),{i
173
173
  <meta name="description" content="${(e.describe??o).replace(/[&<>"]/g,``)}">
174
174
  <style>${i}html,body,#root{margin:0;height:100%;font-family:ui-sans-serif,system-ui,sans-serif}</style></head>
175
175
  <body><div id="root"></div><script id="graph" type="application/json">${JSON.stringify(e).replace(/</g,`\\u003c`)}<\/script>
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 Gd(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=Vd(i,await F(i,`utf8`));if(r.json)return z(a);if(!r.open)return console.log(Ud(a));let o=await Wd(a,n);V(await fa(Gt(o).href)?`Opened ${o}`:`Open ${o}`)})}async function Kd(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 qd(e,t,n){let r=_f(t.parameter),i=n??await Kd(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(yf(a)),a):(vf(a,t.browser===!1?!1:await fa(a.redirectUrl),t.wait),a)}async function Jd(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 qd(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 Yd(){let e=new S(`hub`).description(`Discover and run Tangle Hub tools`);return Xd(e),Zd(e),Qd(e),$d(e),ef(e),e}function Xd(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 Kd(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 qd(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):gf(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 Zd(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 Qd(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):df(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=ff(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):df([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(nf())}function $d(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):pf(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):mf(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):uf(n.tools)}),e.addCommand(t),e.addCommand(tf(`call`)),e.addCommand(tf(`exec`))}function ef(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(af(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);sf(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):bf(t)})}function tf(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}=rf(e,t),{path:i,input:a}=lf(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 nf(){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):of(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)=>{af(e),sf(await(await Oi(n)).approvals[t](e),n.json===!0)});return e}function rf(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 af(e){if(!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`Hub approval ID must contain only letters, numbers, underscores, and dashes.`)}function of(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 sf(e,t){if(t){z(cf(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 cf(e){return{approval:e.approval,...e.capabilityToken?{capabilityToken:{tokenId:e.capabilityToken.tokenId,expiresAt:e.capabilityToken.expiresAt}}:{}}}function lf(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 uf(e){R(e.map(e=>({...e,provider:e.providerId??e.requiredConnectionProviderId,connection:hf(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 df(e){R(e,[{key:`connectionId`,header:`Connection`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`decision`,header:`Decision`},{key:`updatedAt`,header:`Updated`}])}function ff(e){if(e===`allow`||e===`ask`||e===`deny`)return e;throw Error(`--decision must be one of: allow, ask, deny.`)}function pf(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 mf(e){U({Path:e.path,Provider:e.providerId??e.requiredConnectionProviderId,Title:e.title,Description:e.description,Connection:hf(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 hf(e){if(e.connectionRequired===!1)return`not required`;if(e.connectionStatus)return e.connectionStatus}function gf(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 _f(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 vf(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 yf(e){return{provider:e.provider,redirectUrl:e.redirectUrl,expiresAt:e.expiresAt,scopes:e.scopes,cli:e.cli}}function bf(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 xf=t(import.meta.url);if(!xf)throw Error(`Tangle CLI package metadata was not found`);const Sf=ge(xf),$=e=>w(`sha256`).update(e).digest(`hex`);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=>Cl(l,M(c,e))||Cl(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(Sf,`dist`,`stdio.mjs`),f={...process.env,BRIDGE_HOST:`127.0.0.1`,BRIDGE_BEARER:r,BRIDGE_DATA_DIR:M(o,`bridge`),BRIDGE_BACKENDS:Kl,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 Bl(t.resume):void 0,l=r.taskWorkspace??(t.taskWorkspace?await Nl(t.taskWorkspace):void 0)??c?.taskWorkspace;if(c&&(l?kl(l):null)!==(c.taskWorkspace?kl(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 Fl(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 Cu(o,s,t,n);let e=await bl(),l=$(s),u=Object.entries(fu(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),Wl(c,t,l,d,f)}let g={apiKey:t.apiKey,sandboxBaseUrl:t.baseUrl,signal:n,json:t.json,dryRun:t.dryRun&&!r.connectNeeds},_,v=()=>_??=Kd(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 Jd(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:ql(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=[Xl(C.graph),...T].filter(Boolean).join(`,`)||void 0;if(t.dryRun)return C;let O=Zl(C.graph.nodes)?$l(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 Vl(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?tu(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?kl(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(Sf,`dist`,`graph-viewer`),readSessions:n})}async function kf(e,t){if(t.artifacts||t.artifact)return lu(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 Id(e),Il(e),Su(e,Cf),Tu(e,Cf),cu(e),Dd(e),Gd(e,Cf,Sf),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(`
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 Gd(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=Vd(i,await F(i,`utf8`));if(r.json)return z(a);if(!r.open)return console.log(Ud(a));let o=await Wd(a,n);V(await fa(Gt(o).href)?`Opened ${o}`:`Open ${o}`)})}async function Kd(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 qd(e,t,n){let r=_f(t.parameter),i=n??await Kd(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(yf(a)),a):(vf(a,t.browser===!1?!1:await fa(a.redirectUrl),t.wait),a)}async function Jd(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 qd(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 Yd(){let e=new S(`hub`).description(`Discover and run Tangle Hub tools`);return Xd(e),Zd(e),Qd(e),$d(e),ef(e),e}function Xd(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 Kd(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 qd(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):gf(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 Zd(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 Qd(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):df(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=ff(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):df([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(nf())}function $d(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):pf(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):mf(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):uf(n.tools)}),e.addCommand(t),e.addCommand(tf(`call`)),e.addCommand(tf(`exec`))}function ef(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(af(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);sf(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):bf(t)})}function tf(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}=rf(e,t),{path:i,input:a}=lf(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 nf(){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):of(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)=>{af(e),sf(await(await Oi(n)).approvals[t](e),n.json===!0)});return e}function rf(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 af(e){if(!/^[A-Za-z0-9_-]+$/.test(e))throw Error(`Hub approval ID must contain only letters, numbers, underscores, and dashes.`)}function of(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 sf(e,t){if(t){z(cf(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 cf(e){return{approval:e.approval,...e.capabilityToken?{capabilityToken:{tokenId:e.capabilityToken.tokenId,expiresAt:e.capabilityToken.expiresAt}}:{}}}function lf(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 uf(e){R(e.map(e=>({...e,provider:e.providerId??e.requiredConnectionProviderId,connection:hf(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 df(e){R(e,[{key:`connectionId`,header:`Connection`},{key:`providerId`,header:`Provider`},{key:`actionPath`,header:`Action`},{key:`decision`,header:`Decision`},{key:`updatedAt`,header:`Updated`}])}function ff(e){if(e===`allow`||e===`ask`||e===`deny`)return e;throw Error(`--decision must be one of: allow, ask, deny.`)}function pf(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 mf(e){U({Path:e.path,Provider:e.providerId??e.requiredConnectionProviderId,Title:e.title,Description:e.description,Connection:hf(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 hf(e){if(e.connectionRequired===!1)return`not required`;if(e.connectionStatus)return e.connectionStatus}function gf(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 _f(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 vf(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 yf(e){return{provider:e.provider,redirectUrl:e.redirectUrl,expiresAt:e.expiresAt,scopes:e.scopes,cli:e.cli}}function bf(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 xf=t(import.meta.url);if(!xf)throw Error(`Tangle CLI package metadata was not found`);const Sf=ge(xf),$=e=>w(`sha256`).update(e).digest(`hex`);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=>Cl(l,M(c,e))||Cl(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(Sf,`dist`,`stdio.mjs`),f={...process.env,BRIDGE_HOST:`127.0.0.1`,BRIDGE_BEARER:r,BRIDGE_DATA_DIR:M(o,`bridge`),BRIDGE_BACKENDS:Kl,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 Bl(t.resume):void 0,l=r.taskWorkspace??(t.taskWorkspace?await Nl(t.taskWorkspace):void 0)??c?.taskWorkspace;if(c&&(l?kl(l):null)!==(c.taskWorkspace?kl(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 Fl(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 Cu(o,s,t,n);let e=await bl(),l=$(s),u=Object.entries(fu(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),Wl(c,t,l,d,f)}let g={apiKey:t.apiKey,sandboxBaseUrl:t.baseUrl,signal:n,json:t.json,dryRun:t.dryRun&&!r.connectNeeds},_,v=()=>_??=Kd(g),y=new Map,b=(e,{account:t})=>{let n=e.trim().toLowerCase(),r=JSON.stringify([n,t?.toLowerCase()]),i=y.get(r)??(async()=>{let e=await v(),r=e&&await Jd(e,n,g,t);return r?{connectionId:r,capabilities:[`*`]}:void 0})();return y.set(r,i),i},x=async i=>{if(n.throwIfAborted(),c&&h)return 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:ql(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.code}: ${e.message}`).join(`; `)}`,`tangle graph run --mcp-policy <policy.json> --help`);for(let t of Object.values(e.profile.mcp??{}))t.enabled!==!1&&t.url&&T.push(new URL(t.url).hostname)}let D=[Xl(C.graph),...T].filter(Boolean).join(`,`)||void 0;if(t.dryRun)return C;let O=Zl(C.graph.nodes)?$l(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 Vl(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?tu(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?kl(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(Sf,`dist`,`graph-viewer`),readSessions:n})}async function kf(e,t){if(t.artifacts||t.artifact)return lu(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 Id(e),Il(e),Su(e,Cf),Tu(e,Cf),cu(e),Dd(e),Gd(e,Cf,Sf),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
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.`,du,[]).option(`--file <out>`,`Write the instantiated workflow YAML to this file instead of stdout`).action(async(e,t)=>{let n=fu(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
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
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),_u(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(Yd()),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{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/sandbox-cli",
3
- "version": "0.22.109",
3
+ "version": "0.22.111",
4
4
  "description": "CLI for Tangle Sandbox operations",
5
5
  "type": "module",
6
6
  "engines": {
@@ -62,8 +62,8 @@
62
62
  "vitest": "^4.1.12",
63
63
  "@repo/shared": "0.0.0",
64
64
  "@tangle-network/runtime-contracts": "0.20.0",
65
- "@tangle-network/sdk-session-persistence": "0.7.0",
66
- "@repo/knowledge-host": "0.0.0"
65
+ "@repo/knowledge-host": "0.0.0",
66
+ "@tangle-network/sdk-session-persistence": "0.7.0"
67
67
  },
68
68
  "publishConfig": {
69
69
  "access": "public",
@@ -87,8 +87,8 @@
87
87
  "author": "Tangle Network",
88
88
  "license": "MIT",
89
89
  "tangleRelease": {
90
- "sourceSha": "095eae3b9b72bad4e76f010d8d5e251d85f4c59d",
91
- "mergedAt": "2026-11-12T19:57:33-08:00"
90
+ "sourceSha": "b4c16fff0fca68633367e99eec10db2fa105c965",
91
+ "mergedAt": "2026-11-12T20:36:56-08:00"
92
92
  },
93
93
  "scripts": {
94
94
  "build": "tsdown",